<?php
/** Conflict-safe native Pods field create, update and delete abilities. */

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

/** @return array<string,mixed> */
function wpagent_pods_field_write_properties(): array {
	return array(
		'model_name' => array( 'type' => 'string', 'pattern' => '^[a-z][a-z0-9_]{0,63}$' ),
		'expected_model_hash' => array( 'type' => 'string', 'pattern' => '^[a-f0-9]{64}$' ),
		'expected_field_hash' => array( 'type' => 'string', 'pattern' => '^[a-f0-9]{64}$' ),
		'name' => array( 'type' => 'string', 'pattern' => '^[a-z][a-z0-9_]{0,63}$' ),
		'label' => array( 'type' => 'string', 'minLength' => 1, 'maxLength' => 200 ),
		'description' => array( 'type' => 'string', 'maxLength' => 2000 ),
		'type' => array( 'type' => 'string', 'enum' => wpagent_pods_supported_field_types() ),
		'required' => array( 'type' => 'boolean' ), 'repeatable' => array( 'type' => 'boolean' ),
		'multiple' => array( 'type' => 'boolean' ), 'weight' => array( 'type' => 'integer', 'minimum' => 0, 'maximum' => 9999 ),
		'relationship_object' => array( 'type' => 'string', 'enum' => array( 'post_type', 'taxonomy', 'user', 'media' ) ),
		'relationship_target' => array( 'type' => 'string', 'maxLength' => 64 ),
		'file_type' => array( 'type' => 'string', 'enum' => array( 'images', 'images-any', 'video', 'video-any', 'audio', 'audio-any', 'text', 'any' ) ),
		'confirm_data_migration' => array( 'type' => 'boolean' ),
	);
}

function wpagent_ability_upsert_pods_field(): array {
	return array(
		'label'       => __( 'Pods-Feld erstellen oder aktualisieren', 'wp-agent-companion' ),
		'description' => __( 'Erstellt oder aktualisiert ein Pods-Feld über die native API. Modell- und Feld-Hashes verhindern verlorene Änderungen; Typwechsel mit gespeicherten Werten benötigen eine eigene Bestätigung.', 'wp-agent-companion' ),
		'category'    => 'wp-agent',
		'input_schema' => array(
			'type' => 'object', 'properties' => wpagent_pods_field_write_properties(),
			'required' => array( 'model_name', 'expected_model_hash', 'name' ), 'additionalProperties' => false,
		),
		'output_schema' => array(
			'type' => 'object',
			'properties' => array(
				'model' => wpagent_pods_model_output_schema(), 'field' => wpagent_pods_field_output_schema(),
				'created' => array( 'type' => 'boolean' ), 'verified_persistence' => array( 'type' => 'boolean' ),
			),
			'required' => array( 'model', 'field', 'created', 'verified_persistence' ), 'additionalProperties' => false,
		),
		'execute_callback'    => 'wpagent_exec_upsert_pods_field',
		'permission_callback' => 'wpagent_perm_manage_options',
		'meta' => array( 'show_in_rest' => true, 'annotations' => array( 'readonly' => false, 'destructive' => true, 'idempotent' => true ) ),
	);
}

function wpagent_ability_delete_pods_field(): array {
	return array(
		'label'       => __( 'Pods-Feld löschen', 'wp-agent-companion' ),
		'description' => __( 'Löscht eine Pods-Feldkonfiguration konfliktgeschützt. Einfache Metawerte bleiben verborgen erhalten; Pods-Beziehungen können entfernt werden und benötigen bei vorhandenen Daten eine Zusatzbestätigung.', '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}$' ),
				'name' => array( 'type' => 'string', 'pattern' => '^[a-z][a-z0-9_]{0,63}$' ),
				'expected_model_hash' => array( 'type' => 'string', 'pattern' => '^[a-f0-9]{64}$' ),
				'expected_field_hash' => array( 'type' => 'string', 'pattern' => '^[a-f0-9]{64}$' ),
				'confirm' => array( 'type' => 'boolean' ), 'confirm_data_loss' => array( 'type' => 'boolean' ),
			),
			'required' => array( 'model_name', 'name', 'expected_model_hash', 'expected_field_hash', 'confirm' ),
			'additionalProperties' => false,
		),
		'output_schema' => array(
			'type' => 'object',
			'properties' => array(
				'model' => wpagent_pods_model_output_schema(), 'name' => array( 'type' => 'string' ),
				'deleted' => array( 'type' => 'boolean' ), 'retained_values' => array( 'type' => 'integer' ),
				'removed_relationships' => array( 'type' => 'integer' ),
			),
			'required' => array( 'model', 'name', 'deleted', 'retained_values', 'removed_relationships' ),
			'additionalProperties' => false,
		),
		'execute_callback'    => 'wpagent_exec_delete_pods_field',
		'permission_callback' => 'wpagent_perm_manage_options',
		'meta' => array( 'show_in_rest' => true, 'annotations' => array( 'readonly' => false, 'destructive' => true, 'idempotent' => false ) ),
	);
}

