<?php
/**
 * Options Cache Service
 *
 * Manages WordPress options caching to reduce database calls.
 *
 * @package AIPT\Core\Services
 * @since 2.4.0
 */

namespace AIPT\Core\Services;

use AIPT\Core\Activator;

/**
 * Manages WordPress options caching
 *
 * @internal Used by Init and services
 */
class OptionsCache {

	/**
	 * Cache for options
	 *
	 * @var array
	 */
	private $options_cache = array();

	/**
	 * Cache for advanced settings array
	 *
	 * @var array|null
	 */
	private $advanced_settings_cache = null;

	/**
	 * Cache for standard settings array
	 *
	 * @var array|null
	 */
	private $standard_settings_cache = null;

	/**
	 * Cache for general settings array
	 *
	 * @var array|null
	 */
	private $settings_cache = null;

	/**
	 * Get cached option value
	 *
	 * Reduces repeated get_option() calls.
	 *
	 * @param string $key Option name.
	 * @param mixed  $default Default value.
	 * @return mixed Option value.
	 */
	public function get( string $key, $default = '' ) {
		if ( ! isset( $this->options_cache[ $key ] ) ) {
			$this->options_cache[ $key ] = get_option( $key, $default );
		}

		if ( $key === 'aipt_model' ) {
			$provider                    = $this->get( 'aipt_api_provider', Activator::get_default_value( 'api_provider' ) );
			$this->options_cache[ $key ] = $this->normalizeModelSetting( $provider, $this->options_cache[ $key ] );
		}

		return $this->options_cache[ $key ];
	}

	/**
	 * Clear all caches
	 *
	 * Clears options cache and settings cache.
	 */
	public function clear(): void {
		$this->options_cache             = array();
		$this->advanced_settings_cache   = null;
		$this->standard_settings_cache   = null;
		$this->settings_cache            = null;
		$this->primed                    = false;
	}

	/**
	 * Whether non-autoloaded options have been primed for this request.
	 *
	 * @var bool
	 */
	private $primed = false;

	/**
	 * Prime non-autoloaded options with a single DB query.
	 *
	 * After autoload optimization, prompt templates and admin-only options
	 * are no longer in the alloptions cache. This method batch-loads them
	 * before the settings arrays are built, replacing N individual queries
	 * with one SELECT ... WHERE option_name IN (...).
	 *
	 * Requires WP 6.4+ (wp_prime_option_caches). On older versions, each
	 * option is fetched individually — still correct, just not batched.
	 */
	private function primeNonAutoloadedOptions(): void {
		if ( $this->primed ) {
			return;
		}

		$this->primed = true;

		if ( ! function_exists( 'wp_prime_option_caches' ) ) {
			return;
		}

		\wp_prime_option_caches( array(
			'aipt_system_prompt',
			'aipt_user_prompt',
			'aipt_short_system_prompt',
			'aipt_short_user_prompt',
			'aipt_full_system_prompt',
			'aipt_full_user_prompt',
			'aipt_standard_short_system_prompt',
			'aipt_standard_short_user_prompt',
			'aipt_standard_full_system_prompt',
			'aipt_standard_full_user_prompt',
			'aipt_title_additional_prompt',
			'aipt_faq_additional_prompt',
			'aipt_seo_meta_additional_prompt',
			'aipt_taxonomy_additional_prompt',
			'aipt_brand_context',
			'aipt_custom_variables',
			'aipt_enable_tooltip',
			'aipt_metabox_hidden',
		) );
	}

	/**
	 * Get cached settings array
	 *
	 * @param string $type Settings type: 'advanced', 'standard', or 'general'.
	 * @return array Settings data.
	 */
	public function getSettingsArray( string $type = 'general' ): array {
		switch ( $type ) {
			case 'advanced':
				return $this->getAdvancedSettingsArray();
			case 'standard':
				return $this->getStandardSettingsArray();
			case 'general':
			default:
				return $this->getGeneralSettingsArray();
		}
	}

