<?php
/** Mutating Site Editor content abilities. */

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

/** @return array<string,mixed> */
function wpagent_site_editor_write_ability( string $label, string $description, array $input, array $output, string $callback, bool $destructive = false ): array {
	return array(
		'label' => $label, 'description' => $description, 'category' => 'wp-agent',
		'input_schema' => $input, 'output_schema' => $output, 'execute_callback' => $callback,
		'permission_callback' => 'wpagent_perm_edit_theme_options',
		'meta' => array( 'show_in_rest' => true, 'annotations' => array( 'readonly' => false, 'destructive' => $destructive, 'idempotent' => false ) ),
	);
}

/** @return array<string,mixed> */
function wpagent_site_editor_template_write_properties( bool $part ): array {
	$properties = array(
		'slug'        => array( 'type' => 'string', 'maxLength' => 200 ),
		'title'       => array( 'type' => 'string', 'maxLength' => 200 ),
		'description' => array( 'type' => 'string', 'maxLength' => 1000 ),
		'container'   => array( 'type' => 'string', 'enum' => array( 'none', 'group', 'main', 'header', 'footer' ), 'default' => 'none' ),
		'components'  => wpagent_site_editor_components_schema(),
	);
	if ( $part ) $properties['area'] = array( 'type' => 'string', 'maxLength' => 50, 'default' => 'uncategorized' );
	return $properties;
}

/** @return array<string,mixed> */
function wpagent_site_editor_template_create_schema( bool $part ): array {
	return array(
		'type' => 'object', 'properties' => wpagent_site_editor_template_write_properties( $part ),
		'required' => $part ? array( 'slug', 'title', 'area', 'components' ) : array( 'slug', 'title', 'components' ),
		'additionalProperties' => false,
	);
}

/** @return array<string,mixed> */
function wpagent_site_editor_template_update_schema( bool $part ): array {
	$properties = wpagent_site_editor_template_write_properties( $part );
	unset( $properties['container']['default'], $properties['area']['default'] );
	$properties['expected_hash']         = array( 'type' => 'string', 'pattern' => '^[a-f0-9]{64}$' );
	$properties['confirm_theme_override'] = array( 'type' => 'boolean', 'default' => false );
	return array( 'type' => 'object', 'properties' => $properties, 'required' => array( 'slug', 'expected_hash' ), 'additionalProperties' => false );
}

/** @return array<string,mixed> */
function wpagent_site_editor_template_write_output_schema(): array {
	return array(
		'type' => 'object', 'properties' => array( 'resource' => wpagent_site_editor_resource_schema(), 'verified' => array( 'type' => 'boolean' ) ),
		'required' => array( 'resource', 'verified' ), 'additionalProperties' => false,
	);
}

/** @return array<string,mixed> */
function wpagent_site_editor_reference_schema(): array {
	return array(
		'type' => 'object', 'properties' => array(
			'items' => array( 'type' => 'array', 'items' => array(
				'type' => 'object', 'properties' => array(
					'post_id' => array( 'type' => 'integer' ), 'post_type' => array( 'type' => 'string' ), 'title' => array( 'type' => 'string' ),
				), 'required' => array( 'post_id', 'post_type', 'title' ), 'additionalProperties' => false,
			) ),
			'truncated' => array( 'type' => 'boolean' ),
		), 'required' => array( 'items', 'truncated' ), 'additionalProperties' => false,
	);
}

/** @return array<string,mixed> */
function wpagent_site_editor_template_delete_schema(): array {
	return array(
		'type' => 'object', 'properties' => array(
			'slug' => array( 'type' => 'string', 'maxLength' => 200 ),
			'expected_hash' => array( 'type' => 'string', 'pattern' => '^[a-f0-9]{64}$' ),
			'confirm' => array( 'type' => 'boolean' ), 'confirm_references' => array( 'type' => 'boolean', 'default' => false ),
		), 'required' => array( 'slug', 'expected_hash', 'confirm' ), 'additionalProperties' => false,
	);
}

/** @return array<string,mixed> */
function wpagent_site_editor_template_delete_output_schema(): array {
	return array(
		'type' => 'object', 'properties' => array(
			'deleted' => array( 'type' => 'boolean' ), 'reverted_to_theme' => array( 'type' => 'boolean' ),
			'reverted_to_source' => array( 'type' => 'boolean' ),
			'resource' => array( 'type' => array( 'object', 'null' ), 'properties' => wpagent_site_editor_resource_schema()['properties'], 'additionalProperties' => false ),
			'references' => wpagent_site_editor_reference_schema(),
		), 'required' => array( 'deleted', 'reverted_to_theme', 'reverted_to_source', 'resource', 'references' ), 'additionalProperties' => false,
	);
}

