<?php
/** Native creation of bounded Spectra Popup Builder content. */

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

const WPAGENT_SPECTRA_CREATE_KEY_META  = '_wpagent_spectra_create_key';
const WPAGENT_SPECTRA_CREATE_HASH_META = '_wpagent_spectra_create_hash';
const WPAGENT_SPECTRA_CONTENT_HASH_META = '_wpagent_spectra_content_hash';

/** @return array<string,mixed> */
function wpagent_spectra_popup_component_schema(): array {
	return array(
		'type'                 => 'object',
		'properties'           => array(
			'type'     => array( 'type' => 'string', 'enum' => array( 'markdown', 'separator', 'spacer' ) ),
			'markdown' => array( 'type' => 'string', 'maxLength' => 50000 ),
			'height'   => array( 'type' => 'integer', 'minimum' => 0, 'maximum' => 400 ),
		),
		'required'             => array( 'type' ),
		'additionalProperties' => false,
	);
}

/** @return array<string,mixed> */
function wpagent_ability_create_spectra_popup(): array {
	return array(
		'label'       => __( 'Spectra-Popup erstellen', 'wp-agent-companion' ),
		'description' => __( 'Erstellt ein deaktiviertes Spectra-Popup oder Banner aus sicheren Core-Blöcken, idempotent und mit vollständiger Rückleseprüfung.', 'wp-agent-companion' ),
		'category'    => 'wp-agent',
		'input_schema' => array(
			'type'       => 'object',
			'properties' => array(
				'title'           => array( 'type' => 'string', 'minLength' => 1, 'maxLength' => 200 ),
				'status'          => array( 'type' => 'string', 'enum' => array( 'draft', 'pending', 'private', 'publish' ), 'default' => 'draft' ),
				'type'            => array( 'type' => 'string', 'enum' => array( 'popup', 'banner' ) ),
				'repetition'      => array( 'type' => 'integer', 'minimum' => 1, 'maximum' => 100, 'default' => 1 ),
				'components'      => array( 'type' => 'array', 'minItems' => 1, 'maxItems' => 20, 'items' => wpagent_spectra_popup_component_schema() ),
				'idempotency_key' => array( 'type' => 'string', 'minLength' => 8, 'maxLength' => 64, 'pattern' => '^[A-Za-z0-9._:-]+$' ),
			),
			'required'             => array( 'title', 'type', 'components', 'idempotency_key' ),
			'additionalProperties' => false,
		),
		'output_schema' => array(
			'type'       => 'object',
			'properties' => array(
				'popup'    => wpagent_spectra_popup_schema(),
				'verified' => array( 'type' => 'boolean' ),
				'created'  => array( 'type' => 'boolean' ),
			),
			'required'             => array( 'popup', 'verified', 'created' ),
			'additionalProperties' => false,
		),
		'execute_callback'    => 'wpagent_exec_create_spectra_popup',
		'permission_callback' => 'wpagent_perm_manage_options',
		'meta'                => array( 'show_in_rest' => true, 'annotations' => array( 'readonly' => false, 'destructive' => false, 'idempotent' => false ) ),
	);
}

/** @return string|WP_Error */
function wpagent_spectra_build_popup_inner_content( $components ) {
	if ( ! is_array( $components ) || ! array_is_list( $components ) || array() === $components || count( $components ) > 20 ) {
		return new WP_Error( 'wpagent_spectra_components', __( 'components muss 1-20 sichere Popup-Komponenten enthalten.', 'wp-agent-companion' ), array( 'status' => 400 ) );
	}
	$allowed_keys = array(
		'markdown'  => array( 'type', 'markdown' ),
		'separator' => array( 'type' ),
		'spacer'    => array( 'type', 'height' ),
	);
	foreach ( $components as $component ) {
		$type = is_array( $component ) && is_string( $component['type'] ?? null ) ? $component['type'] : '';
		if ( ! isset( $allowed_keys[ $type ] ) || array_diff( array_keys( $component ), $allowed_keys[ $type ] ) ) {
			return new WP_Error( 'wpagent_spectra_component', __( 'Popup-Komponenten dürfen nur Markdown, Trenner oder Abstand sein und keine fremden Felder enthalten.', 'wp-agent-companion' ), array( 'status' => 400 ) );
		}
	}
	return wpagent_site_editor_build_content( $components, 'none' );
}

