<?php
/** Ability: wp-agent/set-seo-settings. */

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

function wpagent_ability_set_seo_settings(): array {
	return array(
		'label'               => __( 'Globale SEO-Einstellungen setzen und verifizieren', 'wp-agent-companion' ),
		'description'         => __( 'Prüft begrenzte globale SEO-Einstellungen gegen den aktiven Provider. Remote-Änderungen sind nicht verfügbar, weil kein Provider eine atomare Vergleichs-und-Schreib-Operation für die vollständige Einstellungsfläche bereitstellt. Nimm Änderungen im SEO-Plugin vor und lies den Zustand anschließend neu.', 'wp-agent-companion' ),
		'category'            => 'wp-agent',
		'input_schema'        => array(
			'type'                 => 'object',
			'properties'           => array(
				'expected_hash' => array( 'type' => 'string', 'pattern' => '^[a-f0-9]{64}$' ),
				'settings'      => array_merge( wpagent_seo_settings_schema(), array( 'minProperties' => 1 ) ),
			),
			'required'             => array( 'expected_hash', 'settings' ),
			'additionalProperties' => false,
		),
		'output_schema'       => array(
			'type'                 => 'object',
			'properties'           => array(
				'plugin'            => array( 'type' => 'string', 'enum' => array( 'rankmath', 'yoast', 'aioseo', 'seopress' ) ),
				'written'           => wpagent_seo_settings_written_schema(),
				'verified'          => array( 'type' => 'boolean' ),
				'rolled_back'       => array( 'type' => 'boolean' ),
				'rollback_verified' => array( 'type' => array( 'boolean', 'null' ) ),
				'previous_hash'     => array( 'type' => 'string', 'pattern' => '^[a-f0-9]{64}$' ),
				'state_hash'        => array( 'type' => 'string', 'pattern' => '^[a-f0-9]{64}$' ),
			),
			'required'             => array( 'plugin', 'written', 'verified', 'rolled_back', 'rollback_verified', 'previous_hash', 'state_hash' ),
			'additionalProperties' => false,
		),
		'execute_callback'    => 'wpagent_exec_set_seo_settings',
		'permission_callback' => 'wpagent_perm_manage_options',
		'meta'                => array(
			'show_in_rest' => true,
			'annotations'  => array( 'readonly' => false, 'destructive' => false, 'idempotent' => false, 'manual_only' => true ),
		),
	);
}

/** @return WP_Error */
function wpagent_seo_settings_manual_write_required( string $plugin, string $current_hash ) {
	return new WP_Error(
		'wpagent_seo_settings_manual_write_required',
		__( 'Der aktive SEO-Provider stellt für diese vollständige globale Einstellungsfläche keine atomare Vergleichs-und-Schreib-Operation bereit. WPAgently hat nichts geändert. Nimm die Änderung im SEO-Plugin vor und lies den Zustand anschließend neu.', 'wp-agent-companion' ),
		array( 'status' => 409, 'plugin' => $plugin, 'current_hash' => $current_hash, 'manual_only' => true )
	);
}

/** Marks a provider failure as manual recovery because no exact owned candidate exists. */
function wpagent_seo_settings_recovery_error( WP_Error $error ): WP_Error {
	$data              = $error->get_error_data();
	$data              = is_array( $data ) ? $data : array();
	$error->add_data( array_merge( $data, array( 'rolled_back' => false, 'rollback_verified' => false, 'recovery_required' => true ) ) );
	return $error;
}

/** @param array<string,mixed> $patch @param array<string,mixed> $before @param array<string,mixed> $after @return array<string,array{previous:mixed,current:mixed,persisted:bool}> */
function wpagent_seo_settings_verification( array $patch, array $before, array $after ): array {
	$written = array();
	foreach ( $patch as $field => $value ) {
		$current = $after['settings'][ $field ] ?? null;
		$written[ $field ] = array(
			'previous'  => $before['settings'][ $field ] ?? null,
			'current'   => $current,
			'persisted' => $current === $value,
		);
	}
	return $written;
}