function wpagent_ability_create_site_template(): array {
	return wpagent_site_editor_write_ability( __( 'Site-Template erstellen', 'wp-agent-companion' ), __( 'Erstellt ein eigenes Blocktemplate aus strukturierten, serverseitig serialisierten Core-Komponenten und verifiziert den gespeicherten Zustand.', 'wp-agent-companion' ), wpagent_site_editor_template_create_schema( false ), wpagent_site_editor_template_write_output_schema(), 'wpagent_exec_create_site_template' );
}
function wpagent_ability_update_site_template(): array {
	return wpagent_site_editor_write_ability( __( 'Site-Template aktualisieren', 'wp-agent-companion' ), __( 'Aktualisiert ein Blocktemplate mit CAS-Schutz. Theme- und Plugin-Vorlagen benötigen eine ausdrückliche Überschreibungsbestätigung.', 'wp-agent-companion' ), wpagent_site_editor_template_update_schema( false ), wpagent_site_editor_template_write_output_schema(), 'wpagent_exec_update_site_template' );
}
function wpagent_ability_delete_site_template(): array {
	return wpagent_site_editor_write_ability( __( 'Site-Template löschen oder zurücksetzen', 'wp-agent-companion' ), __( 'Löscht ein eigenes Blocktemplate. Bei einer Theme- oder Plugin-Überschreibung wird nur die Datenbankversion entfernt und sicher auf die ursprüngliche Quelle zurückgesetzt.', 'wp-agent-companion' ), wpagent_site_editor_template_delete_schema(), wpagent_site_editor_template_delete_output_schema(), 'wpagent_exec_delete_site_template', true );
}
function wpagent_ability_create_template_part(): array {
	return wpagent_site_editor_write_ability( __( 'Template-Teil erstellen', 'wp-agent-companion' ), __( 'Erstellt ein Template-Teil aus strukturierten Core-Komponenten, ordnet seinen Bereich zu und verifiziert den gespeicherten Zustand.', 'wp-agent-companion' ), wpagent_site_editor_template_create_schema( true ), wpagent_site_editor_template_write_output_schema(), 'wpagent_exec_create_template_part' );
}
function wpagent_ability_update_template_part(): array {
	return wpagent_site_editor_write_ability( __( 'Template-Teil aktualisieren', 'wp-agent-companion' ), __( 'Aktualisiert ein Template-Teil mit CAS-Schutz und sicherer Theme-Überschreibung.', 'wp-agent-companion' ), wpagent_site_editor_template_update_schema( true ), wpagent_site_editor_template_write_output_schema(), 'wpagent_exec_update_template_part' );
}
function wpagent_ability_delete_template_part(): array {
	return wpagent_site_editor_write_ability( __( 'Template-Teil löschen oder zurücksetzen', 'wp-agent-companion' ), __( 'Löscht ein eigenes Template-Teil oder entfernt nur dessen Überschreibung. Vorhandene Referenzen werden erkannt.', 'wp-agent-companion' ), wpagent_site_editor_template_delete_schema(), wpagent_site_editor_template_delete_output_schema(), 'wpagent_exec_delete_template_part', true );
}

/** @return array<string,mixed> */
function wpagent_site_editor_navigation_items_schema(): array {
	return array( 'type' => 'array', 'minItems' => 1, 'maxItems' => WPAGENT_SITE_EDITOR_MAX_NAV_ITEMS, 'items' => wpagent_site_editor_nav_item_schema() );
}

function wpagent_ability_create_block_navigation(): array {
	return wpagent_site_editor_write_ability(
		__( 'Blocknavigation erstellen', 'wp-agent-companion' ), __( 'Erstellt eine veröffentlichte Blocknavigation aus sicheren internen, externen und verschachtelten Einträgen.', 'wp-agent-companion' ),
		array( 'type' => 'object', 'properties' => array( 'title' => array( 'type' => 'string', 'maxLength' => 200 ), 'items' => wpagent_site_editor_navigation_items_schema() ), 'required' => array( 'title', 'items' ), 'additionalProperties' => false ),
		array( 'type' => 'object', 'properties' => array( 'navigation' => wpagent_site_editor_navigation_schema(), 'verified' => array( 'type' => 'boolean' ) ), 'required' => array( 'navigation', 'verified' ), 'additionalProperties' => false ),
		'wpagent_exec_create_block_navigation'
	);
}

function wpagent_ability_update_block_navigation(): array {
	return wpagent_site_editor_write_ability(
		__( 'Blocknavigation aktualisieren', 'wp-agent-companion' ), __( 'Aktualisiert Titel oder Einträge einer Blocknavigation mit CAS-Schutz, Sperre, Revision und Read-Back-Verifikation.', 'wp-agent-companion' ),
		array( 'type' => 'object', 'properties' => array(
			'id' => array( 'type' => 'integer', 'minimum' => 1 ), 'expected_hash' => array( 'type' => 'string', 'pattern' => '^[a-f0-9]{64}$' ),
			'title' => array( 'type' => 'string', 'maxLength' => 200 ), 'items' => wpagent_site_editor_navigation_items_schema(),
		), 'required' => array( 'id', 'expected_hash' ), 'additionalProperties' => false ),
		array( 'type' => 'object', 'properties' => array( 'navigation' => wpagent_site_editor_navigation_schema(), 'verified' => array( 'type' => 'boolean' ) ), 'required' => array( 'navigation', 'verified' ), 'additionalProperties' => false ),
		'wpagent_exec_update_block_navigation'
	);
}

