<?php
/** Narrow, version-bound plaintext writer for one Spectra Blocks button. */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

const WPAGENT_SPECTRA_BLOCKS_BUTTON_VERSION            = '1.0.4';
const WPAGENT_SPECTRA_BLOCKS_BUTTON_BLOCK              = 'spectra/button';
const WPAGENT_SPECTRA_BLOCKS_BUTTON_PARENT             = 'spectra/buttons';
const WPAGENT_SPECTRA_BLOCKS_BUTTON_MAX_TEXT_LENGTH    = 200;
const WPAGENT_SPECTRA_BLOCKS_BUTTON_MAX_CONTENT_BYTES  = 1048576;

/** @return array{provider_version:string,block_name:string,parent_name:string}|WP_Error */
function wpagent_spectra_blocks_button_contract() {
	$provider = wpagent_spectra_blocks_read_require_contract();
	if ( is_wp_error( $provider ) ) {
		return $provider;
	}
	if ( ! hash_equals( WPAGENT_SPECTRA_BLOCKS_BUTTON_VERSION, (string) $provider['version'] ) ) {
		return new WP_Error( 'wpagent_spectra_blocks_button_provider', __( 'Der Spectra-Blocks-Buttonvertrag erfordert exakt Version 1.0.4.', 'wp-agent-companion' ), array( 'status' => 409 ) );
	}
	$registry = WP_Block_Type_Registry::get_instance();
	$button   = $registry->get_registered( WPAGENT_SPECTRA_BLOCKS_BUTTON_BLOCK );
	$parent   = $registry->get_registered( WPAGENT_SPECTRA_BLOCKS_BUTTON_PARENT );
	if ( ! $button instanceof WP_Block_Type || ! $parent instanceof WP_Block_Type
		|| WPAGENT_SPECTRA_BLOCKS_BUTTON_BLOCK !== $button->name || WPAGENT_SPECTRA_BLOCKS_BUTTON_PARENT !== $parent->name
		|| 3 !== (int) $button->api_version || 3 !== (int) $parent->api_version
		|| ! is_callable( $button->render_callback ) || ! is_callable( $parent->render_callback )
		|| array( WPAGENT_SPECTRA_BLOCKS_BUTTON_PARENT ) !== array_values( (array) $button->parent )
		|| array( WPAGENT_SPECTRA_BLOCKS_BUTTON_BLOCK ) !== array_values( (array) $parent->allowed_blocks ) ) {
		return new WP_Error( 'wpagent_spectra_blocks_button_provider', __( 'Der registrierte Spectra-Blocks-Button-, Gruppen- oder Rendervertrag ist nicht verfügbar.', 'wp-agent-companion' ), array( 'status' => 409 ) );
	}
	$attributes = $button->get_attributes();
	foreach ( array( 'text' => 'string', 'linkURL' => 'string', 'linkTarget' => 'string', 'linkRel' => 'array', 'isPreview' => 'boolean', 'showText' => 'boolean' ) as $attribute => $type ) {
		if ( ! is_array( $attributes[ $attribute ] ?? null ) || $type !== ( $attributes[ $attribute ]['type'] ?? null ) ) {
			return new WP_Error( 'wpagent_spectra_blocks_button_provider', __( 'Das registrierte Spectra-Blocks-Buttonschema stimmt nicht mit dem getesteten Providervertrag überein.', 'wp-agent-companion' ), array( 'status' => 409 ) );
		}
	}
	if ( false !== ( $attributes['isPreview']['default'] ?? null ) || true !== ( $attributes['showText']['default'] ?? null ) ) {
		return new WP_Error( 'wpagent_spectra_blocks_button_provider', __( 'Die registrierten Spectra-Blocks-Buttonvorgaben stimmen nicht mit dem getesteten Rendervertrag überein.', 'wp-agent-companion' ), array( 'status' => 409 ) );
	}
	return array( 'provider_version' => (string) $provider['version'], 'block_name' => $button->name, 'parent_name' => $parent->name );
}