/** @param mixed $input @return array<string,mixed>|WP_Error */
function wpagent_exec_set_seo_settings( $input ) {
	if ( ! current_user_can( 'manage_options' ) ) {
		return new WP_Error( 'wpagent_forbidden', __( 'Keine Berechtigung zum Ändern globaler SEO-Einstellungen.', 'wp-agent-companion' ), array( 'status' => 403 ) );
	}
	$input         = is_array( $input ) ? $input : array();
	$expected_hash = is_string( $input['expected_hash'] ?? null ) ? strtolower( $input['expected_hash'] ) : '';
	if ( ! preg_match( '/^[a-f0-9]{64}$/', $expected_hash ) ) {
		return new WP_Error( 'wpagent_seo_settings_hash', __( 'expected_hash muss ein vollständiger SHA-256-Hash sein.', 'wp-agent-companion' ), array( 'status' => 400 ) );
	}
	$plugin = wpagent_detect_seo_plugin();
	if ( 'none' === $plugin ) {
		return new WP_Error( 'wpagent_seo_plugin_missing', __( 'Kein unterstütztes SEO-Plugin aktiv.', 'wp-agent-companion' ), array( 'status' => 409 ) );
	}
	$patch = wpagent_validate_seo_settings_patch( $input['settings'] ?? null, $plugin );
	if ( is_wp_error( $patch ) ) {
		return $patch;
	}
	$preflight = wpagent_read_seo_settings( $plugin );
	if ( is_wp_error( $preflight ) ) {
		return $preflight;
	}
	$unsupported = array_diff( array_keys( $patch ), $preflight['supported_fields'] );
	if ( array() !== $unsupported ) {
		/* translators: 1: SEO plugin identifier, 2: comma-separated unsupported field names. */
		return new WP_Error( 'wpagent_seo_settings_unsupported_field', sprintf( __( '%1$s unterstützt diese globalen Felder nicht: %2$s', 'wp-agent-companion' ), $plugin, implode( ', ', $unsupported ) ), array( 'status' => 409, 'supported_fields' => $preflight['supported_fields'] ) );
	}
	$lock = wpagent_seo_settings_acquire_lock();
	if ( is_wp_error( $lock ) ) {
		return $lock;
	}
	try {
		$before = wpagent_read_seo_settings( $plugin );
		if ( is_wp_error( $before ) ) {
			return $before;
		}
		if ( ! hash_equals( $before['state_hash'], $expected_hash ) ) {
			return new WP_Error( 'wpagent_seo_settings_conflict', __( 'Die globalen SEO-Einstellungen wurden seit dem Lesen verändert.', 'wp-agent-companion' ), array( 'status' => 409, 'current_hash' => $before['state_hash'] ) );
		}
		if ( ! wpagent_seo_settings_lock_checkpoint( $lock ) ) {
			return new WP_Error( 'wpagent_seo_settings_recovery_required', __( 'Die globale SEO-Sperre ging vor dem Provider-Write verloren. Es wurde nichts weiter geändert.', 'wp-agent-companion' ), array( 'status' => 500, 'current_hash' => $before['state_hash'], 'recovery_required' => true ) );
		}
		if ( ! current_user_can( 'manage_options' ) ) {
			return new WP_Error( 'wpagent_forbidden', __( 'Keine Berechtigung zum Ändern globaler SEO-Einstellungen.', 'wp-agent-companion' ), array( 'status' => 403 ) );
		}
		// This application lock cannot serialize the provider dashboard, imports,
		// hooks or other option writers. Re-check the entire provider snapshot at
		// the operation boundary and keep the public writer closed until there is
		// a provider-native conditional full-snapshot save primitive.
		$prewrite = wpagent_read_seo_settings( $plugin );
		if ( is_wp_error( $prewrite ) ) {
			return $prewrite;
		}
		if ( ! hash_equals( $expected_hash, $prewrite['state_hash'] ) ) {
			return new WP_Error( 'wpagent_seo_settings_conflict', __( 'Die globalen SEO-Einstellungen wurden vor dem Speichern verändert.', 'wp-agent-companion' ), array( 'status' => 409, 'current_hash' => $prewrite['state_hash'] ) );
		}
		if ( ! wpagent_seo_settings_lock_checkpoint( $lock ) || ! current_user_can( 'manage_options' ) ) {
			return new WP_Error( 'wpagent_seo_settings_recovery_required', __( 'Die globale SEO-Sperre oder Berechtigung ging vor dem manuellen Schritt verloren. Es wurde nichts geändert.', 'wp-agent-companion' ), array( 'status' => 500, 'current_hash' => $prewrite['state_hash'], 'recovery_required' => true ) );
		}
		return wpagent_seo_settings_manual_write_required( $plugin, $prewrite['state_hash'] );
	} finally {
		wpagent_seo_settings_release_lock( $lock );
	}
}
