<?php
/** Shared contract for safe Ocean Extra My Library template mounting. */

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

const WPAGENT_OCEAN_EXTRA_LIBRARY_THEME_VERSION = '4.2.2';
const WPAGENT_OCEAN_EXTRA_LIBRARY_MAX_TEMPLATES  = 100;

/** @return true|WP_Error */
function wpagent_ocean_extra_library_require_runtime() {
	if ( ! wpagent_oceanwp_is_active() ) {
		return new WP_Error( 'wpagent_oceanwp_inactive', __( 'OceanWP oder ein OceanWP-Child-Theme ist nicht aktiv.', 'wp-agent-companion' ), array( 'status' => 409 ) );
	}
	if ( ! class_exists( 'Ocean_Extra' )
		|| WPAGENT_OCEAN_EXTRA_LIBRARY_THEME_VERSION !== wpagent_oceanwp_version()
		|| WPAGENT_OCEAN_EXTRA_MIN_VERSION !== wpagent_oceanwp_extra_version()
		|| 'yes' !== get_option( 'oe_library_active_status', 'yes' )
		|| ! post_type_exists( 'oceanwp_library' )
		|| ! function_exists( 'ocean_is_block_template' )
		|| ! function_exists( 'oceanwp_custom_header_template' )
		|| ! function_exists( 'oceanwp_custom_footer_template' ) ) {
		return new WP_Error( 'wpagent_ocean_extra_library_runtime_missing', __( 'Das sichere Einbinden der OceanWP-Library erfordert genau OceanWP 4.2.2, Ocean Extra 2.5.8 und ein aktives My-Library-Modul.', 'wp-agent-companion' ), array( 'status' => 409 ) );
	}
	return true;
}

/** @return array{id:int,title:string,content_hash:string,block_types:array<int,string>}|WP_Error */
function wpagent_ocean_extra_library_template( int $template_id ) {
	$template = get_post( $template_id );
	if ( ! $template instanceof WP_Post || 'oceanwp_library' !== $template->post_type || 'publish' !== $template->post_status || '' !== $template->post_password ) {
		return new WP_Error( 'wpagent_ocean_extra_library_template_missing', __( 'Das OceanWP-Library-Template ist nicht veröffentlicht oder nicht vorhanden.', 'wp-agent-companion' ), array( 'status' => 404 ) );
	}
	if ( ! current_user_can( 'read_post', $template_id ) ) {
		return new WP_Error( 'wpagent_ocean_extra_library_template_forbidden', __( 'Du darfst dieses OceanWP-Library-Template nicht lesen.', 'wp-agent-companion' ), array( 'status' => 403 ) );
	}
	$elementor     = get_metadata_raw( 'post', $template_id, '_elementor_edit_mode', true );
	$siteorigin    = get_metadata_raw( 'post', $template_id, 'panels_data', true );
	$builder_active = ( defined( 'OCEANWP_BEAVER_BUILDER_ACTIVE' ) && OCEANWP_BEAVER_BUILDER_ACTIVE )
		|| ( null !== $elementor && '' !== $elementor )
		|| ( null !== $siteorigin && '' !== $siteorigin && array() !== $siteorigin );
	$valid          = wpagent_site_editor_validate_content( (string) $template->post_content );
	$static_blocks  = wpagent_validate_generated_core_blocks( (string) $template->post_content );
	if ( $builder_active || is_wp_error( $valid ) || is_wp_error( $static_blocks ) || ! ocean_is_block_template( $template_id ) ) {
		return new WP_Error( 'wpagent_ocean_extra_library_template_unsafe', __( 'Das OceanWP-Library-Template ist nicht als statisches, shortcodefreies Core-Block-Template sicher einbindbar.', 'wp-agent-companion' ), array( 'status' => 409 ) );
	}
	$report = wpagent_site_editor_block_report( (string) $template->post_content );
	$hash   = hash( 'sha256', get_current_blog_id() . "\0" . $template->ID . "\0" . $template->post_status . "\0" . $template->post_password . "\0" . $template->post_content );
	return array(
		'id'           => (int) $template->ID,
		'title'        => get_the_title( $template ),
		'content_hash' => $hash,
		'block_types'  => $report['block_types'],
	);
}

