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

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

function wpagent_ability_set_term_seo_meta(): array {
	$properties = array(
		'term_id' => array( 'type' => 'integer', 'minimum' => 1 ),
		'taxonomy' => array( 'type' => 'string', 'pattern' => '^[a-z0-9_-]+$' ),
		'expected_hash' => array( 'type' => 'string', 'pattern' => '^[a-f0-9]{64}$' ),
		'seo_title' => wpagent_seo_text_input_schema( 'title' ),
		'seo_description' => wpagent_seo_text_input_schema( 'description' ),
		'focus_keyword' => wpagent_seo_text_input_schema( 'focus_keyword' ),
		'canonical_url' => wpagent_seo_text_input_schema( 'canonical_url' ),
		'robots_noindex' => array( 'type' => 'boolean' ),
		'robots_nofollow' => array( 'type' => 'boolean' ),
		'open_graph_title' => wpagent_seo_text_input_schema( 'open_graph_title' ),
		'open_graph_description' => wpagent_seo_text_input_schema( 'open_graph_description' ),
		'twitter_title' => wpagent_seo_text_input_schema( 'twitter_title' ),
		'twitter_description' => wpagent_seo_text_input_schema( 'twitter_description' ),
	);
	return array(
		'label' => __( 'Term-SEO setzen und verifizieren', 'wp-agent-companion' ),
		'description' => __( 'Prüft den vollständigen Term-SEO-Zustand. Das öffentliche Schreiben bleibt ohne provider-atomaren Vergleich-und-Schreib-Vorgang manuell, damit parallele Term- oder Optionsänderungen nicht überschrieben werden.', 'wp-agent-companion' ),
		'category' => 'wp-agent',
		'input_schema' => array(
			'type' => 'object', 'properties' => $properties,
			'required' => array( 'term_id', 'taxonomy', 'expected_hash' ),
			'additionalProperties' => false,
		),
		'output_schema' => array(
			'type' => 'object',
			'properties' => array(
				'term_id' => array( 'type' => 'integer' ),
				'taxonomy' => array( 'type' => 'string' ),
				'plugin' => array( 'type' => 'string' ),
				// The public field list is finite. Keep its verification report typed
				// even though existing-resource writes currently fail manual-only.
				'written' => array(
					'type' => 'object',
					'properties' => array(
						'title' => array( 'type' => 'boolean' ),
						'description' => array( 'type' => 'boolean' ),
						'focus_keyword' => array( 'type' => 'boolean' ),
						'canonical_url' => array( 'type' => 'boolean' ),
						'robots_noindex' => array( 'type' => 'boolean' ),
						'robots_nofollow' => array( 'type' => 'boolean' ),
						'open_graph_title' => array( 'type' => 'boolean' ),
						'open_graph_description' => array( 'type' => 'boolean' ),
						'twitter_title' => array( 'type' => 'boolean' ),
						'twitter_description' => array( 'type' => 'boolean' ),
					),
					'additionalProperties' => false,
				),
				'verified' => array( 'type' => 'boolean' ),
				'indexable_verified' => array( 'type' => array( 'boolean', 'null' ) ),
				'rolled_back' => array( 'type' => 'boolean' ),
				'rollback_verified' => array( 'type' => array( 'boolean', 'null' ) ),
				'state_hash' => array( 'type' => 'string', 'pattern' => '^[a-f0-9]{64}$' ),
			),
			'required' => array( 'term_id', 'taxonomy', 'plugin', 'written', 'verified', 'indexable_verified', 'rolled_back', 'rollback_verified', 'state_hash' ),
			'additionalProperties' => false,
		),
		'execute_callback' => 'wpagent_exec_set_term_seo_meta',
		'permission_callback' => 'wpagent_perm_edit_posts',
		'meta' => array(
			'show_in_rest' => true,
			'annotations' => array( 'readonly' => false, 'destructive' => false, 'idempotent' => false, 'manual_only' => true ),
		),
	);
}

function wpagent_term_seo_manual_write_required( int $term_id, string $taxonomy, string $plugin, string $current_hash ): WP_Error {
	return new WP_Error(
		'wpagent_term_seo_manual_write_required',
		__( 'Term-SEO bleibt ohne einen nachweisbar atomaren Provider-Vergleich-und-Schreib-Vorgang manuell. WPAgently hat keine Providerdaten geändert.', 'wp-agent-companion' ),
		array(
			'status'       => 409,
			'term_id'      => $term_id,
			'taxonomy'     => $taxonomy,
			'plugin'       => $plugin,
			'current_hash' => $current_hash,
			'manual_only'  => true,
		)
	);
}

/** @param mixed $input */
function wpagent_exec_set_term_seo_meta( $input ) {
	$input         = is_array( $input ) ? $input : array();
	$term_id       = (int) ( $input['term_id'] ?? 0 );
	$taxonomy      = sanitize_key( (string) ( $input['taxonomy'] ?? '' ) );
	$expected_hash = strtolower( (string) ( $input['expected_hash'] ?? '' ) );
	if ( ! preg_match( '/^[a-f0-9]{64}$/D', $expected_hash ) ) {
		return new WP_Error( 'wpagent_invalid_expected_hash', __( 'expected_hash muss ein SHA-256-Hash mit 64 Kleinbuchstaben und Ziffern sein.', 'wp-agent-companion' ), array( 'status' => 400 ) );
	}
	$target = wpagent_term_seo_target( $term_id, $taxonomy );
	if ( is_wp_error( $target ) ) {
		return $target;
	}
	$plugin    = wpagent_detect_seo_plugin();
	$supported = wpagent_term_seo_provider_supported( $plugin );
	if ( is_wp_error( $supported ) ) {
		return $supported;
	}
	$fields = wpagent_seo_fields_from_input( $input );
	if ( is_wp_error( $fields ) ) {
		return $fields;
	}
	if ( ! wpagent_seo_fields_have_value( $fields ) ) {
		return new WP_Error( 'wpagent_no_fields', __( 'Kein SEO-Feld übergeben.', 'wp-agent-companion' ), array( 'status' => 400 ) );
	}

	$before = wpagent_capture_term_seo_state( $term_id, $taxonomy, $plugin );
	if ( is_wp_error( $before ) ) {
		return $before;
	}
	$before_hash = wpagent_term_seo_state_hash( $term_id, $taxonomy, $plugin, $before );
	if ( ! hash_equals( $before_hash, $expected_hash ) ) {
		return new WP_Error( 'wpagent_term_seo_conflict', __( 'Die SEO-Daten des Terms wurden seit dem Lesen verändert. Bitte erneut lesen.', 'wp-agent-companion' ), array( 'status' => 409, 'current_hash' => $before_hash ) );
	}

	return wpagent_term_seo_manual_write_required( $term_id, $taxonomy, $plugin, $before_hash );
}