function wpagent_spectra_popup_close_svg(): string {
	return '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><path d="M310.6 361.4c12.5 12.5 12.5 32.75 0 45.25C304.4 412.9 296.2 416 288 416s-16.38-3.125-22.62-9.375L160 301.3L54.63 406.6C48.38 412.9 40.19 416 32 416S15.63 412.9 9.375 406.6c-12.5-12.5-12.5-32.75 0-45.25l105.4-105.4L9.375 150.6c-12.5-12.5-12.5-32.75 0-45.25s32.75-12.5 45.25 0L160 210.8l105.4-105.4c12.5-12.5 32.75-12.5 45.25 0s12.5 32.75 0 45.25l-105.4 105.4L310.6 361.4z"></path></svg>';
}

function wpagent_spectra_popup_native_content( string $inner, string $type, string $block_id ): string {
	$label = 'popup' === $type ? 'Close Popup' : 'Close Info Bar';
	$html  = '<div class="wp-block-uagb-popup-builder uagb-block-' . $block_id . ' uagb-popup-builder">'
		. '<div class="uagb-popup-builder__wrapper uagb-popup-builder__wrapper--' . $type . '">'
		. '<div class="uagb-popup-builder__container uagb-popup-builder__container--' . $type . '">' . $inner . '</div>'
		. '<button class="uagb-popup-builder__close" aria-label="' . $label . '">' . wpagent_spectra_popup_close_svg() . '</button>'
		. '</div></div>';
	return get_comment_delimited_block_content(
		'uagb/popup-builder',
		array( 'block_id' => $block_id, 'variationSelected' => true, 'variantType' => $type ),
		$html
	);
}

/** @return array{type:string,block_id:string}|WP_Error */
function wpagent_spectra_popup_native_contract( string $content ) {
	$blocks = parse_blocks( $content );
	if ( 1 !== count( $blocks ) || 'uagb/popup-builder' !== ( $blocks[0]['blockName'] ?? '' ) ) {
		return new WP_Error( 'wpagent_spectra_popup_contract', __( 'Der Popup-Inhalt besitzt keinen eindeutigen nativen Spectra-Wrapper.', 'wp-agent-companion' ), array( 'status' => 409 ) );
	}
	$attrs    = is_array( $blocks[0]['attrs'] ?? null ) ? $blocks[0]['attrs'] : array();
	$type     = is_string( $attrs['variantType'] ?? null ) ? $attrs['variantType'] : '';
	$block_id = is_string( $attrs['block_id'] ?? null ) ? $attrs['block_id'] : '';
	if ( true !== ( $attrs['variationSelected'] ?? null ) || ! in_array( $type, array( 'popup', 'banner' ), true )
		|| ! preg_match( '/^[A-Za-z0-9_-]{1,64}$/', $block_id ) ) {
		return new WP_Error( 'wpagent_spectra_popup_contract', __( 'Die native Spectra-Wrapperkonfiguration ist unvollständig oder unsicher.', 'wp-agent-companion' ), array( 'status' => 409 ) );
	}
	$required = array(
		'wp-block-uagb-popup-builder', 'uagb-block-' . $block_id,
		'uagb-popup-builder__wrapper--' . $type, 'uagb-popup-builder__container--' . $type,
	);
	foreach ( $required as $class ) {
		if ( 1 !== substr_count( $content, $class ) ) {
			return new WP_Error( 'wpagent_spectra_popup_contract', __( 'Die gespeicherte Spectra-Frontendstruktur ist unvollständig oder mehrdeutig.', 'wp-agent-companion' ), array( 'status' => 409 ) );
		}
	}
	$inner = serialize_blocks( is_array( $blocks[0]['innerBlocks'] ?? null ) ? $blocks[0]['innerBlocks'] : array() );
	$valid = wpagent_site_editor_validate_content( $inner );
	if ( is_wp_error( $valid ) ) {
		return $valid;
	}
	return compact( 'type', 'block_id' );
}

