<?php
/** Native, secret-safe Weglot settings management. */

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

define( 'WPAGENT_WEGLOT_LOCK_OPTION', 'wp_agent_weglot_settings_lock' );
// Covers provider write, forced read-back, rollback write and rollback read-back.
define( 'WPAGENT_WEGLOT_LOCK_TTL', 300 );
define( 'WPAGENT_WEGLOT_MAX_LANGUAGES', 30 );
define( 'WPAGENT_WEGLOT_MAX_EXCLUSIONS', 50 );
function wpagent_weglot_flag_types(): array {
	return array( 'rectangle_mat', 'shiny', 'square', 'circle' );
}
function wpagent_weglot_exclusion_types(): array {
	return array( 'START_WITH', 'NOT_START_WITH', 'END_WITH', 'NOT_END_WITH', 'CONTAIN', 'NOT_CONTAIN', 'IS_EXACTLY', 'NOT_IS_EXACTLY' );
}
function wpagent_weglot_readable_exclusion_types(): array {
	return array_merge( wpagent_weglot_exclusion_types(), array( 'MATCH_REGEX' ) );
}
function wpagent_weglot_destination_schema(): array {
	return array(
		'type'                 => 'object',
		'properties'           => array(
			'code'              => array( 'type' => 'string', 'minLength' => 2, 'maxLength' => 32, 'pattern' => '^[A-Za-z]{2,3}(?:-[A-Za-z0-9]{2,8})?$' ),
			'public'            => array( 'type' => 'boolean' ),
			'custom_code'       => array( 'type' => 'string', 'maxLength' => 32, 'default' => '' ),
			'custom_name'       => array( 'type' => 'string', 'maxLength' => 100, 'default' => '' ),
			'custom_local_name' => array( 'type' => 'string', 'maxLength' => 100, 'default' => '' ),
		),
		'required'             => array( 'code', 'public' ),
		'additionalProperties' => false,
	);
}
function wpagent_weglot_switcher_schema(): array {
	return array(
		'type'                 => 'object',
		'properties'           => array(
			'is_dropdown' => array( 'type' => 'boolean' ),
			'full_name'   => array( 'type' => 'boolean' ),
			'with_name'   => array( 'type' => 'boolean' ),
			'with_flags'  => array( 'type' => 'boolean' ),
			'flag_type'   => array( 'type' => 'string', 'enum' => wpagent_weglot_flag_types() ),
		),
		'additionalProperties' => false,
	);
}
function wpagent_weglot_excluded_url_schema( bool $writable = false ): array {
	return array(
		'type'                 => 'object',
		'properties'           => array(
			'type'               => array( 'type' => 'string', 'enum' => $writable ? wpagent_weglot_exclusion_types() : wpagent_weglot_readable_exclusion_types() ),
			'value'              => array( 'type' => 'string', 'minLength' => 1, 'maxLength' => 300 ),
			'excluded_languages' => array(
				'type' => 'array', 'maxItems' => WPAGENT_WEGLOT_MAX_LANGUAGES, 'uniqueItems' => true,
				'items' => array( 'type' => 'string', 'minLength' => 2, 'maxLength' => 32, 'pattern' => '^[A-Za-z]{2,3}(?:-[A-Za-z0-9]{2,8})?$' ),
			),
		),
		'required'             => array( 'type', 'value', 'excluded_languages' ),
		'additionalProperties' => false,
	);
}
function wpagent_weglot_settings_schema(): array {
	return array(
		'type'                 => 'object',
		'properties'           => array(
			'original_language'    => array( 'type' => 'string', 'maxLength' => 32 ),
			'destination_languages' => array( 'type' => 'array', 'maxItems' => WPAGENT_WEGLOT_MAX_LANGUAGES, 'items' => wpagent_weglot_destination_schema() ),
			'auto_redirect'        => array( 'type' => 'boolean' ),
			'switcher'             => wpagent_weglot_switcher_schema(),
			'excluded_urls'        => array( 'type' => 'array', 'maxItems' => WPAGENT_WEGLOT_MAX_EXCLUSIONS, 'items' => wpagent_weglot_excluded_url_schema() ),
			'excluded_blocks'      => array( 'type' => 'array', 'maxItems' => WPAGENT_WEGLOT_MAX_EXCLUSIONS, 'uniqueItems' => true, 'items' => array( 'type' => 'string', 'minLength' => 1, 'maxLength' => 160 ) ),
		),
		'required'             => array( 'original_language', 'destination_languages', 'auto_redirect', 'switcher', 'excluded_urls', 'excluded_blocks' ),
		'additionalProperties' => false,
	);
}
function wpagent_ability_get_weglot_settings(): array {
	return array(
		'label'               => __( 'Weglot-Einstellungen lesen', 'wp-agent-companion' ),
		'description'         => __( 'Liest Sprachen, Umschalter und Übersetzungsausschlüsse aus Weglot, ohne API-Schlüssel oder fremde Rohdaten offenzulegen.', 'wp-agent-companion' ),
		'category'            => 'wp-agent',
		'input_schema'        => array( 'type' => 'object', 'properties' => array(), 'additionalProperties' => false, 'default' => array() ),
		'output_schema'       => array(
			'type'                 => 'object',
			'properties'           => array(
				'active'     => array( 'type' => 'boolean' ),
				'version'    => array( 'type' => 'string' ),
				'configured' => array( 'type' => 'boolean' ),
				'settings'   => array( 'type' => array( 'object', 'null' ), 'properties' => wpagent_weglot_settings_schema()['properties'], 'required' => wpagent_weglot_settings_schema()['required'], 'additionalProperties' => false ),
				'state_hash' => array( 'type' => array( 'string', 'null' ), 'pattern' => '^[a-f0-9]{64}$' ),
			),
			'required'             => array( 'active', 'version', 'configured', 'settings', 'state_hash' ),
			'additionalProperties' => false,
		),
		'execute_callback'    => 'wpagent_exec_get_weglot_settings',
		'permission_callback' => 'wpagent_perm_manage_options',
		'meta'                => array(
			'show_in_rest' => true,
			'annotations'  => array( 'readonly' => true, 'destructive' => false, 'idempotent' => true ),
			'mcp'          => array(
				'uri'         => 'wpagently://integrations/weglot',
				'annotations' => array( 'audience' => array( 'assistant' ) ),
			),
		),
	);
}

