<?php
/** Verified Rank Math redirection create, update and delete abilities. */

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

/** @return array<string,mixed> */
function wpagent_rank_math_redirection_write_properties(): array {
	return array(
		'source'      => array( 'type' => 'string', 'minLength' => 2, 'maxLength' => 2048, 'pattern' => '^/[^/]' ),
		'destination' => array( 'type' => 'string', 'maxLength' => 4096 ),
		'http_code'   => array( 'type' => 'integer', 'enum' => array( 301, 302, 307, 410, 451 ), 'default' => 301 ),
		'status'      => array( 'type' => 'string', 'enum' => array( 'active', 'inactive' ), 'default' => 'active' ),
		'ignore_case' => array( 'type' => 'boolean', 'default' => false ),
	);
}

/** @return array<string,mixed> */
function wpagent_rank_math_redirection_write_result_schema( bool $include_created = false ): array {
	$properties = array(
		'redirection' => wpagent_rank_math_redirection_schema(),
		'verified'    => array( 'type' => 'boolean' ),
	);
	$required = array( 'redirection', 'verified' );
	if ( $include_created ) {
		$properties['created'] = array( 'type' => 'boolean' );
		$required[]            = 'created';
	}
	return array( 'type' => 'object', 'properties' => $properties, 'required' => $required, 'additionalProperties' => false );
}

function wpagent_ability_create_seo_redirection(): array {
	$properties                             = wpagent_rank_math_redirection_write_properties();
	$properties['expected_collection_hash'] = array( 'type' => 'string', 'pattern' => '^[a-f0-9]{64}$' );
	return array(
		'label'               => __( 'SEO-Weiterleitung erstellen', 'wp-agent-companion' ),
		'description'         => __( 'Erstellt eine sichere exakte Rank-Math-Weiterleitung mit Sammlungskonfliktschutz, Kollisions- und Schleifenprüfung sowie verifiziertem Read-back.', 'wp-agent-companion' ),
		'category'            => 'wp-agent',
		'input_schema'        => array(
			'type'                 => 'object',
			'properties'           => $properties,
			'required'             => array( 'source', 'destination', 'http_code', 'expected_collection_hash' ),
			'additionalProperties' => false,
		),
		'output_schema'       => wpagent_rank_math_redirection_write_result_schema( true ),
		'execute_callback'    => 'wpagent_exec_create_seo_redirection',
		'permission_callback' => 'wpagent_perm_rank_math_redirections',
		'meta'                => array( 'show_in_rest' => true, 'annotations' => array( 'readonly' => false, 'destructive' => true, 'idempotent' => true ) ),
	);
}

function wpagent_ability_update_seo_redirection(): array {
	$properties                        = wpagent_rank_math_redirection_write_properties();
	$properties['redirection_id']       = array( 'type' => 'integer', 'minimum' => 1 );
	$properties['expected_state_hash'] = array( 'type' => 'string', 'pattern' => '^[a-f0-9]{64}$' );
	return array(
		'label'               => __( 'SEO-Weiterleitung aktualisieren', 'wp-agent-companion' ),
		'description'         => __( 'Aktualisiert eine einfache exakte Rank-Math-Weiterleitung konfliktgeschützt. Nicht exakt bestätigte Änderungen werden verifiziert zurückgerollt.', 'wp-agent-companion' ),
		'category'            => 'wp-agent',
		'input_schema'        => array(
			'type'                 => 'object',
			'properties'           => $properties,
			'required'             => array( 'redirection_id', 'expected_state_hash' ),
			'additionalProperties' => false,
		),
		'output_schema'       => wpagent_rank_math_redirection_write_result_schema(),
		'execute_callback'    => 'wpagent_exec_update_seo_redirection',
		'permission_callback' => 'wpagent_perm_rank_math_redirections',
		'meta'                => array( 'show_in_rest' => true, 'annotations' => array( 'readonly' => false, 'destructive' => true, 'idempotent' => true ) ),
	);
}