function wpagent_ability_delete_block_navigation(): array {
	return wpagent_site_editor_write_ability(
		__( 'Blocknavigation löschen', 'wp-agent-companion' ), __( 'Löscht eine Blocknavigation mit CAS-Schutz und erkennt Verwendungen in Beiträgen, Templates und Template-Teilen.', 'wp-agent-companion' ),
		array( 'type' => 'object', 'properties' => array(
			'id' => array( 'type' => 'integer', 'minimum' => 1 ), 'expected_hash' => array( 'type' => 'string', 'pattern' => '^[a-f0-9]{64}$' ),
			'confirm' => array( 'type' => 'boolean' ), 'confirm_references' => array( 'type' => 'boolean', 'default' => false ),
		), 'required' => array( 'id', 'expected_hash', 'confirm' ), 'additionalProperties' => false ),
		array( 'type' => 'object', 'properties' => array( 'deleted' => array( 'type' => 'boolean' ), 'references' => wpagent_site_editor_reference_schema() ), 'required' => array( 'deleted', 'references' ), 'additionalProperties' => false ),
		'wpagent_exec_delete_block_navigation', true
	);
}

function wpagent_exec_create_site_template( $input ) { return wpagent_site_editor_create_template( 'wp_template', is_array( $input ) ? $input : array() ); }
function wpagent_exec_update_site_template( $input ) { return wpagent_site_editor_update_template( 'wp_template', is_array( $input ) ? $input : array() ); }
function wpagent_exec_delete_site_template( $input ) { return wpagent_site_editor_delete_template( 'wp_template', is_array( $input ) ? $input : array() ); }
function wpagent_exec_create_template_part( $input ) { return wpagent_site_editor_create_template( 'wp_template_part', is_array( $input ) ? $input : array() ); }
function wpagent_exec_update_template_part( $input ) { return wpagent_site_editor_update_template( 'wp_template_part', is_array( $input ) ? $input : array() ); }
function wpagent_exec_delete_template_part( $input ) { return wpagent_site_editor_delete_template( 'wp_template_part', is_array( $input ) ? $input : array() ); }

/** @return array<string,mixed>|WP_Error */
function wpagent_site_editor_create_template( string $type, array $input ) {
	$block_theme = wpagent_site_editor_require_block_theme();
	if ( is_wp_error( $block_theme ) ) return $block_theme;
	$slug = wpagent_site_editor_slug( $input['slug'] ?? '' );
	$title = wpagent_site_editor_plain_text( $input['title'] ?? '', 'title', 200 );
	$description = wpagent_site_editor_plain_text( $input['description'] ?? '', 'description', 1000, true );
	foreach ( array( $slug, $title, $description ) as $value ) if ( is_wp_error( $value ) ) return $value;
	$area = null;
	if ( 'wp_template_part' === $type ) {
		$area = wpagent_site_editor_validate_area( $input['area'] ?? '' );
		if ( is_wp_error( $area ) ) return $area;
	}
	$content = wpagent_site_editor_build_content( $input['components'] ?? null, (string) ( $input['container'] ?? 'none' ) );
	if ( is_wp_error( $content ) ) return $content;
	$valid = wpagent_site_editor_validate_content( $content, wpagent_site_editor_validation_root( $type, $slug ) );
	if ( is_wp_error( $valid ) ) return $valid;
	// Creation, update, and deletion must serialize on the same resource key.
	// A separate "create" key would allow an update to race the create read-back.
	$lock_key = $slug;
	$lock = wpagent_site_editor_acquire_lock( $type, $lock_key );
	if ( is_wp_error( $lock ) ) return $lock;
	try {
		if ( get_block_template( wpagent_site_editor_template_id( $slug ), $type ) ) {
			return new WP_Error( 'wpagent_site_editor_exists', __( 'Unter diesem Slug existiert bereits eine Theme-, Plugin- oder Datenbankvorlage.', 'wp-agent-companion' ), array( 'status' => 409 ) );
		}
		$request = new WP_REST_Request( 'POST', '' );
		$request->set_body_params( array( 'slug' => $slug, 'theme' => get_stylesheet(), 'title' => $title, 'description' => $description, 'content' => $content, 'area' => $area ) );
		$prepared = (object) array(
			'post_name' => $slug, 'post_type' => $type, 'post_status' => 'publish', 'post_author' => get_current_user_id(),
			'post_title' => $title, 'post_excerpt' => $description, 'post_content' => $content,
			'tax_input' => array_filter(
				array( 'wp_theme' => get_stylesheet(), 'wp_template_part_area' => $area ),
				static fn( $value ): bool => null !== $value
			),
		);
		$prepared = apply_filters( "rest_pre_insert_{$type}", $prepared, $request );
		if ( is_wp_error( $prepared ) ) return $prepared;
		if ( ! is_object( $prepared ) ) {
			return new WP_Error( 'wpagent_site_editor_filter_result', __( 'Der WordPress-Vorbereitungsfilter lieferte keinen gültigen Beitragsdatensatz.', 'wp-agent-companion' ), array( 'status' => 500 ) );
		}
		$content = (string) ( $prepared->post_content ?? '' );
		$title = wpagent_site_editor_plain_text( $prepared->post_title ?? '', 'title', 200 );
		$description = wpagent_site_editor_plain_text( $prepared->post_excerpt ?? '', 'description', 1000, true );
		foreach ( array( $title, $description ) as $value ) if ( is_wp_error( $value ) ) return $value;
		$valid = wpagent_site_editor_validate_content( $content, wpagent_site_editor_validation_root( $type, $slug ) );
		if ( is_wp_error( $valid ) ) return $valid;
		$insert = array(
			'post_name' => $slug, 'post_type' => $type, 'post_status' => 'publish', 'post_author' => get_current_user_id(),
			'post_title' => $title, 'post_excerpt' => $description, 'post_content' => $content,
		);
		$post_id = wp_insert_post( wp_slash( $insert ), true );
		if ( is_wp_error( $post_id ) ) return $post_id;
		$theme_terms = wp_set_object_terms( $post_id, get_stylesheet(), 'wp_theme', false );
		$area_terms = null === $area ? array() : wp_set_object_terms( $post_id, $area, 'wp_template_part_area', false );
		if ( is_wp_error( $theme_terms ) || is_wp_error( $area_terms ) ) {
			wp_delete_post( $post_id, true );
			return is_wp_error( $theme_terms ) ? $theme_terms : $area_terms;
		}
		$post = get_post( $post_id );
		if ( $post instanceof WP_Post ) {
			do_action( "rest_after_insert_{$type}", $post, $request, true );
		}
		$fresh = wpagent_site_editor_get_template( $type, $slug );
		$verified = ! is_wp_error( $fresh ) && wpagent_site_editor_template_matches( $fresh, $title, $description, $content, $area );
		if ( ! $verified ) {
			wp_delete_post( $post_id, true );
			return new WP_Error( 'wpagent_site_editor_create_verify', __( 'Die Site-Editor-Ressource wich beim Read-Back ab und wurde zurückgerollt.', 'wp-agent-companion' ), array( 'status' => 500 ) );
		}
		return array( 'resource' => wpagent_site_editor_resource_state( $fresh ), 'verified' => true );
	} finally {
		wpagent_site_editor_release_lock( $type, $lock_key, $lock );
	}
}