/** @return array<string,mixed> */
function wpagent_ability_update_spectra_blocks_button_text(): array {
	return array(
		'label'       => __( 'Spectra-Blocks-Buttontext aktualisieren', 'wp-agent-companion' ),
		'description' => __( 'Ändert ausschließlich reinen Text eines exakt verifizierten Spectra-Blocks-Buttons in einer Spectra-Buttons-Gruppe. Der Write ist an Blog, Dokumenthash, Revision, atomaren Vergleich, Rückleseprüfung, Cache-Nachlauf und erneuerbare exklusive Sperre gebunden.', 'wp-agent-companion' ),
		'category'    => 'wp-agent',
		'input_schema' => array(
			'type'       => 'object',
			'properties' => array(
				'post_id'       => array( 'type' => 'integer', 'minimum' => 1 ),
				'path'          => array( 'type' => 'array', 'minItems' => 2, 'maxItems' => 32, 'items' => array( 'type' => 'integer', 'minimum' => 0, 'maximum' => 10000 ) ),
				'text'          => array( 'type' => 'string', 'minLength' => 1, 'maxLength' => WPAGENT_SPECTRA_BLOCKS_BUTTON_MAX_TEXT_LENGTH ),
				'expected_hash' => array( 'type' => 'string', 'pattern' => '^[a-f0-9]{64}$' ),
			),
			'required'             => array( 'post_id', 'path', 'text', 'expected_hash' ),
			'additionalProperties' => false,
		),
		'output_schema' => array(
			'type'       => 'object',
			'properties' => array(
				'post_id'              => array( 'type' => 'integer' ),
				'block_name'           => array( 'type' => 'string', 'enum' => array( WPAGENT_SPECTRA_BLOCKS_BUTTON_BLOCK ) ),
				'path'                 => array( 'type' => 'array', 'items' => array( 'type' => 'integer' ) ),
				'text'                 => array( 'type' => 'string', 'minLength' => 1, 'maxLength' => WPAGENT_SPECTRA_BLOCKS_BUTTON_MAX_TEXT_LENGTH ),
				'provider_version'     => array( 'type' => 'string', 'enum' => array( WPAGENT_SPECTRA_BLOCKS_BUTTON_VERSION ) ),
				'changed'              => array( 'type' => 'boolean' ),
				'verified'             => array( 'type' => 'boolean' ),
				'revision_id'          => array( 'type' => 'integer', 'minimum' => 0 ),
				'rendered_html_length' => array( 'type' => 'integer', 'minimum' => 1 ),
				'previous_hash'        => array( 'type' => 'string', 'pattern' => '^[a-f0-9]{64}$' ),
				'hash'                 => array( 'type' => 'string', 'pattern' => '^[a-f0-9]{64}$' ),
				'cache'                => array(
					'type' => 'object', 'properties' => array(
						'builder' => array( 'type' => 'string', 'enum' => array( 'spectra' ) ),
						'executed' => array( 'type' => 'boolean' ), 'verified' => array( 'type' => 'boolean' ),
					), 'required' => array( 'builder', 'executed', 'verified' ), 'additionalProperties' => false,
				),
			),
			'required'             => array( 'post_id', 'block_name', 'path', 'text', 'provider_version', 'changed', 'verified', 'revision_id', 'rendered_html_length', 'previous_hash', 'hash', 'cache' ),
			'additionalProperties' => false,
		),
		'execute_callback'    => 'wpagent_exec_update_spectra_blocks_button_text',
		'permission_callback' => 'wpagent_perm_edit_posts',
		'meta'                => array( 'show_in_rest' => true, 'annotations' => array( 'readonly' => false, 'destructive' => false, 'idempotent' => false ) ),
	);
}

/** @return string|WP_Error */
function wpagent_spectra_blocks_button_validate_text( $value, string $field = 'text', int $status = 400 ) {
	$text = wpagent_site_editor_plain_text( $value, $field, WPAGENT_SPECTRA_BLOCKS_BUTTON_MAX_TEXT_LENGTH );
	if ( is_wp_error( $text ) ) {
		return new WP_Error( 'wpagent_spectra_blocks_button_text', $text->get_error_message(), array( 'status' => $status ) );
	}
	return $text;
}

/** @return array{post:WP_Post,post_type:string,status:string}|WP_Error */
function wpagent_spectra_blocks_button_editable_post( int $post_id ) {
	$post = get_post( $post_id );
	if ( ! $post instanceof WP_Post ) {
		return new WP_Error( 'wpagent_spectra_blocks_button_not_found', __( 'Der Button-Beitrag wurde nicht gefunden.', 'wp-agent-companion' ), array( 'status' => 404 ) );
	}
	if ( ! current_user_can( 'edit_post', $post_id ) ) {
		return new WP_Error( 'wpagent_spectra_blocks_button_forbidden', __( 'Keine Berechtigung für diesen Button-Beitrag.', 'wp-agent-companion' ), array( 'status' => 403 ) );
	}
	$type = get_post_type_object( $post->post_type );
	if ( ! $type instanceof WP_Post_Type || ! post_type_supports( $post->post_type, 'editor' ) ) {
		return new WP_Error( 'wpagent_spectra_blocks_button_post_type', __( 'Der Zielbeitrag besitzt keinen editierbaren Blockinhalt.', 'wp-agent-companion' ), array( 'status' => 409 ) );
	}
	if ( ! in_array( $post->post_status, array( 'publish', 'future', 'draft', 'pending', 'private' ), true ) ) {
		return new WP_Error( 'wpagent_spectra_blocks_button_post_status', __( 'Der Zielbeitrag besitzt keinen editierbaren Veröffentlichungsstatus.', 'wp-agent-companion' ), array( 'status' => 409 ) );
	}
	return array( 'post' => $post, 'post_type' => (string) $post->post_type, 'status' => (string) $post->post_status );
}

