<?php
namespace WPDRMS\ASP\Index;

use WPDRMS\ASP\Index\ORM\IndexTableOptions;

final class IndexTableMigration {
	public static function run(): void {
		// Ensure the index tables exist, independently of the activation hook
		// (which does not fire on plugin updates) and the one-shot version gate.
		// dbDelta/CREATE TABLE is idempotent, so this is safe to run on every
		// upgrade and back-fills tables added after the previous install
		// (e.g. the skip table introduced in 4.29.0).
		IndexService::instance()->createTables();

		self::migrateFromLegacyFlat();
	}

	private static function migrateFromLegacyFlat(): void {
		$old = get_option( 'asp_it_options', false );
		if ( $old === false || get_site_option( 'asp_it_options_v2', false ) !== false ) {
			return;
		}

		if ( !is_array( $old ) ) {
			$old = array();
		}

		$old = self::decodeLegacyOptions( $old );

		$dir_exc = $old['options']['attachment_exclude_directories']['directories'] ?? array();
		$dir_inc = $old['options']['attachment_include_directories']['directories'] ?? array();

		$old_post_types   = (array) ( $old['it_post_types'] ?? array( 'post', 'page' ) );
		$has_attachment   = in_array( 'attachment', $old_post_types, true );
		$post_types_clean = array_values( array_filter(
			$old_post_types,
			fn( $t ) => $t !== 'attachment'
		) );

		$new_args = array(
			'index_title'                    => array( 'value' => (bool) ( $old['it_index_title'] ?? true ) ),
			'index_content'                  => array( 'value' => (bool) ( $old['it_index_content'] ?? true ) ),
			'index_excerpt'                  => array( 'value' => (bool) ( $old['it_index_excerpt'] ?? true ) ),
			'index_permalinks'               => array( 'value' => (bool) ( $old['it_index_permalinks'] ?? false ) ),
			'index_author_name'              => array( 'value' => (bool) ( $old['it_index_author_name'] ?? false ) ),
			'index_author_bio'               => array( 'value' => (bool) ( $old['it_index_author_bio'] ?? false ) ),
			'index_tags'                     => array( 'value' => (bool) ( $old['it_index_tags'] ?? false ) ),
			'index_categories'               => array( 'value' => (bool) ( $old['it_index_categories'] ?? false ) ),
			'index_taxonomies'               => array( 'value' => self::pipeSplit( $old['it_index_taxonomies'] ?? '' ) ),
			'post_types'                     => array( 'value' => $post_types_clean ?: array( 'post', 'page' ) ),
			'post_statuses'                  => array( 'value' => self::commaSplit( (string) ( $old['it_post_statuses'] ?? 'publish' ) ) ),
			'post_password_protected'        => array( 'value' => (bool) ( $old['it_post_password_protected'] ?? true ) ),
			'blog_ids'                       => array( 'value' => self::commaSplit( (string) ( $old['it_blog_ids'] ?? '' ) ) ),
			'custom_fields'                  => array( 'value' => self::pipeSplit( $old['it_index_customfields'] ?? '' ) ),
			'index_on_update_post_meta'      => array( 'value' => (bool) ( $old['it_index_on_update_post_meta'] ?? false ) ),
			'index_media_files'              => array( 'value' => $has_attachment ),
			'attachment_mime_types'          => array( 'value' => (string) ( $old['it_attachment_mime_types'] ?? 'image/jpeg, image/gif, image/png' ) ),
			'attachment_exclude_directories' => array( 'directories' => (array) $dir_exc ),
			'attachment_include_directories' => array( 'directories' => (array) $dir_inc ),
			'index_pdf_content'              => array( 'value' => (bool) ( $old['it_index_pdf_content'] ?? false ) ),
			'pdf_method'                     => array( 'value' => (string) ( $old['it_index_pdf_method'] ?? 'auto' ) ),
			'index_text_content'             => array( 'value' => (bool) ( $old['it_index_text_content'] ?? false ) ),
			'index_richtext_content'         => array( 'value' => (bool) ( $old['it_index_richtext_content'] ?? false ) ),
			'index_msword_content'           => array( 'value' => (bool) ( $old['it_index_msword_content'] ?? false ) ),
			'index_msexcel_content'          => array( 'value' => (bool) ( $old['it_index_msexcel_content'] ?? false ) ),
			'index_msppt_content'            => array( 'value' => (bool) ( $old['it_index_msppt_content'] ?? false ) ),
			'index_epub_content'             => array( 'value' => (bool) ( $old['it_index_epub_content'] ?? true ) ),
			'media_service_send_file'        => array( 'value' => (bool) ( $old['it_media_service_send_file'] ?? true ) ),
			'limit'                          => array( 'value' => (int) ( $old['it_limit'] ?? 25 ) ),
			'use_stopwords'                  => array( 'value' => (bool) ( $old['it_use_stopwords'] ?? false ) ),
			'stopwords'                      => array( 'value' => self::commaSplit( (string) ( $old['it_stopwords'] ?? '' ) ) ),
			'min_word_length'                => array( 'value' => (int) ( $old['it_min_word_length'] ?? 1 ) ),
			'extract_iframes'                => array( 'value' => (bool) ( $old['it_extract_iframes'] ?? false ) ),
			'extract_gutenberg_blocks'       => array( 'value' => (bool) ( $old['it_extract_gutenberg_blocks'] ?? true ) ),
			'extract_shortcodes'             => array( 'value' => (bool) ( $old['it_extract_shortcodes'] ?? true ) ),
			'exclude_shortcodes'             => array( 'value' => self::commaSplit( (string) ( $old['it_exclude_shortcodes'] ?? 'wpdreams_rpl, wpdreams_rpp' ) ) ),
			'inflections'                    => array( 'value' => (bool) ( $old['it_inflections'] ?? false ) ),
			'language'                       => array( 'value' => (string) ( $old['it_language'] ?? 'english' ) ),
			'index_on_save'                  => array( 'value' => (bool) ( $old['it_index_on_save'] ?? true ) ),
			'cron_enable'                    => array( 'value' => (bool) ( $old['it_cron_enable'] ?? false ) ),
			'cron_period'                    => array( 'value' => (string) ( $old['it_cron_period'] ?? 'asp_cr_five_minutes' ) ),
			'enable_compression'             => array( 'value' => (bool) ( $old['it_enable_compression'] ?? false ) ),
			'pool_size_auto'                 => array( 'value' => (bool) ( $old['it_pool_size_auto'] ?? true ) ),
			'pool_size_one'                  => array( 'value' => (int) ( $old['it_pool_size_one'] ?? 5000 ) ),
			'pool_size_two'                  => array( 'value' => (int) ( $old['it_pool_size_two'] ?? 8000 ) ),
			'pool_size_three'                => array( 'value' => (int) ( $old['it_pool_size_three'] ?? 10000 ) ),
			'pool_size_rest'                 => array( 'value' => (int) ( $old['it_pool_size_rest'] ?? 10000 ) ),
			'cf_exclusion_rules'             => array( 'logic' => 'AND', 'rules' => array() ),
			'taxonomy_exclusion_rules'       => array( 'logic' => 'AND', 'rules' => array() ),
		);

		IndexTableOptions::instance()->setArgs( $new_args, false )->save();
		if ( get_site_option( 'asp_it_options_v2', false ) !== false ) {
			delete_option( 'asp_it_options' );
		}
	}

