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

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

function wpagent_ability_set_seo_settings(): array {
	$string = array( 'type' => 'string' );
	$properties = array_fill_keys( wpagent_seo_settings_fields(), $string );
	foreach ( array( 'author_archives_enabled', 'author_archives_noindex', 'date_archives_enabled', 'date_archives_noindex', 'search_noindex' ) as $field ) {
		$properties[ $field ] = array( 'type' => 'boolean' );
	}
	$properties['identity_type'] = array( 'type' => 'string', 'enum' => array( 'person', 'organization' ) );
	return array(
		'label'               => __( 'Globale SEO-Einstellungen setzen und verifizieren', 'wp-agent-companion' ),
		'description'         => __( 'Schreibt begrenzte globale SEO-Einstellungen provider-nativ, schützt vor verlorenen Aktualisierungen, liest exakt zurück und rollt Teilfehler vollständig zurück.', '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( 'type' => 'object', 'properties' => $properties, 'minProperties' => 1, 'additionalProperties' => false ),
			),
			'required'             => array( 'expected_hash', 'settings' ),
			'additionalProperties' => false,
		),
		'output_schema'       => array(
			'type'       => 'object',
			'properties' => array(
				'plugin'            => array( 'type' => 'string' ),
				'written'           => array( 'type' => 'object' ),
				'verified'          => array( 'type' => 'boolean' ),
				'rolled_back'       => array( 'type' => 'boolean' ),
				'rollback_verified' => array( 'type' => array( 'boolean', 'null' ) ),
				'previous_hash'     => array( 'type' => 'string' ),
				'state_hash'        => array( 'type' => 'string' ),
			),
		),
		'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' => true ),
		),
	);
}

/** @param array<string,array{exists:bool,value:mixed}> $snapshot */
function wpagent_seo_settings_error_after_rollback( WP_Error $error, string $plugin, array $snapshot ): WP_Error {
	$rollback_verified = wpagent_restore_seo_settings_snapshot( $plugin, $snapshot );
	$data              = $error->get_error_data();
	$data              = is_array( $data ) ? $data : array();
	$error->add_data( array_merge( $data, array( 'rolled_back' => true, 'rollback_verified' => $rollback_verified ) ) );
	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'] ) );
		}
		$snapshot = wpagent_seo_settings_snapshot( $plugin );
		try {
			$result = wpagent_write_seo_settings( $plugin, $patch );
		} catch ( Throwable ) {
			$result = new WP_Error( 'wpagent_seo_settings_provider_exception', __( 'Der SEO-Provider hat beim Speichern einen Fehler ausgelöst.', 'wp-agent-companion' ), array( 'status' => 502 ) );
		}
		if ( is_wp_error( $result ) ) {
			return wpagent_seo_settings_error_after_rollback( $result, $plugin, $snapshot );
		}
		$after = wpagent_read_seo_settings( $plugin );
		if ( is_wp_error( $after ) ) {
			return wpagent_seo_settings_error_after_rollback( $after, $plugin, $snapshot );
		}
		$written  = wpagent_seo_settings_verification( $patch, $before, $after );
		$verified = ! in_array( false, array_column( $written, 'persisted' ), true );
		if ( ! $verified ) {
			$rollback_verified = wpagent_restore_seo_settings_snapshot( $plugin, $snapshot );
			return new WP_Error(
				'wpagent_seo_settings_write_unverified',
				$rollback_verified ? __( 'Der SEO-Provider hat die Änderung nicht exakt bestätigt. Der vorherige Zustand wurde verifiziert wiederhergestellt.', 'wp-agent-companion' ) : __( 'Der SEO-Provider hat die Änderung nicht bestätigt und das Rollback konnte nicht verifiziert werden. Prüfe die globalen SEO-Einstellungen sofort manuell.', 'wp-agent-companion' ),
				array( 'status' => $rollback_verified ? 502 : 500, 'written' => $written, 'rolled_back' => true, 'rollback_verified' => $rollback_verified )
			);
		}
		return array(
			'plugin'            => $plugin,
			'written'           => $written,
			'verified'          => true,
			'rolled_back'       => false,
			'rollback_verified' => null,
			'previous_hash'     => $before['state_hash'],
			'state_hash'        => $after['state_hash'],
		);
	} finally {
		wpagent_seo_settings_release_lock( $lock );
	}
}
