<?php
/** Conflict-safe writes for persistent Custom Post Type UI definitions. */

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

/** @return array<string,mixed> */
function wpagent_cptui_write_properties( string $kind, bool $create ): array {
	$properties = array(
		'slug' => array( 'type' => 'string', 'pattern' => '^[a-z0-9_-]+$', 'maxLength' => 'post_type' === $kind ? 20 : 32 ),
		'singular_label' => array( 'type' => 'string', 'minLength' => 1, 'maxLength' => 100 ),
		'plural_label' => array( 'type' => 'string', 'minLength' => 1, 'maxLength' => 100 ),
		'description' => array( 'type' => 'string', 'maxLength' => 1000 ),
		'public' => array( 'type' => 'boolean' ),
		'hierarchical' => array( 'type' => 'boolean' ),
		'show_ui' => array( 'type' => 'boolean' ),
		'show_in_rest' => array( 'type' => 'boolean' ),
		'rewrite_slug' => array( 'type' => 'string', 'maxLength' => 200 ),
	);
	if ( 'post_type' === $kind ) {
		$properties['supports'] = array( 'type' => 'array', 'maxItems' => 11, 'uniqueItems' => true, 'items' => array( 'type' => 'string', 'enum' => array( 'title', 'editor', 'author', 'thumbnail', 'excerpt', 'comments', 'trackbacks', 'revisions', 'page-attributes', 'custom-fields', 'post-formats' ) ) );
		$properties['taxonomies'] = array( 'type' => 'array', 'maxItems' => 20, 'uniqueItems' => true, 'items' => array( 'type' => 'string' ) );
		$properties['has_archive'] = array( 'type' => 'boolean' );
	} else {
		$properties['object_types'] = array( 'type' => 'array', 'minItems' => 1, 'maxItems' => 20, 'uniqueItems' => true, 'items' => array( 'type' => 'string' ) );
		$properties['show_admin_column'] = array( 'type' => 'boolean' );
	}
	if ( ! $create ) {
		$properties['expected_hash'] = array( 'type' => 'string', 'pattern' => '^[a-f0-9]{64}$' );
	}
	return $properties;
}

/** @return array<string,mixed> */
function wpagent_cptui_mutation_output_schema( string $kind ): array {
	return array(
		'type' => 'object',
		'properties' => array(
			'model' => wpagent_cptui_output_schema( $kind ),
			'verified_persistence' => array( 'type' => 'boolean' ),
			'reload_required' => array( 'type' => 'boolean' ),
		),
		'required' => array( 'model', 'verified_persistence', 'reload_required' ),
		'additionalProperties' => false,
	);
}

/** @return array<string,mixed> */
function wpagent_cptui_create_ability( string $kind ): array {
	$is_post_type = 'post_type' === $kind;
	$required = array( 'slug', 'singular_label', 'plural_label', $is_post_type ? 'supports' : 'object_types' );
	return array(
		'label' => $is_post_type ? __( 'CPT-UI-Inhaltstyp erstellen', 'wp-agent-companion' ) : __( 'CPT-UI-Taxonomie erstellen', 'wp-agent-companion' ),
		'description' => $is_post_type
			? __( 'Erstellt eine persistente, begrenzte CPT-UI-Inhaltstypdefinition. Die Laufzeitregistrierung erfolgt beim nächsten WordPress-Request.', 'wp-agent-companion' )
			: __( 'Erstellt eine persistente, begrenzte CPT-UI-Taxonomiedefinition. Die Laufzeitregistrierung erfolgt beim nächsten WordPress-Request.', 'wp-agent-companion' ),
		'category' => 'wp-agent',
		'input_schema' => array( 'type' => 'object', 'properties' => wpagent_cptui_write_properties( $kind, true ), 'required' => $required, 'additionalProperties' => false ),
		'output_schema' => wpagent_cptui_mutation_output_schema( $kind ),
		'execute_callback' => $is_post_type ? 'wpagent_exec_create_cptui_post_type' : 'wpagent_exec_create_cptui_taxonomy',
		'permission_callback' => 'wpagent_perm_manage_options',
		'meta' => array( 'show_in_rest' => true, 'annotations' => array( 'readonly' => false, 'destructive' => false, 'idempotent' => false ) ),
	);
}

