<?php
/** Shared, fail-closed contract for ASE Free 9.0.0 generator-tag control. */

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

const WPAGENT_ASE_FREE_VERSION                = '9.0.0';
const WPAGENT_ASE_FREE_OPTION                 = 'admin_site_enhancements';
const WPAGENT_ASE_FREE_GENERATOR_LOCK_OPTION  = 'wp_agent_ase_free_generator_lock';
const WPAGENT_ASE_FREE_GENERATOR_LOCK_TTL     = 300;

/** @return true|WP_Error */
function wpagent_ase_free_generator_require_runtime() {
	if (
		! defined( 'ASENHA_VERSION' )
		|| ! defined( 'ASENHA_SLUG_U' )
		|| WPAGENT_ASE_FREE_VERSION !== (string) ASENHA_VERSION
		|| WPAGENT_ASE_FREE_OPTION !== (string) ASENHA_SLUG_U
		|| ! class_exists( 'ASENHA\\Classes\\Disable_Smaller_Components' )
	) {
		return new WP_Error( 'wpagent_ase_free_generator_runtime_missing', __( 'Die geprüfte ASE-Free-Generatorsteuerung erfordert genau Admin and Site Enhancements 9.0.0.', 'wp-agent-companion' ), array( 'status' => 409 ) );
	}
	return true;
}

/**
 * Reads the provider option without trusting the object cache or normalizing
 * malformed provider data. A writer needs the exact original bytes for CAS.
 *
 * @return array{blog_id:int,provider_version:string,raw:string,autoload:string,options:array<string,mixed>,smaller_components_enabled:bool,generator_tag_disabled:bool}|WP_Error
 */