function wpagent_ability_delete_seo_redirection(): array {
	return array(
		'label'               => __( 'SEO-Weiterleitung löschen', 'wp-agent-companion' ),
		'description'         => __( 'Verschiebt eine Rank-Math-Weiterleitung nur mit Bestätigung und aktuellem Konflikt-Hash in den Papierkorb und verifiziert das Ergebnis.', 'wp-agent-companion' ),
		'category'            => 'wp-agent',
		'input_schema'        => array(
			'type'                 => 'object',
			'properties'           => array(
				'redirection_id'     => array( 'type' => 'integer', 'minimum' => 1 ),
				'expected_state_hash' => array( 'type' => 'string', 'pattern' => '^[a-f0-9]{64}$' ),
				'confirm'             => array( 'type' => 'boolean' ),
			),
			'required'             => array( 'redirection_id', 'expected_state_hash', 'confirm' ),
			'additionalProperties' => false,
		),
		'output_schema'       => array(
			'type'                 => 'object',
			'properties'           => array(
				'redirection_id' => array( 'type' => 'integer', 'minimum' => 1 ),
				'deleted'        => array( 'type' => 'boolean' ),
				'verified'       => array( 'type' => 'boolean' ),
			),
			'required'             => array( 'redirection_id', 'deleted', 'verified' ),
			'additionalProperties' => false,
		),
		'execute_callback'    => 'wpagent_exec_delete_seo_redirection',
		'permission_callback' => 'wpagent_perm_rank_math_redirections',
		'meta'                => array( 'show_in_rest' => true, 'annotations' => array( 'readonly' => false, 'destructive' => true, 'idempotent' => false ) ),
	);
}

/** @return array<string,mixed> */
function wpagent_rank_math_redirection_provider_data( array $next, int $id = 0, ?array $previous_raw = null ): array {
	$data = is_array( $previous_raw ) ? $previous_raw : array();
	unset( $data['last_accessed'] );
	$data['id']          = $id;
	$data['sources']     = array( array( 'pattern' => ltrim( $next['source'], '/' ), 'comparison' => 'exact', 'ignore' => $next['ignore_case'] ? 'case' : '' ) );
	$data['url_to']      = $next['destination'];
	$data['header_code'] = $next['http_code'];
	$data['status']      = $next['status'];
	return $data;
}

/** @return array<string,mixed>|WP_Error */
function wpagent_rank_math_redirection_load_raw( int $redirection_id, bool $include_trashed = false ) {
	$raw = \RankMath\Redirections\DB::get_redirection_by_id( $redirection_id );
	if ( ! is_array( $raw ) || ( ! $include_trashed && 'trashed' === ( $raw['status'] ?? '' ) ) ) {
		return new WP_Error( 'wpagent_seo_redirection_not_found', __( 'SEO-Weiterleitung nicht gefunden.', 'wp-agent-companion' ), array( 'status' => 404 ) );
	}
	return $raw;
}

/** @return true|WP_Error */
function wpagent_rank_math_redirection_validate_expected_hash( $value, string $current, string $error_code, string $message ) {
	$expected = is_string( $value ) ? strtolower( $value ) : '';
	if ( ! preg_match( '/^[a-f0-9]{64}$/D', $expected ) ) {
		return new WP_Error( 'wpagent_seo_redirection_expected_hash', __( 'Der erwartete Konflikt-Hash muss aus 64 Kleinbuchstaben und Ziffern bestehen.', 'wp-agent-companion' ), array( 'status' => 400 ) );
	}
	return hash_equals( $current, $expected ) ? true : new WP_Error( $error_code, $message, array( 'status' => 409, 'current_hash' => $current ) );
}