/** @param array{post:WP_Post,post_type:string,status:string} $before @param array{post:WP_Post,post_type:string,status:string} $after */
function wpagent_spectra_blocks_button_same_post_state( array $before, array $after ): bool {
	return (int) $before['post']->ID === (int) $after['post']->ID
		&& hash_equals( $before['post_type'], $after['post_type'] )
		&& hash_equals( $before['status'], $after['status'] );
}

/** @param array<string,mixed> $block @return string|WP_Error */
function wpagent_spectra_blocks_button_text_from_block( array $block ) {
	// Spectra Blocks 1.0.4 registers this dynamic child without save(). Core
	// therefore parses its canonical self-closing comment with no inner HTML.
	if ( WPAGENT_SPECTRA_BLOCKS_BUTTON_BLOCK !== ( $block['blockName'] ?? null )
		|| ! isset( $block['innerBlocks'] ) || ! is_array( $block['innerBlocks'] ) || array() !== $block['innerBlocks']
		|| '' !== ( $block['innerHTML'] ?? null ) || array() !== ( $block['innerContent'] ?? null ) ) {
		return new WP_Error( 'wpagent_spectra_blocks_button_target', __( 'Der Zielblock erfüllt nicht den engen nativen Spectra-Blocks-Button-Markupvertrag.', 'wp-agent-companion' ), array( 'status' => 409 ) );
	}
	$attributes = $block['attrs'] ?? null;
	if ( ! is_array( $attributes ) || ! array_key_exists( 'text', $attributes ) || ( isset( $attributes['isPreview'] ) && false !== $attributes['isPreview'] ) || ( isset( $attributes['showText'] ) && true !== $attributes['showText'] ) ) {
		return new WP_Error( 'wpagent_spectra_blocks_button_target', __( 'Der Zielbutton enthält keine verifizierbare sichtbare Spectra-Blocks-Textsteuerung.', 'wp-agent-companion' ), array( 'status' => 409 ) );
	}
	$text = wpagent_spectra_blocks_button_validate_text( $attributes['text'], 'gespeicherter Buttontext', 409 );
	if ( is_wp_error( $text ) || ! is_string( $attributes['text'] ) || ! hash_equals( $attributes['text'], $text ) ) {
		return new WP_Error( 'wpagent_spectra_blocks_button_target', __( 'Der gespeicherte Buttontext ist nicht exakt als reiner Text verifizierbar.', 'wp-agent-companion' ), array( 'status' => 409 ) );
	}
	return $text;
}

/** @param array<int,array<string,mixed>> $blocks @param array<int,int> $path @return array{block:array<string,mixed>,parent:array<string,mixed>,text:string}|WP_Error */
function wpagent_spectra_blocks_button_target_at_path( array $blocks, array $path, int $depth = 0, ?array $parent = null ) {
	$index = $path[ $depth ];
	if ( ! isset( $blocks[ $index ] ) || ! is_array( $blocks[ $index ] ) ) {
		return new WP_Error( 'wpagent_spectra_blocks_button_path', __( 'Der Spectra-Blocks-Buttonpfad wurde im aktuellen Dokument nicht gefunden.', 'wp-agent-companion' ), array( 'status' => 404 ) );
	}
	$block = $blocks[ $index ];
	if ( $depth + 1 < count( $path ) ) {
		$inner = $block['innerBlocks'] ?? null;
		if ( ! is_array( $inner ) ) {
			return new WP_Error( 'wpagent_spectra_blocks_button_path', __( 'Der Spectra-Blocks-Buttonpfad wurde im aktuellen Dokument nicht gefunden.', 'wp-agent-companion' ), array( 'status' => 404 ) );
		}
		return wpagent_spectra_blocks_button_target_at_path( $inner, $path, $depth + 1, $block );
	}
	if ( ! is_array( $parent ) || WPAGENT_SPECTRA_BLOCKS_BUTTON_PARENT !== ( $parent['blockName'] ?? null ) ) {
		return new WP_Error( 'wpagent_spectra_blocks_button_parent', __( 'Der Zielbutton muss direkt in einer verifizierten Spectra-Blocks-Buttons-Gruppe liegen.', 'wp-agent-companion' ), array( 'status' => 409 ) );
	}
	$text = wpagent_spectra_blocks_button_text_from_block( $block );
	return is_wp_error( $text ) ? $text : array( 'block' => $block, 'parent' => $parent, 'text' => $text );
}