/** @return string|WP_Error */
function wpagent_spectra_retarget_popup_content( string $content, string $target_type ) {
	if ( ! in_array( $target_type, array( 'popup', 'banner' ), true ) ) {
		return new WP_Error( 'wpagent_spectra_type', __( 'Der native Popup-Wrapper kann nur auf popup oder banner gesetzt werden.', 'wp-agent-companion' ), array( 'status' => 400 ) );
	}
	$contract = wpagent_spectra_popup_native_contract( $content );
	if ( is_wp_error( $contract ) || $contract['type'] === $target_type ) return is_wp_error( $contract ) ? $contract : $content;
	$source_type = $contract['type'];
	$updated = preg_replace_callback(
		'/<!-- wp:uagb\\/popup-builder (\{[^\r\n]*\}) -->/',
		static function ( array $match ) use ( $target_type ): string {
			$attrs = json_decode( $match[1], true );
			if ( ! is_array( $attrs ) ) return $match[0];
			$attrs['variantType'] = $target_type;
			return '<!-- wp:uagb/popup-builder ' . serialize_block_attributes( $attrs ) . ' -->';
		},
		$content,
		1,
		$comment_count
	);
	if ( ! is_string( $updated ) || 1 !== $comment_count ) {
		return new WP_Error( 'wpagent_spectra_popup_contract', __( 'Der native Spectra-Blockkommentar konnte nicht eindeutig aktualisiert werden.', 'wp-agent-companion' ), array( 'status' => 409 ) );
	}
	$replacements = array(
		'uagb-popup-builder__wrapper--' . $source_type   => 'uagb-popup-builder__wrapper--' . $target_type,
		'uagb-popup-builder__container--' . $source_type => 'uagb-popup-builder__container--' . $target_type,
		'aria-label="' . ( 'popup' === $source_type ? 'Close Popup' : 'Close Info Bar' ) . '"'
			=> 'aria-label="' . ( 'popup' === $target_type ? 'Close Popup' : 'Close Info Bar' ) . '"',
	);
	foreach ( $replacements as $from => $to ) {
		$updated = str_replace( $from, $to, $updated, $count );
		if ( 1 !== $count ) {
			return new WP_Error( 'wpagent_spectra_popup_contract', __( 'Die native Spectra-Frontendstruktur konnte nicht eindeutig auf den neuen Typ umgestellt werden.', 'wp-agent-companion' ), array( 'status' => 409 ) );
		}
	}
	$verified = wpagent_spectra_popup_native_contract( $updated );
	return is_array( $verified ) && $verified['type'] === $target_type ? $updated : new WP_Error( 'wpagent_spectra_popup_contract', __( 'Der umgestellte Spectra-Wrapper bestand die Strukturprüfung nicht.', 'wp-agent-companion' ), array( 'status' => 500 ) );
}

/** @return WP_Post[] */
function wpagent_spectra_popups_by_create_key( string $key ): array {
	return get_posts( array(
		'post_type' => 'spectra-popup', 'post_status' => array( 'draft', 'pending', 'private', 'publish', 'future', 'trash' ),
		'posts_per_page' => 2, 'orderby' => 'ID', 'order' => 'ASC', 'no_found_rows' => true,
		'meta_key' => WPAGENT_SPECTRA_CREATE_KEY_META, 'meta_value' => $key,
	) );
}

/** @param array<string,string> $expected */
function wpagent_spectra_creation_meta_matches( int $post_id, array $expected ): bool {
	foreach ( $expected as $meta_key => $expected_value ) {
		$values = get_post_meta( $post_id, $meta_key, false );
		if ( 1 !== count( $values ) || ! is_string( $values[0] ) || ! hash_equals( $expected_value, $values[0] ) ) {
			return false;
		}
	}
	return true;
}

