<?php

/**
 * AI Magic Provider Manager
 *
 * Manages AI providers and their specific settings
 *
 * @link       https://insya.com/ai-magic
 * @since      1.0.8
 *
 * @package    Ai_Magic
 * @subpackage Ai_Magic/admin
 */

/**
 * Provider Manager Class
 *
 * @package    Ai_Magic
 * @subpackage Ai_Magic/admin
 * @author     AI Magic <info@insya.com>
 */
class AI_Magic_Provider_Manager
{
    /**
     * Available providers configuration
     *
     * @var array
     */
    private static $providers = array(
        'openai' => array(
            'name' => 'OpenAI',
            'description' => 'GPT-4, GPT-4 Turbo, GPT-3.5 Turbo',
            'default_model' => 'gpt-4-turbo',
            'default_max_tokens' => 4000,
            'default_temperature' => 0.7,
            'default_top_p' => 1.0,
            'default_frequency_penalty' => 0,
            'default_presence_penalty' => 0,
            'supports_images' => true,
            'class' => 'AI_Magic_OpenAI'
        ),
        'anthropic' => array(
            'name' => 'Anthropic',
            'description' => 'Claude 3.5 Sonnet, Claude 3 Opus',
            'default_model' => 'claude-3-5-sonnet-20241022',
            'default_max_tokens' => 4096,
            'default_temperature' => 0.5,
            'default_top_p' => 1.0,
            'default_frequency_penalty' => 0,
            'default_presence_penalty' => 0,
            'supports_images' => false,
            'class' => 'AI_Magic_Anthropic'
        ),
        'google' => array(
            'name' => 'Google AI',
            'description' => 'Gemini Pro, Gemini Flash',
            'default_model' => 'gemini-pro',
            'default_max_tokens' => 2048,
            'default_temperature' => 0.9,
            'default_top_p' => 1.0,
            'default_frequency_penalty' => 0,
            'default_presence_penalty' => 0,
            'supports_images' => false,
            'class' => 'AI_Magic_Google'
        ),
        'openrouter' => array(
            'name' => 'OpenRouter',
            'description' => '400+ Models (GPT, Claude, Gemini, Llama, Mistral...)',
            'default_model' => 'openai/gpt-4o',
            'default_max_tokens' => 4096,
            'default_temperature' => 0.7,
            'default_top_p' => 1.0,
            'default_frequency_penalty' => 0,
            'default_presence_penalty' => 0,
            'supports_images' => false,
            'class' => 'AI_Magic_OpenRouter'
        )
    );

    /**
     * Get all providers
     *
     * @since    1.0.8
     * @return   array    List of providers
     */
    public static function get_providers()
    {
        return self::$providers;
    }

    /**
     * Get provider configuration
     *
     * @since    1.0.8
     * @param    string    $provider_id    Provider ID
     * @return   array|null                Provider config or null
     */
    public static function get_provider($provider_id)
    {
        return isset(self::$providers[$provider_id]) ? self::$providers[$provider_id] : null;
    }

    /**
     * Get provider settings
     *
     * @since    1.0.8
     * @param    string    $provider_id    Provider ID
     * @return   array                     Provider settings
     */
    public static function get_provider_settings($provider_id)
    {
        $provider = self::get_provider($provider_id);
        if (!$provider) {
            return array();
        }

        return array(
            'active' => get_option("ai_magic_{$provider_id}_active", $provider_id === 'openai' ? 'yes' : 'no'),
            'api_key' => get_option("ai_magic_api_key_{$provider_id}", ''),
            'model' => get_option("ai_magic_{$provider_id}_model", $provider['default_model']),
            'max_tokens' => (int) get_option("ai_magic_{$provider_id}_max_tokens", $provider['default_max_tokens']),
            'temperature' => (float) get_option("ai_magic_{$provider_id}_temperature", $provider['default_temperature']),
            'top_p' => (float) get_option("ai_magic_{$provider_id}_top_p", $provider['default_top_p']),
            'frequency_penalty' => (float) get_option("ai_magic_{$provider_id}_frequency_penalty", $provider['default_frequency_penalty']),
            'presence_penalty' => (float) get_option("ai_magic_{$provider_id}_presence_penalty", $provider['default_presence_penalty']),
            'language' => get_option("ai_magic_{$provider_id}_language", 'en'),
            'style' => get_option("ai_magic_{$provider_id}_style", 'informative'),
            'tone' => get_option("ai_magic_{$provider_id}_tone", 'professional')
        );
    }