/** @return array<string,mixed> */
function wpagent_cptui_update_ability( string $kind ): array {
	$is_post_type = 'post_type' === $kind;
	return array(
		'label' => $is_post_type ? __( 'CPT-UI-Inhaltstyp aktualisieren', 'wp-agent-companion' ) : __( 'CPT-UI-Taxonomie aktualisieren', 'wp-agent-companion' ),
		'description' => $is_post_type
			? __( 'Aktualisiert freigegebene Felder einer persistenten CPT-UI-Inhaltstypdefinition und bewahrt alle unbekannten Providerfelder.', 'wp-agent-companion' )
			: __( 'Aktualisiert freigegebene Felder einer persistenten CPT-UI-Taxonomiedefinition und bewahrt alle unbekannten Providerfelder.', 'wp-agent-companion' ),
		'category' => 'wp-agent',
		'input_schema' => array( 'type' => 'object', 'properties' => wpagent_cptui_write_properties( $kind, false ), 'required' => array( 'slug', 'expected_hash' ), 'minProperties' => 3, 'additionalProperties' => false ),
		'output_schema' => wpagent_cptui_mutation_output_schema( $kind ),
		'execute_callback' => $is_post_type ? 'wpagent_exec_update_cptui_post_type' : 'wpagent_exec_update_cptui_taxonomy',
		'permission_callback' => 'wpagent_perm_manage_options',
		'meta' => array( 'show_in_rest' => true, 'annotations' => array( 'readonly' => false, 'destructive' => false, 'idempotent' => false ) ),
	);
}

/** @return array<string,mixed> */
function wpagent_cptui_delete_ability( string $kind ): array {
	$is_post_type = 'post_type' === $kind;
	return array(
		'label' => $is_post_type ? __( 'CPT-UI-Inhaltstypdefinition löschen', 'wp-agent-companion' ) : __( 'CPT-UI-Taxonomiedefinition löschen', 'wp-agent-companion' ),
		'description' => $is_post_type
			? __( 'Prüft den aktuellen Konflikt-Hash einer persistenten CPT-UI-Inhaltstypdefinition. Die endgültige Remote-Löschung ist deaktiviert, weil CPT UI keine atomare Compare-and-Delete-Prüfung bietet. Lösche die Definition manuell in der WordPress-Verwaltung.', 'wp-agent-companion' )
			: __( 'Prüft den aktuellen Konflikt-Hash einer persistenten CPT-UI-Taxonomiedefinition. Die endgültige Remote-Löschung ist deaktiviert, weil CPT UI keine atomare Compare-and-Delete-Prüfung bietet. Lösche die Definition manuell in der WordPress-Verwaltung.', 'wp-agent-companion' ),
		'category' => 'wp-agent',
		'input_schema' => array(
			'type' => 'object',
			'properties' => array(
				'slug' => array( 'type' => 'string', 'pattern' => '^[a-z0-9_-]+$', 'maxLength' => $is_post_type ? 20 : 32 ),
				'expected_hash' => array( 'type' => 'string', 'pattern' => '^[a-f0-9]{64}$' ),
				'confirm' => array( 'type' => 'boolean' ),
				'confirm_content' => array( 'type' => 'boolean', 'default' => false ),
			),
			'required' => array( 'slug', 'expected_hash', 'confirm' ),
			'additionalProperties' => false,
		),
		'output_schema' => array(
			'type' => 'object',
			'properties' => array(
				'deleted' => array( 'type' => 'boolean' ),
				'slug' => array( 'type' => 'string' ),
				'retained_content' => array( 'type' => 'integer' ),
				'verified_persistence' => array( 'type' => 'boolean' ),
				'reload_required' => array( 'type' => 'boolean' ),
			),
			'required' => array( 'deleted', 'slug', 'retained_content', 'verified_persistence', 'reload_required' ),
			'additionalProperties' => false,
		),
		'execute_callback' => $is_post_type ? 'wpagent_exec_delete_cptui_post_type' : 'wpagent_exec_delete_cptui_taxonomy',
		'permission_callback' => 'wpagent_perm_manage_options',
		'meta' => array( 'show_in_rest' => true, 'annotations' => array( 'readonly' => false, 'destructive' => true, 'idempotent' => false, 'manual_only' => true ) ),
	);
}

