<?php
/** Exact, read-only Spectra editor settings with no secret-bearing provider data. */

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

const WPAGENT_SPECTRA_SETTINGS_VERSION              = '2.20.1';
const WPAGENT_SPECTRA_SETTINGS_PROVIDER             = 'ultimate-addons-for-gutenberg';
const WPAGENT_SPECTRA_SETTINGS_MAX_FONT_FAMILIES    = 32;
const WPAGENT_SPECTRA_SETTINGS_MAX_FONT_VARIANTS    = 16;
const WPAGENT_SPECTRA_SETTINGS_MAX_FONT_FIELD_BYTES = 120;
const WPAGENT_SPECTRA_SETTINGS_MAX_FONT_BYTES       = 16384;
const WPAGENT_SPECTRA_SETTINGS_MAX_FONT_DEPTH       = 4;
const WPAGENT_SPECTRA_SETTINGS_MAX_FONT_NODES       = 8192;

/** @return array<string,mixed> */
function wpagent_ability_get_spectra_editor_settings(): array {
	return array(
		'label'       => __( 'Spectra-Editor-Einstellungen lesen', 'wp-agent-companion' ),
		'description' => __( 'Liest ausschließlich ausgewählte, nicht geheime Spectra-Editor-Schalter und die begrenzte Google-Font-Konfiguration. reCAPTCHA, Konten, Global Block Styles und alle Schreibpfade bleiben ausgeschlossen.', 'wp-agent-companion' ),
		'category'    => 'wp-agent',
		'input_schema' => array(
			'type'                 => 'object',
			'properties'           => array(),
			'additionalProperties' => false,
			'default'              => array(),
		),
		'output_schema' => wpagent_spectra_editor_settings_schema(),
		'execute_callback'    => 'wpagent_exec_get_spectra_editor_settings',
		'permission_callback' => 'wpagent_perm_manage_options',
		'meta'                => array(
			'show_in_rest' => true,
			'annotations'  => array( 'readonly' => true, 'destructive' => false, 'idempotent' => true ),
		),
	);
}

/** @return array{slug:string,version:string}|WP_Error */
function wpagent_spectra_editor_settings_provider() {
	$available = wpagent_spectra_require_available();
	if ( is_wp_error( $available ) ) {
		return $available;
	}
	$plugin_file = defined( 'UAGB_FILE' ) ? plugin_basename( UAGB_FILE ) : '';
	if ( 'ultimate-addons-for-gutenberg/ultimate-addons-for-gutenberg.php' !== $plugin_file ) {
		return new WP_Error(
			'wpagent_spectra_settings_provider',
			__( 'Die Spectra-Einstellungsoberfläche ist nur für den exakt geprüften Provider verfügbar.', 'wp-agent-companion' ),
			array( 'status' => 409 )
		);
	}
	$version = wpagent_spectra_version();
	if ( ! hash_equals( WPAGENT_SPECTRA_SETTINGS_VERSION, $version ) ) {
		return new WP_Error(
			'wpagent_spectra_settings_version',
			__( 'Die Spectra-Einstellungsoberfläche ist nur für die explizit geprüfte Provider-Version verfügbar.', 'wp-agent-companion' ),
			array( 'status' => 409, 'expected_version' => WPAGENT_SPECTRA_SETTINGS_VERSION, 'actual_version' => $version )
		);
	}
	return array( 'slug' => WPAGENT_SPECTRA_SETTINGS_PROVIDER, 'version' => $version );
}