/** @param array<string,mixed> $block @return string|WP_Error */
function wpagent_spectra_blocks_button_render_target( array $block ) {
	$text = wpagent_spectra_blocks_button_text_from_block( $block );
	if ( is_wp_error( $text ) ) {
		return $text;
	}
	try {
		$html = do_blocks( serialize_blocks( array( $block ) ) );
	} catch ( Throwable $error ) {
		return new WP_Error( 'wpagent_spectra_blocks_button_render', __( 'Der Spectra-Blocks-Button konnte nicht serverseitig gerendert werden.', 'wp-agent-companion' ), array( 'status' => 409 ) );
	}
	if ( ! is_string( $html ) || 1 !== preg_match_all( '/<div class="spectra-button__link">([^<]*)<\\/div>/D', $html, $matches ) ) {
		return new WP_Error( 'wpagent_spectra_blocks_button_render', __( 'Der serverseitige Spectra-Blocks-Button-Output erfüllt den getesteten sichtbaren Textvertrag nicht.', 'wp-agent-companion' ), array( 'status' => 409 ) );
	}
	if ( ! hash_equals( $text, $matches[1][0] ) || false === strpos( $html, 'wp-block-button__link' ) ) {
		return new WP_Error( 'wpagent_spectra_blocks_button_render', __( 'Der serverseitige Spectra-Blocks-Button-Output weicht vom getesteten Rendervertrag ab.', 'wp-agent-companion' ), array( 'status' => 409 ) );
	}
	return $html;
}

/** @param array<int,array<string,mixed>> $blocks @param array<int,int> $path @return array{text:string,html:string}|WP_Error */
function wpagent_spectra_blocks_button_target_state( array $blocks, array $path ) {
	$target = wpagent_spectra_blocks_button_target_at_path( $blocks, $path );
	if ( is_wp_error( $target ) ) {
		return $target;
	}
	$html = wpagent_spectra_blocks_button_render_target( $target['block'] );
	return is_wp_error( $html ) ? $html : array( 'text' => $target['text'], 'html' => $html );
}

/** @param array<int,array<string,mixed>> $blocks @param array<int,int> $path @return array{block_name:string,text:string,changed:bool}|WP_Error */
function wpagent_spectra_blocks_button_patch_path( array &$blocks, array $path, string $text, int $depth = 0, ?array $parent = null ) {
	$index = $path[ $depth ];
	if ( ! isset( $blocks[ $index ] ) || ! is_array( $blocks[ $index ] ) ) {
		return new WP_Error( 'wpagent_spectra_blocks_button_path', __( 'Der Spectra-Blocks-Buttonpfad wurde im aktuellen Dokument nicht gefunden.', 'wp-agent-companion' ), array( 'status' => 404 ) );
	}
	if ( $depth + 1 < count( $path ) ) {
		if ( ! isset( $blocks[ $index ]['innerBlocks'] ) || ! is_array( $blocks[ $index ]['innerBlocks'] ) ) {
			return new WP_Error( 'wpagent_spectra_blocks_button_path', __( 'Der Spectra-Blocks-Buttonpfad wurde im aktuellen Dokument nicht gefunden.', 'wp-agent-companion' ), array( 'status' => 404 ) );
		}
		return wpagent_spectra_blocks_button_patch_path( $blocks[ $index ]['innerBlocks'], $path, $text, $depth + 1, $blocks[ $index ] );
	}
	if ( ! is_array( $parent ) || WPAGENT_SPECTRA_BLOCKS_BUTTON_PARENT !== ( $parent['blockName'] ?? null ) ) {
		return new WP_Error( 'wpagent_spectra_blocks_button_parent', __( 'Der Zielbutton muss direkt in einer Spectra-Blocks-Buttons-Gruppe liegen.', 'wp-agent-companion' ), array( 'status' => 409 ) );
	}
	$before = wpagent_spectra_blocks_button_text_from_block( $blocks[ $index ] );
	if ( is_wp_error( $before ) ) {
		return $before;
	}
	if ( hash_equals( $before, $text ) ) {
		return array( 'block_name' => WPAGENT_SPECTRA_BLOCKS_BUTTON_BLOCK, 'text' => $before, 'changed' => false );
	}
	$blocks[ $index ]['attrs']['text'] = $text;
	return array( 'block_name' => WPAGENT_SPECTRA_BLOCKS_BUTTON_BLOCK, 'text' => $text, 'changed' => true );
}

/** @return array{builder:string,executed:bool,verified:bool} */
function wpagent_spectra_blocks_button_refresh_cache( int $post_id ): array {
	$cache = wpagent_refresh_builder_cache_spectra( $post_id );
	return array( 'builder' => 'spectra', 'executed' => ! empty( $cache['executed'] ), 'verified' => ! empty( $cache['verified'] ) );
}

/** @return array{builder:string,executed:bool,verified:bool} */
function wpagent_spectra_blocks_button_noop_cache(): array {
	return array( 'builder' => 'spectra', 'executed' => false, 'verified' => true );
}