function wpagent_ability_create_cptui_post_type(): array {
	return wpagent_cptui_create_ability( 'post_type' );
}

function wpagent_ability_update_cptui_post_type(): array {
	return wpagent_cptui_update_ability( 'post_type' );
}

function wpagent_ability_delete_cptui_post_type(): array {
	return wpagent_cptui_delete_ability( 'post_type' );
}

function wpagent_ability_create_cptui_taxonomy(): array {
	return wpagent_cptui_create_ability( 'taxonomy' );
}

function wpagent_ability_update_cptui_taxonomy(): array {
	return wpagent_cptui_update_ability( 'taxonomy' );
}

function wpagent_ability_delete_cptui_taxonomy(): array {
	return wpagent_cptui_delete_ability( 'taxonomy' );
}

/** @return array<string,mixed>|WP_Error */
function wpagent_cptui_validate_changes( string $kind, array $input, bool $create ) {
	$changes = array();
	if ( $create ) {
		$slug = wpagent_cptui_slug( $input['slug'] ?? '', $kind );
		if ( is_wp_error( $slug ) ) {
			return $slug;
		}
		$changes['slug'] = $slug;
	}
	foreach ( array( 'singular_label' => 100, 'plural_label' => 100 ) as $field => $max ) {
		if ( $create || array_key_exists( $field, $input ) ) {
			$value = wpagent_cptui_text( $input[ $field ] ?? '', $field, $max );
			if ( is_wp_error( $value ) ) {
				return $value;
			}
			$changes[ $field ] = $value;
		}
	}
	if ( array_key_exists( 'description', $input ) ) {
		$value = wpagent_cptui_text( $input['description'], 'description', 1000, true );
		if ( is_wp_error( $value ) ) {
			return $value;
		}
		$changes['description'] = $value;
	}
	foreach ( array( 'public', 'hierarchical', 'show_ui', 'show_in_rest' ) as $field ) {
		if ( array_key_exists( $field, $input ) ) {
			if ( ! is_bool( $input[ $field ] ) ) {
				return new WP_Error( 'wpagent_cptui_boolean', __( 'Boolesche CPT-UI-Felder akzeptieren nur true oder false.', 'wp-agent-companion' ), array( 'status' => 400 ) );
			}
			$changes[ $field ] = $input[ $field ];
		}
	}
	if ( array_key_exists( 'rewrite_slug', $input ) ) {
		$value = wpagent_cptui_rewrite_slug( $input['rewrite_slug'] );
		if ( is_wp_error( $value ) ) {
			return $value;
		}
		$changes['rewrite_slug'] = $value;
	}
	if ( 'post_type' === $kind ) {
		if ( $create || array_key_exists( 'supports', $input ) ) {
			$value = wpagent_cptui_supports( $input['supports'] ?? null );
			if ( is_wp_error( $value ) ) {
				return $value;
			}
			$changes['supports'] = $value;
		}
		if ( array_key_exists( 'taxonomies', $input ) ) {
			$value = wpagent_cptui_object_names( $input['taxonomies'], 'post_type', true );
			if ( is_wp_error( $value ) ) {
				return $value;
			}
			$changes['taxonomies'] = $value;
		}
		if ( array_key_exists( 'has_archive', $input ) ) {
			if ( ! is_bool( $input['has_archive'] ) ) {
				return new WP_Error( 'wpagent_cptui_boolean', __( 'has_archive akzeptiert nur true oder false.', 'wp-agent-companion' ), array( 'status' => 400 ) );
			}
			$changes['has_archive'] = $input['has_archive'];
		}
	} else {
		if ( $create || array_key_exists( 'object_types', $input ) ) {
			$value = wpagent_cptui_object_names( $input['object_types'] ?? null, 'taxonomy' );
			if ( is_wp_error( $value ) ) {
				return $value;
			}
			$changes['object_types'] = $value;
		}
		if ( array_key_exists( 'show_admin_column', $input ) ) {
			if ( ! is_bool( $input['show_admin_column'] ) ) {
				return new WP_Error( 'wpagent_cptui_boolean', __( 'show_admin_column akzeptiert nur true oder false.', 'wp-agent-companion' ), array( 'status' => 400 ) );
			}
			$changes['show_admin_column'] = $input['show_admin_column'];
		}
	}
	if ( ! $create && array() === $changes ) {
		return new WP_Error( 'wpagent_cptui_no_changes', __( 'Die Aktualisierung enthält keine freigegebene Änderung.', 'wp-agent-companion' ), array( 'status' => 400 ) );
	}
	return $changes;
}

