<?php
/**
 * AI hotspot settings.
 *
 * @package Ugcify\AI
 */

namespace Ugcify\AI;

// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

class AISettings {
	public const OPTION_NAME = 'ugcify_ai_hotspot_settings';
	public const DEFAULT_PROVIDER = 'anthropic';

	/**
	 * Get provider definitions.
	 *
	 * @return array<string,array<string,mixed>>
	 */
	public static function get_provider_definitions(): array {
		return array(
			'wordpress' => array(
				'label'            => __( 'WordPress AI', 'ugcify' ),
				'api_key_label'    => '',
				'api_key_placeholder' => '',
				'requires_api_key' => false,
				'default_model'    => 'wordpress-ai',
				'models'           => array(
					array( 'value' => 'wordpress-ai', 'label' => __( 'WordPress AI', 'ugcify' ) ),
				),
			),
			'anthropic' => array(
				'label'         => __( 'Anthropic', 'ugcify' ),
				'api_key_label' => __( 'Anthropic API key', 'ugcify' ),
				'api_key_placeholder' => __( 'Enter Anthropic API key', 'ugcify' ),
				'default_model' => 'claude-sonnet-5',
				'models'        => array(
					array( 'value' => 'claude-fable-5', 'label' => __( 'Claude Fable 5', 'ugcify' ) ),
					array( 'value' => 'claude-opus-4-8', 'label' => __( 'Claude Opus 4.8', 'ugcify' ) ),
					array( 'value' => 'claude-sonnet-5', 'label' => __( 'Claude Sonnet 5', 'ugcify' ) ),
					array( 'value' => 'claude-haiku-4-5', 'label' => __( 'Claude Haiku 4.5', 'ugcify' ) ),
				),
			),
			'openai'    => array(
				'label'         => __( 'OpenAI', 'ugcify' ),
				'api_key_label' => __( 'OpenAI API key', 'ugcify' ),
				'api_key_placeholder' => __( 'Enter OpenAI API key', 'ugcify' ),
				'default_model' => 'gpt-5.4-mini',
				'models'        => array(
					array( 'value' => 'gpt-5.5', 'label' => __( 'GPT-5.5', 'ugcify' ) ),
					array( 'value' => 'gpt-5.4', 'label' => __( 'GPT-5.4', 'ugcify' ) ),
					array( 'value' => 'gpt-5.4-mini', 'label' => __( 'GPT-5.4 Mini', 'ugcify' ) ),
				),
			),
			'gemini'    => array(
				'label'         => __( 'Gemini', 'ugcify' ),
				'api_key_label' => __( 'Gemini API key', 'ugcify' ),
				'api_key_placeholder' => __( 'Enter Gemini API key', 'ugcify' ),
				'default_model' => 'gemini-2.5-flash',
				'models'        => array(
					array( 'value' => 'gemini-2.5-flash', 'label' => __( 'Gemini 2.5 Flash', 'ugcify' ) ),
					array( 'value' => 'gemini-2.5-flash-lite', 'label' => __( 'Gemini 2.5 Flash-Lite', 'ugcify' ) ),
					array( 'value' => 'gemini-2.5-pro', 'label' => __( 'Gemini 2.5 Pro', 'ugcify' ) ),
				),
			),
		);
	}

	/**
	 * Get normalized stored settings.
	 *
	 * @return array<string,mixed>
	 */
	public static function get_settings(): array {
		$stored = get_option( self::OPTION_NAME, array() );
		$stored = is_array( $stored ) ? $stored : array();

		return self::normalize( $stored );
	}