	/**
	 * Get cached advanced settings array
	 *
	 * For Advanced Bulk Generator.
	 *
	 * @return array Advanced settings.
	 */
	private function getAdvancedSettingsArray(): array {
		if ( $this->advanced_settings_cache === null ) {

			$this->primeNonAutoloadedOptions();

			$openai_key     = '';
			$gemini_key     = '';
			$openrouter_key = '';
			$claude_key     = '';

			try {
				$openai_key = \AIPT\Utils\ApiKeyManager::get_openai_key();
			} catch ( \Exception $e ) {

			}

			try {
				$gemini_key = \AIPT\Utils\ApiKeyManager::get_gemini_key();
			} catch ( \Exception $e ) {

			}

			try {
				$openrouter_key = \AIPT\Utils\ApiKeyManager::get_openrouter_key();
			} catch ( \Exception $e ) {

			}

			try {
				$claude_key = \AIPT\Utils\ApiKeyManager::get_claude_key();
			} catch ( \Exception $e ) {

			}

			$this->advanced_settings_cache = array(
				'openai_api_key'      => $openai_key,
				'gemini_api_key'      => $gemini_key,
				'openrouter_api_key'  => $openrouter_key,
				'claude_api_key'      => $claude_key,
				'api_provider'        => $this->get( 'aipt_api_provider', Activator::get_default_value( 'api_provider' ) ),
				'system_prompt'       => $this->get( 'aipt_system_prompt', Activator::get_default_value( 'system_prompt' ) ),
				'user_prompt'         => $this->get( 'aipt_user_prompt', Activator::get_default_value( 'user_prompt' ) ),
				'short_system_prompt' => $this->get( 'aipt_short_system_prompt', Activator::get_default_value( 'short_system_prompt' ) ),
				'short_user_prompt'   => $this->get( 'aipt_short_user_prompt', Activator::get_default_value( 'short_user_prompt' ) ),
				'full_system_prompt'  => $this->get( 'aipt_full_system_prompt', Activator::get_default_value( 'full_system_prompt' ) ),
				'full_user_prompt'    => $this->get( 'aipt_full_user_prompt', Activator::get_default_value( 'full_user_prompt' ) ),
				'language'              => $this->get( 'aipt_language', Activator::get_default_value( 'language' ) ),
				'writing_style'         => $this->get( 'aipt_writing_style', Activator::get_default_value( 'writing_style' ) ),
				'content_length_preset' => $this->get( 'aipt_content_length_preset', Activator::get_default_value( 'content_length_preset' ) ),
				'short_length_preset'   => $this->get( 'aipt_short_length_preset', Activator::get_default_value( 'short_length_preset' ) ),
				'max_tags_count'        => $this->get( 'aipt_max_tags_count', Activator::get_default_value( 'max_tags_count' ) ),
				'model'               => $this->get( 'aipt_model', Activator::get_default_value( 'model' ) ),
				'enable_tooltip'      => rest_sanitize_boolean( $this->get( 'aipt_enable_tooltip', Activator::get_default_value( 'enable_tooltip' ) ) ),
			);

			$this->advanced_settings_cache['model'] = $this->normalizeModelSetting(
				$this->advanced_settings_cache['api_provider'],
				$this->advanced_settings_cache['model']
			);
		}

		return $this->advanced_settings_cache;
	}

	/**
	 * Get cached standard settings array
	 *
	 * For Standard Bulk Generator.
	 *
	 * @return array Standard settings.
	 */
	private function getStandardSettingsArray(): array {
		if ( $this->standard_settings_cache === null ) {

			$this->primeNonAutoloadedOptions();

			$openai_key     = '';
			$gemini_key     = '';
			$openrouter_key = '';
			$claude_key     = '';

			try {
				$openai_key = \AIPT\Utils\ApiKeyManager::get_openai_key();
			} catch ( \Exception $e ) {

			}

			try {
				$gemini_key = \AIPT\Utils\ApiKeyManager::get_gemini_key();
			} catch ( \Exception $e ) {

			}

			try {
				$openrouter_key = \AIPT\Utils\ApiKeyManager::get_openrouter_key();
			} catch ( \Exception $e ) {

			}

			try {
				$claude_key = \AIPT\Utils\ApiKeyManager::get_claude_key();
			} catch ( \Exception $e ) {

			}

			$this->standard_settings_cache = array(
				'openai_api_key'                => $openai_key,
				'gemini_api_key'                => $gemini_key,
				'openrouter_api_key'            => $openrouter_key,
				'claude_api_key'                => $claude_key,
				'api_provider'                  => $this->get( 'aipt_api_provider', Activator::get_default_value( 'api_provider' ) ),
				'standard_short_system_prompt'  => $this->get( 'aipt_standard_short_system_prompt', Activator::get_default_value( 'standard_short_system_prompt' ) ),
				'standard_short_user_prompt'    => $this->get( 'aipt_standard_short_user_prompt', Activator::get_default_value( 'standard_short_user_prompt' ) ),
				'standard_full_system_prompt'   => $this->get( 'aipt_standard_full_system_prompt', Activator::get_default_value( 'standard_full_system_prompt' ) ),
				'standard_full_user_prompt'     => $this->get( 'aipt_standard_full_user_prompt', Activator::get_default_value( 'standard_full_user_prompt' ) ),
				'language'                      => $this->get( 'aipt_language', Activator::get_default_value( 'language' ) ),
				'writing_style'                 => $this->get( 'aipt_writing_style', Activator::get_default_value( 'writing_style' ) ),
				'content_length_preset'         => $this->get( 'aipt_content_length_preset', Activator::get_default_value( 'content_length_preset' ) ),
				'short_length_preset'           => $this->get( 'aipt_short_length_preset', Activator::get_default_value( 'short_length_preset' ) ),
				'max_tags_count'                => $this->get( 'aipt_max_tags_count', Activator::get_default_value( 'max_tags_count' ) ),
				'model'                         => $this->get( 'aipt_model', Activator::get_default_value( 'model' ) ),
				'enable_tooltip'                => rest_sanitize_boolean( $this->get( 'aipt_enable_tooltip', Activator::get_default_value( 'enable_tooltip' ) ) ),
			);

			$this->standard_settings_cache['model'] = $this->normalizeModelSetting(
				$this->standard_settings_cache['api_provider'],
				$this->standard_settings_cache['model']
			);
		}

		return $this->standard_settings_cache;
	}