/** @return array<string,mixed> */
function wpagent_ocean_extra_library_mount_schema( bool $complete = false ): array {
	$schema = array(
		'type'                 => 'object',
		'properties'           => array(
			'mode'        => array( 'type' => 'string', 'enum' => array( 'inherit', 'set' ) ),
			'template_id' => array( 'type' => 'integer', 'minimum' => 1 ),
			'template_hash' => array( 'type' => 'string', 'pattern' => '^[a-f0-9]{64}$' ),
		),
		'required'             => array( 'mode' ),
		'additionalProperties' => false,
	);
	if ( ! $complete ) {
		$schema['minProperties'] = 1;
		$schema['maxProperties'] = 3;
	}
	return $schema;
}

/** @return array<string,mixed> */
function wpagent_ocean_extra_library_state_schema( bool $write = false ): array {
	$properties = array(
		'post_id'    => array( 'type' => 'integer' ),
		'post_type'  => array( 'type' => 'string' ),
		'header'     => wpagent_ocean_extra_library_mount_schema( true ),
		'footer'     => wpagent_ocean_extra_library_mount_schema( true ),
		'state_hash' => array( 'type' => 'string', 'pattern' => '^[a-f0-9]{64}$' ),
	);
	$required = array_keys( $properties );
	if ( $write ) {
		$properties['verified'] = array( 'type' => 'boolean' );
		$required[] = 'verified';
	}
	return array( 'type' => 'object', 'properties' => $properties, 'required' => $required, 'additionalProperties' => false );
}

/** @return array{post_id:int,post_type:string,blog_id:int,theme_version:string,plugin_version:string,meta:array<string,array{exists:bool,value:string}>,templates:array<int,array{id:int,title:string,content_hash:string,block_types:array<int,string>}>}|WP_Error */
function wpagent_ocean_extra_library_snapshot( WP_Post $post, int $blog_id ) {
	if ( $blog_id < 1 || $blog_id !== (int) get_current_blog_id() ) {
		return new WP_Error( 'wpagent_ocean_extra_library_site_changed', __( 'Die Websitezuordnung hat sich während des OceanWP-Library-Vorgangs geändert.', 'wp-agent-companion' ), array( 'status' => 409 ) );
	}
	$fresh_post = get_post( $post->ID );
	if ( ! $fresh_post instanceof WP_Post || $fresh_post->post_type !== $post->post_type || ! current_user_can( 'edit_post', $fresh_post->ID ) ) {
		return new WP_Error( 'wpagent_ocean_extra_library_post_changed', __( 'Der Zielbeitrag ist nicht mehr sicher bearbeitbar.', 'wp-agent-companion' ), array( 'status' => 409 ) );
	}
	$ready = wpagent_ocean_extra_library_require_runtime();
	if ( is_wp_error( $ready ) ) {
		return $ready;
	}
	$meta = array();
	foreach ( array( 'ocean_header_style', 'ocean_custom_header_template', 'ocean_custom_footer_template' ) as $key ) {
		$raw  = get_metadata_raw( 'post', $fresh_post->ID, $key, false );
		$rows = null === $raw ? array() : ( is_array( $raw ) ? $raw : array( $raw ) );
		if ( count( $rows ) > 1 || ( isset( $rows[0] ) && ! is_string( $rows[0] ) ) ) {
			return new WP_Error( 'wpagent_ocean_extra_library_invalid_state', __( 'Der Beitrag enthält einen nicht sicher auswertbaren OceanWP-Library-Zustand.', 'wp-agent-companion' ), array( 'status' => 502 ) );
		}
		$meta[ $key ] = array( 'exists' => 1 === count( $rows ), 'value' => 1 === count( $rows ) ? $rows[0] : '' );
	}
	$styles = array( '', 'minimal', 'transparent', 'top', 'full_screen', 'center', 'medium', 'vertical', 'custom' );
	if ( ! in_array( $meta['ocean_header_style']['value'], $styles, true ) ) {
		return new WP_Error( 'wpagent_ocean_extra_library_invalid_state', __( 'Der Beitrag enthält einen unbekannten OceanWP-Headerstil.', 'wp-agent-companion' ), array( 'status' => 502 ) );
	}
	$templates = array();
	foreach ( array( 'ocean_custom_header_template', 'ocean_custom_footer_template' ) as $key ) {
		$value = $meta[ $key ]['value'];
		if ( '' === $value ) {
			continue;
		}
		if ( ! ctype_digit( $value ) || (int) $value < 1 ) {
			return new WP_Error( 'wpagent_ocean_extra_library_invalid_state', __( 'Der Beitrag enthält eine ungültige OceanWP-Library-Template-ID.', 'wp-agent-companion' ), array( 'status' => 502 ) );
		}
		$descriptor = wpagent_ocean_extra_library_template( (int) $value );
		if ( is_wp_error( $descriptor ) ) {
			return $descriptor;
		}
		$templates[ (int) $value ] = $descriptor;
	}
	if ( 'custom' === $meta['ocean_header_style']['value'] && '' === $meta['ocean_custom_header_template']['value'] ) {
		return new WP_Error( 'wpagent_ocean_extra_library_invalid_state', __( 'Der individuelle OceanWP-Header verweist auf kein sicheres Library-Template.', 'wp-agent-companion' ), array( 'status' => 502 ) );
	}
	return array(
		'post_id'        => (int) $fresh_post->ID,
		'post_type'      => $fresh_post->post_type,
		'blog_id'        => $blog_id,
		'theme_version'  => wpagent_oceanwp_version(),
		'plugin_version' => wpagent_oceanwp_extra_version(),
		'meta'           => $meta,
		'templates'      => $templates,
	);
}