function wpagent_spectra_popup_owned_meta_hash( int $post_id ): string {
	$meta = get_post_meta( $post_id );
	if ( ! is_array( $meta ) ) {
		return '';
	}
	ksort( $meta, SORT_STRING );
	return hash( 'sha256', serialize( $meta ) );
}

/** @param array<string,mixed> $state @param array<string,string> $expected_meta @return array<string,mixed>|WP_Error */
function wpagent_spectra_popup_capture_owned_candidate( int $post_id, array $state, array $expected_meta ) {
	$expected_hash = is_string( $state['hash'] ?? null ) ? $state['hash'] : '';
	$key           = is_string( $expected_meta[ WPAGENT_SPECTRA_CREATE_KEY_META ] ?? null ) ? $expected_meta[ WPAGENT_SPECTRA_CREATE_KEY_META ] : '';
	if ( $post_id < 1 || $post_id !== (int) ( $state['id'] ?? 0 ) || ! preg_match( '/^[a-f0-9]{64}$/D', $expected_hash ) || '' === $key ) {
		return new WP_Error( 'wpagent_spectra_create_candidate_invalid', __( 'Der neu angelegte Popup-Zustand konnte nicht sicher für eine mögliche Bereinigung gebunden werden.', 'wp-agent-companion' ), array( 'status' => 500, 'recovery_required' => true ) );
	}
	$post  = wpagent_spectra_get_popup( $post_id );
	$fresh = is_wp_error( $post ) ? $post : wpagent_spectra_popup_state( $post, true );
	if ( is_wp_error( $fresh ) || ! hash_equals( $expected_hash, (string) ( $fresh['hash'] ?? '' ) ) || ! wpagent_spectra_creation_meta_matches( $post_id, $expected_meta ) ) {
		return new WP_Error( 'wpagent_spectra_create_candidate_drift', __( 'Der neu angelegte Popup-Zustand änderte sich vor der Verifikation und bleibt zur manuellen Prüfung erhalten.', 'wp-agent-companion' ), array( 'status' => 500, 'recovery_required' => true, 'popup_id' => $post_id ) );
	}
	$meta_hash = wpagent_spectra_popup_owned_meta_hash( $post_id );
	if ( ! preg_match( '/^[a-f0-9]{64}$/D', $meta_hash ) ) {
		return new WP_Error( 'wpagent_spectra_create_candidate_drift', __( 'Die vollständigen Popup-Metadaten konnten nicht sicher für eine mögliche Bereinigung gebunden werden.', 'wp-agent-companion' ), array( 'status' => 500, 'recovery_required' => true, 'popup_id' => $post_id ) );
	}
	return array( 'id' => $post_id, 'state_hash' => $expected_hash, 'meta_hash' => $meta_hash, 'key' => $key, 'meta' => $expected_meta );
}

/** @param array<string,mixed> $candidate */
function wpagent_spectra_popup_cleanup_owned_candidate( array $candidate, string $lock ): bool {
	$post_id       = absint( $candidate['id'] ?? 0 );
	$expected_hash = is_string( $candidate['state_hash'] ?? null ) ? $candidate['state_hash'] : '';
	$expected_meta_hash = is_string( $candidate['meta_hash'] ?? null ) ? $candidate['meta_hash'] : '';
	$key           = is_string( $candidate['key'] ?? null ) ? $candidate['key'] : '';
	$expected_meta = is_array( $candidate['meta'] ?? null ) ? $candidate['meta'] : array();
	if ( $post_id < 1 || ! preg_match( '/^[a-f0-9]{64}$/D', $expected_hash ) || ! preg_match( '/^[a-f0-9]{64}$/D', $expected_meta_hash ) || '' === $key || ! current_user_can( 'delete_post', $post_id ) || ! wpagent_site_editor_lock_is_owned( 'spectra-popup-create', $key, $lock ) ) {
		return false;
	}
	$post  = wpagent_spectra_get_popup( $post_id );
	$fresh = is_wp_error( $post ) ? $post : wpagent_spectra_popup_state( $post, true );
	if ( is_wp_error( $fresh ) || ! hash_equals( $expected_hash, (string) ( $fresh['hash'] ?? '' ) ) || ! hash_equals( $expected_meta_hash, wpagent_spectra_popup_owned_meta_hash( $post_id ) ) || ! wpagent_spectra_creation_meta_matches( $post_id, $expected_meta ) ) {
		return false;
	}
	$deleted = wp_delete_post( $post_id, true );
	return $deleted instanceof WP_Post && null === get_post( $post_id );
}

