<?php
/** Conflict-safe native write abilities for bounded Pods Advanced Content Types. */

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

/** @return array<string,mixed> */
function wpagent_pods_act_values_input_schema(): array {
	return array( 'type' => 'object', 'minProperties' => 1, 'maxProperties' => WPAGENT_PODS_ACT_MAX_FIELDS, 'additionalProperties' => array( 'type' => 'string', 'maxLength' => WPAGENT_PODS_ACT_MAX_TEXT ) );
}

/** @return array<string,mixed> */
function wpagent_pods_act_write_result_schema( bool $created = false ): array {
	$properties = array(
		'record' => wpagent_pods_act_record_output_schema(), 'schema_hash' => array( 'type' => 'string', 'pattern' => '^[a-f0-9]{64}$' ),
		'verified_persistence' => array( 'type' => 'boolean' ),
	);
	if ( $created ) {
		$properties['created'] = array( 'type' => 'boolean' );
	}
	return array( 'type' => 'object', 'properties' => $properties, 'required' => array_keys( $properties ), 'additionalProperties' => false );
}

function wpagent_ability_create_pods_act_record(): array {
	return array(
		'label'       => __( 'Pods Advanced-Content-Type-Datensatz erstellen', 'wp-agent-companion' ),
		'description' => __( 'Erstellt einen Datensatz in einem bestehenden, standardmäßigen tabellenbasierten Pods Advanced Content Type über Pods add(). Der native Read-back muss jeden angeforderten Wert exakt bestätigen.', 'wp-agent-companion' ),
		'category'    => 'wp-agent',
		'input_schema' => array(
			'type' => 'object', 'properties' => array(
				'model_name' => array( 'type' => 'string', 'pattern' => '^[a-z][a-z0-9_]{0,63}$' ),
				'expected_schema_hash' => array( 'type' => 'string', 'pattern' => '^[a-f0-9]{64}$' ),
				'values' => wpagent_pods_act_values_input_schema(),
			),
			'required' => array( 'model_name', 'expected_schema_hash', 'values' ), 'additionalProperties' => false,
		),
		'output_schema'       => wpagent_pods_act_write_result_schema( true ),
		'execute_callback'    => 'wpagent_exec_create_pods_act_record',
		'permission_callback' => 'wpagent_perm_manage_options',
		'meta' => array( 'show_in_rest' => true, 'annotations' => array( 'readonly' => false, 'destructive' => false, 'idempotent' => false ) ),
	);
}

function wpagent_ability_update_pods_act_record(): array {
	return array(
		'label'       => __( 'Pods Advanced-Content-Type-Datensatz aktualisieren', 'wp-agent-companion' ),
		'description' => __( 'Aktualisiert ausschließlich freigegebene Textfelder eines bestehenden tabellenbasierten Pods Advanced Content Type konfliktgeschützt über Pods save().', 'wp-agent-companion' ),
		'category'    => 'wp-agent',
		'input_schema' => array(
			'type' => 'object', 'properties' => array(
				'model_name' => array( 'type' => 'string', 'pattern' => '^[a-z][a-z0-9_]{0,63}$' ),
				'record_id' => array( 'type' => 'integer', 'minimum' => 1 ),
				'expected_schema_hash' => array( 'type' => 'string', 'pattern' => '^[a-f0-9]{64}$' ),
				'expected_hash' => array( 'type' => 'string', 'pattern' => '^[a-f0-9]{64}$' ),
				'values' => wpagent_pods_act_values_input_schema(),
			),
			'required' => array( 'model_name', 'record_id', 'expected_schema_hash', 'expected_hash', 'values' ), 'additionalProperties' => false,
		),
		'output_schema'       => wpagent_pods_act_write_result_schema(),
		'execute_callback'    => 'wpagent_exec_update_pods_act_record',
		'permission_callback' => 'wpagent_perm_manage_options',
		'meta' => array( 'show_in_rest' => true, 'annotations' => array( 'readonly' => false, 'destructive' => false, 'idempotent' => true ) ),
	);
}