/** @return array<string,mixed> */
function wpagent_cptui_default_definition( string $kind, string $slug ): array {
	if ( 'post_type' === $kind ) {
		return array(
			'name' => $slug, 'label' => '', 'singular_label' => '', 'description' => '',
			'public' => 'true', 'publicly_queryable' => 'true', 'show_ui' => 'true', 'show_in_nav_menus' => 'true',
			'delete_with_user' => 'false', 'show_in_rest' => 'true', 'rest_base' => '', 'rest_controller_class' => '', 'rest_namespace' => '',
			'has_archive' => 'false', 'has_archive_string' => '', 'exclude_from_search' => 'false', 'capability_type' => 'post',
			'hierarchical' => 'false', 'can_export' => 'true', 'rewrite' => 'true', 'rewrite_slug' => '', 'rewrite_withfront' => 'true',
			'query_var' => 'true', 'query_var_slug' => '', 'menu_position' => '', 'show_in_menu' => 'true', 'show_in_menu_string' => '',
			'menu_icon' => null, 'register_meta_box_cb' => null, 'supports' => array(), 'taxonomies' => array(), 'labels' => array(),
			'custom_supports' => '', 'enter_title_here' => '',
		);
	}
	return array(
		'name' => $slug, 'label' => '', 'singular_label' => '', 'description' => '',
		'public' => 'true', 'publicly_queryable' => 'true', 'hierarchical' => 'false', 'show_ui' => 'true', 'show_in_menu' => 'true',
		'show_in_nav_menus' => 'true', 'query_var' => 'true', 'query_var_slug' => '', 'rewrite' => 'true', 'rewrite_slug' => '',
		'rewrite_withfront' => 'true', 'rewrite_hierarchical' => 'false', 'show_admin_column' => 'false', 'show_in_rest' => 'true',
		'show_tagcloud' => 'true', 'sort' => 'false', 'show_in_quick_edit' => 'true', 'rest_base' => '',
		'rest_controller_class' => '', 'rest_namespace' => '', 'labels' => array(), 'meta_box_cb' => '', 'default_term' => '', 'object_types' => array(),
	);
}