/** @return array<int,array{output:string,option:string,enabled:string,disabled:string,default:string}> */
function wpagent_spectra_editor_toggle_specs(): array {
	return array(
		array( 'output' => 'legacy_blocks', 'option' => 'uag_enable_legacy_blocks', 'enabled' => 'yes', 'disabled' => 'no', 'default' => 'no' ),
		array( 'output' => 'templates_button', 'option' => 'uag_enable_templates_button', 'enabled' => 'yes', 'disabled' => 'no', 'default' => 'yes' ),
		array( 'output' => 'on_page_css_button', 'option' => 'uag_enable_on_page_css_button', 'enabled' => 'yes', 'disabled' => 'no', 'default' => 'yes' ),
		array( 'output' => 'block_conditions', 'option' => 'uag_enable_block_condition', 'enabled' => 'enabled', 'disabled' => 'disabled', 'default' => 'disabled' ),
		array( 'output' => 'masonry_gallery', 'option' => 'uag_enable_masonry_gallery', 'enabled' => 'enabled', 'disabled' => 'disabled', 'default' => 'enabled' ),
		array( 'output' => 'quick_action_sidebar', 'option' => 'uag_enable_quick_action_sidebar', 'enabled' => 'enabled', 'disabled' => 'disabled', 'default' => 'enabled' ),
		array( 'output' => 'animations_extension', 'option' => 'uag_enable_animations_extension', 'enabled' => 'enabled', 'disabled' => 'disabled', 'default' => 'enabled' ),
		array( 'output' => 'responsive_controls', 'option' => 'uag_enable_block_responsive', 'enabled' => 'enabled', 'disabled' => 'disabled', 'default' => 'enabled' ),
		array( 'output' => 'collapse_panels', 'option' => 'uag_collapse_panels', 'enabled' => 'enabled', 'disabled' => 'disabled', 'default' => 'enabled' ),
		array( 'output' => 'copy_paste_styles', 'option' => 'uag_copy_paste', 'enabled' => 'enabled', 'disabled' => 'disabled', 'default' => 'enabled' ),
		array( 'output' => 'visibility_controls', 'option' => 'uag_visibility_mode', 'enabled' => 'enabled', 'disabled' => 'disabled', 'default' => 'disabled' ),
	);
}

/** @return bool|WP_Error */
function wpagent_spectra_editor_toggle_value( array $spec ) {
	$value = UAGB_Admin_Helper::get_admin_settings_option( $spec['option'], $spec['default'] );
	if ( ! is_string( $value ) || ! in_array( $value, array( $spec['enabled'], $spec['disabled'] ), true ) ) {
		return new WP_Error(
			'wpagent_spectra_settings_corrupt',
			__( 'Eine ausgewählte Spectra-Editor-Einstellung hat keinen geprüften Wert und wird nicht geraten.', 'wp-agent-companion' ),
			array( 'status' => 409 )
		);
	}
	return $spec['enabled'] === $value;
}

/** @return array<string,bool>|WP_Error */
function wpagent_spectra_editor_toggles() {
	$result = array();
	foreach ( wpagent_spectra_editor_toggle_specs() as $spec ) {
		$value = wpagent_spectra_editor_toggle_value( $spec );
		if ( is_wp_error( $value ) ) {
			return $value;
		}
		$result[ $spec['output'] ] = $value;
	}
	return $result;
}

/** @return string|WP_Error */
function wpagent_spectra_editor_settings_text( $value ) {
	if ( ! is_string( $value ) || '' === $value || strlen( $value ) > WPAGENT_SPECTRA_SETTINGS_MAX_FONT_FIELD_BYTES || sanitize_text_field( $value ) !== $value ) {
		return new WP_Error(
			'wpagent_spectra_settings_corrupt',
			__( 'Die gespeicherte Spectra-Font-Konfiguration überschreitet den geprüften Textvertrag.', 'wp-agent-companion' ),
			array( 'status' => 409 )
		);
	}
	return $value;
}