function wpagent_ability_delete_pods_act_record(): array {
	return array(
		'label'       => __( 'Pods Advanced-Content-Type-Datensatz löschen', 'wp-agent-companion' ),
		'description' => __( 'Löscht einen tabellenbasierten Pods Advanced-Content-Type-Datensatz nur nach Konfliktprüfung, ausdrücklicher Bestätigung und nativer Abwesenheitsprüfung.', 'wp-agent-companion' ),
		'category'    => 'wp-agent',
		'input_schema' => array(
			'type' => 'object', 'properties' => array(
				'model_name' => array( 'type' => 'string', 'pattern' => '^[a-z][a-z0-9_]{0,63}$' ),
				'record_id' => array( 'type' => 'integer', 'minimum' => 1 ),
				'expected_schema_hash' => array( 'type' => 'string', 'pattern' => '^[a-f0-9]{64}$' ),
				'expected_hash' => array( 'type' => 'string', 'pattern' => '^[a-f0-9]{64}$' ), 'confirm' => array( 'type' => 'boolean' ),
			),
			'required' => array( 'model_name', 'record_id', 'expected_schema_hash', 'expected_hash', 'confirm' ), 'additionalProperties' => false,
		),
		'output_schema' => array(
			'type' => 'object', 'properties' => array(
				'model_name' => array( 'type' => 'string' ), 'record_id' => array( 'type' => 'integer', 'minimum' => 1 ),
				'deleted' => array( 'type' => 'boolean' ), 'verified_persistence' => array( 'type' => 'boolean' ),
			),
			'required' => array( 'model_name', 'record_id', 'deleted', 'verified_persistence' ), 'additionalProperties' => false,
		),
		'execute_callback'    => 'wpagent_exec_delete_pods_act_record',
		'permission_callback' => 'wpagent_perm_manage_options',
		'meta' => array( 'show_in_rest' => true, 'annotations' => array( 'readonly' => false, 'destructive' => true, 'idempotent' => false ) ),
	);
}

/** @return array{model_name:string,expected_schema_hash:string,blog_id:int,lock_name:string,token:string}|WP_Error */
function wpagent_pods_act_begin_locked_write( array $input ): array|WP_Error {
	$writable = wpagent_pods_act_require_writable_database();
	if ( is_wp_error( $writable ) ) {
		return $writable;
	}
	$model_name = wpagent_pods_name( $input['model_name'] ?? null );
	if ( is_wp_error( $model_name ) ) {
		return $model_name;
	}
	$schema_hash = wpagent_pods_act_expected_hash( $input['expected_schema_hash'] ?? null, 'expected_schema_hash' );
	if ( is_wp_error( $schema_hash ) ) {
		return $schema_hash;
	}
	$blog_id = get_current_blog_id();
	$lock_name = wpagent_pods_act_lock_name( $blog_id, $model_name );
	$token = wpagent_pods_acquire_lock( $lock_name );
	if ( is_wp_error( $token ) ) {
		return $token;
	}
	return array( 'model_name' => $model_name, 'expected_schema_hash' => $schema_hash, 'blog_id' => $blog_id, 'lock_name' => $lock_name, 'token' => $token );
}