/** @return array<string,mixed>|WP_Error */
function wpagent_site_editor_update_template( string $type, array $input ) {
	$block_theme = wpagent_site_editor_require_block_theme();
	if ( is_wp_error( $block_theme ) ) return $block_theme;
	$slug = wpagent_site_editor_slug( $input['slug'] ?? '' );
	if ( is_wp_error( $slug ) ) return $slug;
	$expected = wpagent_site_editor_expected_hash( $input['expected_hash'] ?? '' );
	if ( is_wp_error( $expected ) ) return $expected;
	$lock = wpagent_site_editor_acquire_lock( $type, $slug );
	if ( is_wp_error( $lock ) ) return $lock;
	try {
		$template = wpagent_site_editor_get_template( $type, $slug );
		if ( is_wp_error( $template ) ) return $template;
		$before = wpagent_site_editor_resource_state( $template );
		if ( ! hash_equals( $before['hash'], $expected ) ) return new WP_Error( 'wpagent_site_editor_conflict', __( 'Die Site-Editor-Ressource wurde seit dem Lesen verändert.', 'wp-agent-companion' ), array( 'status' => 409, 'current_hash' => $before['hash'] ) );
		if ( 'custom' !== $template->source && empty( $input['confirm_theme_override'] ) ) return new WP_Error( 'wpagent_site_editor_override_confirmation', __( 'Eine Theme- oder Plugin-Vorlage darf nur mit confirm_theme_override=true überschrieben werden.', 'wp-agent-companion' ), array( 'status' => 400 ) );
		$mutable = array_intersect( array_keys( $input ), array( 'title', 'description', 'area', 'components' ) );
		if ( array() === $mutable ) return new WP_Error( 'wpagent_site_editor_no_changes', __( 'Es wurde keine Änderung angegeben.', 'wp-agent-companion' ), array( 'status' => 400 ) );
		$title = isset( $input['title'] ) ? wpagent_site_editor_plain_text( $input['title'], 'title', 200 ) : $before['title'];
		$description = isset( $input['description'] ) ? wpagent_site_editor_plain_text( $input['description'], 'description', 1000, true ) : $before['description'];
		foreach ( array( $title, $description ) as $value ) if ( is_wp_error( $value ) ) return $value;
		$area = 'wp_template_part' === $type ? $before['area'] : null;
		if ( 'wp_template_part' === $type && isset( $input['area'] ) ) {
			$area = wpagent_site_editor_validate_area( $input['area'] );
			if ( is_wp_error( $area ) ) return $area;
		}
		if ( isset( $input['container'] ) && ! isset( $input['components'] ) ) return new WP_Error( 'wpagent_site_editor_container_without_components', __( 'container kann nur zusammen mit components geändert werden.', 'wp-agent-companion' ), array( 'status' => 400 ) );
		$content = isset( $input['components'] ) ? wpagent_site_editor_build_content( $input['components'], (string) ( $input['container'] ?? 'none' ) ) : $before['content'];
		if ( is_wp_error( $content ) ) return $content;
		$valid = wpagent_site_editor_validate_content( $content, wpagent_site_editor_validation_root( $type, $slug ) );
		if ( is_wp_error( $valid ) ) return $valid;
		$snapshot = wpagent_site_editor_template_snapshot( $template );
		if ( $template->wp_id && null === $snapshot ) return new WP_Error( 'wpagent_site_editor_snapshot_failed', __( 'Der vorherige Template-Zustand konnte nicht für einen sicheren Rollback gelesen werden.', 'wp-agent-companion' ), array( 'status' => 500 ) );
		$request = new WP_REST_Request( 'PUT', '' );
		$params = array( 'id' => $template->id, 'title' => $title, 'description' => $description, 'content' => $content );
		if ( null !== $area ) $params['area'] = $area;
		$request->set_body_params( $params );
		$result = ( new WP_REST_Templates_Controller( $type ) )->update_item( $request );
		if ( is_wp_error( $result ) ) {
			$current = wpagent_site_editor_get_template( $type, $slug );
			$changed = is_wp_error( $current ) || $before['hash'] !== wpagent_site_editor_resource_state( $current )['hash'];
			if ( $changed && ! wpagent_site_editor_restore_template_snapshot( $type, $slug, $snapshot ) ) {
				return new WP_Error( 'wpagent_site_editor_update_error_rollback', __( 'Die Aktualisierung schlug fehl und der vorherige Zustand konnte nicht vollständig wiederhergestellt werden.', 'wp-agent-companion' ), array( 'status' => 500, 'original_error' => $result->get_error_code() ) );
			}
			return $result;
		}
		$fresh = wpagent_site_editor_get_template( $type, $slug );
		if ( is_wp_error( $fresh ) || ! wpagent_site_editor_template_matches( $fresh, $title, $description, $content, $area ) ) {
			$rolled_back = wpagent_site_editor_restore_template_snapshot( $type, $slug, $snapshot );
			return new WP_Error( 'wpagent_site_editor_update_verify', __( 'Die Aktualisierung wich beim Read-Back ab und wurde zurückgerollt.', 'wp-agent-companion' ), array( 'status' => 500, 'rolled_back' => $rolled_back ) );
		}
		return array( 'resource' => wpagent_site_editor_resource_state( $fresh ), 'verified' => true );
	} finally {
		wpagent_site_editor_release_lock( $type, $slug, $lock );
	}
}