function wpagent_spectra_create_recovery_required( int $post_id ): WP_Error {
	return new WP_Error( 'wpagent_spectra_create_recovery_required', __( 'Der neu angelegte Spectra-Popup-Zustand konnte nicht mehr als unverändert eigener Kandidat bestätigt werden. Er bleibt erhalten und muss manuell geprüft werden.', 'wp-agent-companion' ), array( 'status' => 500, 'recovery_required' => true, 'popup_id' => $post_id ) );
}

/** @return array<string,mixed>|WP_Error */
function wpagent_exec_create_spectra_popup( $input ) {
	$available = wpagent_spectra_require_available();
	if ( is_wp_error( $available ) ) return $available;
	$input = is_array( $input ) ? $input : array();
	$title = wpagent_site_editor_plain_text( $input['title'] ?? '', 'title', 200 );
	if ( is_wp_error( $title ) ) return $title;
	$type = is_string( $input['type'] ?? null ) ? $input['type'] : '';
	if ( ! in_array( $type, array( 'popup', 'banner' ), true ) ) return new WP_Error( 'wpagent_spectra_type', __( 'type muss popup oder banner sein.', 'wp-agent-companion' ), array( 'status' => 400 ) );
	$status = $input['status'] ?? 'draft';
	if ( ! in_array( $status, array( 'draft', 'pending', 'private', 'publish' ), true ) ) return new WP_Error( 'wpagent_spectra_status', __( 'Ungültiger Popup-Status.', 'wp-agent-companion' ), array( 'status' => 400 ) );
	$repetition = $input['repetition'] ?? 1;
	if ( ! is_int( $repetition ) || $repetition < 1 || $repetition > 100 ) return new WP_Error( 'wpagent_spectra_repetition', __( 'repetition muss eine ganze Zahl zwischen 1 und 100 sein.', 'wp-agent-companion' ), array( 'status' => 400 ) );
	$key = is_string( $input['idempotency_key'] ?? null ) ? $input['idempotency_key'] : '';
	if ( ! preg_match( '/^[A-Za-z0-9._:-]{8,64}$/', $key ) ) return new WP_Error( 'wpagent_spectra_idempotency', __( 'idempotency_key muss 8-64 sichere Zeichen enthalten.', 'wp-agent-companion' ), array( 'status' => 400 ) );
	$inner = wpagent_spectra_build_popup_inner_content( $input['components'] ?? null );
	if ( is_wp_error( $inner ) ) return $inner;
	$request_hash = hash( 'sha256', serialize( compact( 'title', 'status', 'type', 'repetition', 'inner' ) ) );
	$lock = wpagent_site_editor_acquire_lock( 'spectra-popup-create', $key );
	if ( is_wp_error( $lock ) ) return $lock;
	try {
		$existing = wpagent_spectra_popups_by_create_key( $key );
		if ( count( $existing ) > 1 ) return new WP_Error( 'wpagent_spectra_idempotency_duplicate', __( 'Der Idempotenzschlüssel ist mehreren Spectra-Popups zugeordnet.', 'wp-agent-companion' ), array( 'status' => 500 ) );
		if ( 1 === count( $existing ) ) {
			$post  = $existing[0];
			$state = wpagent_spectra_popup_state( $post, true );
			$contract = is_wp_error( $state ) ? $state : wpagent_spectra_popup_native_contract( $state['content'] );
			$matches = is_array( $state ) && is_array( $contract ) && wpagent_spectra_creation_meta_matches( $post->ID, array(
				WPAGENT_SPECTRA_CREATE_KEY_META => $key, WPAGENT_SPECTRA_CREATE_HASH_META => $request_hash,
				WPAGENT_SPECTRA_CONTENT_HASH_META => hash( 'sha256', $state['content'] ),
			) ) && $state['title'] === $title
				&& $state['status'] === $status && $state['type'] === $type && false === $state['enabled'] && $state['repetition'] === $repetition;
			if ( ! $matches ) return new WP_Error( 'wpagent_spectra_idempotency_conflict', __( 'Der Idempotenzschlüssel wurde bereits für einen anderen oder nachträglich geänderten Popup-Zustand verwendet.', 'wp-agent-companion' ), array( 'status' => 409 ) );
			return array( 'popup' => $state, 'verified' => true, 'created' => false );
		}

		$block_id = 'wpagently-' . substr( str_replace( '-', '', wp_generate_uuid4() ), 0, 24 );
		$content  = wpagent_spectra_popup_native_content( $inner, $type, $block_id );
		$post_id  = wp_insert_post( wp_slash( array( 'post_type' => 'spectra-popup', 'post_status' => $status, 'post_title' => $title, 'post_content' => $content ) ), true );
		if ( is_wp_error( $post_id ) ) return $post_id;
		$owned_candidate = null;
		try {
			$writes = array(
				'spectra-popup-type' => $type, 'spectra-popup-enabled' => false, 'spectra-popup-repetition' => $repetition,
				WPAGENT_SPECTRA_CREATE_KEY_META => $key, WPAGENT_SPECTRA_CREATE_HASH_META => $request_hash,
				WPAGENT_SPECTRA_CONTENT_HASH_META => hash( 'sha256', $content ),
			);
			foreach ( $writes as $meta_key => $value ) {
				if ( false === update_post_meta( $post_id, $meta_key, $value ) ) throw new RuntimeException( __( 'Spectras Popup-Metadaten konnten nicht gespeichert werden.', 'wp-agent-companion' ) );
			}
			$fresh = wpagent_spectra_get_popup( $post_id );
			$state = is_wp_error( $fresh ) ? $fresh : wpagent_spectra_popup_state( $fresh, true );
			$contract = is_wp_error( $state ) ? $state : wpagent_spectra_popup_native_contract( $state['content'] );
			$verified = is_array( $state ) && is_array( $contract ) && $state['title'] === $title && $state['status'] === $status
				&& $state['type'] === $type && false === $state['enabled'] && $state['repetition'] === $repetition && $state['content'] === $content
				&& wpagent_spectra_creation_meta_matches( $post_id, array(
					WPAGENT_SPECTRA_CREATE_KEY_META => $key, WPAGENT_SPECTRA_CREATE_HASH_META => $request_hash,
					WPAGENT_SPECTRA_CONTENT_HASH_META => hash( 'sha256', $content ),
				) );
			if ( ! $verified ) throw new RuntimeException( __( 'Das neue Spectra-Popup bestand die vollständige Rückleseprüfung nicht.', 'wp-agent-companion' ) );
			$owned_candidate = wpagent_spectra_popup_capture_owned_candidate( $post_id, $state, array(
				WPAGENT_SPECTRA_CREATE_KEY_META => $key, WPAGENT_SPECTRA_CREATE_HASH_META => $request_hash,
				WPAGENT_SPECTRA_CONTENT_HASH_META => hash( 'sha256', $content ),
			) );
			if ( is_wp_error( $owned_candidate ) ) {
				return wpagent_spectra_create_recovery_required( $post_id );
			}
			return array( 'popup' => $state, 'verified' => true, 'created' => true );
		} catch ( Throwable $error ) {
			if ( is_array( $owned_candidate ) && wpagent_spectra_popup_cleanup_owned_candidate( $owned_candidate, $lock ) ) {
				return new WP_Error( 'wpagent_spectra_create_failed', $error->getMessage(), array( 'status' => 500, 'rolled_back' => true ) );
			}
			return wpagent_spectra_create_recovery_required( $post_id );
		}
	} finally {
		wpagent_site_editor_release_lock( 'spectra-popup-create', $key, $lock );
	}
}