/** @return object|false|WP_Error */
function wpagent_pods_find_field( object $pod, string $name ) {
	try {
		$field = pods_api()->load_field( array( 'pod_id' => (int) $pod->get_id(), 'name' => $name, 'bypass_cache' => true ) );
	} catch ( Throwable $error ) {
		return new WP_Error( 'wpagent_pods_field_read_failed', __( 'Das Pods-Feld konnte nicht gelesen werden.', 'wp-agent-companion' ), array( 'status' => 500 ) );
	}
	return is_object( $field ) && method_exists( $field, 'get_args' ) ? $field : false;
}

/** @return array<string,mixed>|WP_Error */
function wpagent_pods_validate_field_input( array $input, object $pod, ?array $current = null ) {
	$create = null === $current;
	$name = wpagent_pods_name( $input['name'] ?? null );
	if ( is_wp_error( $name ) ) return $name;
	$state = $create ? array(
		'name' => $name, 'label' => '', 'description' => '', 'type' => '', 'required' => false,
		'repeatable' => false, 'multiple' => false, 'weight' => 0, 'relationship_object' => '',
		'relationship_target' => '', 'file_type' => '',
	) : $current;
	if ( ! $create && $name !== $current['name'] ) {
		return new WP_Error( 'wpagent_pods_field_rename', __( 'Pods-Felder werden aus Sicherheitsgründen nicht umbenannt. Erstelle ein neues Feld und migriere die Werte ausdrücklich.', 'wp-agent-companion' ), array( 'status' => 400 ) );
	}
	foreach ( array( 'label' => 200, 'description' => 2000 ) as $field => $max ) {
		if ( $create || array_key_exists( $field, $input ) ) {
			$text = wpagent_pods_text( $input[ $field ] ?? '', $field, $max, 'description' === $field );
			if ( is_wp_error( $text ) ) return $text;
			$state[ $field ] = $text;
		}
	}
	if ( $create || array_key_exists( 'type', $input ) ) {
		$type = is_string( $input['type'] ?? null ) ? $input['type'] : '';
		if ( ! in_array( $type, wpagent_pods_supported_field_types(), true ) ) {
			return new WP_Error( 'wpagent_pods_field_type', __( 'Dieser Pods-Feldtyp ist im verifizierten Schreibpfad nicht freigegeben.', 'wp-agent-companion' ), array( 'status' => 400 ) );
		}
		$state['type'] = $type;
	}
	foreach ( array( 'required', 'repeatable', 'multiple' ) as $field ) {
		if ( array_key_exists( $field, $input ) ) {
			$value = wpagent_pods_boolean( $input[ $field ], $field );
			if ( is_wp_error( $value ) ) return $value;
			$state[ $field ] = $value;
		}
	}
	if ( array_key_exists( 'weight', $input ) ) {
		$weight = is_int( $input['weight'] ) ? $input['weight'] : ( is_string( $input['weight'] ) && ctype_digit( $input['weight'] ) ? (int) $input['weight'] : -1 );
		if ( $weight < 0 || $weight > 9999 ) {
			return new WP_Error( 'wpagent_pods_field_weight', __( 'weight muss eine ganze Zahl zwischen 0 und 9999 sein.', 'wp-agent-companion' ), array( 'status' => 400 ) );
		}
		$state['weight'] = $weight;
	}
	$type = $state['type'];
	if ( 'pick' === $type ) {
		$object = array_key_exists( 'relationship_object', $input ) ? (string) $input['relationship_object'] : $state['relationship_object'];
		$target = array_key_exists( 'relationship_target', $input ) ? (string) $input['relationship_target'] : $state['relationship_target'];
		if ( ! in_array( $object, array( 'post_type', 'taxonomy', 'user', 'media' ), true ) ) {
			return new WP_Error( 'wpagent_pods_relationship_object', __( 'relationship_object muss post_type, taxonomy, user oder media sein.', 'wp-agent-companion' ), array( 'status' => 400 ) );
		}
		if ( 'post_type' === $object && ( sanitize_key( $target ) !== $target || ! post_type_exists( $target ) ) ) {
			return new WP_Error( 'wpagent_pods_relationship_target', __( 'Das Beziehungsziel ist kein registrierter Inhaltstyp.', 'wp-agent-companion' ), array( 'status' => 400 ) );
		}
		if ( 'taxonomy' === $object && ( sanitize_key( $target ) !== $target || ! taxonomy_exists( $target ) ) ) {
			return new WP_Error( 'wpagent_pods_relationship_target', __( 'Das Beziehungsziel ist keine registrierte Taxonomie.', 'wp-agent-companion' ), array( 'status' => 400 ) );
		}
		if ( in_array( $object, array( 'user', 'media' ), true ) && '' !== $target ) {
			return new WP_Error( 'wpagent_pods_relationship_target', __( 'user- und media-Beziehungen dürfen kein relationship_target enthalten.', 'wp-agent-companion' ), array( 'status' => 400 ) );
		}
		$state['relationship_object'] = $object;
		$state['relationship_target'] = $target;
		$state['file_type'] = '';
		if ( $state['repeatable'] ) {
			return new WP_Error( 'wpagent_pods_relationship_repeatable', __( 'Beziehungsfelder verwenden multiple statt repeatable.', 'wp-agent-companion' ), array( 'status' => 400 ) );
		}
	} elseif ( in_array( $type, array( 'file', 'avatar' ), true ) ) {
		if ( array_key_exists( 'relationship_object', $input ) || array_key_exists( 'relationship_target', $input ) ) {
			return new WP_Error( 'wpagent_pods_file_relationship', __( 'Dateifelder besitzen ein festes Medienziel und akzeptieren keine Beziehungsoptionen.', 'wp-agent-companion' ), array( 'status' => 400 ) );
		}
		$file_type = array_key_exists( 'file_type', $input ) ? (string) $input['file_type'] : ( $state['file_type'] ?: 'images' );
		if ( ! in_array( $file_type, array( 'images', 'images-any', 'video', 'video-any', 'audio', 'audio-any', 'text', 'any' ), true ) ) {
			return new WP_Error( 'wpagent_pods_file_type', __( 'file_type ist nicht freigegeben.', 'wp-agent-companion' ), array( 'status' => 400 ) );
		}
		$state['file_type'] = $file_type;
		$state['relationship_object'] = 'media';
		$state['relationship_target'] = 'attachment';
		if ( $state['repeatable'] ) {
			return new WP_Error( 'wpagent_pods_file_repeatable', __( 'Dateifelder verwenden multiple statt repeatable.', 'wp-agent-companion' ), array( 'status' => 400 ) );
		}
	} else {
		if ( array_key_exists( 'multiple', $input ) || array_key_exists( 'relationship_object', $input ) || array_key_exists( 'relationship_target', $input ) || array_key_exists( 'file_type', $input ) ) {
			return new WP_Error( 'wpagent_pods_field_options', __( 'Beziehungs-, Datei- und Mehrfachoptionen gelten nur für die passenden Pods-Feldtypen.', 'wp-agent-companion' ), array( 'status' => 400 ) );
		}
		$state['multiple'] = false;
		$state['relationship_object'] = '';
		$state['relationship_target'] = '';
		$state['file_type'] = '';
		if ( 'wysiwyg' === $type && $state['repeatable'] ) {
			return new WP_Error( 'wpagent_pods_wysiwyg_repeatable', __( 'Pods unterstützt wiederholbare TinyMCE-Felder nicht verlässlich.', 'wp-agent-companion' ), array( 'status' => 400 ) );
		}
	}
	$pod_args = $pod->get_args();
	if ( in_array( $name, array( 'id', 'ID' ), true ) || ( 'post_type' === (string) $pod_args['type'] && taxonomy_exists( $name ) ) ) {
		return new WP_Error( 'wpagent_pods_field_reserved', __( 'Der Feldname kollidiert mit einer internen Pods- oder WordPress-Eigenschaft.', 'wp-agent-companion' ), array( 'status' => 400 ) );
	}
	return $state;
}