/** @return array<string,mixed>|WP_Error */
function wpagent_site_editor_delete_template( string $type, array $input ) {
	$block_theme = wpagent_site_editor_require_block_theme();
	if ( is_wp_error( $block_theme ) ) return $block_theme;
	$slug = wpagent_site_editor_slug( $input['slug'] ?? '' );
	if ( is_wp_error( $slug ) ) return $slug;
	$expected = wpagent_site_editor_expected_hash( $input['expected_hash'] ?? '' );
	if ( is_wp_error( $expected ) ) return $expected;
	if ( true !== ( $input['confirm'] ?? false ) ) return new WP_Error( 'wpagent_site_editor_delete_confirmation', __( 'Zum Löschen ist confirm=true erforderlich.', 'wp-agent-companion' ), array( 'status' => 400 ) );
	$lock = wpagent_site_editor_acquire_lock( $type, $slug );
	if ( is_wp_error( $lock ) ) return $lock;
	try {
		$template = wpagent_site_editor_get_template( $type, $slug );
		if ( is_wp_error( $template ) ) return $template;
		$before = wpagent_site_editor_resource_state( $template );
		if ( ! hash_equals( $before['hash'], $expected ) ) return new WP_Error( 'wpagent_site_editor_conflict', __( 'Die Site-Editor-Ressource wurde seit dem Lesen verändert.', 'wp-agent-companion' ), array( 'status' => 409, 'current_hash' => $before['hash'] ) );
		if ( 'custom' !== $template->source || ! $template->wp_id ) return new WP_Error( 'wpagent_site_editor_source_delete', __( 'Eine unveränderte Theme- oder Plugin-Vorlage kann nicht gelöscht werden.', 'wp-agent-companion' ), array( 'status' => 400 ) );
		$snapshot = wpagent_site_editor_template_snapshot( $template );
		if ( null === $snapshot ) return new WP_Error( 'wpagent_site_editor_snapshot_failed', __( 'Der Template-Zustand konnte nicht für ein sicheres Löschen gelesen werden.', 'wp-agent-companion' ), array( 'status' => 500 ) );
		$references = 'wp_template_part' === $type ? wpagent_site_editor_find_references( 'template_part', $slug ) : array( 'items' => array(), 'truncated' => false );
		if ( is_wp_error( $references ) ) return $references;
		if ( array() !== $references['items'] && empty( $input['confirm_references'] ) ) return new WP_Error( 'wpagent_site_editor_referenced', __( 'Das Template-Teil wird noch verwendet. Zum bewussten Löschen confirm_references=true setzen.', 'wp-agent-companion' ), array( 'status' => 409, 'references' => $references ) );
		$trashed = wp_update_post( array( 'ID' => $template->wp_id, 'post_status' => 'trash' ), true );
		if ( is_wp_error( $trashed ) ) return $trashed;
		$fresh = get_block_template( $template->id, $type );
		if ( $fresh && 'custom' === $fresh->source && $fresh->wp_id ) {
			$rolled_back = wpagent_site_editor_restore_template_snapshot( $type, $slug, $snapshot );
			return new WP_Error( 'wpagent_site_editor_delete_verify', __( 'Die Site-Editor-Ressource blieb nach dem reversiblen Löschschritt aktiv und wurde wiederhergestellt.', 'wp-agent-companion' ), array( 'status' => 500, 'rolled_back' => $rolled_back ) );
		}
		$result = wp_delete_post( $template->wp_id, true );
		if ( ! $result || get_post( $template->wp_id ) ) {
			$rolled_back = wpagent_site_editor_restore_template_snapshot( $type, $slug, $snapshot );
			return new WP_Error( 'wpagent_site_editor_delete_failed', __( 'Die Site-Editor-Ressource konnte nicht endgültig gelöscht werden und wurde wiederhergestellt.', 'wp-agent-companion' ), array( 'status' => 500, 'rolled_back' => $rolled_back ) );
		}
		$fresh = get_block_template( $template->id, $type );
		if ( $fresh && 'custom' === $fresh->source && $fresh->wp_id ) {
			$rolled_back = wpagent_site_editor_restore_template_snapshot( $type, $slug, $snapshot );
			return new WP_Error( 'wpagent_site_editor_delete_verify', __( 'Die endgültig gelöschte Site-Editor-Ressource blieb aktiv und wurde wiederhergestellt.', 'wp-agent-companion' ), array( 'status' => 500, 'rolled_back' => $rolled_back ) );
		}
		$resource = $fresh ? wpagent_site_editor_resource_state( $fresh ) : null;
		return array( 'deleted' => true, 'reverted_to_theme' => $fresh && 'theme' === $fresh->source, 'reverted_to_source' => (bool) $fresh, 'resource' => $resource, 'references' => $references );
	} finally {
		wpagent_site_editor_release_lock( $type, $slug, $lock );
	}
}