/** @return int|WP_Error */
function wpagent_spectra_editor_font_value_bytes( $value, int $depth, int &$nodes ) {
	if ( $depth > WPAGENT_SPECTRA_SETTINGS_MAX_FONT_DEPTH || ++$nodes > WPAGENT_SPECTRA_SETTINGS_MAX_FONT_NODES ) {
		return new WP_Error( 'wpagent_spectra_settings_corrupt', __( 'Die gespeicherte Spectra-Font-Konfiguration überschreitet die geprüfte Strukturgrenze.', 'wp-agent-companion' ), array( 'status' => 409 ) );
	}
	if ( is_string( $value ) ) {
		$text = wpagent_spectra_editor_settings_text( $value );
		return is_wp_error( $text ) ? $text : strlen( $text );
	}
	if ( ! is_array( $value ) || count( $value ) > WPAGENT_SPECTRA_SETTINGS_MAX_FONT_FAMILIES ) {
		return new WP_Error( 'wpagent_spectra_settings_corrupt', __( 'Die gespeicherte Spectra-Font-Konfiguration überschreitet die geprüfte Strukturgrenze.', 'wp-agent-companion' ), array( 'status' => 409 ) );
	}
	$bytes = 0;
	foreach ( $value as $key => $item ) {
		if ( ! is_int( $key ) && ! is_string( $key ) ) {
			return new WP_Error( 'wpagent_spectra_settings_corrupt', __( 'Die gespeicherte Spectra-Font-Konfiguration enthält einen ungültigen Strukturwert.', 'wp-agent-companion' ), array( 'status' => 409 ) );
		}
		$key_bytes = strlen( (string) $key );
		if ( $key_bytes > WPAGENT_SPECTRA_SETTINGS_MAX_FONT_FIELD_BYTES ) {
			return new WP_Error( 'wpagent_spectra_settings_corrupt', __( 'Die gespeicherte Spectra-Font-Konfiguration überschreitet die geprüfte Textgrenze.', 'wp-agent-companion' ), array( 'status' => 409 ) );
		}
		$item_bytes = wpagent_spectra_editor_font_value_bytes( $item, $depth + 1, $nodes );
		if ( is_wp_error( $item_bytes ) ) {
			return $item_bytes;
		}
		$bytes += $key_bytes + $item_bytes;
		if ( $bytes > WPAGENT_SPECTRA_SETTINGS_MAX_FONT_BYTES ) {
			return new WP_Error( 'wpagent_spectra_settings_corrupt', __( 'Die gespeicherte Spectra-Font-Konfiguration überschreitet die sichere Byte-Grenze.', 'wp-agent-companion' ), array( 'status' => 409 ) );
		}
	}
	return $bytes;
}

/** @return array<int,string>|WP_Error */
function wpagent_spectra_editor_font_variants( $value, string $kind ) {
	if ( ! is_array( $value ) || count( $value ) > WPAGENT_SPECTRA_SETTINGS_MAX_FONT_VARIANTS ) {
		return new WP_Error( 'wpagent_spectra_settings_corrupt', __( 'Die gespeicherte Spectra-Font-Konfiguration überschreitet den geprüften Variantenvertrag.', 'wp-agent-companion' ), array( 'status' => 409 ) );
	}
	$variants = array();
	foreach ( $value as $item ) {
		if ( ! is_array( $item ) || array_diff( array_keys( $item ), array( 'value', 'label' ) ) || 2 !== count( $item ) || ! array_key_exists( 'value', $item ) || ! array_key_exists( 'label', $item ) ) {
			return new WP_Error( 'wpagent_spectra_settings_corrupt', __( 'Die gespeicherte Spectra-Font-Konfiguration enthält ein unbekanntes Variantenfeld.', 'wp-agent-companion' ), array( 'status' => 409 ) );
		}
		$variant = wpagent_spectra_editor_settings_text( $item['value'] );
		$label   = wpagent_spectra_editor_settings_text( $item['label'] );
		if ( is_wp_error( $variant ) || is_wp_error( $label ) ) {
			return is_wp_error( $variant ) ? $variant : $label;
		}
		$valid = 'weight' === $kind
			? (bool) preg_match( '/^(?:[1-9]00|variable)$/D', $variant )
			: in_array( $variant, array( 'normal', 'italic' ), true );
		if ( ! $valid || in_array( $variant, $variants, true ) ) {
			return new WP_Error( 'wpagent_spectra_settings_corrupt', __( 'Die gespeicherte Spectra-Font-Konfiguration enthält eine ungültige oder doppelte Variante.', 'wp-agent-companion' ), array( 'status' => 409 ) );
		}
		$variants[] = $variant;
	}
	return $variants;
}