/** @return array<string,mixed> */
function wpagent_pods_field_api_params( array $state, object $pod, ?array $snapshot = null ): array {
	$params = null === $snapshot ? array() : $snapshot;
	$params['pod_id'] = (int) $pod->get_id();
	$params['pod'] = (string) $pod->get_name();
	$params['name'] = $state['name'];
	$params['label'] = $state['label'];
	$params['description'] = $state['description'];
	$params['type'] = $state['type'];
	$params['required'] = $state['required'] ? 1 : 0;
	$params['repeatable'] = $state['repeatable'] ? 1 : 0;
	$params['weight'] = $state['weight'];
	if ( 'pick' === $state['type'] ) {
		$params['pick_object'] = $state['relationship_object'];
		$params['pick_val'] = $state['relationship_target'];
		$params['pick_format_type'] = $state['multiple'] ? 'multi' : 'single';
		$params['pick_format_single'] = 'autocomplete';
		$params['pick_format_multi'] = 'autocomplete';
	} elseif ( in_array( $state['type'], array( 'file', 'avatar' ), true ) ) {
		$params[ $state['type'] . '_format_type' ] = $state['multiple'] ? 'multi' : 'single';
		$params[ $state['type'] . '_type' ] = $state['file_type'];
	}
	return $params;
}