/** @return string|WP_Error */
function wpagent_site_editor_validate_area( $value ) {
	$area = is_string( $value ) ? sanitize_key( $value ) : '';
	$allowed = array( WP_TEMPLATE_PART_AREA_UNCATEGORIZED );
	foreach ( get_allowed_block_template_part_areas() as $item ) if ( is_string( $item['area'] ?? null ) ) $allowed[] = $item['area'];
	if ( '' === $area || ! in_array( $area, array_unique( $allowed ), true ) ) return new WP_Error( 'wpagent_site_editor_area', __( 'area ist kein registrierter Template-Teil-Bereich.', 'wp-agent-companion' ), array( 'status' => 400 ) );
	return $area;
}

/** @return string|WP_Error */
function wpagent_site_editor_expected_hash( $value ) {
	$hash = is_string( $value ) ? $value : '';
	return preg_match( '/^[a-f0-9]{64}$/', $hash ) ? $hash : new WP_Error( 'wpagent_site_editor_hash', __( 'expected_hash muss ein SHA-256-Hash sein.', 'wp-agent-companion' ), array( 'status' => 400 ) );
}

function wpagent_site_editor_template_matches( WP_Block_Template $template, string $title, string $description, string $content, ?string $area ): bool {
	$raw_valid = wpagent_site_editor_validate_content(
		wpagent_site_editor_template_raw_content( $template ),
		wpagent_site_editor_validation_root( (string) $template->type, (string) $template->slug )
	);
	$effective_valid = wpagent_site_editor_validate_content(
		(string) $template->content,
		wpagent_site_editor_validation_root( (string) $template->type, (string) $template->slug )
	);
	return 'custom' === $template->source && $title === (string) $template->title && $description === (string) $template->description
		&& $content === wpagent_site_editor_template_raw_content( $template ) && ! is_wp_error( $raw_valid ) && ! is_wp_error( $effective_valid )
		&& ( 'wp_template_part' !== $template->type || $area === (string) $template->area );
}

/** @return array<string,mixed>|null */
function wpagent_site_editor_template_snapshot( WP_Block_Template $template ): ?array {
	if ( ! $template->wp_id ) return null;
	$post = get_post( $template->wp_id, ARRAY_A );
	if ( ! is_array( $post ) ) return null;
	$theme = wp_get_object_terms( $template->wp_id, 'wp_theme', array( 'fields' => 'slugs' ) );
	$area = wp_get_object_terms( $template->wp_id, 'wp_template_part_area', array( 'fields' => 'slugs' ) );
	if ( is_wp_error( $theme ) || is_wp_error( $area ) ) return null;
	return array( 'post' => $post, 'theme' => $theme, 'area' => $area, 'origin' => get_post_meta( $template->wp_id, 'origin', true ) );
}

/** @param array<string,mixed> $post */
function wpagent_site_editor_restore_post_record( array $post ): bool {
	$id = absint( $post['ID'] ?? 0 );
	if ( ! $id ) return false;
	if ( get_post( $id ) ) {
		$result = wp_update_post( wp_slash( $post ), true );
	} else {
		$insert = $post;
		unset( $insert['ID'] );
		$insert['import_id'] = $id;
		$result = wp_insert_post( wp_slash( $insert ), true );
	}
	if ( is_wp_error( $result ) || $id !== (int) $result ) return false;
	global $wpdb;
	$restored_dates = $wpdb->update(
		$wpdb->posts,
		array( 'post_modified' => $post['post_modified'], 'post_modified_gmt' => $post['post_modified_gmt'] ),
		array( 'ID' => $id ),
		array( '%s', '%s' ),
		array( '%d' )
	);
	if ( false === $restored_dates ) return false;
	clean_post_cache( $id );
	$restored = get_post( $id, ARRAY_A );
	foreach ( array( 'post_type', 'post_status', 'post_name', 'post_title', 'post_excerpt', 'post_content', 'post_author', 'post_parent', 'menu_order', 'post_modified', 'post_modified_gmt' ) as $field ) {
		if ( (string) ( $post[ $field ] ?? '' ) !== (string) ( $restored[ $field ] ?? '' ) ) return false;
	}
	return true;
}