/** @return array<string,mixed> */
function wpagent_cptui_apply_changes( string $kind, array $definition, array $changes ): array {
	foreach ( $changes as $field => $value ) {
		switch ( $field ) {
			case 'slug':
				$definition['name'] = $value;
				break;
			case 'plural_label':
				$definition['label'] = $value;
				break;
			case 'singular_label':
				$definition['singular_label'] = $value;
				break;
			case 'description':
				$definition['description'] = $value;
				break;
			case 'rewrite_slug':
				$definition['rewrite'] = 'true';
				$definition['rewrite_slug'] = $value;
				break;
			case 'supports':
				$definition['supports'] = $value;
				break;
			case 'taxonomies':
				$definition['taxonomies'] = $value;
				break;
			case 'object_types':
				$definition['object_types'] = $value;
				break;
			case 'has_archive':
				$definition['has_archive'] = $value ? 'true' : 'false';
				$definition['has_archive_string'] = '';
				break;
			case 'show_admin_column':
				$definition['show_admin_column'] = $value ? 'true' : 'false';
				break;
			case 'public':
				$boolean = $value ? 'true' : 'false';
				$definition['public'] = $boolean;
				$definition['publicly_queryable'] = $boolean;
				$definition['show_in_nav_menus'] = $boolean;
				if ( 'post_type' === $kind ) {
					$definition['exclude_from_search'] = $value ? 'false' : 'true';
				}
				break;
			case 'show_ui':
				$boolean = $value ? 'true' : 'false';
				$definition['show_ui'] = $boolean;
				$definition['show_in_menu'] = $boolean;
				if ( 'taxonomy' === $kind ) {
					$definition['show_tagcloud'] = $boolean;
					$definition['show_in_quick_edit'] = $boolean;
				}
				break;
			case 'hierarchical':
			case 'show_in_rest':
				$definition[ $field ] = $value ? 'true' : 'false';
				break;
		}
	}
	return $definition;
}

/** @return array<string,mixed>|WP_Error */
function wpagent_cptui_create_model( string $kind, $input ) {
	$provider = wpagent_cptui_require_provider();
	if ( is_wp_error( $provider ) ) {
		return $provider;
	}
	$input = is_array( $input ) ? $input : array();
	$changes = wpagent_cptui_validate_changes( $kind, $input, true );
	if ( is_wp_error( $changes ) ) {
		return $changes;
	}
	$slug = $changes['slug'];
	$lock = wpagent_cptui_acquire_lock( $kind );
	if ( is_wp_error( $lock ) ) {
		return $lock;
	}
	try {
		$definitions = wpagent_cptui_option_data( $kind );
		if ( is_wp_error( $definitions ) ) {
			return $definitions;
		}
		if ( isset( $definitions[ $slug ] ) ) {
			return new WP_Error( 'wpagent_cptui_exists', __( 'Diese CPT-UI-Definition existiert bereits.', 'wp-agent-companion' ), array( 'status' => 409 ) );
		}
		$slug_filter = 'post_type' === $kind ? 'cptui_post_type_slug_exists' : 'cptui_taxonomy_slug_exists';
		if ( true === apply_filters( $slug_filter, false, $slug, $definitions ) ) {
			return new WP_Error( 'wpagent_cptui_provider_slug', __( 'CPT UI oder eine seiner Erweiterungen hat diesen Slug als belegt markiert.', 'wp-agent-companion' ), array( 'status' => 409 ) );
		}
		if ( 'post_type' === $kind ? post_type_exists( $slug ) : taxonomy_exists( $slug ) ) {
			return new WP_Error( 'wpagent_cptui_runtime_exists', __( 'Der Slug ist bereits durch WordPress oder einen anderen Provider registriert.', 'wp-agent-companion' ), array( 'status' => 409 ) );
		}
		if ( 'post_type' === $kind && true === cptui_check_page_slugs( $slug ) ) {
			return new WP_Error( 'wpagent_cptui_page_slug', __( 'Der Slug wird bereits von einer WordPress-Seite verwendet und würde einen Permalink-Konflikt verursachen.', 'wp-agent-companion' ), array( 'status' => 409 ) );
		}
		$config = wpagent_cptui_kinds()[ $kind ];
		$snapshot = wpagent_cptui_option_snapshot( $config['option'] );
		$definition = wpagent_cptui_apply_changes( $kind, wpagent_cptui_default_definition( $kind, $slug ), $changes );
		$definitions[ $slug ] = $definition;
		$persisted = wpagent_cptui_persist( $kind, $definitions, $snapshot );
		if ( is_wp_error( $persisted ) ) {
			$error_data = $persisted->get_error_data();
			if ( ! is_array( $error_data ) || empty( $error_data['write_performed'] ) ) {
				return $persisted;
			}
			$rolled_back = wpagent_cptui_restore_option( $config['option'], $snapshot );
			return new WP_Error( 'wpagent_cptui_create_failed', $persisted->get_error_message(), array( 'status' => 500, 'rollback_verified' => $rolled_back ) );
		}
		$model = wpagent_cptui_state( $kind, $definition, $definitions, 0 );
		if ( is_wp_error( $model ) ) {
			return $model;
		}
		$model['registration_conflict'] = false;
		return array( 'model' => $model, 'verified_persistence' => true, 'reload_required' => true );
	} finally {
		wpagent_cptui_release_lock( $kind, $lock );
	}
}