    /**
     * Save provider settings
     *
     * @since    1.0.8
     * @param    string    $provider_id    Provider ID
     * @param    array     $settings       Settings to save
     * @return   bool                      Success status
     */
    public static function save_provider_settings($provider_id, $settings)
    {
        if (!self::get_provider($provider_id)) {
            return false;
        }

        $allowed_settings = array(
            'active',
            'api_key',
            'model',
            'max_tokens',
            'temperature',
            'top_p',
            'frequency_penalty',
            'presence_penalty',
            'language',
            'style',
            'tone'
        );

        foreach ($settings as $key => $value) {
            if (!in_array($key, $allowed_settings)) {
                continue;
            }

            $option_name = "ai_magic_{$provider_id}_{$key}";
            if ($key === 'api_key') {
                $option_name = "ai_magic_api_key_{$provider_id}";
            }

            // Sanitize values based on type
            switch ($key) {
                case 'active':
                    $value = $value === 'yes' ? 'yes' : 'no';
                    break;
                case 'api_key':
                case 'model':
                case 'language':
                case 'style':
                case 'tone':
                    $value = sanitize_text_field($value);
                    break;
                case 'max_tokens':
                    $value = absint($value);
                    break;
                case 'temperature':
                case 'top_p':
                case 'frequency_penalty':
                case 'presence_penalty':
                    $value = floatval($value);
                    break;
            }

            update_option($option_name, $value);
        }

        return true;
    }

    /**
     * Get all provider settings
     *
     * @since    1.0.8
     * @return   array    All provider settings
     */
    public static function get_all_provider_settings()
    {
        $all_settings = array();
        foreach (array_keys(self::$providers) as $provider_id) {
            $all_settings[$provider_id] = self::get_provider_settings($provider_id);
        }
        return $all_settings;
    }

    /**
     * Get active providers
     *
     * @since    1.0.8
     * @return   array    List of active provider IDs
     */
    public static function get_active_providers()
    {
        $active = array();
        foreach (array_keys(self::$providers) as $provider_id) {
            if (get_option("ai_magic_{$provider_id}_active", 'no') === 'yes') {
                $active[] = $provider_id;
            }
        }
        return $active;
    }

    /**
     * Get provider instance
     *
     * @since    1.0.8
     * @param    string    $provider_id    Provider ID
     * @return   object|null               Provider instance or null
     */
    public static function get_provider_instance($provider_id)
    {
        $provider = self::get_provider($provider_id);
        if (!$provider) {
            return null;
        }

        $class = $provider['class'];
        if (!class_exists($class)) {
            $file = plugin_dir_path(__FILE__) . 'class-ai-magic-' . $provider_id . '.php';
            if (file_exists($file)) {
                require_once $file;
            }
        }

        if (class_exists($class)) {
            return new $class();
        }

        return null;
    }

    /**
     * Get default provider
     *
     * @since    1.0.8
     * @return   string    Default provider ID
     */
    public static function get_default_provider()
    {
        $active_provider = get_option('ai_magic_active_provider');
        if ($active_provider && self::get_provider($active_provider)) {
            return $active_provider;
        }

        $active = self::get_active_providers();
        if (!empty($active)) {
            return $active[0];
        }
        return 'openai';
    }

    /**
     * Check if provider is configured
     *
     * @since    1.0.8
     * @param    string    $provider_id    Provider ID
     * @return   bool                      True if configured
     */
    public static function is_provider_configured($provider_id)
    {
        $settings = self::get_provider_settings($provider_id);
        return !empty($settings['api_key']) && $settings['active'] === 'yes';
    }

    /**
     * Migrate legacy settings to new structure
     *
     * @since    1.0.8
     * @return   bool    Success status
     */
    public static function migrate_legacy_settings()
    {
        // Check if migration already done
        if (get_option('ai_magic_settings_migrated', false)) {
            return true;
        }

        // Migrate OpenAI legacy settings
        $legacy_api_key = get_option('ai_magic_api_key', '');
        if (!empty($legacy_api_key) && empty(get_option('ai_magic_api_key_openai', ''))) {
            update_option('ai_magic_api_key_openai', $legacy_api_key);
            update_option('ai_magic_openai_active', 'yes');
        }

        // Migrate model setting
        $legacy_model = get_option('ai_magic_model', '');
        if (!empty($legacy_model)) {
            // Determine which provider this model belongs to
            if (strpos($legacy_model, 'gpt') !== false) {
                update_option('ai_magic_openai_model', $legacy_model);
            } elseif (strpos($legacy_model, 'claude') !== false) {
                update_option('ai_magic_anthropic_model', $legacy_model);
            } elseif (strpos($legacy_model, 'gemini') !== false) {
                update_option('ai_magic_google_model', $legacy_model);
            }
        }

        // Migrate common settings to all providers
        $common_settings = array(
            'max_tokens' => get_option('ai_magic_max_tokens', ''),
            'temperature' => get_option('ai_magic_temperature', ''),
            'top_p' => get_option('ai_magic_top_p', ''),
            'frequency_penalty' => get_option('ai_magic_frequency_penalty', ''),
            'presence_penalty' => get_option('ai_magic_presence_penalty', '')
        );

        foreach (array_keys(self::$providers) as $provider_id) {
            foreach ($common_settings as $setting => $value) {
                if (!empty($value) && empty(get_option("ai_magic_{$provider_id}_{$setting}", ''))) {
                    update_option("ai_magic_{$provider_id}_{$setting}", $value);
                }
            }
        }

        // Mark migration as complete
        update_option('ai_magic_settings_migrated', true);

        return true;
    }