function wpagent_site_editor_restore_template_snapshot( string $type, string $slug, ?array $snapshot ): bool {
	$fresh = get_block_template( wpagent_site_editor_template_id( $slug ), $type );
	if ( null === $snapshot ) {
		if ( $fresh && $fresh->wp_id ) wp_delete_post( $fresh->wp_id, true );
		$remaining = get_block_template( wpagent_site_editor_template_id( $slug ), $type );
		return ! $remaining || ! $remaining->wp_id || 'custom' !== $remaining->source;
	}
	$post = $snapshot['post'];
	$post['ID'] = (int) $post['ID'];
	if ( ! wpagent_site_editor_restore_post_record( $post ) ) return false;
	$theme_terms = wp_set_object_terms( $post['ID'], $snapshot['theme'], 'wp_theme', false );
	if ( is_wp_error( $theme_terms ) ) return false;
	if ( 'wp_template_part' === $type ) {
		$area_terms = wp_set_object_terms( $post['ID'], $snapshot['area'], 'wp_template_part_area', false );
		if ( is_wp_error( $area_terms ) ) return false;
	}
	if ( '' === $snapshot['origin'] ) delete_post_meta( $post['ID'], 'origin' ); else update_post_meta( $post['ID'], 'origin', $snapshot['origin'] );
	$restored = wpagent_site_editor_get_template( $type, $slug );
	return ! is_wp_error( $restored )
		&& (string) $post['post_title'] === (string) $restored->title
		&& (string) $post['post_excerpt'] === (string) $restored->description
		&& (string) $post['post_content'] === wpagent_site_editor_template_raw_content( $restored )
		&& ( 'wp_template_part' !== $type || in_array( (string) $restored->area, $snapshot['area'], true ) );
}

/** @return array<string,mixed>|WP_Error */
function wpagent_exec_create_block_navigation( $input ) {
	$input = is_array( $input ) ? $input : array();
	$title = wpagent_site_editor_plain_text( $input['title'] ?? '', 'title', 200 );
	if ( is_wp_error( $title ) ) return $title;
	$content = wpagent_site_editor_build_navigation_content( $input['items'] ?? null );
	if ( is_wp_error( $content ) ) return $content;
	$identity = 'create:' . hash( 'sha256', strtolower( $title ) );
	$lock = wpagent_site_editor_acquire_lock( 'wp_navigation', $identity );
	if ( is_wp_error( $lock ) ) return $lock;
	try {
		$id = wp_insert_post( array( 'post_type' => 'wp_navigation', 'post_status' => 'publish', 'post_title' => $title, 'post_content' => $content ), true );
		if ( is_wp_error( $id ) ) return $id;
		$fresh = wpagent_site_editor_navigation_state( (int) $id );
		$post = get_post( (int) $id );
		$effective_valid = $post instanceof WP_Post ? wpagent_site_editor_validate_content( wpagent_site_editor_effective_post_content( $post ) ) : new WP_Error( 'wpagent_site_editor_navigation_missing' );
		if ( is_wp_error( $fresh ) || $title !== $fresh['title'] || $content !== $fresh['content'] || $fresh['has_disallowed_blocks'] || is_wp_error( $effective_valid ) ) {
			wp_delete_post( (int) $id, true );
			return new WP_Error( 'wpagent_site_editor_navigation_create_verify', __( 'Die Blocknavigation wich beim Read-Back ab und wurde zurückgerollt.', 'wp-agent-companion' ), array( 'status' => 500 ) );
		}
		return array( 'navigation' => $fresh, 'verified' => true );
	} finally {
		wpagent_site_editor_release_lock( 'wp_navigation', $identity, $lock );
	}
}