/** @return array<string,mixed>|WP_Error */
function wpagent_cptui_update_model( string $kind, $input ) {
	$provider = wpagent_cptui_require_provider();
	if ( is_wp_error( $provider ) ) {
		return $provider;
	}
	$input = is_array( $input ) ? $input : array();
	$slug = wpagent_cptui_slug( $input['slug'] ?? '', $kind, true );
	if ( is_wp_error( $slug ) ) {
		return $slug;
	}
	$expected_hash = is_string( $input['expected_hash'] ?? null ) ? $input['expected_hash'] : '';
	if ( ! preg_match( '/^[a-f0-9]{64}$/', $expected_hash ) ) {
		return new WP_Error( 'wpagent_cptui_hash', __( 'expected_hash ist ungültig.', 'wp-agent-companion' ), array( 'status' => 400 ) );
	}
	$changes = wpagent_cptui_validate_changes( $kind, $input, false );
	if ( is_wp_error( $changes ) ) {
		return $changes;
	}
	$lock = wpagent_cptui_acquire_lock( $kind );
	if ( is_wp_error( $lock ) ) {
		return $lock;
	}
	try {
		$definitions = wpagent_cptui_option_data( $kind );
		if ( is_wp_error( $definitions ) ) {
			return $definitions;
		}
		if ( ! isset( $definitions[ $slug ] ) || (string) ( $definitions[ $slug ]['name'] ?? '' ) !== $slug ) {
			return new WP_Error( 'wpagent_cptui_not_found', __( 'Persistente CPT-UI-Definition nicht gefunden.', 'wp-agent-companion' ), array( 'status' => 404 ) );
		}
		if ( ! hash_equals( wpagent_cptui_option_hash( $definitions ), $expected_hash ) ) {
			return new WP_Error( 'wpagent_cptui_conflict', __( 'Die CPT-UI-Definitionen wurden seit dem Lesen geändert. Lade den aktuellen Zustand neu.', 'wp-agent-companion' ), array( 'status' => 409 ) );
		}
		$current_state = wpagent_cptui_state( $kind, $definitions[ $slug ], $definitions );
		if ( is_wp_error( $current_state ) ) {
			return $current_state;
		}
		if ( $current_state['registration_conflict'] ) {
			return new WP_Error( 'wpagent_cptui_registration_conflict', __( 'Die Laufzeitregistrierung gehört nicht eindeutig zu dieser CPT-UI-Definition.', 'wp-agent-companion' ), array( 'status' => 409 ) );
		}
		$config = wpagent_cptui_kinds()[ $kind ];
		$snapshot = wpagent_cptui_option_snapshot( $config['option'] );
		$definition = wpagent_cptui_apply_changes( $kind, $definitions[ $slug ], $changes );
		$definitions[ $slug ] = $definition;
		$persisted = wpagent_cptui_persist( $kind, $definitions, $snapshot );
		if ( is_wp_error( $persisted ) ) {
			$error_data = $persisted->get_error_data();
			if ( ! is_array( $error_data ) || empty( $error_data['write_performed'] ) ) {
				return $persisted;
			}
			$rolled_back = wpagent_cptui_restore_option( $config['option'], $snapshot );
			return new WP_Error( 'wpagent_cptui_update_failed', $persisted->get_error_message(), array( 'status' => 500, 'rollback_verified' => $rolled_back ) );
		}
		$model = wpagent_cptui_state( $kind, $definition, $definitions, $current_state['content_count'] );
		if ( is_wp_error( $model ) ) {
			return $model;
		}
		$model['registration_conflict'] = false;
		return array( 'model' => $model, 'verified_persistence' => true, 'reload_required' => true );
	} finally {
		wpagent_cptui_release_lock( $kind, $lock );
	}
}

