<?php
/** Shared helpers for native Spectra administration. */

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

const WPAGENT_SPECTRA_MAX_CONTENT_BYTES = 1048576;

/** @return true|WP_Error */
function wpagent_spectra_require_available() {
	if ( class_exists( 'UAGB_Block_Module' ) && class_exists( 'UAGB_Admin_Helper' ) && post_type_exists( 'spectra-popup' ) ) {
		return true;
	}
	return new WP_Error(
		'wpagent_spectra_unavailable',
		__( 'Spectra ist nicht aktiv oder seine native API ist nicht verfügbar.', 'wp-agent-companion' ),
		array( 'status' => 409 )
	);
}

function wpagent_spectra_version(): string {
	return defined( 'UAGB_VER' ) ? sanitize_text_field( (string) UAGB_VER ) : '';
}

/** @return bool|WP_Error */
function wpagent_spectra_boolean( $value, string $field ) {
	if ( is_bool( $value ) ) return $value;
	if ( 0 === $value || '0' === $value || 'false' === $value ) return false;
	if ( 1 === $value || '1' === $value || 'true' === $value ) return true;
	/* translators: %s: input field name. */
	return new WP_Error( 'wpagent_spectra_boolean', sprintf( __( '%s muss ein boolescher Wert sein.', 'wp-agent-companion' ), $field ), array( 'status' => 400 ) );
}

/** @return array{exists:bool,value:array<string,mixed>,hash:string}|WP_Error */
function wpagent_spectra_block_option_snapshot() {
	$missing = new stdClass();
	$value   = get_option( '_uagb_blocks', $missing );
	$exists  = $missing !== $value;
	if ( $exists && ! is_array( $value ) ) {
		return new WP_Error(
			'wpagent_spectra_blocks_corrupt',
			__( 'Spectras Blockstatus ist beschädigt und wird deshalb nicht überschrieben.', 'wp-agent-companion' ),
			array( 'status' => 409 )
		);
	}
	$value = $exists ? $value : array();
	return array(
		'exists' => $exists,
		'value'  => $value,
		'hash'   => hash( 'sha256', serialize( array( 'exists' => $exists, 'value' => $value ) ) ),
	);
}

/** @return string[] */
function wpagent_spectra_hidden_block_slugs(): array {
	return array(
		'column', 'icon-list-child', 'social-share-child', 'buttons-child', 'faq-child',
		'forms-name', 'forms-email', 'forms-hidden', 'forms-phone', 'forms-textarea',
		'forms-url', 'forms-select', 'forms-radio', 'forms-checkbox', 'forms-upload',
		'forms-toggle', 'forms-date', 'forms-accept', 'post-title', 'post-image',
		'post-button', 'post-excerpt', 'post-taxonomy', 'post-meta', 'restaurant-menu-child',
		'content-timeline-child', 'tabs-child', 'how-to-step', 'slider-child', 'slider-pro',
		'image-gallery-pro', 'loop-wrapper', 'loop-search', 'loop-sort', 'loop-reset',
		'loop-pagination', 'loop-category', 'modal-pro', 'countdown-pro',
	);
}