    /**
     * Get available models for a provider
     *
     * @since    1.0.8
     * @param    string    $provider_id    Provider ID
     * @return   array                     List of models
     */
    public static function get_available_models($provider_id)
    {
        $models = array();

        switch ($provider_id) {
            case 'openai':
                $models = array(
                    array('id' => 'gpt-4o', 'name' => 'GPT-4o (Latest)', 'recommended' => true),
                    array('id' => 'gpt-4o-mini', 'name' => 'GPT-4o Mini (Fast & Cheap)', 'recommended' => true),
                    array('id' => 'gpt-4-turbo', 'name' => 'GPT-4 Turbo'),
                    array('id' => 'gpt-4', 'name' => 'GPT-4'),
                    array('id' => 'gpt-3.5-turbo', 'name' => 'GPT-3.5 Turbo'),
                    array('id' => 'gpt-3.5-turbo-16k', 'name' => 'GPT-3.5 Turbo 16K')
                );
                break;

            case 'anthropic':
                $models = array(
                    array('id' => 'claude-3-5-sonnet-20241022', 'name' => 'Claude 3.5 Sonnet', 'recommended' => true),
                    array('id' => 'claude-3-opus-20240229', 'name' => 'Claude 3 Opus'),
                    array('id' => 'claude-3-sonnet-20240229', 'name' => 'Claude 3 Sonnet'),
                    array('id' => 'claude-3-haiku-20240307', 'name' => 'Claude 3 Haiku (Fast)')
                );
                break;

            case 'google':
                $models = array(
                    array('id' => 'gemini-1.5-pro', 'name' => 'Gemini 1.5 Pro', 'recommended' => true),
                    array('id' => 'gemini-1.5-flash', 'name' => 'Gemini 1.5 Flash (Fast)'),
                    array('id' => 'gemini-pro', 'name' => 'Gemini Pro'),
                    array('id' => 'gemini-pro-vision', 'name' => 'Gemini Pro Vision')
                );
                break;

            case 'openrouter':
                $models = array(
                    // OpenAI via OpenRouter
                    array('id' => 'openai/gpt-4o', 'name' => 'GPT-4o (OpenAI)', 'recommended' => true),
                    array('id' => 'openai/gpt-4o-mini', 'name' => 'GPT-4o Mini (OpenAI)'),
                    array('id' => 'openai/o1-preview', 'name' => 'O1 Preview (OpenAI)'),
                    array('id' => 'openai/o1-mini', 'name' => 'O1 Mini (OpenAI)'),
                    // Anthropic via OpenRouter
                    array('id' => 'anthropic/claude-3.5-sonnet', 'name' => 'Claude 3.5 Sonnet', 'recommended' => true),
                    array('id' => 'anthropic/claude-3-opus', 'name' => 'Claude 3 Opus'),
                    array('id' => 'anthropic/claude-3-haiku', 'name' => 'Claude 3 Haiku (Fast)'),
                    // Google via OpenRouter
                    array('id' => 'google/gemini-pro-1.5', 'name' => 'Gemini Pro 1.5'),
                    array('id' => 'google/gemini-flash-1.5', 'name' => 'Gemini Flash 1.5'),
                    array('id' => 'google/gemini-2.0-flash-exp:free', 'name' => 'Gemini 2.0 Flash (Free)'),
                    // Meta Llama
                    array('id' => 'meta-llama/llama-3.3-70b-instruct', 'name' => 'Llama 3.3 70B'),
                    array('id' => 'meta-llama/llama-3.1-405b-instruct', 'name' => 'Llama 3.1 405B'),
                    // Mistral
                    array('id' => 'mistralai/mistral-large', 'name' => 'Mistral Large'),
                    array('id' => 'mistralai/mixtral-8x22b-instruct', 'name' => 'Mixtral 8x22B'),
                    // DeepSeek
                    array('id' => 'deepseek/deepseek-chat', 'name' => 'DeepSeek Chat'),
                    // Qwen
                    array('id' => 'qwen/qwen-2.5-72b-instruct', 'name' => 'Qwen 2.5 72B'),
                    // Free Models
                    array('id' => 'nousresearch/hermes-3-llama-3.1-405b:free', 'name' => 'Hermes 3 405B (Free)'),
                    array('id' => 'meta-llama/llama-3.2-3b-instruct:free', 'name' => 'Llama 3.2 3B (Free)')
                );
                break;
        }

        return $models;
    }
}