/** @param mixed $input @return array<string,mixed>|WP_Error */
function wpagent_exec_create_seo_redirection( $input ) {
	$runtime = wpagent_rank_math_redirection_runtime();
	if ( is_wp_error( $runtime ) ) {
		return $runtime;
	}
	$input = is_array( $input ) ? $input : array();
	$lock  = wpagent_rank_math_redirection_acquire_lock();
	if ( is_wp_error( $lock ) ) {
		return $lock;
	}
	$created_id = 0;
	try {
		$all = wpagent_rank_math_redirection_all_payloads();
		if ( is_wp_error( $all ) ) {
			return $all;
		}
		$hash_check = wpagent_rank_math_redirection_validate_expected_hash(
			$input['expected_collection_hash'] ?? null,
			wpagent_rank_math_redirection_collection_hash( $all ),
			'wpagent_seo_redirection_collection_conflict',
			__( 'Die SEO-Weiterleitungen wurden seit dem Lesen verändert. Bitte erneut auflisten.', 'wp-agent-companion' )
		);
		if ( is_wp_error( $hash_check ) ) {
			return $hash_check;
		}
		$next = wpagent_rank_math_redirection_next( $input );
		if ( is_wp_error( $next ) ) {
			return $next;
		}
		$collision = wpagent_rank_math_redirection_source_collision( $next['source'], $next['ignore_case'], $all );
		if ( is_array( $collision ) ) {
			$candidate = wpagent_rank_math_redirection_candidate_payload( (int) $collision['redirection_id'], $next );
			if ( wpagent_rank_math_redirection_semantics_match( $collision, $candidate ) ) {
				return array( 'redirection' => $collision, 'created' => false, 'verified' => true );
			}
			return new WP_Error( 'wpagent_seo_redirection_source_conflict', __( 'Für source existiert bereits eine andere exakte Weiterleitung.', 'wp-agent-companion' ), array( 'status' => 409, 'redirection_id' => $collision['redirection_id'] ) );
		}
		$graph = wpagent_rank_math_redirection_validate_graph( wpagent_rank_math_redirection_candidate_payload( 0, $next ), $all );
		if ( is_wp_error( $graph ) ) {
			return $graph;
		}
		$item       = \RankMath\Redirections\Redirection::from( wpagent_rank_math_redirection_provider_data( $next ) );
		$created_id = absint( $item->save() );
		if ( $created_id < 1 ) {
			throw new RuntimeException( 'Rank Math redirection create failed.' );
		}
		$fresh     = wpagent_rank_math_redirection_record( $created_id );
		$candidate = wpagent_rank_math_redirection_candidate_payload( $created_id, $next );
		if ( is_wp_error( $fresh ) || ! wpagent_rank_math_redirection_semantics_match( $fresh, $candidate ) ) {
			return wpagent_rank_math_redirection_rollback_error( null, $created_id );
		}
		return array( 'redirection' => $fresh, 'created' => true, 'verified' => true );
	} catch ( Throwable ) {
		return wpagent_rank_math_redirection_rollback_error( null, $created_id );
	} finally {
		wpagent_rank_math_redirection_release_lock( $lock );
	}
}

/** @param mixed $input @return array<string,mixed>|WP_Error */
function wpagent_exec_update_seo_redirection( $input ) {
	$runtime = wpagent_rank_math_redirection_runtime();
	if ( is_wp_error( $runtime ) ) {
		return $runtime;
	}
	$input = is_array( $input ) ? $input : array();
	$id    = absint( $input['redirection_id'] ?? 0 );
	$lock  = wpagent_rank_math_redirection_acquire_lock();
	if ( is_wp_error( $lock ) ) {
		return $lock;
	}
	$previous_raw = null;
	$written      = false;
	try {
		$previous_raw = wpagent_rank_math_redirection_load_raw( $id );
		if ( is_wp_error( $previous_raw ) ) {
			return $previous_raw;
		}
		$previous = wpagent_rank_math_redirection_payload( $previous_raw, false );
		if ( is_wp_error( $previous ) ) {
			return $previous;
		}
		if ( ! $previous['writable'] ) {
			return new WP_Error( 'wpagent_seo_redirection_readonly', __( 'Komplexe Rank-Math-Regeln mit mehreren Quellen oder nicht exaktem Vergleich sind schreibgeschützt.', 'wp-agent-companion' ), array( 'status' => 409 ) );
		}
		$hash_check = wpagent_rank_math_redirection_validate_expected_hash(
			$input['expected_state_hash'] ?? null,
			$previous['state_hash'],
			'wpagent_seo_redirection_conflict',
			__( 'Die SEO-Weiterleitung wurde seit dem Lesen verändert. Bitte erneut lesen.', 'wp-agent-companion' )
		);
		if ( is_wp_error( $hash_check ) ) {
			return $hash_check;
		}
		$next = wpagent_rank_math_redirection_next( $input, $previous );
		if ( is_wp_error( $next ) ) {
			return $next;
		}
		$all = wpagent_rank_math_redirection_all_payloads();
		if ( is_wp_error( $all ) ) {
			return $all;
		}
		$collision = wpagent_rank_math_redirection_source_collision( $next['source'], $next['ignore_case'], $all, $id );
		if ( is_array( $collision ) ) {
			return new WP_Error( 'wpagent_seo_redirection_source_conflict', __( 'Für source existiert bereits eine andere exakte Weiterleitung.', 'wp-agent-companion' ), array( 'status' => 409, 'redirection_id' => $collision['redirection_id'] ) );
		}
		$candidate = wpagent_rank_math_redirection_candidate_payload( $id, $next );
		$graph     = wpagent_rank_math_redirection_validate_graph( $candidate, $all, $id );
		if ( is_wp_error( $graph ) ) {
			return $graph;
		}
		$item    = \RankMath\Redirections\Redirection::from( wpagent_rank_math_redirection_provider_data( $next, $id, $previous_raw ) );
		$result  = $item->save();
		$written = true;
		if ( $id !== absint( $result ) ) {
			throw new RuntimeException( 'Rank Math redirection update failed.' );
		}
		$fresh   = wpagent_rank_math_redirection_record( $id );
		if ( is_wp_error( $fresh ) || ! wpagent_rank_math_redirection_semantics_match( $fresh, $candidate ) ) {
			return wpagent_rank_math_redirection_rollback_error( $previous_raw );
		}
		return array( 'redirection' => $fresh, 'verified' => true );
	} catch ( Throwable ) {
		return $written && is_array( $previous_raw )
			? wpagent_rank_math_redirection_rollback_error( $previous_raw )
			: new WP_Error( 'wpagent_seo_redirection_write_failed', __( 'Rank Math konnte die Weiterleitung nicht sicher aktualisieren.', 'wp-agent-companion' ), array( 'status' => 500 ) );
	} finally {
		wpagent_rank_math_redirection_release_lock( $lock );
	}
}