function wpagent_pods_field_state_matches( array $actual, array $expected ): bool {
	foreach ( array( 'name', 'label', 'description', 'type', 'required', 'repeatable', 'multiple', 'weight', 'relationship_object', 'relationship_target', 'file_type' ) as $key ) {
		if ( $actual[ $key ] !== $expected[ $key ] ) return false;
	}
	return true;
}

/** @return array<string,mixed>|WP_Error */
function wpagent_exec_upsert_pods_field( $input ) {
	$available = wpagent_pods_require_api();
	if ( is_wp_error( $available ) ) return $available;
	$input = is_array( $input ) ? $input : array();
	$model_name = is_string( $input['model_name'] ?? null ) ? $input['model_name'] : '';
	$lock = wpagent_pods_acquire_lock( $model_name );
	if ( is_wp_error( $lock ) ) return $lock;
	try {
		$pod = wpagent_pods_get_model( $model_name );
		if ( is_wp_error( $pod ) ) return $pod;
		$model = wpagent_pods_model_state( $pod );
		$expected_model_hash = is_string( $input['expected_model_hash'] ?? null ) ? $input['expected_model_hash'] : '';
		if ( ! preg_match( '/^[a-f0-9]{64}$/', $expected_model_hash ) || ! hash_equals( $model['hash'], $expected_model_hash ) ) {
			return new WP_Error( 'wpagent_pods_conflict', __( 'Das Pods-Modell wurde seit dem Lesen verändert oder der Modell-Hash ist ungültig.', 'wp-agent-companion' ), array( 'status' => 409, 'current_hash' => $model['hash'] ) );
		}
		$field_name = wpagent_pods_name( $input['name'] ?? null );
		if ( is_wp_error( $field_name ) ) return $field_name;
		$field = wpagent_pods_find_field( $pod, $field_name );
		if ( is_wp_error( $field ) ) return $field;
		$current = $field ? wpagent_pods_field_state( $pod, $field ) : null;
		if ( $field ) {
			$expected_field_hash = is_string( $input['expected_field_hash'] ?? null ) ? $input['expected_field_hash'] : '';
			if ( ! preg_match( '/^[a-f0-9]{64}$/', $expected_field_hash ) || ! hash_equals( $current['hash'], $expected_field_hash ) ) {
				return new WP_Error( 'wpagent_pods_field_conflict', __( 'Das Pods-Feld wurde seit dem Lesen verändert oder expected_field_hash fehlt.', 'wp-agent-companion' ), array( 'status' => 409, 'current_hash' => $current['hash'] ) );
			}
		} elseif ( array_key_exists( 'expected_field_hash', $input ) ) {
			return new WP_Error( 'wpagent_pods_field_missing', __( 'expected_field_hash wurde angegeben, aber das Pods-Feld existiert nicht.', 'wp-agent-companion' ), array( 'status' => 409 ) );
		}
		$next = wpagent_pods_validate_field_input( $input, $pod, $current );
		if ( is_wp_error( $next ) ) return $next;
		if ( $current && $current['type'] !== $next['type'] && ( $current['value_count'] > 0 || $current['relationship_count'] > 0 ) && true !== ( $input['confirm_data_migration'] ?? false ) ) {
			return new WP_Error( 'wpagent_pods_field_data_exists', __( 'Der Feldtyp ändert sich, obwohl Werte oder Beziehungen gespeichert sind. Dafür ist confirm_data_migration=true erforderlich.', 'wp-agent-companion' ), array( 'status' => 409, 'value_count' => $current['value_count'], 'relationship_count' => $current['relationship_count'] ) );
		}
		$snapshot = $field ? $field->get_args() : null;
		$params = wpagent_pods_field_api_params( $next, $pod, $snapshot );
		if ( $field ) $params['id'] = (int) $field->get_id();
		try {
			$saved = pods_api()->save_field( $params );
			if ( is_wp_error( $saved ) || ! $saved ) throw new RuntimeException( 'Pods field save failed.' );
			$fresh_field = wpagent_pods_find_field( $pod, $next['name'] );
			$fresh_pod = wpagent_pods_get_model( $model_name );
			$result = ! is_wp_error( $fresh_field ) && $fresh_field && ! is_wp_error( $fresh_pod ) ? wpagent_pods_field_state( $fresh_pod, $fresh_field ) : null;
			if ( ! is_array( $result ) || ! wpagent_pods_field_state_matches( $result, $next ) ) throw new RuntimeException( 'Pods field read-back failed.' );
			return array( 'model' => wpagent_pods_model_state( $fresh_pod ), 'field' => $result, 'created' => ! $field, 'verified_persistence' => true );
		} catch ( Throwable $error ) {
			if ( null === $snapshot ) {
				$fresh = wpagent_pods_find_field( $pod, $next['name'] );
				if ( is_object( $fresh ) ) try { pods_api()->delete_field( $fresh ); } catch ( Throwable $cleanup_error ) { unset( $cleanup_error ); }
			} else {
				$rollback = $snapshot;
				$rollback['id'] = (int) $field->get_id();
				$rollback['pod_id'] = (int) $pod->get_id();
				$rollback['pod'] = $model_name;
				try { pods_api()->save_field( $rollback ); } catch ( Throwable $rollback_error ) { unset( $rollback_error ); }
			}
			$fresh_pod = wpagent_pods_get_model( $model_name );
			$rolled_back = ! is_wp_error( $fresh_pod ) && hash_equals( $model['hash'], wpagent_pods_model_state( $fresh_pod )['hash'] );
			return new WP_Error( 'wpagent_pods_field_save_failed', __( 'Das Pods-Feld konnte nicht verifiziert gespeichert werden. Der vorherige Zustand wurde nach Möglichkeit wiederhergestellt.', 'wp-agent-companion' ), array( 'status' => 500, 'rolled_back' => $rolled_back ) );
		}
	} finally {
		wpagent_pods_release_lock( $model_name, $lock );
	}
}