/** @return array<string,array<string,mixed>>|WP_Error */
function wpagent_spectra_block_registry() {
	$available = wpagent_spectra_require_available();
	if ( is_wp_error( $available ) ) {
		return $available;
	}
	$blocks = UAGB_Block_Module::get_blocks_info();
	if ( ! is_array( $blocks ) ) {
		return new WP_Error( 'wpagent_spectra_registry', __( 'Spectras Blockbibliothek konnte nicht gelesen werden.', 'wp-agent-companion' ), array( 'status' => 500 ) );
	}
	$hidden = array_flip( wpagent_spectra_hidden_block_slugs() );
	if ( 'yes' !== UAGB_Admin_Helper::get_admin_settings_option( 'uag_enable_legacy_blocks' ) ) {
		foreach ( array( 'wp-search', 'columns', 'section', 'cf7-styler', 'gf-styler', 'post-masonry' ) as $slug ) {
			$hidden[ $slug ] = true;
		}
	}
	if ( ! class_exists( 'WPCF7' ) ) {
		$hidden['cf7-styler'] = true;
	}
	if ( ! class_exists( 'GFForms' ) ) {
		$hidden['gf-styler'] = true;
	}
	$result = array();
	foreach ( $blocks as $name => $definition ) {
		if ( ! is_string( $name ) || ! str_starts_with( $name, 'uagb/' ) || ! is_array( $definition ) ) {
			continue;
		}
		$slug = substr( $name, strlen( 'uagb/' ) );
		if ( '' === $slug || isset( $hidden[ $slug ] ) || ! empty( $definition['extension'] ) || ! empty( $definition['is_child'] ) || ! empty( $definition['deprecated'] ) ) {
			continue;
		}
		$title = sanitize_text_field( (string) ( $definition['title'] ?? '' ) );
		if ( '' === $title ) {
			continue;
		}
		$categories = array();
		foreach ( is_array( $definition['admin_categories'] ?? null ) ? $definition['admin_categories'] : array() as $category ) {
			if ( is_string( $category ) && '' !== sanitize_key( $category ) ) {
				$categories[] = sanitize_key( $category );
			}
		}
		$result[ $slug ] = array(
			'slug'            => $slug,
			'name'            => $name,
			'title'           => $title,
			'description'     => wp_html_excerpt( sanitize_text_field( (string) ( $definition['description'] ?? '' ) ), 1000, '' ),
			'default_enabled' => ! empty( $definition['default'] ),
			'categories'      => array_values( array_unique( $categories ) ),
		);
	}
	ksort( $result, SORT_NATURAL | SORT_FLAG_CASE );
	return $result;
}

/** @return array<string,mixed> */
function wpagent_spectra_block_state( array $definition, array $saved ): array {
	$slug                  = $definition['slug'];
	$definition['enabled'] = array_key_exists( $slug, $saved ) ? 'disabled' !== $saved[ $slug ] : $definition['default_enabled'];
	return $definition;
}

/** @return array<string,mixed> */
function wpagent_spectra_block_schema(): array {
	$properties = array(
		'slug' => array( 'type' => 'string' ), 'name' => array( 'type' => 'string' ), 'title' => array( 'type' => 'string' ),
		'description' => array( 'type' => 'string' ), 'enabled' => array( 'type' => 'boolean' ), 'default_enabled' => array( 'type' => 'boolean' ),
		'categories' => array( 'type' => 'array', 'items' => array( 'type' => 'string' ) ),
	);
	return array( 'type' => 'object', 'properties' => $properties, 'required' => array_keys( $properties ), 'additionalProperties' => false );
}

function wpagent_spectra_popup_type( $value ): string {
	return in_array( $value, array( 'popup', 'banner' ), true ) ? $value : 'unset';
}

/** @return array{exists:bool,value:mixed} */
function wpagent_spectra_popup_meta_snapshot( int $post_id, string $key ): array {
	return array(
		'exists' => metadata_exists( 'post', $post_id, $key ),
		'value'  => get_post_meta( $post_id, $key, true ),
	);
}

/** @param array<int,array<string,mixed>> $blocks */
function wpagent_spectra_walk_popup_blocks( array $blocks, array &$report ): void {
	foreach ( $blocks as $block ) {
		$name  = $block['blockName'] ?? null;
		$inner = trim( (string) ( $block['innerHTML'] ?? '' ) );
		if ( null === $name ) {
			if ( '' !== $inner ) {
				++$report['block_count'];
				++$report['freeform_count'];
				$report['block_types'][] = 'core/freeform';
			}
		} else {
			++$report['block_count'];
			$report['block_types'][] = (string) $name;
			if ( 'core/freeform' === $name ) {
				++$report['freeform_count'];
			}
			if ( 'uagb/popup-builder' === $name ) {
				$report['has_popup_wrapper'] = true;
			}
		}
		if ( ! empty( $block['innerBlocks'] ) ) {
			wpagent_spectra_walk_popup_blocks( $block['innerBlocks'], $report );
		}
	}
}

/** @return array{block_count:int,freeform_count:int,block_types:array<int,string>,has_popup_wrapper:bool} */
function wpagent_spectra_popup_block_report( string $content ): array {
	$report = array( 'block_count' => 0, 'freeform_count' => 0, 'block_types' => array(), 'has_popup_wrapper' => false );
	wpagent_spectra_walk_popup_blocks( parse_blocks( $content ), $report );
	$report['block_types'] = array_values( array_unique( $report['block_types'] ) );
	sort( $report['block_types'], SORT_STRING );
	return $report;
}