	/**
	 * Get cached general settings array
	 *
	 * For Settings page and general use.
	 *
	 * @return array General settings.
	 */
	private function getGeneralSettingsArray(): array {
		if ( $this->settings_cache === null ) {

			$this->primeNonAutoloadedOptions();

			$openai_key     = '';
			$gemini_key     = '';
			$openrouter_key = '';
			$claude_key     = '';

			try {
				$openai_key = \AIPT\Utils\ApiKeyManager::get_openai_key();
			} catch ( \Exception $e ) {

			}

			try {
				$gemini_key = \AIPT\Utils\ApiKeyManager::get_gemini_key();
			} catch ( \Exception $e ) {

			}

			try {
				$openrouter_key = \AIPT\Utils\ApiKeyManager::get_openrouter_key();
			} catch ( \Exception $e ) {

			}

			try {
				$claude_key = \AIPT\Utils\ApiKeyManager::get_claude_key();
			} catch ( \Exception $e ) {

			}

			$this->settings_cache = array(
				'openai_api_key'                => $openai_key,
				'gemini_api_key'                => $gemini_key,
				'openrouter_api_key'            => $openrouter_key,
				'claude_api_key'                => $claude_key,
				'api_provider'                  => $this->get( 'aipt_api_provider', Activator::get_default_value( 'api_provider' ) ),
				'system_prompt'                 => $this->get( 'aipt_system_prompt', Activator::get_default_value( 'system_prompt' ) ),
				'user_prompt'                   => $this->get( 'aipt_user_prompt', Activator::get_default_value( 'user_prompt' ) ),
				'short_system_prompt'           => $this->get( 'aipt_short_system_prompt', Activator::get_default_value( 'short_system_prompt' ) ),
				'short_user_prompt'             => $this->get( 'aipt_short_user_prompt', Activator::get_default_value( 'short_user_prompt' ) ),
				'full_system_prompt'            => $this->get( 'aipt_full_system_prompt', Activator::get_default_value( 'full_system_prompt' ) ),
				'full_user_prompt'              => $this->get( 'aipt_full_user_prompt', Activator::get_default_value( 'full_user_prompt' ) ),
				'standard_short_system_prompt'  => $this->get( 'aipt_standard_short_system_prompt', Activator::get_default_value( 'standard_short_system_prompt' ) ),
				'standard_short_user_prompt'    => $this->get( 'aipt_standard_short_user_prompt', Activator::get_default_value( 'standard_short_user_prompt' ) ),
				'standard_full_system_prompt'   => $this->get( 'aipt_standard_full_system_prompt', Activator::get_default_value( 'standard_full_system_prompt' ) ),
				'standard_full_user_prompt'     => $this->get( 'aipt_standard_full_user_prompt', Activator::get_default_value( 'standard_full_user_prompt' ) ),
				'title_additional_prompt'       => $this->get( 'aipt_title_additional_prompt', Activator::get_default_value( 'title_additional_prompt' ) ),
				'faq_additional_prompt'         => $this->get( 'aipt_faq_additional_prompt', Activator::get_default_value( 'faq_additional_prompt' ) ),
				'seo_meta_additional_prompt'    => $this->get( 'aipt_seo_meta_additional_prompt', Activator::get_default_value( 'seo_meta_additional_prompt' ) ),
				'taxonomy_additional_prompt'    => $this->get( 'aipt_taxonomy_additional_prompt', Activator::get_default_value( 'taxonomy_additional_prompt' ) ),
				'language'                      => $this->get( 'aipt_language', Activator::get_default_value( 'language' ) ),
				'writing_style'                 => $this->get( 'aipt_writing_style', Activator::get_default_value( 'writing_style' ) ),
				'content_length_preset'         => $this->get( 'aipt_content_length_preset', Activator::get_default_value( 'content_length_preset' ) ),
				'short_length_preset'           => $this->get( 'aipt_short_length_preset', Activator::get_default_value( 'short_length_preset' ) ),
				'max_tags_count'                => $this->get( 'aipt_max_tags_count', Activator::get_default_value( 'max_tags_count' ) ),
				'model'                         => $this->get( 'aipt_model', Activator::get_default_value( 'model' ) ),

				'enable_tooltip'                => rest_sanitize_boolean( $this->get( 'aipt_enable_tooltip', Activator::get_default_value( 'enable_tooltip' ) ) ),
				'metabox_hidden'                => rest_sanitize_boolean( $this->get( 'aipt_metabox_hidden', Activator::get_default_value( 'metabox_hidden' ) ) ),
				'preserve_content_images'       => rest_sanitize_boolean( $this->get( 'aipt_preserve_content_images', Activator::get_default_value( 'preserve_content_images' ) ) ),
			);

			$this->settings_cache['model'] = $this->normalizeModelSetting(
				$this->settings_cache['api_provider'],
				$this->settings_cache['model']
			);
		}

		return $this->settings_cache;
	}