/** @return array<string,mixed>|WP_Error */
function wpagent_cptui_delete_model( string $kind, $input ) {
	$provider = wpagent_cptui_require_provider();
	if ( is_wp_error( $provider ) ) {
		return $provider;
	}
	$input = is_array( $input ) ? $input : array();
	$slug = wpagent_cptui_slug( $input['slug'] ?? '', $kind, true );
	if ( is_wp_error( $slug ) ) {
		return $slug;
	}
	$expected_hash = is_string( $input['expected_hash'] ?? null ) ? $input['expected_hash'] : '';
	if ( ! preg_match( '/^[a-f0-9]{64}$/', $expected_hash ) ) {
		return new WP_Error( 'wpagent_cptui_hash', __( 'expected_hash ist ungültig.', 'wp-agent-companion' ), array( 'status' => 400 ) );
	}
	if ( true !== ( $input['confirm'] ?? false ) ) {
		return new WP_Error( 'wpagent_cptui_confirm', __( 'Zum Löschen muss confirm ausdrücklich true sein.', 'wp-agent-companion' ), array( 'status' => 400 ) );
	}
	$definitions = wpagent_cptui_option_data( $kind );
	if ( is_wp_error( $definitions ) ) {
		return $definitions;
	}
	if ( ! isset( $definitions[ $slug ] ) || (string) ( $definitions[ $slug ]['name'] ?? '' ) !== $slug ) {
		return new WP_Error( 'wpagent_cptui_not_found', __( 'Persistente CPT-UI-Definition nicht gefunden.', 'wp-agent-companion' ), array( 'status' => 404 ) );
	}
	if ( ! hash_equals( wpagent_cptui_option_hash( $definitions ), $expected_hash ) ) {
		return new WP_Error( 'wpagent_cptui_conflict', __( 'Die CPT-UI-Definitionen wurden seit dem Lesen geändert. Lade den aktuellen Zustand neu.', 'wp-agent-companion' ), array( 'status' => 409 ) );
	}
	$current_state = wpagent_cptui_state( $kind, $definitions[ $slug ], $definitions );
	if ( is_wp_error( $current_state ) ) {
		return $current_state;
	}
	return new WP_Error(
		'wpagent_cptui_delete_manual_only',
		__( 'CPT-UI-Inhaltstyp- und Taxonomiedefinitionen werden nicht remote endgültig gelöscht, weil CPT UI keine atomare Compare-and-Delete-Prüfung gegen parallele Optionsänderungen anbietet. Lösche die Definition manuell in der WordPress-Verwaltung.', 'wp-agent-companion' ),
		array( 'status' => 409, 'slug' => $slug, 'current_hash' => wpagent_cptui_option_hash( $definitions ), 'retained_content' => $current_state['content_count'] )
	);
}

function wpagent_exec_create_cptui_post_type( $input ) {
	return wpagent_cptui_create_model( 'post_type', $input );
}

function wpagent_exec_update_cptui_post_type( $input ) {
	return wpagent_cptui_update_model( 'post_type', $input );
}

function wpagent_exec_delete_cptui_post_type( $input ) {
	return wpagent_cptui_delete_model( 'post_type', $input );
}

function wpagent_exec_create_cptui_taxonomy( $input ) {
	return wpagent_cptui_create_model( 'taxonomy', $input );
}

function wpagent_exec_update_cptui_taxonomy( $input ) {
	return wpagent_cptui_update_model( 'taxonomy', $input );
}

function wpagent_exec_delete_cptui_taxonomy( $input ) {
	return wpagent_cptui_delete_model( 'taxonomy', $input );
}