/** @return array<string,mixed>|WP_Error */
function wpagent_exec_create_pods_act_record( $input ) {
	$input = is_array( $input ) ? $input : array();
	$write = wpagent_pods_act_begin_locked_write( $input );
	if ( is_wp_error( $write ) ) {
		return $write;
	}
	try {
		$context = wpagent_pods_act_locked_context( $write['model_name'], $write['blog_id'], $write['expected_schema_hash'], $write['lock_name'], $write['token'] );
		if ( is_wp_error( $context ) ) {
			return $context;
		}
		$values = wpagent_pods_act_validate_values( $input['values'] ?? null, $context['field_map'], true );
		if ( is_wp_error( $values ) ) {
			return $values;
		}
		$expected_values = wpagent_pods_act_expected_record_values( $context, $values );
		$ready = wpagent_pods_act_prepare_native_write( $write['lock_name'], $write['token'] );
		if ( is_wp_error( $ready ) ) {
			return $ready;
		}
		try {
			$record_id = $context['native']->add( $values );
		} catch ( Throwable $error ) {
			return wpagent_pods_act_recovery_required( $write['model_name'] );
		}
		if ( ! is_int( $record_id ) || 0 >= $record_id || ! wpagent_pods_act_lock_owned( $write['lock_name'], $write['token'] ) ) {
			return wpagent_pods_act_recovery_required( $write['model_name'], is_numeric( $record_id ) ? (int) $record_id : 0 );
		}
		$record = wpagent_pods_act_verify_written_record( $write['model_name'], $write['blog_id'], $write['expected_schema_hash'], $write['lock_name'], $write['token'], $record_id, $expected_values );
		if ( is_wp_error( $record ) || ! wpagent_pods_act_refresh_lock( $write['lock_name'], $write['token'] ) ) {
			return wpagent_pods_act_recovery_required( $write['model_name'], $record_id );
		}
		return array( 'record' => $record, 'schema_hash' => $write['expected_schema_hash'], 'verified_persistence' => true, 'created' => true );
	} finally {
		wpagent_pods_release_lock( $write['lock_name'], $write['token'] );
	}
}

/** @return array<string,mixed>|WP_Error */
function wpagent_exec_update_pods_act_record( $input ) {
	$input = is_array( $input ) ? $input : array();
	$write = wpagent_pods_act_begin_locked_write( $input );
	if ( is_wp_error( $write ) ) {
		return $write;
	}
	try {
		$context = wpagent_pods_act_locked_context( $write['model_name'], $write['blog_id'], $write['expected_schema_hash'], $write['lock_name'], $write['token'] );
		if ( is_wp_error( $context ) ) {
			return $context;
		}
		$record_id = wpagent_pods_act_record_id( $input['record_id'] ?? null );
		$expected_hash = wpagent_pods_act_expected_hash( $input['expected_hash'] ?? null, 'expected_hash' );
		if ( is_wp_error( $record_id ) || is_wp_error( $expected_hash ) ) {
			return is_wp_error( $record_id ) ? $record_id : $expected_hash;
		}
		$current = wpagent_pods_act_get_record( $context, $record_id );
		if ( is_wp_error( $current ) ) {
			return $current;
		}
		if ( ! hash_equals( $current['hash'], $expected_hash ) ) {
			return new WP_Error( 'wpagent_pods_act_conflict', __( 'Der Advanced-Content-Type-Datensatz wurde seit dem Lesen verändert oder der Konflikt-Hash ist ungültig.', 'wp-agent-companion' ), array( 'status' => 409, 'current_hash' => $current['hash'] ) );
		}
		$values = wpagent_pods_act_validate_values( $input['values'] ?? null, $context['field_map'], false );
		if ( is_wp_error( $values ) ) {
			return $values;
		}
		$expected_values = wpagent_pods_act_expected_record_values( $context, $values, $current['values'] );
		if ( wpagent_pods_act_record_values_match( $current['values'], $expected_values ) ) {
			$ready = wpagent_pods_act_prepare_native_write( $write['lock_name'], $write['token'] );
			if ( is_wp_error( $ready ) ) {
				return $ready;
			}
			return array( 'record' => $current, 'schema_hash' => $write['expected_schema_hash'], 'verified_persistence' => true );
		}
		$ready = wpagent_pods_act_prepare_native_write( $write['lock_name'], $write['token'] );
		if ( is_wp_error( $ready ) ) {
			return $ready;
		}
		try {
			$saved = $context['native']->save( $values, null, $record_id );
		} catch ( Throwable $error ) {
			return wpagent_pods_act_recovery_required( $write['model_name'], $record_id );
		}
		if ( ! is_int( $saved ) || $record_id !== $saved || ! wpagent_pods_act_lock_owned( $write['lock_name'], $write['token'] ) ) {
			return wpagent_pods_act_recovery_required( $write['model_name'], $record_id );
		}
		$record = wpagent_pods_act_verify_written_record( $write['model_name'], $write['blog_id'], $write['expected_schema_hash'], $write['lock_name'], $write['token'], $record_id, $expected_values );
		if ( is_wp_error( $record ) || ! wpagent_pods_act_refresh_lock( $write['lock_name'], $write['token'] ) ) {
			return wpagent_pods_act_recovery_required( $write['model_name'], $record_id );
		}
		return array( 'record' => $record, 'schema_hash' => $write['expected_schema_hash'], 'verified_persistence' => true );
	} finally {
		wpagent_pods_release_lock( $write['lock_name'], $write['token'] );
	}
}