/** @return array<int,array{family:string,weights:array<int,string>,styles:array<int,string>}>|WP_Error */
function wpagent_spectra_editor_font_families() {
	$value = UAGB_Admin_Helper::get_admin_settings_option( 'uag_select_font_globally', array() );
	$nodes = 0;
	$bytes = wpagent_spectra_editor_font_value_bytes( $value, 0, $nodes );
	if ( is_wp_error( $bytes ) || $bytes > WPAGENT_SPECTRA_SETTINGS_MAX_FONT_BYTES ) {
		return new WP_Error( 'wpagent_spectra_settings_corrupt', __( 'Die gespeicherte Spectra-Font-Konfiguration überschreitet die sicheren Grenzen.', 'wp-agent-companion' ), array( 'status' => 409 ) );
	}
	$families = array();
	foreach ( $value as $item ) {
		$allowed = array( 'value', 'label', 'weight', 'style', 'weights', 'styles' );
		if ( ! is_array( $item ) || array_diff( array_keys( $item ), $allowed ) || ! isset( $item['value'], $item['label'], $item['weight'], $item['style'] ) ) {
			return new WP_Error( 'wpagent_spectra_settings_corrupt', __( 'Die gespeicherte Spectra-Font-Konfiguration enthält ein unbekanntes Familienfeld.', 'wp-agent-companion' ), array( 'status' => 409 ) );
		}
		$family = wpagent_spectra_editor_settings_text( $item['value'] );
		$label  = wpagent_spectra_editor_settings_text( $item['label'] );
		if ( is_wp_error( $family ) || is_wp_error( $label ) || in_array( $family, array_column( $families, 'family' ), true ) ) {
			return new WP_Error( 'wpagent_spectra_settings_corrupt', __( 'Die gespeicherte Spectra-Font-Konfiguration enthält eine ungültige oder doppelte Familie.', 'wp-agent-companion' ), array( 'status' => 409 ) );
		}
		$weights = wpagent_spectra_editor_font_variants( $item['weight'], 'weight' );
		$styles  = wpagent_spectra_editor_font_variants( $item['style'], 'style' );
		if ( is_wp_error( $weights ) || is_wp_error( $styles ) ) {
			return is_wp_error( $weights ) ? $weights : $styles;
		}
		foreach ( array( 'weights' => 'weight', 'styles' => 'style' ) as $field => $kind ) {
			if ( array_key_exists( $field, $item ) ) {
				$available = wpagent_spectra_editor_font_variants( $item[ $field ], $kind );
				if ( is_wp_error( $available ) ) {
					return $available;
				}
			}
		}
		$families[] = array( 'family' => $family, 'weights' => $weights, 'styles' => $styles );
	}
	return $families;
}

/** @return bool|WP_Error */
function wpagent_spectra_editor_font_toggle( string $option, string $default = 'disabled' ) {
	$value = UAGB_Admin_Helper::get_admin_settings_option( $option, $default );
	if ( ! is_string( $value ) || ! in_array( $value, array( 'enabled', 'disabled' ), true ) ) {
		return new WP_Error( 'wpagent_spectra_settings_corrupt', __( 'Eine ausgewählte Spectra-Font-Einstellung hat keinen geprüften Wert und wird nicht geraten.', 'wp-agent-companion' ), array( 'status' => 409 ) );
	}
	return 'enabled' === $value;
}

/** @return array<string,mixed>|WP_Error */
function wpagent_spectra_editor_settings_state() {
	$provider = wpagent_spectra_editor_settings_provider();
	$toggles  = wpagent_spectra_editor_toggles();
	$families = wpagent_spectra_editor_font_families();
	$selected = wpagent_spectra_editor_font_toggle( 'uag_load_select_font_globally' );
	$local    = wpagent_spectra_editor_font_toggle( 'uag_load_gfonts_locally' );
	$preload  = wpagent_spectra_editor_font_toggle( 'uag_preload_local_fonts' );
	foreach ( array( $provider, $toggles, $families, $selected, $local, $preload ) as $result ) {
		if ( is_wp_error( $result ) ) {
			return $result;
		}
	}
	$wordpress_version = sanitize_text_field( (string) get_bloginfo( 'version' ) );
	if ( '' === $wordpress_version ) {
		return new WP_Error( 'wpagent_spectra_settings_runtime', __( 'Die WordPress-Laufzeit konnte nicht sicher bestimmt werden.', 'wp-agent-companion' ), array( 'status' => 500 ) );
	}
	return array(
		'provider'       => $provider,
		'runtime'        => array(
			'blog_id'           => (int) get_current_blog_id(),
			'wordpress_version' => $wordpress_version,
			'php_version'       => PHP_MAJOR_VERSION . '.' . PHP_MINOR_VERSION,
		),
		'editor_toggles' => $toggles,
		'google_fonts'   => array(
			'selected_families_enabled' => $selected,
			'selected_families'         => $families,
			'load_locally'              => $local,
			'preload_local'             => $preload,
		),
	);
}

function wpagent_spectra_editor_settings_hash( array $state ): string {
	return hash( 'sha256', serialize( $state ) );
}