	/**
	 * Get public settings for REST response.
	 *
	 * @return array<string,mixed>
	 */
	public static function get_public_settings(): array {
		$settings    = self::get_settings();
		$definitions = self::get_provider_definitions();
		$providers   = array();
		$wp_ai_connectors = self::get_wordpress_ai_connectors();
		$wp_ai_installed   = self::is_wordpress_ai_plugin_installed();
		$wp_ai_active      = self::is_wordpress_ai_plugin_active();
		$wp_ai_enabled    = self::is_wordpress_ai_enabled();
		$wp_ai_available  = self::is_wordpress_ai_available();
		$wp_ai_has_credentials = self::has_wordpress_ai_credentials();
		$wp_ai_has_connectors  = ! empty( $wp_ai_connectors );

		foreach ( $definitions as $provider => $definition ) {
			$config = isset( $settings['providers'][ $provider ] ) && is_array( $settings['providers'][ $provider ] )
				? $settings['providers'][ $provider ]
				: array();

			$providers[ $provider ] = array(
				'label'               => (string) $definition['label'],
				'api_key_label'       => (string) ( $definition['api_key_label'] ?? '' ),
				'api_key_placeholder' => (string) ( $definition['api_key_placeholder'] ?? '' ),
				'requires_api_key'    => isset( $definition['requires_api_key'] ) ? (bool) $definition['requires_api_key'] : true,
				'available'           => 'wordpress' === $provider ? $wp_ai_available : true,
				'model'               => (string) ( $config['model'] ?? $definition['default_model'] ),
				'default_model'       => (string) $definition['default_model'],
				'models'              => $definition['models'],
				'has_api_key'         => self::has_api_key( $provider, $settings ),
				'has_stored_api_key'  => 'wordpress' !== $provider && '' !== (string) ( $config['api_key'] ?? '' ),
			);

			if ( 'wordpress' === $provider ) {
				$providers[ $provider ]['connectors'] = $wp_ai_connectors;
			}
		}

		return array(
			'enabled'         => (bool) $settings['enabled'],
			'provider'        => (string) $settings['provider'],
			'providers'       => $providers,
			'has_api_key'     => self::has_api_key( (string) $settings['provider'], $settings ),
			'model'           => self::get_model( (string) $settings['provider'], $settings ),
			'max_candidates'  => (int) $settings['max_candidates'],
			'max_suggestions' => (int) $settings['max_suggestions'],
			'min_confidence'  => (float) $settings['min_confidence'],
			'wordpress_ai'    => array(
				'installed'       => $wp_ai_installed,
				'active'          => $wp_ai_active,
				'enabled'         => $wp_ai_enabled,
				'has_connectors'  => $wp_ai_has_connectors,
				'available'       => $wp_ai_available,
				'has_credentials' => $wp_ai_has_credentials,
				'connectors'      => $wp_ai_connectors,
			),
		);
	}

	/**
	 * Save settings from REST payload.
	 *
	 * @param array<string,mixed> $params Request params.
	 * @return array<string,mixed>
	 */
	public static function save_from_request( array $params ): array {
		$current = self::get_settings();
		$updated = $current;

		if ( isset( $params['enabled'] ) ) {
			$updated['enabled'] = (bool) $params['enabled'];
		}

		if ( isset( $params['provider'] ) ) {
			$provider = sanitize_key( (string) $params['provider'] );
			if ( self::is_supported_provider( $provider ) ) {
				$updated['provider'] = $provider;
				$updated['prefer_native_ai'] = 'wordpress' !== $provider && self::is_wordpress_ai_available();
			}
		}

		$providers_param = isset( $params['providers'] ) && is_array( $params['providers'] ) ? $params['providers'] : array();
		foreach ( self::get_provider_definitions() as $provider => $definition ) {
			$config_param = isset( $providers_param[ $provider ] ) && is_array( $providers_param[ $provider ] ) ? $providers_param[ $provider ] : array();

			if ( isset( $config_param['model'] ) ) {
				$updated['providers'][ $provider ]['model'] = self::sanitize_model( $provider, (string) $config_param['model'] );
			}

			if ( ! empty( $config_param['delete_api_key'] ) && 'wordpress' !== $provider ) {
				$updated['providers'][ $provider ]['api_key'] = '';
				continue;
			}

			if ( array_key_exists( 'api_key', $config_param ) && '' !== trim( (string) $config_param['api_key'] ) ) {
				$updated['providers'][ $provider ]['api_key'] = sanitize_text_field( (string) $config_param['api_key'] );
			}
		}

		if ( isset( $params['model'] ) ) {
			$updated['providers'][ $updated['provider'] ]['model'] = self::sanitize_model( (string) $updated['provider'], (string) $params['model'] );
		}

		if ( array_key_exists( 'anthropic_api_key', $params ) && '' !== trim( (string) $params['anthropic_api_key'] ) ) {
			$updated['providers']['anthropic']['api_key'] = sanitize_text_field( (string) $params['anthropic_api_key'] );
		}

		if ( isset( $params['max_candidates'] ) ) {
			$updated['max_candidates'] = max( 1, min( 20, (int) $params['max_candidates'] ) );
		}

		if ( isset( $params['max_suggestions'] ) ) {
			$updated['max_suggestions'] = max( 1, min( 10, (int) $params['max_suggestions'] ) );
		}

		if ( isset( $params['min_confidence'] ) ) {
			$updated['min_confidence'] = max( 0, min( 1, (float) $params['min_confidence'] ) );
		}

		$updated = self::normalize( $updated );
		update_option( self::OPTION_NAME, $updated, false );

		return $updated;
	}

