<?php
/** Fail-closed handling for Elementor's global design-system kit settings. */

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

/** @return array<string,mixed> */
function wpagent_elementor_design_system_input_schema(): array {
	$color = array(
		'type' => 'object',
		'properties' => array(
			'id' => array( 'type' => 'string', 'pattern' => '^[a-z0-9][a-z0-9_-]{0,63}$' ),
			'title' => array( 'type' => 'string', 'minLength' => 1, 'maxLength' => 100 ),
			'value' => array( 'type' => 'string', 'minLength' => 1, 'maxLength' => 100 ),
		),
		'required' => array( 'id', 'title', 'value' ),
		'additionalProperties' => false,
	);
	$typography = array(
		'type' => 'object',
		'properties' => array(
			'id' => array( 'type' => 'string', 'pattern' => '^[a-z0-9][a-z0-9_-]{0,63}$' ),
			'title' => array( 'type' => 'string', 'minLength' => 1, 'maxLength' => 100 ),
			'styles' => wpagent_elementor_design_style_schema(),
		),
		'required' => array( 'id', 'title', 'styles' ),
		'additionalProperties' => false,
	);
	return array(
		'type' => 'object',
		'properties' => array(
			'expected_hash' => array( 'type' => 'string', 'pattern' => '^[a-f0-9]{64}$' ),
			'system_colors' => array( 'type' => 'array', 'minItems' => 4, 'maxItems' => 4, 'items' => $color ),
			'custom_colors' => array( 'type' => 'array', 'maxItems' => WPAGENT_ELEMENTOR_DESIGN_MAX_TOKENS, 'items' => $color ),
			'system_typography' => array( 'type' => 'array', 'minItems' => 4, 'maxItems' => 4, 'items' => $typography ),
			'custom_typography' => array( 'type' => 'array', 'maxItems' => WPAGENT_ELEMENTOR_DESIGN_MAX_TOKENS, 'items' => $typography ),
			'fallback_font' => array( 'type' => 'string', 'minLength' => 1, 'maxLength' => 200 ),
		),
		'required' => array( 'expected_hash' ),
		'additionalProperties' => false,
	);
}