/** @param array<string,mixed> $snapshot */
function wpagent_ocean_extra_library_state_hash( array $snapshot ): string {
	$state = $snapshot['blog_id'] . "\0" . $snapshot['post_id'] . "\0" . $snapshot['post_type'] . "\0" . $snapshot['theme_version'] . "\0" . $snapshot['plugin_version'];
	foreach ( $snapshot['meta'] as $key => $entry ) {
		$state .= "\0" . $key . "\0" . ( $entry['exists'] ? '1' : '0' ) . "\0" . $entry['value'];
	}
	foreach ( $snapshot['templates'] as $id => $template ) {
		$state .= "\0template\0" . $id . "\0" . $template['content_hash'];
	}
	return hash( 'sha256', $state );
}

/** @param array<string,mixed> $snapshot @return array{header:array{mode:string,template_id?:int,template_hash?:string},footer:array{mode:string,template_id?:int,template_hash?:string}} */
function wpagent_ocean_extra_library_normalize( array $snapshot ): array {
	$header_id = (int) $snapshot['meta']['ocean_custom_header_template']['value'];
	$footer_id = (int) $snapshot['meta']['ocean_custom_footer_template']['value'];
	return array(
		'header' => 'custom' === $snapshot['meta']['ocean_header_style']['value'] && $header_id > 0
			? array( 'mode' => 'set', 'template_id' => $header_id, 'template_hash' => $snapshot['templates'][ $header_id ]['content_hash'] )
			: array( 'mode' => 'inherit' ),
		'footer' => $footer_id > 0 ? array( 'mode' => 'set', 'template_id' => $footer_id, 'template_hash' => $snapshot['templates'][ $footer_id ]['content_hash'] ) : array( 'mode' => 'inherit' ),
	);
}

/** @param array<string,mixed> $templates */
function wpagent_ocean_extra_library_settings_are_safe( array $templates ): bool {
	if ( ! $templates || count( $templates ) > 2 ) {
		return false;
	}
	foreach ( $templates as $area => $setting ) {
		if ( ! in_array( $area, array( 'header', 'footer' ), true ) || ! is_array( $setting ) || ! is_string( $setting['mode'] ?? null ) ) {
			return false;
		}
		if ( 'inherit' === $setting['mode'] ) {
			if ( array_key_exists( 'template_id', $setting ) || array_key_exists( 'template_hash', $setting ) ) {
				return false;
			}
		} elseif ( 'set' !== $setting['mode']
			|| ! is_int( $setting['template_id'] ?? null )
			|| $setting['template_id'] < 1
			|| ! is_string( $setting['template_hash'] ?? null )
			|| 1 !== preg_match( '/^[a-f0-9]{64}$/', $setting['template_hash'] ) ) {
			return false;
		}
	}
	return true;
}