	/**
	 * Get API key for provider.
	 *
	 * @param string              $provider Provider slug.
	 * @param array<string,mixed> $settings Settings.
	 * @return string
	 */
	public static function get_api_key( string $provider, array $settings ): string {
		$constant = self::get_api_key_constant( $provider );
		if ( $constant && defined( $constant ) && constant( $constant ) ) {
			return (string) constant( $constant );
		}

		return isset( $settings['providers'][ $provider ]['api_key'] ) ? (string) $settings['providers'][ $provider ]['api_key'] : '';
	}

	/**
	 * Check provider API key.
	 *
	 * @param string              $provider Provider slug.
	 * @param array<string,mixed> $settings Settings.
	 * @return bool
	 */
	public static function has_api_key( string $provider, array $settings ): bool {
		if ( 'wordpress' === $provider ) {
			return self::is_wordpress_ai_available();
		}

		return '' !== self::get_api_key( $provider, $settings );
	}

	/**
	 * Check whether a WordPress-provided AI connection is available.
	 *
	 * @return bool
	 */
	public static function is_wordpress_ai_available(): bool {
		$available = self::is_wordpress_ai_enabled() && self::has_wordpress_ai_credentials();

		return (bool) apply_filters( 'ugcify_wordpress_ai_available', $available );
	}

	/**
	 * Check whether the WordPress AI plugin is installed.
	 *
	 * @return bool
	 */
	public static function is_wordpress_ai_plugin_installed(): bool {
		if ( self::is_wordpress_ai_plugin_active() ) {
			return (bool) apply_filters( 'ugcify_wordpress_ai_plugin_installed', true );
		}

		if ( ! function_exists( 'get_plugins' ) && defined( 'ABSPATH' ) ) {
			$plugin_api_file = ABSPATH . 'wp-admin/includes/plugin.php';
			if ( is_readable( $plugin_api_file ) ) {
				require_once $plugin_api_file;
			}
		}

		$installed = false;
		if ( function_exists( 'get_plugins' ) ) {
			foreach ( (array) get_plugins() as $plugin_file => $plugin_data ) {
				$text_domain = is_array( $plugin_data ) ? (string) ( $plugin_data['TextDomain'] ?? '' ) : '';
				$plugin_name = is_array( $plugin_data ) ? (string) ( $plugin_data['Name'] ?? '' ) : '';

				if ( 'ai/ai.php' === $plugin_file || ( 'ai' === $text_domain && 'AI' === $plugin_name ) ) {
					$installed = true;
					break;
				}
			}
		}

		return (bool) apply_filters( 'ugcify_wordpress_ai_plugin_installed', $installed );
	}

	/**
	 * Check whether the WordPress AI plugin is active.
	 *
	 * @return bool
	 */
	public static function is_wordpress_ai_plugin_active(): bool {
		$active = defined( 'WPAI_PLUGIN_FILE' )
			|| function_exists( '\\WordPress\\AI\\get_ai_connectors' )
			|| function_exists( '\\WordPress\\AI\\has_ai_credentials' );

		return (bool) apply_filters( 'ugcify_wordpress_ai_plugin_active', $active );
	}