/** @return array<string,mixed>|WP_Error */
function wpagent_exec_delete_pods_act_record( $input ) {
	$input = is_array( $input ) ? $input : array();
	$write = wpagent_pods_act_begin_locked_write( $input );
	if ( is_wp_error( $write ) ) {
		return $write;
	}
	try {
		$context = wpagent_pods_act_locked_context( $write['model_name'], $write['blog_id'], $write['expected_schema_hash'], $write['lock_name'], $write['token'] );
		if ( is_wp_error( $context ) ) {
			return $context;
		}
		$record_id = wpagent_pods_act_record_id( $input['record_id'] ?? null );
		$expected_hash = wpagent_pods_act_expected_hash( $input['expected_hash'] ?? null, 'expected_hash' );
		if ( is_wp_error( $record_id ) || is_wp_error( $expected_hash ) ) {
			return is_wp_error( $record_id ) ? $record_id : $expected_hash;
		}
		if ( true !== ( $input['confirm'] ?? false ) ) {
			return new WP_Error( 'wpagent_pods_act_confirm', __( 'Das Löschen eines Advanced-Content-Type-Datensatzes erfordert confirm=true.', 'wp-agent-companion' ), array( 'status' => 400 ) );
		}
		$current = wpagent_pods_act_get_record( $context, $record_id );
		if ( is_wp_error( $current ) ) {
			return $current;
		}
		if ( ! hash_equals( $current['hash'], $expected_hash ) ) {
			return new WP_Error( 'wpagent_pods_act_conflict', __( 'Der Advanced-Content-Type-Datensatz wurde seit dem Lesen verändert oder der Konflikt-Hash ist ungültig.', 'wp-agent-companion' ), array( 'status' => 409, 'current_hash' => $current['hash'] ) );
		}
		$ready = wpagent_pods_act_prepare_native_write( $write['lock_name'], $write['token'] );
		if ( is_wp_error( $ready ) ) {
			return $ready;
		}
		try {
			$deleted = $context['native']->delete( $record_id );
		} catch ( Throwable $error ) {
			return wpagent_pods_act_recovery_required( $write['model_name'], $record_id );
		}
		if ( true !== $deleted || ! wpagent_pods_act_lock_owned( $write['lock_name'], $write['token'] ) ) {
			return wpagent_pods_act_recovery_required( $write['model_name'], $record_id );
		}
		$fresh = wpagent_pods_act_locked_context( $write['model_name'], $write['blog_id'], $write['expected_schema_hash'], $write['lock_name'], $write['token'] );
		if ( is_wp_error( $fresh ) ) {
			return wpagent_pods_act_recovery_required( $write['model_name'], $record_id );
		}
		$remaining = wpagent_pods_act_get_record( $fresh, $record_id );
		if ( ! is_wp_error( $remaining ) || 'wpagent_pods_act_record_not_found' !== $remaining->get_error_code() || ! wpagent_pods_act_refresh_lock( $write['lock_name'], $write['token'] ) ) {
			return wpagent_pods_act_recovery_required( $write['model_name'], $record_id );
		}
		return array( 'model_name' => $write['model_name'], 'record_id' => $record_id, 'deleted' => true, 'verified_persistence' => true );
	} finally {
		wpagent_pods_release_lock( $write['lock_name'], $write['token'] );
	}
}