function wpagent_ability_update_elementor_design_system(): array {
	$output = wpagent_elementor_design_system_output_schema();
	$output['properties']['previous_hash'] = array( 'type' => 'string', 'pattern' => '^[a-f0-9]{64}$' );
	$output['properties']['changed'] = array( 'type' => 'boolean' );
	$output['properties']['verified'] = array( 'type' => 'boolean' );
	return array(
		'label' => __( 'Elementor-Designsystem aktualisieren', 'wp-agent-companion' ),
		'description' => __( 'Prüft eine geplante Änderung des globalen Elementor-Designsystems gegen den aktuellen vollständigen Konflikt-Hash. Remote-Änderungen sind deaktiviert, weil Elementor für Kit-Einstellungen keine atomare Compare-and-Write-Operation gegen parallele Editor-Änderungen bietet.', 'wp-agent-companion' ),
		'category' => 'wp-agent',
		'input_schema' => wpagent_elementor_design_system_input_schema(),
		'output_schema' => $output,
		'execute_callback' => 'wpagent_exec_update_elementor_design_system',
		'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_elementor_design_manual_write_required( int $kit_id, string $current_hash ): WP_Error {
	return new WP_Error(
		'wpagent_elementor_design_manual_write_required',
		__( 'Elementors Kit-Einstellungen haben keine nachweisbar atomare Compare-and-Write-Operation. Prüfe und speichere diese Änderung im Elementor-Editor.', 'wp-agent-companion' ),
		array( 'status' => 409, 'kit_id' => $kit_id, 'current_hash' => $current_hash, 'manual_only' => true )
	);
}

/** @return array<string,mixed>|WP_Error */
function wpagent_exec_update_elementor_design_system( $input ) {
	$input = is_array( $input ) ? $input : array();
	$kit = wpagent_elementor_design_active_kit();
	if ( is_wp_error( $kit ) ) {
		return $kit;
	}
	$expected_hash = is_string( $input['expected_hash'] ?? null ) ? $input['expected_hash'] : '';
	if ( ! preg_match( '/^[a-f0-9]{64}$/', $expected_hash ) ) {
		return new WP_Error( 'wpagent_elementor_design_bad_hash', __( 'expected_hash muss ein vollständiger SHA-256-Hash sein.', 'wp-agent-companion' ), array( 'status' => 400 ) );
	}
	$managed_keys = array( 'system_colors', 'custom_colors', 'system_typography', 'custom_typography', 'fallback_font' );
	$provided = array_values( array_filter( $managed_keys, static fn( string $key ): bool => array_key_exists( $key, $input ) ) );
	if ( ! $provided ) {
		return new WP_Error( 'wpagent_elementor_design_no_changes', __( 'Mindestens ein globaler Elementor-Designbereich muss angegeben werden.', 'wp-agent-companion' ), array( 'status' => 400 ) );
	}
	if ( array_diff( array_keys( $input ), array_merge( array( 'expected_hash' ), $managed_keys ) ) ) {
		return new WP_Error( 'wpagent_elementor_design_unknown_field', __( 'Die Anfrage enthält ein unbekanntes Elementor-Designfeld.', 'wp-agent-companion' ), array( 'status' => 400 ) );
	}

	$before = wpagent_elementor_design_system_state( $kit );
	if ( is_wp_error( $before ) ) {
		return $before;
	}
	if ( ! hash_equals( $before['hash'], $expected_hash ) ) {
		return new WP_Error( 'wpagent_elementor_design_conflict', __( 'Das globale Elementor-Designsystem wurde seit dem letzten Lesen geändert.', 'wp-agent-companion' ), array( 'status' => 409, 'current_hash' => $before['hash'] ) );
	}
	$target = $before;
	foreach ( $provided as $key ) {
		if ( in_array( $key, array( 'system_colors', 'custom_colors' ), true ) ) {
			if ( ! is_array( $input[ $key ] ) ) {
				return new WP_Error( 'wpagent_elementor_design_bad_colors', __( 'Elementor-Farben müssen als Liste übergeben werden.', 'wp-agent-companion' ), array( 'status' => 400 ) );
			}
			$value = wpagent_elementor_design_normalize_colors( $input[ $key ], 'system_colors' === $key );
			if ( is_wp_error( $value ) ) {
				return $value;
			}
			$target[ $key ] = $value;
		} elseif ( in_array( $key, array( 'system_typography', 'custom_typography' ), true ) ) {
			if ( ! is_array( $input[ $key ] ) ) {
				return new WP_Error( 'wpagent_elementor_design_bad_typography', __( 'Elementor-Typografie muss als Liste übergeben werden.', 'wp-agent-companion' ), array( 'status' => 400 ) );
			}
			$value = wpagent_elementor_design_normalize_typography( $input[ $key ], 'system_typography' === $key );
			if ( is_wp_error( $value ) ) {
				return $value;
			}
			$target[ $key ] = $value;
		} else {
			$value = wpagent_elementor_design_font_list( $input[ $key ], 200, 'wpagent_elementor_design_bad_fallback', true );
			if ( is_wp_error( $value ) || str_contains( $value, ';' ) || str_contains( $value, '{' ) || str_contains( $value, '}' ) ) {
				return is_wp_error( $value ) ? $value : new WP_Error( 'wpagent_elementor_design_bad_fallback', __( 'Die Fallback-Schrift enthält nicht erlaubte CSS-Zeichen.', 'wp-agent-companion' ), array( 'status' => 400 ) );
			}
			$target['fallback_font'] = $value;
		}
	}
	$hash_target = $target;
	unset( $hash_target['kit_id'], $hash_target['elementor_version'], $hash_target['hash'] );
	$target_hash = hash( 'sha256', (string) wp_json_encode( wpagent_elementor_canonicalize( $hash_target ), JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE ) );
	if ( hash_equals( $before['hash'], $target_hash ) ) {
		$before['previous_hash'] = $before['hash'];
		$before['changed'] = false;
		$before['verified'] = true;
		return $before;
	}

	$kit_id = absint( $before['kit_id'] );
	$lock = wpagent_elementor_acquire_lock( $kit_id );
	if ( is_wp_error( $lock ) ) {
		return $lock;
	}
	try {
		if ( ! wpagent_elementor_design_lock_checkpoint( $kit_id, $lock ) ) {
			return new WP_Error( 'wpagent_elementor_design_lock_lost', __( 'Die Sperre für das Elementor-Designsystem ging vor der Prüfung verloren.', 'wp-agent-companion' ), array( 'status' => 409 ) );
		}
		$active_kit = wpagent_elementor_design_active_kit();
		if ( is_wp_error( $active_kit ) ) {
			return $active_kit;
		}
		if ( absint( $active_kit->get_id() ) !== $kit_id ) {
			return new WP_Error( 'wpagent_elementor_design_conflict', __( 'Das aktive Elementor-Kit wurde während der Vorbereitung geändert.', 'wp-agent-companion' ), array( 'status' => 409 ) );
		}
		$fresh_kit = wpagent_elementor_design_fresh_kit( $kit_id );
		$fresh_before = is_wp_error( $fresh_kit ) ? $fresh_kit : wpagent_elementor_design_system_state( $fresh_kit );
		if ( is_wp_error( $fresh_before ) ) {
			return $fresh_before;
		}
		if ( ! hash_equals( $fresh_before['hash'], $expected_hash ) ) {
			return new WP_Error( 'wpagent_elementor_design_conflict', __( 'Das globale Elementor-Designsystem wurde während der Vorbereitung geändert.', 'wp-agent-companion' ), array( 'status' => 409, 'current_hash' => $fresh_before['hash'] ) );
		}
		if ( ! wpagent_elementor_design_lock_checkpoint( $kit_id, $lock ) ) {
			return new WP_Error( 'wpagent_elementor_design_lock_lost', __( 'Die Sperre für das Elementor-Designsystem ging während der Prüfung verloren.', 'wp-agent-companion' ), array( 'status' => 409 ) );
		}
		$active_kit = wpagent_elementor_design_active_kit();
		if ( is_wp_error( $active_kit ) ) {
			return $active_kit;
		}
		if ( absint( $active_kit->get_id() ) !== $kit_id ) {
			return new WP_Error( 'wpagent_elementor_design_conflict', __( 'Das aktive Elementor-Kit wurde während der Prüfung geändert.', 'wp-agent-companion' ), array( 'status' => 409, 'current_hash' => $fresh_before['hash'] ) );
		}
		return wpagent_elementor_design_manual_write_required( $kit_id, $fresh_before['hash'] );
	} finally {
		wpagent_elementor_release_lock( $kit_id, $lock );
	}
}