/** @return array<string,mixed>|WP_Error */
function wpagent_exec_delete_pods_field( $input ) {
	$available = wpagent_pods_require_api();
	if ( is_wp_error( $available ) ) return $available;
	$input = is_array( $input ) ? $input : array();
	if ( true !== ( $input['confirm'] ?? false ) ) {
		return new WP_Error( 'wpagent_confirmation_required', __( 'Zum Löschen des Pods-Feldes ist confirm=true erforderlich.', 'wp-agent-companion' ), array( 'status' => 400 ) );
	}
	$model_name = is_string( $input['model_name'] ?? null ) ? $input['model_name'] : '';
	$lock = wpagent_pods_acquire_lock( $model_name );
	if ( is_wp_error( $lock ) ) return $lock;
	try {
		$pod = wpagent_pods_get_model( $model_name );
		if ( is_wp_error( $pod ) ) return $pod;
		$model = wpagent_pods_model_state( $pod );
		$model_hash = is_string( $input['expected_model_hash'] ?? null ) ? $input['expected_model_hash'] : '';
		if ( ! preg_match( '/^[a-f0-9]{64}$/', $model_hash ) || ! hash_equals( $model['hash'], $model_hash ) ) {
			return new WP_Error( 'wpagent_pods_conflict', __( 'Das Pods-Modell wurde seit dem Lesen verändert oder der Modell-Hash ist ungültig.', 'wp-agent-companion' ), array( 'status' => 409, 'current_hash' => $model['hash'] ) );
		}
		$name = wpagent_pods_name( $input['name'] ?? null );
		if ( is_wp_error( $name ) ) return $name;
		$field = wpagent_pods_find_field( $pod, $name );
		if ( is_wp_error( $field ) ) return $field;
		if ( ! $field ) return new WP_Error( 'wpagent_pods_field_not_found', __( 'Pods-Feld nicht gefunden.', 'wp-agent-companion' ), array( 'status' => 404 ) );
		$current = wpagent_pods_field_state( $pod, $field );
		$field_hash = is_string( $input['expected_field_hash'] ?? null ) ? $input['expected_field_hash'] : '';
		if ( ! preg_match( '/^[a-f0-9]{64}$/', $field_hash ) || ! hash_equals( $current['hash'], $field_hash ) ) {
			return new WP_Error( 'wpagent_pods_field_conflict', __( 'Das Pods-Feld wurde seit dem Lesen verändert oder der Feld-Hash ist ungültig.', 'wp-agent-companion' ), array( 'status' => 409, 'current_hash' => $current['hash'] ) );
		}
		if ( ( $current['value_count'] > 0 || $current['relationship_count'] > 0 ) && true !== ( $input['confirm_data_loss'] ?? false ) ) {
			return new WP_Error( 'wpagent_pods_field_data_exists', __( 'Das Feld besitzt Werte oder Beziehungen. Das Entfernen der Feldkonfiguration erfordert confirm_data_loss=true.', 'wp-agent-companion' ), array( 'status' => 409, 'value_count' => $current['value_count'], 'relationship_count' => $current['relationship_count'] ) );
		}
		try {
			$deleted = pods_api()->delete_field( $field );
		} catch ( Throwable $error ) {
			return new WP_Error( 'wpagent_pods_field_delete_failed', __( 'Pods konnte die Feldkonfiguration nicht vollständig löschen.', 'wp-agent-companion' ), array( 'status' => 500 ) );
		}
		$remaining_field = wpagent_pods_find_field( $pod, $name );
		if ( is_wp_error( $deleted ) || true !== $deleted || is_wp_error( $remaining_field ) || $remaining_field ) {
			return new WP_Error( 'wpagent_pods_field_delete_failed', __( 'Pods konnte die Feldkonfiguration nicht vollständig löschen.', 'wp-agent-companion' ), array( 'status' => 500 ) );
		}
		$fresh_pod = wpagent_pods_get_model( $model_name );
		if ( is_wp_error( $fresh_pod ) ) return $fresh_pod;
		$remaining_relations = wpagent_pods_relationship_count( (int) $pod->get_id(), (int) $field->get_id() );
		return array(
			'model' => wpagent_pods_model_state( $fresh_pod ), 'name' => $name, 'deleted' => true,
			'retained_values' => $current['value_count'],
			'removed_relationships' => max( 0, $current['relationship_count'] - $remaining_relations ),
		);
	} finally {
		wpagent_pods_release_lock( $model_name, $lock );
	}
}