/** @param array<int,int> $path @return array<string,mixed>|WP_Error */
function wpagent_spectra_blocks_button_verify_noop_state( int $post_id, string $expected_content, array $path, string $expected_text ) {
	$raw = wpagent_native_block_raw_content( $post_id );
	$state = wpagent_native_block_document_state( $post_id );
	if ( is_wp_error( $raw ) || is_wp_error( $state ) || $raw !== $expected_content || $state['content'] !== $expected_content ) {
		return new WP_Error( 'wpagent_spectra_blocks_button_noop_conflict', __( 'Das Button-Dokument wurde während der No-op-Prüfung verändert.', 'wp-agent-companion' ), array( 'status' => 409, 'current_hash' => is_array( $state ) ? $state['hash'] : '' ) );
	}
	$blocks = parse_blocks( $raw );
	if ( serialize_blocks( $blocks ) !== $raw ) {
		return new WP_Error( 'wpagent_spectra_blocks_button_noop_conflict', __( 'Das Button-Dokument ist während der No-op-Prüfung nicht mehr kanonisch lesbar.', 'wp-agent-companion' ), array( 'status' => 409, 'current_hash' => $state['hash'] ) );
	}
	$target = wpagent_spectra_blocks_button_target_state( $blocks, $path );
	if ( is_wp_error( $target ) || ! hash_equals( $expected_text, $target['text'] ) ) {
		return new WP_Error( 'wpagent_spectra_blocks_button_noop_conflict', __( 'Der Zielbutton änderte sich während der No-op-Prüfung.', 'wp-agent-companion' ), array( 'status' => 409, 'current_hash' => $state['hash'] ) );
	}
	return $state;
}

/** @return array{rolled_back:bool,rollback_verified:bool,recovery_required:bool} */
function wpagent_spectra_blocks_button_rollback_after_cache( int $post_id, string $before_content, string $candidate_content ): array {
	$rollback = wpagent_native_block_rollback( $post_id, $before_content, $candidate_content );
	if ( ! $rollback['rolled_back'] ) {
		return $rollback;
	}
	$cache = wpagent_spectra_blocks_button_refresh_cache( $post_id );
	$raw = wpagent_native_block_raw_content( $post_id );
	$state = wpagent_native_block_document_state( $post_id );
	if ( ! $cache['verified'] || is_wp_error( $raw ) || $raw !== $before_content || is_wp_error( $state ) || $state['content'] !== $before_content ) {
		return array( 'rolled_back' => true, 'rollback_verified' => false, 'recovery_required' => true );
	}
	return $rollback;
}

/** @return array{rolled_back:bool,rollback_verified:bool,recovery_required:bool} */
function wpagent_spectra_blocks_button_recover_lost_lock_after_write( int $post_id, string $before_content, string $candidate_content ): array {
	$raw = wpagent_native_block_raw_content( $post_id );
	if ( is_wp_error( $raw ) || $raw !== $candidate_content ) {
		return array( 'rolled_back' => false, 'rollback_verified' => false, 'recovery_required' => true );
	}
	return wpagent_spectra_blocks_button_rollback_after_cache( $post_id, $before_content, $candidate_content );
}

/** @param array{rolled_back:bool,rollback_verified:bool,recovery_required:bool} $rollback @return WP_Error */
function wpagent_spectra_blocks_button_write_error( string $code, string $message, int $revision_id, array $rollback ) {
	$data = array( 'status' => 500, 'revision_id' => $revision_id, 'rolled_back' => $rollback['rolled_back'], 'rollback_verified' => $rollback['rollback_verified'], 'recovery_required' => $rollback['recovery_required'] );
	if ( $rollback['recovery_required'] ) {
		return new WP_Error( 'wpagent_spectra_blocks_button_recovery_required', __( 'Der Button- oder Spectra-Cachezustand konnte nicht vollständig verifiziert werden. Prüfe die angelegte Revision, bevor du den Vorgang wiederholst.', 'wp-agent-companion' ), $data );
	}
	return new WP_Error( $code, $message, $data );
}

/** @return WP_Error */
function wpagent_spectra_blocks_button_lock_lost_after_write( int $revision_id, int $post_id, string $before_content, string $candidate_content ) {
	$rollback = wpagent_spectra_blocks_button_recover_lost_lock_after_write( $post_id, $before_content, $candidate_content );
	return wpagent_spectra_blocks_button_write_error(
		'wpagent_spectra_blocks_button_lock_lost',
		__( 'Die exklusive Sperre ging nach Beginn der Spectra-Blocks-Buttonänderung verloren. Der eigene Kandidat wurde nur bei bytegenauem Besitz bedingt zurückgesetzt und andernfalls zur manuellen Prüfung belassen.', 'wp-agent-companion' ),
		$revision_id,
		$rollback
	);
}