/** @param array<string,mixed> $snapshot @param array<string,mixed> $settings @return array<string,mixed>|WP_Error */
function wpagent_ocean_extra_library_expected_snapshot( array $snapshot, array $settings ) {
	$expected = $snapshot;
	if ( isset( $settings['header'] ) ) {
		if ( 'set' === $settings['header']['mode'] ) {
			$expected['meta']['ocean_header_style'] = array( 'exists' => true, 'value' => 'custom' );
			$expected['meta']['ocean_custom_header_template'] = array( 'exists' => true, 'value' => (string) $settings['header']['template_id'] );
		} else {
			$expected['meta']['ocean_custom_header_template'] = array( 'exists' => false, 'value' => '' );
			if ( 'custom' === $expected['meta']['ocean_header_style']['value'] ) {
				$expected['meta']['ocean_header_style'] = array( 'exists' => false, 'value' => '' );
			}
		}
	}
	if ( isset( $settings['footer'] ) ) {
		$expected['meta']['ocean_custom_footer_template'] = 'set' === $settings['footer']['mode']
			? array( 'exists' => true, 'value' => (string) $settings['footer']['template_id'] )
			: array( 'exists' => false, 'value' => '' );
	}
	$expected['templates'] = array();
	foreach ( array( 'ocean_custom_header_template', 'ocean_custom_footer_template' ) as $key ) {
		$id = (int) $expected['meta'][ $key ]['value'];
		if ( $id < 1 ) {
			continue;
		}
		$template = wpagent_ocean_extra_library_template( $id );
		if ( is_wp_error( $template ) ) {
			return $template;
		}
		$area = 'ocean_custom_header_template' === $key ? 'header' : 'footer';
		if ( isset( $settings[ $area ] )
			&& 'set' === $settings[ $area ]['mode']
			&& ! hash_equals( $template['content_hash'], $settings[ $area ]['template_hash'] ) ) {
			return new WP_Error( 'wpagent_ocean_extra_library_template_changed', __( 'Das OceanWP-Library-Template hat sich seit dem Lesen geändert. Liste es neu auf und wiederhole den Vorgang.', 'wp-agent-companion' ), array( 'status' => 409, 'current_template_hash' => $template['content_hash'] ) );
		}
		$expected['templates'][ $id ] = $template;
	}
	return $expected;
}

/** @return array{header_style:string,header_template:int,footer_template:int}|WP_Error */
function wpagent_ocean_extra_library_runtime_state( int $post_id ) {
	$target = static fn( $current_id = null ) => $post_id;
	add_filter( 'ocean_post_id', $target, PHP_INT_MAX );
	try {
		return array(
			'header_style'    => (string) oceanwp_header_style(),
			'header_template' => (int) oceanwp_custom_header_template(),
			'footer_template' => (int) oceanwp_custom_footer_template(),
		);
	} catch ( Throwable $error ) {
		return new WP_Error( 'wpagent_ocean_extra_library_runtime_failed', __( 'OceanWP konnte die Library-Template-Zuordnung nicht sicher auswerten.', 'wp-agent-companion' ), array( 'status' => 502 ) );
	} finally {
		remove_filter( 'ocean_post_id', $target, PHP_INT_MAX );
	}
}

/** @param array<string,mixed> $settings @param array<string,mixed> $runtime */
function wpagent_ocean_extra_library_runtime_matches( array $settings, array $runtime ): bool {
	if ( isset( $settings['header'] ) ) {
		$header = $settings['header'];
		if ( 'set' === $header['mode'] && ( 'custom' !== $runtime['header_style'] || $header['template_id'] !== $runtime['header_template'] ) ) {
			return false;
		}
		if ( 'inherit' === $header['mode'] && ( 'custom' === $runtime['header_style'] || 0 !== $runtime['header_template'] ) ) {
			return false;
		}
	}
	if ( isset( $settings['footer'] ) ) {
		$footer = $settings['footer'];
		if ( 'set' === $footer['mode'] ? $footer['template_id'] !== $runtime['footer_template'] : 0 !== $runtime['footer_template'] ) {
			return false;
		}
	}
	return true;
}

function wpagent_ocean_extra_library_recovery_required( int $post_id, int $blog_id ): WP_Error {
	$data = array( 'status' => 500, 'rollback_verified' => false, 'recovery_required' => true );
	$post = get_post( $post_id );
	if ( $post instanceof WP_Post ) {
		$snapshot = wpagent_ocean_extra_library_snapshot( $post, $blog_id );
		if ( is_array( $snapshot ) ) {
			$data['current_hash'] = wpagent_ocean_extra_library_state_hash( $snapshot );
			$data['current_templates'] = wpagent_ocean_extra_library_normalize( $snapshot );
		}
	}
	return new WP_Error( 'wpagent_ocean_extra_library_recovery_required', __( 'Die OceanWP-Library-Zuordnung 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 );
}