	/**
	 * Check whether WordPress AI is enabled.
	 *
	 * @return bool
	 */
	public static function is_wordpress_ai_enabled(): bool {
		$enabled = false;

		if ( function_exists( '\WordPress\AI\has_ai_credentials' ) ) {
			$enabled = (bool) get_option( 'wpai_features_enabled', false );
		} else {
			$enabled = (
				function_exists( 'wp_ai_generate' )
				|| function_exists( 'wp_ai_generate_text' )
				|| function_exists( 'wp_ai_client_prompt' )
				|| class_exists( 'WP_AI_Client' )
				|| class_exists( '\WP\AI\Client' )
			);
		}

		return (bool) apply_filters( 'ugcify_wordpress_ai_enabled', $enabled );
	}

	/**
	 * Check whether WordPress AI has usable connector credentials.
	 *
	 * @return bool
	 */
	public static function has_wordpress_ai_credentials(): bool {
		$has_credentials = false;

		if ( function_exists( '\WordPress\AI\has_ai_credentials' ) ) {
			try {
				$has_credentials = (bool) \WordPress\AI\has_ai_credentials();
			} catch ( \Throwable $throwable ) {
				$has_credentials = false;
			}
		} elseif (
			function_exists( '\WordPress\AI\get_ai_connectors' )
			&& function_exists( '\WordPress\AI\has_connector_authentication' )
		) {
			try {
				foreach ( (array) \WordPress\AI\get_ai_connectors() as $connector_id => $connector ) {
					if ( \WordPress\AI\has_connector_authentication( (string) $connector_id ) ) {
						$has_credentials = true;
						break;
					}
				}
			} catch ( \Throwable $throwable ) {
				$has_credentials = false;
			}
		}

		return (bool) apply_filters( 'ugcify_wordpress_ai_has_credentials', $has_credentials );
	}

	/**
	 * Get active WordPress AI connectors.
	 *
	 * @return array<int,array<string,mixed>>
	 */
	public static function get_wordpress_ai_connectors(): array {
		$connectors = array();

		if ( ! function_exists( '\WordPress\AI\get_ai_connectors' ) ) {
			return (array) apply_filters( 'ugcify_wordpress_ai_connectors', $connectors );
		}

		try {
			$wp_connectors = \WordPress\AI\get_ai_connectors();
		} catch ( \Throwable $throwable ) {
			return (array) apply_filters( 'ugcify_wordpress_ai_connectors', $connectors );
		}

		foreach ( $wp_connectors as $connector_id => $connector ) {
			if ( ! is_array( $connector ) ) {
				continue;
			}

			$label = '';
			foreach ( array( 'name', 'label', 'title' ) as $label_key ) {
				if ( ! empty( $connector[ $label_key ] ) && is_string( $connector[ $label_key ] ) ) {
					$label = $connector[ $label_key ];
					break;
				}
			}

			if ( '' === $label && ! empty( $connector['provider'] ) && is_string( $connector['provider'] ) ) {
				$label = $connector['provider'];
			}

			if ( '' === $label ) {
				$label = (string) $connector_id;
			}

			$has_credentials = false;
			if ( function_exists( '\WordPress\AI\has_connector_authentication' ) ) {
				try {
					$has_credentials = (bool) \WordPress\AI\has_connector_authentication( (string) $connector_id );
				} catch ( \Throwable $throwable ) {
					$has_credentials = false;
				}
			}

			$connectors[] = array(
				'id'              => (string) $connector_id,
				'label'           => sanitize_text_field( $label ),
				'has_credentials' => $has_credentials,
			);
		}

		return (array) apply_filters( 'ugcify_wordpress_ai_connectors', array_values( $connectors ) );
	}

	/**
	 * Get selected model.
	 *
	 * @param string              $provider Provider slug.
	 * @param array<string,mixed> $settings Settings.
	 * @return string
	 */
	public static function get_model( string $provider, array $settings ): string {
		$definitions = self::get_provider_definitions();
		$default     = isset( $definitions[ $provider ] ) ? (string) $definitions[ $provider ]['default_model'] : '';
		$model       = isset( $settings['providers'][ $provider ]['model'] ) ? (string) $settings['providers'][ $provider ]['model'] : $default;

		return self::sanitize_model( $provider, $model );
	}