/** @param mixed $input @return array<string,mixed>|WP_Error */
function wpagent_exec_delete_seo_redirection( $input ) {
	$runtime = wpagent_rank_math_redirection_runtime();
	if ( is_wp_error( $runtime ) ) {
		return $runtime;
	}
	$input = is_array( $input ) ? $input : array();
	if ( true !== ( $input['confirm'] ?? false ) ) {
		return new WP_Error( 'wpagent_seo_redirection_confirmation', __( 'Zum Löschen muss confirm ausdrücklich true sein.', 'wp-agent-companion' ), array( 'status' => 400 ) );
	}
	$id   = absint( $input['redirection_id'] ?? 0 );
	$lock = wpagent_rank_math_redirection_acquire_lock();
	if ( is_wp_error( $lock ) ) {
		return $lock;
	}
	$previous_raw = null;
	$written      = false;
	try {
		$previous_raw = wpagent_rank_math_redirection_load_raw( $id );
		if ( is_wp_error( $previous_raw ) ) {
			return $previous_raw;
		}
		$previous = wpagent_rank_math_redirection_payload( $previous_raw, false );
		if ( is_wp_error( $previous ) ) {
			return $previous;
		}
		$hash_check = wpagent_rank_math_redirection_validate_expected_hash(
			$input['expected_state_hash'] ?? null,
			$previous['state_hash'],
			'wpagent_seo_redirection_conflict',
			__( 'Die SEO-Weiterleitung wurde seit dem Lesen verändert. Bitte erneut lesen.', 'wp-agent-companion' )
		);
		if ( is_wp_error( $hash_check ) ) {
			return $hash_check;
		}
		$written = 1 === \RankMath\Redirections\DB::change_status( array( $id ), 'trashed' );
		if ( ! $written ) {
			throw new RuntimeException( 'Rank Math redirection trash failed.' );
		}
		$fresh = wpagent_rank_math_redirection_load_raw( $id, true );
		if ( is_wp_error( $fresh ) || 'trashed' !== ( $fresh['status'] ?? '' ) ) {
			return wpagent_rank_math_redirection_rollback_error( $previous_raw );
		}
		return array( 'redirection_id' => $id, 'deleted' => true, 'verified' => true );
	} catch ( Throwable ) {
		return $written && is_array( $previous_raw )
			? wpagent_rank_math_redirection_rollback_error( $previous_raw )
			: new WP_Error( 'wpagent_seo_redirection_delete_failed', __( 'Rank Math konnte die Weiterleitung nicht sicher löschen.', 'wp-agent-companion' ), array( 'status' => 500 ) );
	} finally {
		wpagent_rank_math_redirection_release_lock( $lock );
	}
}