	/**
	 * Normalize model setting based on provider
	 *
	 * @param string $provider API provider.
	 * @param string $model Model name.
	 * @return string Normalized model name.
	 */
	private function normalizeModelSetting( string $provider, string $model ): string {
		$provider = sanitize_text_field( $provider );
		$model    = sanitize_text_field( $model );

		if ( $provider === 'gemini' ) {
			$valid = array(
				'gemini-3.5-flash',
				'gemini-3.1-pro-preview',
				'gemini-3.1-flash-lite',
				'gemini-3-flash-preview',
				'gemini-2.5-pro',
				'gemini-2.5-flash',
				'gemini-2.5-flash-lite',
			);

			if ( in_array( $model, $valid, true ) ) {
				return $model;
			}

			$this->persistModelOption( 'gemini-2.5-flash' );
			return 'gemini-2.5-flash';
		}

		if ( $provider === 'openrouter' ) {
			if ( $model === '' ) {
				$this->persistModelOption( 'openrouter/free' );
				return 'openrouter/free';
			}

			return $model;
		}

		if ( $provider === 'claude' ) {
			$valid = array(
				'claude-opus-4-8',
				'claude-opus-4-7',
				'claude-opus-4-6',
				'claude-sonnet-4-6',
				'claude-opus-4-5-20251101',
				'claude-sonnet-4-5-20250929',
				'claude-haiku-4-5-20251001',
				'claude-opus-4-1-20250805',
			);

			if ( in_array( $model, $valid, true ) ) {
				return $model;
			}

			$this->persistModelOption( 'claude-sonnet-4-6' );
			return 'claude-sonnet-4-6';
		}

		$valid = array(
			'gpt-5.5',
			'gpt-5.5-pro',
			'gpt-5.4',
			'gpt-5.4-mini',
			'gpt-5.4-nano',
			'gpt-4.1',
			'gpt-4.1-mini',
			'gpt-4.1-nano',
			'o4-mini',
			'o3-pro',
			'o3',
		);

		if ( $model !== '' && in_array( $model, $valid, true ) ) {
			return $model;
		}

		$this->persistModelOption( 'gpt-4.1-mini' );
		return 'gpt-4.1-mini';
	}

	/**
	 * Persist model option to database
	 *
	 * @param string $value Model value to persist.
	 */
	private function persistModelOption( string $value ): void {
		$sanitized_value                = sanitize_text_field( (string) $value );
		$this->options_cache['aipt_model'] = $sanitized_value;
		update_option( 'aipt_model', $sanitized_value );
	}
}