	/**
	 * Normalize setting array.
	 *
	 * @param array<string,mixed> $settings Raw settings.
	 * @return array<string,mixed>
	 */
	private static function normalize( array $settings ): array {
		$definitions = self::get_provider_definitions();
		$provider    = isset( $settings['provider'] ) ? sanitize_key( (string) $settings['provider'] ) : self::DEFAULT_PROVIDER;
		$prefer_native_ai = ! empty( $settings['prefer_native_ai'] );
		if ( ! self::is_supported_provider( $provider ) ) {
			$provider = self::DEFAULT_PROVIDER;
		}
		if ( self::is_wordpress_ai_available() && ! $prefer_native_ai ) {
			$provider = 'wordpress';
		} elseif ( 'wordpress' === $provider && ! self::is_wordpress_ai_available() ) {
			$provider = self::DEFAULT_PROVIDER;
		}

		$providers = array();
		$stored_providers = isset( $settings['providers'] ) && is_array( $settings['providers'] ) ? $settings['providers'] : array();

		foreach ( $definitions as $slug => $definition ) {
			$stored = isset( $stored_providers[ $slug ] ) && is_array( $stored_providers[ $slug ] ) ? $stored_providers[ $slug ] : array();
			$providers[ $slug ] = array(
				'api_key' => isset( $stored['api_key'] ) ? (string) $stored['api_key'] : '',
				'model'   => self::sanitize_model( $slug, isset( $stored['model'] ) ? (string) $stored['model'] : (string) $definition['default_model'] ),
			);
		}

		if ( ! empty( $settings['anthropic_api_key'] ) && '' === $providers['anthropic']['api_key'] ) {
			$providers['anthropic']['api_key'] = (string) $settings['anthropic_api_key'];
		}

		if ( ! empty( $settings['model'] ) ) {
			$providers['anthropic']['model'] = self::sanitize_model( 'anthropic', (string) $settings['model'] );
		}

		return array(
			'enabled'         => isset( $settings['enabled'] ) ? (bool) $settings['enabled'] : true,
			'provider'        => $provider,
			'prefer_native_ai' => $prefer_native_ai,
			'providers'       => $providers,
			'max_candidates'  => isset( $settings['max_candidates'] ) ? max( 1, min( 20, (int) $settings['max_candidates'] ) ) : 8,
			'max_suggestions' => isset( $settings['max_suggestions'] ) ? max( 1, min( 10, (int) $settings['max_suggestions'] ) ) : 5,
			'min_confidence'  => isset( $settings['min_confidence'] ) ? max( 0, min( 1, (float) $settings['min_confidence'] ) ) : 0.65,
		);
	}

	/**
	 * Check provider support.
	 *
	 * @param string $provider Provider slug.
	 * @return bool
	 */
	private static function is_supported_provider( string $provider ): bool {
		return array_key_exists( $provider, self::get_provider_definitions() );
	}

	/**
	 * Validate model.
	 *
	 * @param string $provider Provider slug.
	 * @param string $model Model.
	 * @return string
	 */
	private static function sanitize_model( string $provider, string $model ): string {
		$definitions = self::get_provider_definitions();
		if ( ! isset( $definitions[ $provider ] ) ) {
			return '';
		}

		$allowed = array_map(
			static function ( array $item ) {
				return (string) $item['value'];
			},
			$definitions[ $provider ]['models']
		);

		$model = sanitize_text_field( $model );
		return in_array( $model, $allowed, true ) ? $model : (string) $definitions[ $provider ]['default_model'];
	}

	/**
	 * Get provider API key constant name.
	 *
	 * @param string $provider Provider slug.
	 * @return string
	 */
	private static function get_api_key_constant( string $provider ): string {
		$constants = array(
			'anthropic' => 'UGCIFY_ANTHROPIC_API_KEY',
			'openai'    => 'UGCIFY_OPENAI_API_KEY',
			'gemini'    => 'UGCIFY_GEMINI_API_KEY',
		);

		return isset( $constants[ $provider ] ) ? $constants[ $provider ] : '';
	}
}