/** @return array<string,mixed> */
function wpagent_spectra_editor_settings_schema(): array {
	$font = array(
		'type' => 'object', 'properties' => array(
			'family' => array( 'type' => 'string', 'maxLength' => WPAGENT_SPECTRA_SETTINGS_MAX_FONT_FIELD_BYTES ),
			'weights' => array( 'type' => 'array', 'maxItems' => WPAGENT_SPECTRA_SETTINGS_MAX_FONT_VARIANTS, 'items' => array( 'type' => 'string' ) ),
			'styles' => array( 'type' => 'array', 'maxItems' => WPAGENT_SPECTRA_SETTINGS_MAX_FONT_VARIANTS, 'items' => array( 'type' => 'string' ) ),
		), 'required' => array( 'family', 'weights', 'styles' ), 'additionalProperties' => false,
	);
	return array(
		'type' => 'object', 'properties' => array(
			'provider' => array( 'type' => 'object', 'properties' => array(
				'slug' => array( 'type' => 'string', 'enum' => array( WPAGENT_SPECTRA_SETTINGS_PROVIDER ) ),
				'version' => array( 'type' => 'string', 'enum' => array( WPAGENT_SPECTRA_SETTINGS_VERSION ) ),
			), 'required' => array( 'slug', 'version' ), 'additionalProperties' => false ),
			'runtime' => array( 'type' => 'object', 'properties' => array(
				'blog_id' => array( 'type' => 'integer', 'minimum' => 1 ),
				'wordpress_version' => array( 'type' => 'string' ), 'php_version' => array( 'type' => 'string', 'pattern' => '^\d+\.\d+$' ),
			), 'required' => array( 'blog_id', 'wordpress_version', 'php_version' ), 'additionalProperties' => false ),
			'editor_toggles' => array( 'type' => 'object', 'properties' => array(
				'legacy_blocks' => array( 'type' => 'boolean' ), 'templates_button' => array( 'type' => 'boolean' ), 'on_page_css_button' => array( 'type' => 'boolean' ),
				'block_conditions' => array( 'type' => 'boolean' ), 'masonry_gallery' => array( 'type' => 'boolean' ), 'quick_action_sidebar' => array( 'type' => 'boolean' ),
				'animations_extension' => array( 'type' => 'boolean' ), 'responsive_controls' => array( 'type' => 'boolean' ), 'collapse_panels' => array( 'type' => 'boolean' ),
				'copy_paste_styles' => array( 'type' => 'boolean' ), 'visibility_controls' => array( 'type' => 'boolean' ),
			), 'required' => array( 'legacy_blocks', 'templates_button', 'on_page_css_button', 'block_conditions', 'masonry_gallery', 'quick_action_sidebar', 'animations_extension', 'responsive_controls', 'collapse_panels', 'copy_paste_styles', 'visibility_controls' ), 'additionalProperties' => false ),
			'google_fonts' => array( 'type' => 'object', 'properties' => array(
				'selected_families_enabled' => array( 'type' => 'boolean' ),
				'selected_families' => array( 'type' => 'array', 'maxItems' => WPAGENT_SPECTRA_SETTINGS_MAX_FONT_FAMILIES, 'items' => $font ),
				'load_locally' => array( 'type' => 'boolean' ), 'preload_local' => array( 'type' => 'boolean' ),
			), 'required' => array( 'selected_families_enabled', 'selected_families', 'load_locally', 'preload_local' ), 'additionalProperties' => false ),
			'state_hash' => array( 'type' => 'string', 'pattern' => '^[a-f0-9]{64}$' ),
		), 'required' => array( 'provider', 'runtime', 'editor_toggles', 'google_fonts', 'state_hash' ), 'additionalProperties' => false,
	);
}

/** @return array<string,mixed>|WP_Error */
function wpagent_exec_get_spectra_editor_settings( $input = array() ) {
	if ( ! is_array( $input ) || array() !== $input ) {
		return new WP_Error( 'wpagent_spectra_settings_input', __( 'Diese Spectra-Leseoberfläche akzeptiert keine Eingabefelder.', 'wp-agent-companion' ), array( 'status' => 400 ) );
	}
	$state = wpagent_spectra_editor_settings_state();
	if ( is_wp_error( $state ) ) {
		return $state;
	}
	$state['state_hash'] = wpagent_spectra_editor_settings_hash( $state );
	return $state;
}