/** @return array<string,mixed>|WP_Error */
function wpagent_exec_update_spectra_blocks_button_text( $input ) {
	$input = is_array( $input ) ? $input : array();
	$post_id = absint( $input['post_id'] ?? 0 );
	$path = is_array( $input['path'] ?? null ) ? $input['path'] : array();
	$path_ok = wpagent_native_block_validate_path( $path );
	if ( is_wp_error( $path_ok ) || count( $path ) < 2 ) {
		return is_wp_error( $path_ok ) ? $path_ok : new WP_Error( 'wpagent_spectra_blocks_button_path', __( 'path muss einen Button innerhalb einer Spectra-Blocks-Buttons-Gruppe bezeichnen.', 'wp-agent-companion' ), array( 'status' => 400 ) );
	}
	$text = wpagent_spectra_blocks_button_validate_text( $input['text'] ?? null );
	if ( is_wp_error( $text ) ) {
		return $text;
	}
	$expected_hash = is_string( $input['expected_hash'] ?? null ) ? $input['expected_hash'] : '';
	if ( 1 !== preg_match( '/^[a-f0-9]{64}$/D', $expected_hash ) ) {
		return new WP_Error( 'wpagent_spectra_blocks_button_hash', __( 'expected_hash muss ein SHA-256-Hash sein.', 'wp-agent-companion' ), array( 'status' => 400 ) );
	}
	$editable = wpagent_spectra_blocks_button_editable_post( $post_id );
	if ( is_wp_error( $editable ) ) {
		return $editable;
	}
	$contract = wpagent_spectra_blocks_button_contract();
	if ( is_wp_error( $contract ) ) {
		return $contract;
	}
	$lock = wpagent_site_editor_acquire_lock( 'spectra-blocks-button', (string) $post_id );
	if ( is_wp_error( $lock ) ) {
		return $lock;
	}
	try {
		$fresh_editable = wpagent_spectra_blocks_button_editable_post( $post_id );
		if ( is_wp_error( $fresh_editable ) ) {
			return $fresh_editable;
		}
		if ( ! wpagent_spectra_blocks_button_same_post_state( $editable, $fresh_editable ) ) {
			return new WP_Error( 'wpagent_spectra_blocks_button_conflict', __( 'Posttyp oder Veröffentlichungsstatus des Zielbeitrags änderten sich vor der Buttonänderung.', 'wp-agent-companion' ), array( 'status' => 409 ) );
		}
		$before = wpagent_native_block_document_state( $post_id );
		if ( is_wp_error( $before ) ) {
			return $before;
		}
		if ( ! hash_equals( $before['hash'], $expected_hash ) ) {
			return new WP_Error( 'wpagent_spectra_blocks_button_conflict', __( 'Das Button-Dokument wurde seit dem Lesen verändert.', 'wp-agent-companion' ), array( 'status' => 409, 'current_hash' => $before['hash'] ) );
		}
		if ( ! hash_equals( $editable['post_type'], $before['post_type'] ) || ! hash_equals( $editable['status'], $before['status'] ) ) {
			return new WP_Error( 'wpagent_spectra_blocks_button_conflict', __( 'Posttyp oder Veröffentlichungsstatus des Zielbeitrags änderten sich vor der Buttonänderung.', 'wp-agent-companion' ), array( 'status' => 409 ) );
		}
		if ( strlen( $before['content'] ) > WPAGENT_SPECTRA_BLOCKS_BUTTON_MAX_CONTENT_BYTES ) {
			return new WP_Error( 'wpagent_spectra_blocks_button_document', __( 'Das Button-Dokument ist größer als 1 MB und wird nicht automatisch geändert.', 'wp-agent-companion' ), array( 'status' => 413 ) );
		}
		$blocks = parse_blocks( $before['content'] );
		if ( serialize_blocks( $blocks ) !== $before['content'] ) {
			return new WP_Error( 'wpagent_spectra_blocks_button_document', __( 'Das bestehende Button-Dokument ist nicht exakt parse- und serialisierbar und wird deshalb nicht automatisch verändert.', 'wp-agent-companion' ), array( 'status' => 409 ) );
		}
		$target = wpagent_spectra_blocks_button_patch_path( $blocks, $path, $text );
		if ( is_wp_error( $target ) ) {
			return $target;
		}
		if ( ! wpagent_site_editor_refresh_lock( 'spectra-blocks-button', (string) $post_id, $lock ) ) {
			return new WP_Error( 'wpagent_spectra_blocks_button_lock_lost', __( 'Die exklusive Sperre ging vor der Buttonänderung verloren.', 'wp-agent-companion' ), array( 'status' => 409 ) );
		}
		if ( ! $target['changed'] ) {
			$fresh = wpagent_spectra_blocks_button_verify_noop_state( $post_id, $before['content'], $path, $text );
			if ( is_wp_error( $fresh ) ) {
				return $fresh;
			}
			if ( ! wpagent_site_editor_lock_is_owned( 'spectra-blocks-button', (string) $post_id, $lock ) ) {
				return new WP_Error( 'wpagent_spectra_blocks_button_lock_lost', __( 'Die exklusive Sperre ging während der No-op-Prüfung verloren.', 'wp-agent-companion' ), array( 'status' => 409 ) );
			}
			$final_editable = wpagent_spectra_blocks_button_editable_post( $post_id );
			if ( is_wp_error( $final_editable ) || ! wpagent_spectra_blocks_button_same_post_state( $editable, $final_editable ) ) {
				return new WP_Error( 'wpagent_spectra_blocks_button_noop_conflict', __( 'Posttyp, Veröffentlichungsstatus oder Berechtigung änderten sich während der No-op-Prüfung.', 'wp-agent-companion' ), array( 'status' => 409, 'current_hash' => $fresh['hash'] ) );
			}
			$state = wpagent_spectra_blocks_button_target_state( $blocks, $path );
			return is_wp_error( $state ) ? $state : array(
				'post_id' => $post_id, 'block_name' => $target['block_name'], 'path' => $path, 'text' => $state['text'], 'provider_version' => $contract['provider_version'],
				'changed' => false, 'verified' => true, 'revision_id' => 0, 'rendered_html_length' => strlen( $state['html'] ), 'previous_hash' => $before['hash'], 'hash' => $fresh['hash'], 'cache' => wpagent_spectra_blocks_button_noop_cache(),
			);
		}
		$candidate = serialize_blocks( $blocks );
		if ( strlen( $candidate ) > WPAGENT_SPECTRA_BLOCKS_BUTTON_MAX_CONTENT_BYTES || serialize_blocks( parse_blocks( $candidate ) ) !== $candidate ) {
			return new WP_Error( 'wpagent_spectra_blocks_button_document', __( 'Das geänderte Button-Dokument ist nicht stabil serialisierbar oder überschreitet 1 MB.', 'wp-agent-companion' ), array( 'status' => 400 ) );
		}
		$before_report = array( 'block_count' => 0, 'freeform_count' => 0, 'block_types' => array() );
		$after_report = array( 'block_count' => 0, 'freeform_count' => 0, 'block_types' => array() );
		wpagent_native_block_report_walk( parse_blocks( $before['content'] ), $before_report );
		wpagent_native_block_report_walk( parse_blocks( $candidate ), $after_report );
		if ( $before_report !== $after_report ) {
			return new WP_Error( 'wpagent_spectra_blocks_button_structure_changed', __( 'Der Buttontext-Patch würde die Blockstruktur verändern und wurde abgelehnt.', 'wp-agent-companion' ), array( 'status' => 400 ) );
		}
		$candidate_state = wpagent_spectra_blocks_button_target_state( parse_blocks( $candidate ), $path );
		if ( is_wp_error( $candidate_state ) || ! hash_equals( $text, $candidate_state['text'] ) ) {
			return new WP_Error( 'wpagent_spectra_blocks_button_document', __( 'Der geänderte Buttonzustand verletzt den nativen Rendervertrag.', 'wp-agent-companion' ), array( 'status' => 400 ) );
		}
		if ( ! wpagent_site_editor_refresh_lock( 'spectra-blocks-button', (string) $post_id, $lock ) ) {
			return new WP_Error( 'wpagent_spectra_blocks_button_lock_lost', __( 'Die exklusive Sperre ging vor der Buttonänderung verloren.', 'wp-agent-companion' ), array( 'status' => 409 ) );
		}
		$revision_id = wpagent_native_block_create_revision( $post_id, $before['content'] );
		if ( is_wp_error( $revision_id ) ) {
			return $revision_id;
		}
		if ( ! wpagent_site_editor_refresh_lock( 'spectra-blocks-button', (string) $post_id, $lock ) ) {
			return new WP_Error( 'wpagent_spectra_blocks_button_lock_lost', __( 'Die exklusive Sperre ging vor dem Button-Write verloren.', 'wp-agent-companion' ), array( 'status' => 409, 'revision_id' => $revision_id ) );
		}
		$write_editable = wpagent_spectra_blocks_button_editable_post( $post_id );
		if ( is_wp_error( $write_editable ) || ! wpagent_spectra_blocks_button_same_post_state( $editable, $write_editable ) ) {
			return new WP_Error( 'wpagent_spectra_blocks_button_conflict', __( 'Posttyp, Veröffentlichungsstatus oder Berechtigung änderten sich unmittelbar vor dem Button-Write.', 'wp-agent-companion' ), array( 'status' => 409, 'revision_id' => $revision_id ) );
		}
		$saved = wpagent_native_block_write_if_current( $post_id, $before['content'], $candidate );
		if ( is_wp_error( $saved ) ) {
			$data = $saved->get_error_data();
			return new WP_Error( $saved->get_error_code(), $saved->get_error_message(), array_merge( is_array( $data ) ? $data : array(), array( 'revision_id' => $revision_id ) ) );
		}
		if ( ! wpagent_site_editor_lock_is_owned( 'spectra-blocks-button', (string) $post_id, $lock ) ) {
			return wpagent_spectra_blocks_button_lock_lost_after_write( $revision_id, $post_id, $before['content'], $candidate );
		}
		$after_raw = wpagent_native_block_raw_content( $post_id );
		$after = wpagent_native_block_document_state( $post_id );
		$after_state = ! is_wp_error( $after_raw ) && $after_raw === $candidate && ! is_wp_error( $after ) && $after['content'] === $candidate ? wpagent_spectra_blocks_button_target_state( parse_blocks( $after_raw ), $path ) : null;
		$verified = is_string( $after_raw ) && $after_raw === $candidate && is_array( $after ) && ! is_wp_error( $after ) && $after['content'] === $candidate && hash_equals( $editable['post_type'], $after['post_type'] ) && hash_equals( $editable['status'], $after['status'] ) && is_array( $after_state ) && hash_equals( $text, $after_state['text'] );
		if ( ! $verified ) {
			$rollback = wpagent_native_block_rollback( $post_id, $before['content'], $candidate );
			return wpagent_spectra_blocks_button_write_error( 'wpagent_spectra_blocks_button_verify_failed', __( 'Der Spectra-Blocks-Button bestand die Parse-, Rücklese- oder Renderprüfung nicht.', 'wp-agent-companion' ), $revision_id, $rollback );
		}
		if ( ! wpagent_site_editor_refresh_lock( 'spectra-blocks-button', (string) $post_id, $lock ) ) {
			return wpagent_spectra_blocks_button_lock_lost_after_write( $revision_id, $post_id, $before['content'], $candidate );
		}
		$cache = wpagent_spectra_blocks_button_refresh_cache( $post_id );
		if ( ! wpagent_site_editor_lock_is_owned( 'spectra-blocks-button', (string) $post_id, $lock ) ) {
			return wpagent_spectra_blocks_button_lock_lost_after_write( $revision_id, $post_id, $before['content'], $candidate );
		}
		if ( ! $cache['verified'] ) {
			$rollback = wpagent_spectra_blocks_button_rollback_after_cache( $post_id, $before['content'], $candidate );
			return wpagent_spectra_blocks_button_write_error( 'wpagent_spectra_blocks_button_cache_failed', __( 'Spectras Beitrags- und Asset-Cache konnte nicht verifiziert aktualisiert werden.', 'wp-agent-companion' ), $revision_id, $rollback );
		}
		$after_cache_raw = wpagent_native_block_raw_content( $post_id );
		$after_cache = wpagent_native_block_document_state( $post_id );
		$after_cache_state = ! is_wp_error( $after_cache_raw ) && $after_cache_raw === $candidate && ! is_wp_error( $after_cache ) && $after_cache['content'] === $candidate ? wpagent_spectra_blocks_button_target_state( parse_blocks( $after_cache_raw ), $path ) : null;
		$final_editable = wpagent_spectra_blocks_button_editable_post( $post_id );
		$cache_verified = is_string( $after_cache_raw ) && $after_cache_raw === $candidate && is_array( $after_cache ) && ! is_wp_error( $after_cache ) && $after_cache['content'] === $candidate && hash_equals( $editable['post_type'], $after_cache['post_type'] ) && hash_equals( $editable['status'], $after_cache['status'] ) && is_array( $final_editable ) && wpagent_spectra_blocks_button_same_post_state( $editable, $final_editable ) && is_array( $after_cache_state ) && hash_equals( $text, $after_cache_state['text'] );
		if ( ! $cache_verified ) {
			$rollback = wpagent_spectra_blocks_button_rollback_after_cache( $post_id, $before['content'], $candidate );
			return wpagent_spectra_blocks_button_write_error( 'wpagent_spectra_blocks_button_cache_readback_failed', __( 'Spectras Cache-Nachlauf veränderte den gespeicherten Buttonzustand oder konnte ihn nicht erneut verifizieren.', 'wp-agent-companion' ), $revision_id, $rollback );
		}
		if ( ! wpagent_site_editor_refresh_lock( 'spectra-blocks-button', (string) $post_id, $lock ) ) {
			return wpagent_spectra_blocks_button_lock_lost_after_write( $revision_id, $post_id, $before['content'], $candidate );
		}
		return array(
			'post_id' => $post_id, 'block_name' => $target['block_name'], 'path' => $path, 'text' => $after_cache_state['text'], 'provider_version' => $contract['provider_version'],
			'changed' => true, 'verified' => true, 'revision_id' => $revision_id, 'rendered_html_length' => strlen( $after_cache_state['html'] ), 'previous_hash' => $before['hash'], 'hash' => $after_cache['hash'], 'cache' => $cache,
		);
	} finally {
		wpagent_site_editor_release_lock( 'spectra-blocks-button', (string) $post_id, $lock );
	}
}