/** @return array<string,mixed>|WP_Error */
function wpagent_exec_update_block_navigation( $input ) {
	$input = is_array( $input ) ? $input : array();
	$id = absint( $input['id'] ?? 0 );
	$expected = wpagent_site_editor_expected_hash( $input['expected_hash'] ?? '' );
	if ( is_wp_error( $expected ) ) return $expected;
	if ( ! isset( $input['title'] ) && ! isset( $input['items'] ) ) return new WP_Error( 'wpagent_site_editor_no_changes', __( 'Es wurde keine Änderung angegeben.', 'wp-agent-companion' ), array( 'status' => 400 ) );
	$lock = wpagent_site_editor_acquire_lock( 'wp_navigation', (string) $id );
	if ( is_wp_error( $lock ) ) return $lock;
	try {
		$before = wpagent_site_editor_navigation_state( $id );
		if ( is_wp_error( $before ) ) return $before;
		$snapshot = get_post( $id, ARRAY_A );
		if ( ! is_array( $snapshot ) ) return new WP_Error( 'wpagent_site_editor_snapshot_failed', __( 'Der vorherige Navigationszustand konnte nicht für einen sicheren Rollback gelesen werden.', 'wp-agent-companion' ), array( 'status' => 500 ) );
		if ( ! hash_equals( $before['hash'], $expected ) ) return new WP_Error( 'wpagent_site_editor_conflict', __( 'Die Blocknavigation wurde seit dem Lesen verändert.', 'wp-agent-companion' ), array( 'status' => 409, 'current_hash' => $before['hash'] ) );
		$title = isset( $input['title'] ) ? wpagent_site_editor_plain_text( $input['title'], 'title', 200 ) : $before['title'];
		if ( is_wp_error( $title ) ) return $title;
		$content = isset( $input['items'] ) ? wpagent_site_editor_build_navigation_content( $input['items'] ) : $before['content'];
		if ( is_wp_error( $content ) ) return $content;
		$result = wp_update_post( array( 'ID' => $id, 'post_title' => $title, 'post_content' => $content, 'post_status' => 'publish' ), true );
		if ( is_wp_error( $result ) ) return $result;
		$fresh = wpagent_site_editor_navigation_state( $id );
		$post = get_post( $id );
		$effective_valid = $post instanceof WP_Post ? wpagent_site_editor_validate_content( wpagent_site_editor_effective_post_content( $post ) ) : new WP_Error( 'wpagent_site_editor_navigation_missing' );
		if ( is_wp_error( $fresh ) || $title !== $fresh['title'] || $content !== $fresh['content'] || $fresh['has_disallowed_blocks'] || is_wp_error( $effective_valid ) ) {
			$rolled_back = wpagent_site_editor_restore_post_record( $snapshot );
			return new WP_Error( 'wpagent_site_editor_navigation_update_verify', __( 'Die Blocknavigation wich beim Read-Back ab und wurde zurückgerollt.', 'wp-agent-companion' ), array( 'status' => 500, 'rolled_back' => $rolled_back ) );
		}
		return array( 'navigation' => $fresh, 'verified' => true );
	} finally {
		wpagent_site_editor_release_lock( 'wp_navigation', (string) $id, $lock );
	}
}

/** @return array<string,mixed>|WP_Error */
function wpagent_exec_delete_block_navigation( $input ) {
	$input = is_array( $input ) ? $input : array();
	$id = absint( $input['id'] ?? 0 );
	$expected = wpagent_site_editor_expected_hash( $input['expected_hash'] ?? '' );
	if ( is_wp_error( $expected ) ) return $expected;
	if ( true !== ( $input['confirm'] ?? false ) ) return new WP_Error( 'wpagent_site_editor_delete_confirmation', __( 'Zum Löschen ist confirm=true erforderlich.', 'wp-agent-companion' ), array( 'status' => 400 ) );
	$lock = wpagent_site_editor_acquire_lock( 'wp_navigation', (string) $id );
	if ( is_wp_error( $lock ) ) return $lock;
	try {
		$before = wpagent_site_editor_navigation_state( $id );
		if ( is_wp_error( $before ) ) return $before;
		$snapshot = get_post( $id, ARRAY_A );
		if ( ! is_array( $snapshot ) ) return new WP_Error( 'wpagent_site_editor_snapshot_failed', __( 'Der Navigationszustand konnte nicht für ein sicheres Löschen gelesen werden.', 'wp-agent-companion' ), array( 'status' => 500 ) );
		if ( ! hash_equals( $before['hash'], $expected ) ) return new WP_Error( 'wpagent_site_editor_conflict', __( 'Die Blocknavigation wurde seit dem Lesen verändert.', 'wp-agent-companion' ), array( 'status' => 409, 'current_hash' => $before['hash'] ) );
		$references = wpagent_site_editor_find_references( 'navigation', (string) $id );
		if ( is_wp_error( $references ) ) return $references;
		if ( array() !== $references['items'] && empty( $input['confirm_references'] ) ) return new WP_Error( 'wpagent_site_editor_referenced', __( 'Die Blocknavigation wird noch verwendet. Zum bewussten Löschen confirm_references=true setzen.', 'wp-agent-companion' ), array( 'status' => 409, 'references' => $references ) );
		$trashed = wp_update_post( array( 'ID' => $id, 'post_status' => 'trash' ), true );
		if ( is_wp_error( $trashed ) || ! is_wp_error( wpagent_site_editor_navigation_state( $id ) ) ) {
			$rolled_back = wpagent_site_editor_restore_post_record( $snapshot );
			return new WP_Error( 'wpagent_site_editor_navigation_delete_verify', __( 'Die Blocknavigation blieb nach dem reversiblen Löschschritt aktiv und wurde wiederhergestellt.', 'wp-agent-companion' ), array( 'status' => 500, 'rolled_back' => $rolled_back ) );
		}
		if ( ! wp_delete_post( $id, true ) || get_post( $id ) ) {
			$rolled_back = wpagent_site_editor_restore_post_record( $snapshot );
			return new WP_Error( 'wpagent_site_editor_navigation_delete_failed', __( 'Die Blocknavigation konnte nicht endgültig gelöscht werden und wurde wiederhergestellt.', 'wp-agent-companion' ), array( 'status' => 500, 'rolled_back' => $rolled_back ) );
		}
		return array( 'deleted' => true, 'references' => $references );
	} finally {
		wpagent_site_editor_release_lock( 'wp_navigation', (string) $id, $lock );
	}
}