	/**
	 * Decodes any _decode_ prefixed values in the legacy option array,
	 * mirroring what asp_decode_params() does when loading options into memory.
	 *
	 * @param array<string, mixed> $old
	 * @return array<string, mixed>
	 */
	private static function decodeLegacyOptions( array $old ): array {
		foreach ( $old as $k => $v ) {
			if ( is_string( $v ) && substr( $v, 0, 8 ) === '_decode_' ) {
				$decoded = json_decode( base64_decode( substr( $v, 8 ) ), true );
				if ( $decoded !== null ) {
					$old[ $k ] = $decoded;
				}
			}
		}
		return $old;
	}

	/**
	 * Split a pipe-delimited string into a trimmed, filtered array.
	 *
	 * @param string $value Pipe-delimited string.
	 * @return string[]
	 */
	private static function pipeSplit( string $value ): array {
		if ( $value === '' ) {
			return array();
		}
		return array_values( array_filter( array_map( 'trim', explode( '|', $value ) ) ) );
	}

	/**
	 * Split a comma-delimited string into a trimmed, filtered array.
	 *
	 * @param string $value Comma-delimited string.
	 * @return string[]
	 */
	private static function commaSplit( string $value ): array {
		if ( $value === '' ) {
			return array();
		}
		return array_values( array_filter( array_map( 'trim', explode( ',', $value ) ) ) );
	}
}