/** @return WP_Post|WP_Error */
function wpagent_spectra_get_popup( int $post_id ) {
	$post = get_post( $post_id );
	if ( ! $post instanceof WP_Post || 'spectra-popup' !== $post->post_type ) {
		return new WP_Error( 'wpagent_spectra_popup_not_found', __( 'Spectra-Popup nicht gefunden.', 'wp-agent-companion' ), array( 'status' => 404 ) );
	}
	return $post;
}

/** @return array<string,mixed>|WP_Error */
function wpagent_spectra_popup_state( WP_Post $post, bool $with_content = true ) {
	$content = (string) $post->post_content;
	if ( $with_content && strlen( $content ) > WPAGENT_SPECTRA_MAX_CONTENT_BYTES ) {
		return new WP_Error( 'wpagent_spectra_popup_too_large', __( 'Der Spectra-Popup-Inhalt ist größer als 1 MiB und wird nicht verarbeitet.', 'wp-agent-companion' ), array( 'status' => 413 ) );
	}
	$type_meta       = wpagent_spectra_popup_meta_snapshot( $post->ID, 'spectra-popup-type' );
	$enabled_meta    = wpagent_spectra_popup_meta_snapshot( $post->ID, 'spectra-popup-enabled' );
	$repetition_meta = wpagent_spectra_popup_meta_snapshot( $post->ID, 'spectra-popup-repetition' );
	$hash = hash( 'sha256', serialize( array(
		'id' => $post->ID, 'post_type' => $post->post_type, 'title' => $post->post_title, 'slug' => $post->post_name,
		'status' => $post->post_status, 'content' => $content, 'modified' => $post->post_modified_gmt,
		'type' => $type_meta, 'enabled' => $enabled_meta, 'repetition' => $repetition_meta,
	) ) );
	$state = array(
		'id' => (int) $post->ID, 'title' => (string) $post->post_title, 'slug' => (string) $post->post_name,
		'status' => (string) $post->post_status, 'type' => wpagent_spectra_popup_type( $type_meta['value'] ),
		'enabled' => rest_sanitize_boolean( $enabled_meta['value'] ),
		'repetition' => max( 1, absint( $repetition_meta['value'] ) ),
		'modified' => mysql_to_rfc3339( $post->post_modified ), 'hash' => $hash,
	);
	if ( $with_content ) {
		$report = wpagent_spectra_popup_block_report( $content );
		$state['content'] = $content;
		$state += $report;
	}
	return $state;
}

/** @return array<string,mixed> */
function wpagent_spectra_popup_summary_schema(): array {
	$properties = array(
		'id' => array( 'type' => 'integer' ), 'title' => array( 'type' => 'string' ), 'slug' => array( 'type' => 'string' ),
		'status' => array( 'type' => 'string' ), 'type' => array( 'type' => 'string', 'enum' => array( 'unset', 'popup', 'banner' ) ),
		'enabled' => array( 'type' => 'boolean' ), 'repetition' => array( 'type' => 'integer' ), 'modified' => array( 'type' => 'string' ),
		'hash' => array( 'type' => 'string', 'pattern' => '^[a-f0-9]{64}$' ),
	);
	return array( 'type' => 'object', 'properties' => $properties, 'required' => array_keys( $properties ), 'additionalProperties' => false );
}

/** @return array<string,mixed> */
function wpagent_spectra_popup_schema(): array {
	$schema = wpagent_spectra_popup_summary_schema();
	$extra  = array(
		'content' => array( 'type' => 'string' ), 'block_count' => array( 'type' => 'integer' ), 'freeform_count' => array( 'type' => 'integer' ),
		'block_types' => array( 'type' => 'array', 'items' => array( 'type' => 'string' ) ), 'has_popup_wrapper' => array( 'type' => 'boolean' ),
	);
	$schema['properties'] = array_merge( $schema['properties'], $extra );
	$schema['required']   = array_keys( $schema['properties'] );
	return $schema;
}

/** @param array{exists:bool,value:mixed} $snapshot */
function wpagent_spectra_restore_popup_meta( int $post_id, string $key, array $snapshot ): void {
	if ( $snapshot['exists'] ) {
		update_post_meta( $post_id, $key, $snapshot['value'] );
	} else {
		delete_post_meta( $post_id, $key );
	}
}