function wpagent_ase_free_generator_snapshot() {
	$row = wpagent_companion_read_option_row_direct( WPAGENT_ASE_FREE_OPTION );
	if ( ! is_array( $row ) || ! is_string( $row['raw'] ?? null ) || ! is_string( $row['autoload'] ?? null ) ) {
		return new WP_Error( 'wpagent_ase_free_generator_storage_missing', __( 'Die ASE-Free-Einstellungen konnten nicht sicher gelesen werden.', 'wp-agent-companion' ), array( 'status' => 502 ) );
	}
	if ( ! is_serialized( $row['raw'] ) ) {
		return new WP_Error( 'wpagent_ase_free_generator_invalid_state', __( 'ASE Free enthält keinen sicher auswertbaren Einstellungsstand.', 'wp-agent-companion' ), array( 'status' => 502 ) );
	}
	$options = @unserialize( $row['raw'], array( 'allowed_classes' => false ) ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.serialize_unserialize
	if ( ! is_array( $options ) ) {
		return new WP_Error( 'wpagent_ase_free_generator_invalid_state', __( 'ASE Free enthält keinen sicher auswertbaren Einstellungsstand.', 'wp-agent-companion' ), array( 'status' => 502 ) );
	}
	$smaller_components = $options['disable_smaller_components'] ?? false;
	$generator_disabled = $options['disable_head_generator_tag'] ?? false;
	if ( ! is_bool( $smaller_components ) || ! is_bool( $generator_disabled ) ) {
		return new WP_Error( 'wpagent_ase_free_generator_invalid_state', __( 'ASE Free enthält einen nicht kanonischen Generator-Einstellungsstand.', 'wp-agent-companion' ), array( 'status' => 502 ) );
	}
	return array(
		'blog_id'                   => (int) get_current_blog_id(),
		'provider_version'          => (string) ASENHA_VERSION,
		'raw'                       => $row['raw'],
		'autoload'                  => $row['autoload'],
		'options'                   => $options,
		'smaller_components_enabled' => $smaller_components,
		'generator_tag_disabled'    => $generator_disabled,
	);
}

/** @param array{blog_id:int,provider_version:string,raw:string} $snapshot */
function wpagent_ase_free_generator_state_hash( array $snapshot ): string {
	return hash( 'sha256', $snapshot['blog_id'] . "\0" . $snapshot['provider_version'] . "\0" . $snapshot['raw'] );
}

/** @param array{blog_id:int} $snapshot */
function wpagent_ase_free_generator_same_blog( array $snapshot ): bool {
	return (int) $snapshot['blog_id'] === (int) get_current_blog_id();
}

/**
 * @param array{blog_id:int,provider_version:string,raw:string,autoload:string,options:array<string,mixed>,smaller_components_enabled:bool,generator_tag_disabled:bool} $snapshot
 * @return array<string,mixed>
 */
function wpagent_ase_free_generator_output( array $snapshot, bool $write = false ): array {
	$output = array(
		'provider_version'          => $snapshot['provider_version'],
		'smaller_components_enabled' => $snapshot['smaller_components_enabled'],
		'generator_tag_disabled'    => $snapshot['generator_tag_disabled'],
		'state_hash'                 => wpagent_ase_free_generator_state_hash( $snapshot ),
	);
	if ( $write ) {
		$output['verified']                   = true;
		$output['effective_after_new_request'] = true;
	}
	return $output;
}

/** @return array<string,mixed> */
function wpagent_ase_free_generator_output_schema( bool $write = false ): array {
	$properties = array(
		'provider_version'          => array( 'type' => 'string', 'enum' => array( WPAGENT_ASE_FREE_VERSION ) ),
		'smaller_components_enabled' => array( 'type' => 'boolean' ),
		'generator_tag_disabled'    => array( 'type' => 'boolean' ),
		'state_hash'                 => array( 'type' => 'string', 'pattern' => '^[a-f0-9]{64}$' ),
	);
	$required = array_keys( $properties );
	if ( $write ) {
		$properties['verified']                    = array( 'type' => 'boolean' );
		$properties['effective_after_new_request'] = array( 'type' => 'boolean' );
		$required[]                                = 'verified';
		$required[]                                = 'effective_after_new_request';
	}
	return array( 'type' => 'object', 'properties' => $properties, 'required' => $required, 'additionalProperties' => false );
}

/** @return string|WP_Error */
function wpagent_ase_free_generator_acquire_lock() {
	$token = wpagent_companion_acquire_option_lock( WPAGENT_ASE_FREE_GENERATOR_LOCK_OPTION, WPAGENT_ASE_FREE_GENERATOR_LOCK_TTL );
	if ( is_string( $token ) ) {
		return $token;
	}
	return new WP_Error( 'wpagent_ase_free_generator_locked', __( 'Die ASE-Free-Generatormarkierung wird gerade durch einen anderen Vorgang geändert.', 'wp-agent-companion' ), array( 'status' => 409 ) );
}

function wpagent_ase_free_generator_refresh_lock( string $token ): bool {
	return wpagent_companion_refresh_option_lock( WPAGENT_ASE_FREE_GENERATOR_LOCK_OPTION, $token, WPAGENT_ASE_FREE_GENERATOR_LOCK_TTL );
}

function wpagent_ase_free_generator_release_lock( string $token ): void {
	wpagent_companion_release_option_lock( WPAGENT_ASE_FREE_GENERATOR_LOCK_OPTION, $token );
}

/** @return WP_Error */
function wpagent_ase_free_generator_recovery_required() {
	$data     = array( 'status' => 500, 'recovery_required' => true, 'rollback_verified' => false );
	$snapshot = wpagent_ase_free_generator_snapshot();
	if ( is_array( $snapshot ) ) {
		$data['current_hash']                 = wpagent_ase_free_generator_state_hash( $snapshot );
		$data['generator_tag_disabled']       = $snapshot['generator_tag_disabled'];
		$data['smaller_components_enabled']   = $snapshot['smaller_components_enabled'];
	}
	return new WP_Error( 'wpagent_ase_free_generator_recovery_required', __( 'Die ASE-Free-Generatoränderung wurde nicht vollständig verifiziert. Es wurde kein automatisches Rollback ausgeführt. Wiederhole den Vorgang nicht automatisch und prüfe den aktuellen Zustand manuell.', 'wp-agent-companion' ), $data );
}

/** @return WP_Error */
function wpagent_ase_free_generator_permission_changed() {
	return new WP_Error( 'wpagent_ase_free_generator_permission_changed', __( 'Die Berechtigung zum Verwalten der ASE-Free-Generatorsteuerung ist nicht mehr vorhanden.', 'wp-agent-companion' ), array( 'status' => 403 ) );
}

/** @return WP_Error */
function wpagent_ase_free_generator_context_changed() {
	return new WP_Error( 'wpagent_ase_free_generator_context_changed', __( 'Der WordPress-Blogkontext hat sich während der ASE-Free-Änderung geändert.', 'wp-agent-companion' ), array( 'status' => 409 ) );
}