function wpagent_ability_update_weglot_settings(): array {
	$properties = array(
		'expected_hash'        => array( 'type' => 'string', 'pattern' => '^[a-f0-9]{64}$' ),
		'original_language'    => array( 'type' => 'string', 'minLength' => 2, 'maxLength' => 32, 'pattern' => '^[A-Za-z]{2,3}(?:-[A-Za-z0-9]{2,8})?$' ),
		'destination_languages' => array( 'type' => 'array', 'minItems' => 1, 'maxItems' => WPAGENT_WEGLOT_MAX_LANGUAGES, 'items' => wpagent_weglot_destination_schema() ),
		'auto_redirect'        => array( 'type' => 'boolean' ),
		'switcher'             => wpagent_weglot_switcher_schema(),
		'excluded_urls'        => array( 'type' => 'array', 'maxItems' => WPAGENT_WEGLOT_MAX_EXCLUSIONS, 'items' => wpagent_weglot_excluded_url_schema( true ) ),
		'excluded_blocks'      => array( 'type' => 'array', 'maxItems' => WPAGENT_WEGLOT_MAX_EXCLUSIONS, 'uniqueItems' => true, 'items' => array( 'type' => 'string', 'minLength' => 1, 'maxLength' => 160 ) ),
	);
	return array(
		'label'               => __( 'Weglot-Einstellungen: manuelle Änderung erforderlich', 'wp-agent-companion' ),
		'description'         => __( 'Weglot stellt keine versionsgebundene bedingte Speicherung bereit. Diese registrierte Schreib-Ability lehnt Änderungen deshalb ab, damit Dashboard- oder API-Änderungen nicht überschrieben werden. Ändere Weglot manuell und lies die Einstellungen anschließend neu.', 'wp-agent-companion' ),
		'category'            => 'wp-agent',
		'input_schema'        => array( 'type' => 'object', 'properties' => $properties, 'required' => array( 'expected_hash' ), 'additionalProperties' => false ),
		'output_schema'       => array(
			'type'                 => 'object',
			'properties'           => array(
				'settings'      => wpagent_weglot_settings_schema(),
				'previous_hash' => array( 'type' => 'string', 'pattern' => '^[a-f0-9]{64}$' ),
				'state_hash'    => array( 'type' => 'string', 'pattern' => '^[a-f0-9]{64}$' ),
				'verified'      => array( 'type' => 'boolean' ),
			),
			'required'             => array( 'settings', 'previous_hash', 'state_hash', 'verified' ),
			'additionalProperties' => false,
		),
		'execute_callback'    => 'wpagent_exec_update_weglot_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 object|WP_Error */
function wpagent_weglot_service() {
	if ( ! function_exists( 'weglot_get_service' ) ) {
		return new WP_Error( 'wpagent_weglot_inactive', __( 'Weglot ist nicht aktiv. Installiere und aktiviere Weglot zuerst.', 'wp-agent-companion' ), array( 'status' => 409 ) );
	}
	try {
		$service = weglot_get_service( 'WeglotWP\\Services\\Option_Service_Weglot' );
	} catch ( Throwable $error ) {
		return new WP_Error( 'wpagent_weglot_unavailable', __( 'Der Weglot-Einstellungsdienst ist nicht verfügbar.', 'wp-agent-companion' ), array( 'status' => 503 ) );
	}
	if ( ! is_object( $service ) || ! method_exists( $service, 'get_options' ) || ! method_exists( $service, 'get_api_key_private' ) || ! method_exists( $service, 'save_options_to_weglot' ) ) {
		return new WP_Error( 'wpagent_weglot_incompatible', __( 'Die aktive Weglot-Version stellt die benötigte Einstellungs-API nicht bereit.', 'wp-agent-companion' ), array( 'status' => 409 ) );
	}
	return $service;
}

/** @return string|WP_Error */
function wpagent_weglot_private_key( $service ) {
	try {
		$key = $service->get_api_key_private();
	} catch ( Throwable $error ) {
		return new WP_Error( 'wpagent_weglot_key_read_failed', __( 'Der Weglot-Verbindungsstatus konnte nicht gelesen werden.', 'wp-agent-companion' ), array( 'status' => 502 ) );
	}
	return is_string( $key ) ? trim( $key ) : '';
}

/** @return array<string,mixed>|WP_Error */
function wpagent_weglot_read_options( $service, bool $fresh = false ) {
	try {
		if ( $fresh ) {
			if ( ! method_exists( $service, 'get_options_from_api_with_api_key' ) ) {
				return new WP_Error( 'wpagent_weglot_readback_unsupported', __( 'Die aktive Weglot-Version unterstützt keinen erzwungenen Remote-Readback.', 'wp-agent-companion' ), array( 'status' => 409 ) );
			}
			$key = wpagent_weglot_private_key( $service );
			if ( is_wp_error( $key ) ) {
				return $key;
			}
			if ( '' === $key ) {
				return new WP_Error( 'wpagent_weglot_not_configured', __( 'Weglot ist noch nicht mit einem Projekt verbunden.', 'wp-agent-companion' ), array( 'status' => 409 ) );
			}
			$response = $service->get_options_from_api_with_api_key( $key, ! str_starts_with( $key, 'wg_' ), true );
			if ( ! is_array( $response ) || empty( $response['success'] ) || ! is_array( $response['result'] ?? null ) ) {
				return new WP_Error( 'wpagent_weglot_readback_failed', __( 'Weglot hat keinen verifizierbaren Einstellungsstand zurückgegeben.', 'wp-agent-companion' ), array( 'status' => 502 ) );
			}
			$result = $response['result'];
			$has_original = is_string( $result['language_from'] ?? null ) || is_string( $result['original_language'] ?? null );
			$has_destinations = is_array( $result['languages'] ?? null ) || is_array( $result['destination_language'] ?? null );
			if ( ! $has_original || ! $has_destinations || ! empty( $result['error'] ) || ( isset( $result['status'] ) && (int) $result['status'] >= 400 ) ) {
				return new WP_Error( 'wpagent_weglot_readback_failed', __( 'Weglot hat keinen verifizierbaren Projektzustand zurückgegeben.', 'wp-agent-companion' ), array( 'status' => 502 ) );
			}
			return $result;
		}
		$options = $service->get_options();
	} catch ( Throwable $error ) {
		return new WP_Error( 'wpagent_weglot_read_failed', __( 'Die Weglot-Einstellungen konnten nicht gelesen werden.', 'wp-agent-companion' ), array( 'status' => 502 ) );
	}
	return is_array( $options )
		? $options
		: new WP_Error( 'wpagent_weglot_invalid_response', __( 'Weglot hat einen ungültigen Einstellungsstand geliefert.', 'wp-agent-companion' ), array( 'status' => 502 ) );
}

function wpagent_weglot_bool( $value ): bool {
	return in_array( $value, array( true, 1, '1', 'true', 'on', 'yes' ), true );
}

/** @return bool|WP_Error */
function wpagent_weglot_provider_bool( $value, string $field ) {
	if ( in_array( $value, array( true, 1, '1', 'true', 'on', 'yes' ), true ) ) {
		return true;
	}
	if ( in_array( $value, array( false, 0, '0', 'false', 'off', 'no' ), true ) ) {
		return false;
	}
	/* translators: %s: Weglot setting field name. */
	return new WP_Error( 'wpagent_weglot_provider_state_invalid', sprintf( __( 'Weglot enthält einen ungültigen Wert für %s.', 'wp-agent-companion' ), $field ), array( 'status' => 502 ) );
}

/** @return string|WP_Error */
function wpagent_weglot_language_code( $value, string $field ) {
	$code = is_string( $value ) ? strtolower( trim( $value ) ) : '';
	if ( ! preg_match( '/^[a-z]{2,3}(?:-[a-z0-9]{2,8})?$/', $code ) ) {
		/* translators: %s: Weglot language setting field name. */
		return new WP_Error( 'wpagent_weglot_invalid_language', sprintf( __( '%s enthält keinen gültigen Weglot-Sprachcode.', 'wp-agent-companion' ), $field ), array( 'status' => 400 ) );
	}
	return $code;
}

/** @return string|WP_Error */
function wpagent_weglot_text( $value, string $field, int $limit ) {
	if ( null === $value ) {
		return '';
	}
	if ( ! is_string( $value ) || wp_check_invalid_utf8( $value ) !== $value ) {
		/* translators: %s: Weglot text setting field name. */
		return new WP_Error( 'wpagent_weglot_invalid_text', sprintf( __( '%s enthält ungültigen oder zu langen Text.', 'wp-agent-companion' ), $field ), array( 'status' => 400 ) );
	}
	$text = trim( $value );
	$length = function_exists( 'mb_strlen' ) ? mb_strlen( $text ) : strlen( $text );
	if ( preg_match( '/[\x00-\x1F\x7F]/u', $text ) || wp_strip_all_tags( $text ) !== $text || $length > $limit ) {
		/* translators: %s: Weglot text setting field name. */
		return new WP_Error( 'wpagent_weglot_invalid_text', sprintf( __( '%s enthält ungültigen oder zu langen Text.', 'wp-agent-companion' ), $field ), array( 'status' => 400 ) );
	}
	return $text;
}

/** @return array<string,mixed>|WP_Error */
function wpagent_weglot_project_settings( array $raw ) {
	$original = $raw['language_from'] ?? $raw['original_language'] ?? '';
	if ( '' !== $original ) {
		$original = wpagent_weglot_language_code( $original, 'original_language' );
		if ( is_wp_error( $original ) ) {
			return new WP_Error( 'wpagent_weglot_provider_state_invalid', __( 'Weglot enthält eine ungültige Originalsprache.', 'wp-agent-companion' ), array( 'status' => 502 ) );
		}
	}

	$raw_languages = $raw['languages'] ?? $raw['destination_language'] ?? array();
	if ( ! is_array( $raw_languages ) ) {
		return new WP_Error( 'wpagent_weglot_provider_state_invalid', __( 'Weglot enthält eine ungültige Zielsprachenliste.', 'wp-agent-companion' ), array( 'status' => 502 ) );
	}
	$destinations = array();
	foreach ( array_slice( $raw_languages, 0, WPAGENT_WEGLOT_MAX_LANGUAGES + 1 ) as $item ) {
		$item = is_string( $item ) ? array( 'language_to' => $item ) : $item;
		if ( ! is_array( $item ) ) {
			return new WP_Error( 'wpagent_weglot_provider_state_invalid', __( 'Weglot enthält einen ungültigen Zielspracheneintrag.', 'wp-agent-companion' ), array( 'status' => 502 ) );
		}
		$code = wpagent_weglot_language_code( $item['language_to'] ?? $item['code'] ?? '', 'destination_languages.code' );
		if ( is_wp_error( $code ) ) {
			return new WP_Error( 'wpagent_weglot_provider_state_invalid', __( 'Weglot enthält einen ungültigen Zielsprachencode.', 'wp-agent-companion' ), array( 'status' => 502 ) );
		}
		$custom_code = wpagent_weglot_text( $item['custom_code'] ?? '', 'destination_languages.custom_code', 32 );
		$custom_name = wpagent_weglot_text( $item['custom_name'] ?? '', 'destination_languages.custom_name', 100 );
		$custom_local_name = wpagent_weglot_text( $item['custom_local_name'] ?? '', 'destination_languages.custom_local_name', 100 );
			if ( is_wp_error( $custom_code ) || is_wp_error( $custom_name ) || is_wp_error( $custom_local_name ) ) {
				return new WP_Error( 'wpagent_weglot_provider_state_invalid', __( 'Weglot enthält ungültige benutzerdefinierte Sprachangaben.', 'wp-agent-companion' ), array( 'status' => 502 ) );
			}
			$public_value = array_key_exists( 'public', $item ) ? $item['public'] : ( array_key_exists( 'enabled', $item ) ? $item['enabled'] : true );
			$public = wpagent_weglot_provider_bool( $public_value, 'destination_languages.public' );
			if ( is_wp_error( $public ) ) {
				return $public;
			}
			$destinations[] = array(
				'code'              => $code,
				'public'            => $public,
			'custom_code'       => $custom_code,
			'custom_name'       => $custom_name,
			'custom_local_name' => $custom_local_name,
		);
	}
	if ( count( $destinations ) > WPAGENT_WEGLOT_MAX_LANGUAGES ) {
		return new WP_Error( 'wpagent_weglot_provider_state_too_large', __( 'Weglot enthält mehr Zielsprachen als sicher verarbeitet werden können.', 'wp-agent-companion' ), array( 'status' => 502 ) );
	}

	if ( array_key_exists( 'custom_settings', $raw ) && ! is_array( $raw['custom_settings'] ) ) {
		return new WP_Error( 'wpagent_weglot_provider_state_invalid', __( 'Weglot enthält ungültige benutzerdefinierte Einstellungen.', 'wp-agent-companion' ), array( 'status' => 502 ) );
	}
	$custom = $raw['custom_settings'] ?? array();
	if ( array_key_exists( 'button_style', $custom ) && ! is_array( $custom['button_style'] ) ) {
		return new WP_Error( 'wpagent_weglot_provider_state_invalid', __( 'Weglot enthält ungültige Umschaltereinstellungen.', 'wp-agent-companion' ), array( 'status' => 502 ) );
	}
	$button = $custom['button_style'] ?? array();
	$flag_type = $button['flag_type'] ?? 'rectangle_mat';
	if ( ! is_string( $flag_type ) || ! in_array( $flag_type, wpagent_weglot_flag_types(), true ) ) {
		return new WP_Error( 'wpagent_weglot_provider_state_invalid', __( 'Weglot enthält einen ungültigen Flaggentyp.', 'wp-agent-companion' ), array( 'status' => 502 ) );
	}
	$provider_booleans = array();
	foreach ( array(
		'auto_redirect' => array( 'auto_switch', 'auto_redirect', false ),
		'is_dropdown'   => array( 'is_dropdown', 'is_dropdown', true ),
		'full_name'     => array( 'full_name', 'is_fullname', true ),
		'with_name'     => array( 'with_name', 'with_name', true ),
		'with_flags'    => array( 'with_flags', 'with_flags', true ),
	) as $field => $source ) {
		$value = array_key_exists( $source[0], 'auto_redirect' === $field ? $raw : $button )
			? ( 'auto_redirect' === $field ? $raw[ $source[0] ] : $button[ $source[0] ] )
			: ( array_key_exists( $source[1], $raw ) ? $raw[ $source[1] ] : $source[2] );
		$provider_booleans[ $field ] = wpagent_weglot_provider_bool( $value, $field );
		if ( is_wp_error( $provider_booleans[ $field ] ) ) {
			return $provider_booleans[ $field ];
		}
	}

	$excluded_urls = array();
	$raw_urls = $raw['excluded_paths'] ?? $raw['exclude_urls'] ?? array();
	if ( ! is_array( $raw_urls ) ) {
		return new WP_Error( 'wpagent_weglot_provider_state_invalid', __( 'Weglot enthält eine ungültige URL-Ausschlussliste.', 'wp-agent-companion' ), array( 'status' => 502 ) );
	}
	if ( count( $raw_urls ) > WPAGENT_WEGLOT_MAX_EXCLUSIONS ) {
		return new WP_Error( 'wpagent_weglot_provider_state_too_large', __( 'Weglot enthält mehr URL-Ausschlüsse als sicher verarbeitet werden können.', 'wp-agent-companion' ), array( 'status' => 502 ) );
	}
	$destination_codes = array_column( $destinations, 'code' );
	foreach ( $raw_urls as $item ) {
		if ( ! is_array( $item ) || ! is_string( $item['value'] ?? null ) ) {
			return new WP_Error( 'wpagent_weglot_provider_state_invalid', __( 'Weglot enthält einen ungültigen URL-Ausschluss.', 'wp-agent-companion' ), array( 'status' => 502 ) );
		}
		$type = is_string( $item['type'] ?? null ) ? $item['type'] : 'CONTAIN';
		if ( ! in_array( $type, wpagent_weglot_readable_exclusion_types(), true ) ) {
			return new WP_Error( 'wpagent_weglot_provider_state_invalid', __( 'Weglot enthält einen nicht unterstützten URL-Ausschlusstyp.', 'wp-agent-companion' ), array( 'status' => 502 ) );
		}
		$value = trim( (string) $item['value'] );
		$length = function_exists( 'mb_strlen' ) ? mb_strlen( $value ) : strlen( $value );
		if ( wp_check_invalid_utf8( $value ) !== $value || '' === $value || $length > 300 || preg_match( '/[\x00-\x1F\x7F]/u', $value ) ) {
			return new WP_Error( 'wpagent_weglot_provider_state_invalid', __( 'Weglot enthält einen ungültigen URL-Ausschluss.', 'wp-agent-companion' ), array( 'status' => 502 ) );
		}
		if ( array_key_exists( 'excluded_languages', $item ) ) {
			if ( ! is_array( $item['excluded_languages'] ) ) {
				return new WP_Error( 'wpagent_weglot_provider_state_invalid', __( 'Weglot enthält einen URL-Ausschluss mit ungültiger Sprache.', 'wp-agent-companion' ), array( 'status' => 502 ) );
			}
			$languages = $item['excluded_languages'];
		} elseif ( array_key_exists( 'languages', $item ) ) {
			if ( ! is_array( $item['languages'] ) ) {
				return new WP_Error( 'wpagent_weglot_provider_state_invalid', __( 'Weglot enthält einen URL-Ausschluss mit ungültiger Sprache.', 'wp-agent-companion' ), array( 'status' => 502 ) );
			}
			$languages = $item['languages'];
			} else {
				$languages = array();
			}
			if ( count( $languages ) > WPAGENT_WEGLOT_MAX_LANGUAGES ) {
				return new WP_Error( 'wpagent_weglot_provider_state_too_large', __( 'Weglot enthält einen URL-Ausschluss mit zu vielen Sprachen.', 'wp-agent-companion' ), array( 'status' => 502 ) );
			}
		$normalized_languages = array();
		foreach ( $languages as $language ) {
			$code = wpagent_weglot_language_code( $language, 'excluded_languages' );
			if ( is_wp_error( $code ) || ! in_array( $code, $destination_codes, true ) ) {
				return new WP_Error( 'wpagent_weglot_provider_state_invalid', __( 'Weglot enthält einen URL-Ausschluss mit ungültiger Sprache.', 'wp-agent-companion' ), array( 'status' => 502 ) );
			}
			if ( ! in_array( $code, $normalized_languages, true ) ) {
				$normalized_languages[] = $code;
			}
		}
		$excluded_urls[] = array( 'type' => $type, 'value' => $value, 'excluded_languages' => $normalized_languages );
	}

	$excluded_blocks = array();
	$raw_blocks = $raw['excluded_blocks'] ?? array();
	if ( ! is_array( $raw_blocks ) ) {
		return new WP_Error( 'wpagent_weglot_provider_state_invalid', __( 'Weglot enthält eine ungültige Blockausschlussliste.', 'wp-agent-companion' ), array( 'status' => 502 ) );
	}
	if ( count( $raw_blocks ) > WPAGENT_WEGLOT_MAX_EXCLUSIONS ) {
		return new WP_Error( 'wpagent_weglot_provider_state_too_large', __( 'Weglot enthält mehr Blockausschlüsse als sicher verarbeitet werden können.', 'wp-agent-companion' ), array( 'status' => 502 ) );
	}
	foreach ( $raw_blocks as $item ) {
		$value = is_array( $item ) ? ( $item['value'] ?? '' ) : $item;
		if ( ! is_string( $value ) || '' === trim( $value ) ) {
			return new WP_Error( 'wpagent_weglot_provider_state_invalid', __( 'Weglot enthält einen ungültigen Blockausschluss.', 'wp-agent-companion' ), array( 'status' => 502 ) );
		}
		$value = trim( $value );
		$valid = wpagent_weglot_validate_selector( $value );
		if ( is_wp_error( $valid ) ) {
			return new WP_Error( 'wpagent_weglot_provider_state_invalid', __( 'Weglot enthält einen ungültigen Blockausschluss.', 'wp-agent-companion' ), array( 'status' => 502 ) );
		}
		$excluded_blocks[] = $value;
	}

	return array(
		'original_language'     => (string) $original,
		'destination_languages' => $destinations,
		'auto_redirect'         => $provider_booleans['auto_redirect'],
		'switcher'              => array(
			'is_dropdown' => $provider_booleans['is_dropdown'],
			'full_name'   => $provider_booleans['full_name'],
			'with_name'   => $provider_booleans['with_name'],
			'with_flags'  => $provider_booleans['with_flags'],
			'flag_type'   => $flag_type,
		),
		'excluded_urls'         => $excluded_urls,
		'excluded_blocks'       => array_values( array_unique( $excluded_blocks ) ),
	);
}

function wpagent_weglot_state_hash( array $settings ): string {
	return hash( 'sha256', (string) wp_json_encode( $settings, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE ) );
}

/** @return array<string,mixed>|WP_Error */
function wpagent_exec_get_weglot_settings( $input = array() ) {
	$service = wpagent_weglot_service();
	if ( is_wp_error( $service ) ) {
		if ( 'wpagent_weglot_inactive' === $service->get_error_code() ) {
			return array( 'active' => false, 'version' => '', 'configured' => false, 'settings' => null, 'state_hash' => null );
		}
		return $service;
	}
	$key = wpagent_weglot_private_key( $service );
	if ( is_wp_error( $key ) ) {
		return $key;
	}
	$raw = wpagent_weglot_read_options( $service );
	if ( is_wp_error( $raw ) ) {
		return $raw;
	}
	$settings = wpagent_weglot_project_settings( $raw );
	if ( is_wp_error( $settings ) ) {
		return $settings;
	}
	return array(
		'active'     => true,
		'version'    => defined( 'WEGLOT_VERSION' ) ? (string) WEGLOT_VERSION : '',
		'configured' => '' !== $key,
		'settings'   => $settings,
		'state_hash' => wpagent_weglot_state_hash( $settings ),
	);
}

function wpagent_weglot_invalid_selector_error(): WP_Error {
	return new WP_Error( 'wpagent_weglot_invalid_selector', __( 'Ein Weglot-Ausschluss enthält keinen sicheren CSS-Selektor.', 'wp-agent-companion' ), array( 'status' => 400 ) );
}

/** @return true|WP_Error */
function wpagent_weglot_validate_selector( string $selector ) {
	if ( wp_check_invalid_utf8( $selector ) !== $selector ) {
		return wpagent_weglot_invalid_selector_error();
	}
	$length = function_exists( 'mb_strlen' ) ? mb_strlen( $selector ) : strlen( $selector );
	if ( '' === $selector || $length > 160 || preg_match( '/[\x00-\x1F\x7F]/u', $selector ) ) {
		return wpagent_weglot_invalid_selector_error();
	}
	$bracket_depth = 0;
	$parenthesis_depth = 0;
	$quote = '';
	for ( $index = 0, $bytes = strlen( $selector ); $index < $bytes; $index++ ) {
		$character = $selector[ $index ];
		if ( '\\' === $character ) {
			if ( ++$index >= $bytes ) {
				return wpagent_weglot_invalid_selector_error();
			}
			continue;
		}
		if ( '' !== $quote ) {
			if ( $character === $quote ) {
				$quote = '';
			}
			continue;
		}
		if ( in_array( $character, array( '{', '}', ';', '@' ), true ) ) {
			return wpagent_weglot_invalid_selector_error();
		}
		if ( '"' === $character || "'" === $character ) {
			if ( 0 === $bracket_depth && 0 === $parenthesis_depth ) {
				return wpagent_weglot_invalid_selector_error();
			}
			$quote = $character;
		} elseif ( '[' === $character ) {
			if ( 1 === $bracket_depth ) {
				return wpagent_weglot_invalid_selector_error();
			}
			$bracket_depth = 1;
		} elseif ( ']' === $character ) {
			if ( 1 !== $bracket_depth ) {
				return wpagent_weglot_invalid_selector_error();
			}
			$bracket_depth = 0;
		} elseif ( '(' === $character ) {
			if ( 1 === $bracket_depth ) {
				return wpagent_weglot_invalid_selector_error();
			}
			$parenthesis_depth++;
		} elseif ( ')' === $character ) {
			if ( 1 === $bracket_depth || 0 === $parenthesis_depth ) {
				return wpagent_weglot_invalid_selector_error();
			}
			$parenthesis_depth--;
		}
	}
	if ( '' !== $quote || 0 !== $bracket_depth || 0 !== $parenthesis_depth ) {
		return wpagent_weglot_invalid_selector_error();
	}
	return true;
}

/** @return array<int,array<string,mixed>>|WP_Error */
function wpagent_weglot_validate_destinations( $value, string $original ) {
	if ( ! is_array( $value ) || ! $value || count( $value ) > WPAGENT_WEGLOT_MAX_LANGUAGES ) {
		return new WP_Error( 'wpagent_weglot_invalid_destinations', __( 'Weglot benötigt zwischen 1 und 30 Zielsprachen.', 'wp-agent-companion' ), array( 'status' => 400 ) );
	}
	$result = array();
	$seen = array();
	$seen_effective = array();
	foreach ( $value as $item ) {
		if ( ! is_array( $item ) ) {
			return new WP_Error( 'wpagent_weglot_invalid_destination', __( 'Eine Weglot-Zielsprache ist ungültig.', 'wp-agent-companion' ), array( 'status' => 400 ) );
		}
		$code = wpagent_weglot_language_code( $item['code'] ?? '', 'destination_languages.code' );
		if ( is_wp_error( $code ) ) {
			return $code;
		}
		if ( $code === $original || isset( $seen[ $code ] ) || isset( $seen_effective[ $code ] ) ) {
			return new WP_Error( 'wpagent_weglot_language_conflict', __( 'Original- und Zielsprachen müssen eindeutig sein.', 'wp-agent-companion' ), array( 'status' => 400 ) );
		}
		$seen[ $code ] = true;
		$destination = array( 'code' => $code, 'public' => wpagent_weglot_bool( $item['public'] ?? false ) );
		foreach ( array( 'custom_code' => 32, 'custom_name' => 100, 'custom_local_name' => 100 ) as $field => $limit ) {
			$text = wpagent_weglot_text( $item[ $field ] ?? '', 'destination_languages.' . $field, $limit );
			if ( is_wp_error( $text ) ) {
				return $text;
			}
			if ( 'custom_code' === $field && '' !== $text && ! preg_match( '/^[a-z0-9]{2,20}(?:-[a-z0-9]{2,20})?$/', strtolower( $text ) ) ) {
				return new WP_Error( 'wpagent_weglot_invalid_custom_code', __( 'Ein benutzerdefinierter Sprachcode ist ungültig.', 'wp-agent-companion' ), array( 'status' => 400 ) );
			}
			$destination[ $field ] = 'custom_code' === $field ? strtolower( $text ) : $text;
		}
		$effective = '' !== $destination['custom_code'] ? $destination['custom_code'] : $code;
		if ( $effective === $original || isset( $seen_effective[ $effective ] ) || ( $effective !== $code && isset( $seen[ $effective ] ) ) ) {
			return new WP_Error( 'wpagent_weglot_language_conflict', __( 'Benutzerdefinierte und reguläre Sprachcodes müssen eindeutig sein.', 'wp-agent-companion' ), array( 'status' => 400 ) );
		}
		$seen_effective[ $effective ] = true;
		$result[] = $destination;
	}
	return $result;
}

/** @return array<string,mixed>|WP_Error */
function wpagent_weglot_apply_patch( array $raw, array $input ) {
	$current = wpagent_weglot_project_settings( $raw );
	if ( is_wp_error( $current ) ) {
		return $current;
	}
	$original = $current['original_language'];
	if ( array_key_exists( 'original_language', $input ) ) {
		$original = wpagent_weglot_language_code( $input['original_language'], 'original_language' );
		if ( is_wp_error( $original ) ) {
			return $original;
		}
	}
	$destinations = array_key_exists( 'destination_languages', $input )
		? wpagent_weglot_validate_destinations( $input['destination_languages'], $original )
		: wpagent_weglot_validate_destinations( $current['destination_languages'], $original );
	if ( is_wp_error( $destinations ) ) {
		return $destinations;
	}

	$raw['language_from'] = $original;
	$raw['original_language'] = $original;
	$existing = is_array( $raw['languages'] ?? null )
		? $raw['languages']
		: ( is_array( $raw['destination_language'] ?? null ) ? $raw['destination_language'] : array() );
	$raw['languages'] = array();
	foreach ( $destinations as $destination ) {
		$provider = array();
		foreach ( $existing as $item ) {
			if ( is_array( $item ) && strtolower( (string) ( $item['language_to'] ?? $item['code'] ?? '' ) ) === $destination['code'] ) {
				$provider = $item;
				break;
			}
		}
		$provider['language_to'] = $destination['code'];
		$provider['public'] = $destination['public'];
		foreach ( array( 'custom_code', 'custom_name', 'custom_local_name' ) as $field ) {
			$provider[ $field ] = '' === $destination[ $field ] ? null : $destination[ $field ];
		}
		$raw['languages'][] = $provider;
	}
	$raw['destination_language'] = $raw['languages'];
	if ( array_key_exists( 'auto_redirect', $input ) ) {
		$raw['auto_switch'] = (bool) $input['auto_redirect'];
	}
	if ( array_key_exists( 'switcher', $input ) ) {
		if ( ! is_array( $input['switcher'] ) ) {
			return new WP_Error( 'wpagent_weglot_invalid_switcher', __( 'Die Weglot-Umschaltereinstellungen sind ungültig.', 'wp-agent-companion' ), array( 'status' => 400 ) );
		}
		if ( ! isset( $raw['custom_settings'] ) || ! is_array( $raw['custom_settings'] ) ) {
			$raw['custom_settings'] = array();
		}
		if ( ! isset( $raw['custom_settings']['button_style'] ) || ! is_array( $raw['custom_settings']['button_style'] ) ) {
			$raw['custom_settings']['button_style'] = array();
		}
		foreach ( array( 'is_dropdown', 'full_name', 'with_name', 'with_flags' ) as $field ) {
			if ( array_key_exists( $field, $input['switcher'] ) ) {
				$raw['custom_settings']['button_style'][ $field ] = (bool) $input['switcher'][ $field ];
			}
		}
		if ( array_key_exists( 'flag_type', $input['switcher'] ) ) {
			$flag = (string) $input['switcher']['flag_type'];
			if ( ! in_array( $flag, wpagent_weglot_flag_types(), true ) ) {
				return new WP_Error( 'wpagent_weglot_invalid_flag', __( 'Der Weglot-Flaggentyp ist ungültig.', 'wp-agent-companion' ), array( 'status' => 400 ) );
			}
			$raw['custom_settings']['button_style']['flag_type'] = $flag;
		}
	}
	if ( array_key_exists( 'excluded_urls', $input ) ) {
		if ( ! is_array( $input['excluded_urls'] ) || count( $input['excluded_urls'] ) > WPAGENT_WEGLOT_MAX_EXCLUSIONS ) {
			return new WP_Error( 'wpagent_weglot_invalid_exclusions', __( 'Die Liste der Weglot-URL-Ausschlüsse ist ungültig oder zu lang.', 'wp-agent-companion' ), array( 'status' => 400 ) );
		}
		$raw['excluded_paths'] = array();
		$destination_codes = array_column( $destinations, 'code' );
		$seen_urls = array();
		foreach ( $input['excluded_urls'] as $item ) {
			$type = is_array( $item ) ? (string) ( $item['type'] ?? '' ) : '';
			$value = is_array( $item ) ? trim( (string) ( $item['value'] ?? '' ) ) : '';
			$length = function_exists( 'mb_strlen' ) ? mb_strlen( $value ) : strlen( $value );
			if ( ! in_array( $type, wpagent_weglot_exclusion_types(), true ) || ! str_starts_with( $value, '/' ) || str_starts_with( $value, '//' ) || $length > 300 || preg_match( '/[\x00-\x20\x7F?#]/u', $value ) || str_contains( $value, '://' ) ) {
				return new WP_Error( 'wpagent_weglot_invalid_exclusion', __( 'Ein Weglot-URL-Ausschluss ist ungültig. Verwende einen relativen Pfad ohne Abfrage oder Fragment.', 'wp-agent-companion' ), array( 'status' => 400 ) );
			}
			$languages = array();
			foreach ( (array) ( $item['excluded_languages'] ?? array() ) as $language ) {
				$code = wpagent_weglot_language_code( $language, 'excluded_languages' );
				if ( is_wp_error( $code ) || ! in_array( $code, $destination_codes, true ) ) {
					return new WP_Error( 'wpagent_weglot_invalid_excluded_language', __( 'Ein URL-Ausschluss verweist auf keine aktive Zielsprache.', 'wp-agent-companion' ), array( 'status' => 400 ) );
				}
				if ( ! in_array( $code, $languages, true ) ) {
					$languages[] = $code;
				}
			}
			$identity = $type . "\n" . $value . "\n" . implode( ',', $languages );
			if ( isset( $seen_urls[ $identity ] ) ) {
				return new WP_Error( 'wpagent_weglot_duplicate_exclusion', __( 'Doppelte Weglot-URL-Ausschlüsse sind nicht erlaubt.', 'wp-agent-companion' ), array( 'status' => 400 ) );
			}
			$seen_urls[ $identity ] = true;
			$raw['excluded_paths'][] = array( 'type' => $type, 'value' => $value, 'excluded_languages' => $languages );
		}
		$raw['exclude_urls'] = $raw['excluded_paths'];
	}
	if ( array_key_exists( 'excluded_blocks', $input ) ) {
		if ( ! is_array( $input['excluded_blocks'] ) || count( $input['excluded_blocks'] ) > WPAGENT_WEGLOT_MAX_EXCLUSIONS ) {
			return new WP_Error( 'wpagent_weglot_invalid_blocks', __( 'Die Liste der Weglot-Blockausschlüsse ist ungültig oder zu lang.', 'wp-agent-companion' ), array( 'status' => 400 ) );
		}
		$raw['excluded_blocks'] = array();
		$seen_blocks = array();
		foreach ( $input['excluded_blocks'] as $selector ) {
			if ( ! is_string( $selector ) ) {
				return new WP_Error( 'wpagent_weglot_invalid_selector', __( 'Ein Weglot-Ausschluss enthält keinen sicheren CSS-Selektor.', 'wp-agent-companion' ), array( 'status' => 400 ) );
			}
			$selector = trim( $selector );
			$valid = wpagent_weglot_validate_selector( $selector );
			if ( is_wp_error( $valid ) ) {
				return $valid;
			}
			if ( isset( $seen_blocks[ $selector ] ) ) {
				return new WP_Error( 'wpagent_weglot_duplicate_selector', __( 'Doppelte Weglot-Blockausschlüsse sind nicht erlaubt.', 'wp-agent-companion' ), array( 'status' => 400 ) );
			}
			$seen_blocks[ $selector ] = true;
			$raw['excluded_blocks'][] = array( 'value' => $selector );
		}
	}
	$candidate = wpagent_weglot_project_settings( $raw );
	if ( is_wp_error( $candidate ) ) {
		return $candidate;
	}
	if ( ! $candidate['switcher']['with_name'] && ! $candidate['switcher']['with_flags'] ) {
		return new WP_Error( 'wpagent_weglot_invisible_switcher', __( 'Der Weglot-Umschalter muss Namen oder Flaggen anzeigen.', 'wp-agent-companion' ), array( 'status' => 400 ) );
	}
	return $raw;
}

require_once __DIR__ . '/weglot-write.php';
