<?php

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

class AI_eShop_Chat_Model_Registry {

    
    private static $instance = null;

    
    private $table_name;

    
    const ANTHROPIC_MODELS_URL = 'https://api.anthropic.com/v1/models';
    const OPENAI_MODELS_URL = 'https://api.openai.com/v1/models';
    const VOYAGE_MODELS_URL = 'https://api.voyageai.com/v1/models';

    
    const TYPE_CHAT = 'chat';
    const TYPE_EMBEDDING = 'embedding';

    
    const PROVIDER_ANTHROPIC = 'anthropic';
    const PROVIDER_OPENAI = 'openai';
    const PROVIDER_VOYAGE = 'voyage';

    
    public static function get_instance() {
        if (null === self::$instance) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    
    private function __construct() {
        global $wpdb;
        $this->table_name = $wpdb->prefix . 'aieo_ai_models';

        
        add_action('wp_ajax_aieo_refresh_ai_models', array($this, 'ajax_refresh_models'));
        add_action('wp_ajax_aieo_validate_api_keys', array($this, 'ajax_validate_api_keys'));
        add_action('wp_ajax_aieo_chat_model_test', array($this, 'ajax_model_test'));
        add_action('wp_ajax_aieo_chat_model_detect', array($this, 'ajax_model_detect'));

        
        add_action('admin_init', array($this, 'maybe_create_table'));

        
        if (!wp_next_scheduled('aieo_monthly_model_refresh')) {
            wp_schedule_event(time(), 'monthly', 'aieo_monthly_model_refresh');
        }
        add_action('aieo_monthly_model_refresh', array($this, 'cron_refresh_models'));
    }

    
    public function cron_refresh_models() {
        if ('' === (string) get_option('aieo_rooster_api_key', '')) { return; }
        return $this->refresh_all_models();
    }

    
    public function maybe_create_table() {
        global $wpdb;

        $table_exists = $wpdb->get_var("SHOW TABLES LIKE '{$this->table_name}'");
        if ($table_exists) {
            return;
        }

        $this->create_table();
    }

    
    public function create_table() {
        global $wpdb;

        $charset_collate = $wpdb->get_charset_collate();

        $sql = "CREATE TABLE IF NOT EXISTS {$this->table_name} (
            id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,
            provider varchar(50) NOT NULL,
            model_id varchar(100) NOT NULL,
            model_name varchar(255) NOT NULL,
            model_type varchar(50) NOT NULL DEFAULT 'chat',
            description text DEFAULT NULL,
            max_tokens int(11) DEFAULT NULL,
            dimensions int(11) DEFAULT NULL,
            is_recommended tinyint(1) DEFAULT 0,
            is_active tinyint(1) DEFAULT 1,
            sort_order int(11) DEFAULT 0,
            metadata longtext DEFAULT NULL,
            created_at datetime DEFAULT CURRENT_TIMESTAMP,
            updated_at datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
            PRIMARY KEY (id),
            UNIQUE KEY provider_model (provider, model_id),
            KEY model_type (model_type),
            KEY is_active (is_active),
            KEY sort_order (sort_order)
        ) $charset_collate;";

        require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
        dbDelta($sql);

        
        $count = $wpdb->get_var("SELECT COUNT(*) FROM {$this->table_name}");
        if ($count == 0) {
            $this->insert_fallback_models();
        }
    }

    
    private function insert_fallback_models() {
        
        $this->insert_model(self::PROVIDER_ANTHROPIC, 'claude-opus-4-5-20251101', 'Claude Opus 4.5', self::TYPE_CHAT, 'Most intelligent model - hybrid reasoning', 16384, null, true, 10);
        $this->insert_model(self::PROVIDER_ANTHROPIC, 'claude-sonnet-4-5-20250929', 'Claude Sonnet 4.5', self::TYPE_CHAT, 'Balanced performance and speed', 16384, null, false, 20);
        $this->insert_model(self::PROVIDER_ANTHROPIC, 'claude-haiku-4-5-20251001', 'Claude Haiku 4.5', self::TYPE_CHAT, 'Fastest and most economical', 8192, null, false, 30);
        $this->insert_model(self::PROVIDER_ANTHROPIC, 'claude-opus-4-1-20250805', 'Claude Opus 4.1', self::TYPE_CHAT, 'Advanced reasoning capabilities', 8192, null, false, 40);
        $this->insert_model(self::PROVIDER_ANTHROPIC, 'claude-sonnet-4-20250514', 'Claude Sonnet 4', self::TYPE_CHAT, 'Balanced Claude 4 model', 8192, null, false, 50);
        $this->insert_model(self::PROVIDER_ANTHROPIC, 'claude-3-5-sonnet-20241022', 'Claude 3.5 Sonnet', self::TYPE_CHAT, 'Previous generation model', 8192, null, false, 60);
        $this->insert_model(self::PROVIDER_ANTHROPIC, 'claude-3-5-haiku-20241022', 'Claude 3.5 Haiku', self::TYPE_CHAT, 'Fast and economical', 8192, null, false, 70);

        
        $this->insert_model(self::PROVIDER_OPENAI, 'gpt-4o', 'GPT-4o', self::TYPE_CHAT, 'Most capable multimodal model', 16384, null, true, 10);
        $this->insert_model(self::PROVIDER_OPENAI, 'gpt-4o-mini', 'GPT-4o Mini', self::TYPE_CHAT, 'Fast and economical', 16384, null, false, 20);
        $this->insert_model(self::PROVIDER_OPENAI, 'gpt-4-turbo', 'GPT-4 Turbo', self::TYPE_CHAT, 'GPT-4 Turbo with vision', 4096, null, false, 30);
        $this->insert_model(self::PROVIDER_OPENAI, 'o1', 'O1', self::TYPE_CHAT, 'Advanced reasoning model', 32768, null, false, 40);
        $this->insert_model(self::PROVIDER_OPENAI, 'o1-mini', 'O1 Mini', self::TYPE_CHAT, 'Reasoning model - economical', 16384, null, false, 50);
        $this->insert_model(self::PROVIDER_OPENAI, 'o3-mini', 'O3 Mini', self::TYPE_CHAT, 'Latest reasoning model', 16384, null, false, 60);
        $this->insert_model(self::PROVIDER_OPENAI, 'gpt-3.5-turbo', 'GPT-3.5 Turbo', self::TYPE_CHAT, 'Budget-friendly option', 4096, null, false, 70);

        
        $this->insert_model(self::PROVIDER_OPENAI, 'text-embedding-3-large', 'Text Embedding 3 Large', self::TYPE_EMBEDDING, 'Best quality embeddings', null, 3072, true, 10);
        $this->insert_model(self::PROVIDER_OPENAI, 'text-embedding-3-small', 'Text Embedding 3 Small', self::TYPE_EMBEDDING, 'Efficient embeddings', null, 1536, false, 20);
        $this->insert_model(self::PROVIDER_OPENAI, 'text-embedding-ada-002', 'Text Embedding Ada 002', self::TYPE_EMBEDDING, 'Legacy embeddings', null, 1536, false, 30);

        
        $this->insert_model(self::PROVIDER_VOYAGE, 'voyage-3', 'Voyage 3', self::TYPE_EMBEDDING, 'Latest generation - recommended', null, 1024, true, 10);
        $this->insert_model(self::PROVIDER_VOYAGE, 'voyage-3-lite', 'Voyage 3 Lite', self::TYPE_EMBEDDING, 'Faster, smaller dimensions', null, 512, false, 20);
        $this->insert_model(self::PROVIDER_VOYAGE, 'voyage-3-large', 'Voyage 3 Large', self::TYPE_EMBEDDING, 'Best quality, larger dimensions', null, 2048, false, 30);
        $this->insert_model(self::PROVIDER_VOYAGE, 'voyage-3.5', 'Voyage 3.5', self::TYPE_EMBEDDING, 'Newest generation', null, 1024, false, 15);
        $this->insert_model(self::PROVIDER_VOYAGE, 'voyage-3.5-lite', 'Voyage 3.5 Lite', self::TYPE_EMBEDDING, 'Fast newest generation', null, 1024, false, 25);
        $this->insert_model(self::PROVIDER_VOYAGE, 'voyage-multilingual-2', 'Voyage Multilingual 2', self::TYPE_EMBEDDING, 'Optimized for non-English (Greek)', null, 1024, false, 40);
        $this->insert_model(self::PROVIDER_VOYAGE, 'voyage-large-2', 'Voyage Large 2', self::TYPE_EMBEDDING, 'Better quality, larger', null, 1536, false, 50);
        $this->insert_model(self::PROVIDER_VOYAGE, 'voyage-2', 'Voyage 2', self::TYPE_EMBEDDING, 'Legacy model', null, 1024, false, 60);
    }

    
    private function insert_model($provider, $model_id, $name, $type, $description = '', $max_tokens = null, $dimensions = null, $recommended = false, $sort = 0) {
        global $wpdb;

        $wpdb->replace(
            $this->table_name,
            array(
                'provider' => $provider,
                'model_id' => $model_id,
                'model_name' => $name,
                'model_type' => $type,
                'description' => $description,
                'max_tokens' => $max_tokens,
                'dimensions' => $dimensions,
                'is_recommended' => $recommended ? 1 : 0,
                'is_active' => 1,
                'sort_order' => $sort
            ),
            array('%s', '%s', '%s', '%s', '%s', '%d', '%d', '%d', '%d', '%d')
        );
    }

    
    public function get_models($provider = null, $type = null, $active_only = true) {
        global $wpdb;

        $where = array();
        $values = array();

        if ($provider !== null) {
            $where[] = 'provider = %s';
            $values[] = $provider;
        }

        if ($type !== null) {
            $where[] = 'model_type = %s';
            $values[] = $type;
        }

        if ($active_only) {
            $where[] = 'is_active = 1';
        }

        $where_clause = !empty($where) ? 'WHERE ' . implode(' AND ', $where) : '';

        $sql = "SELECT * FROM {$this->table_name} {$where_clause} ORDER BY sort_order ASC, model_name ASC";

        if (!empty($values)) {
            
            $sql = $wpdb->prepare($sql, $values);
        }

        
        return $wpdb->get_results($sql);
    }

    
    public function get_chat_models($provider) {
        return $this->get_models($provider, self::TYPE_CHAT);
    }

    
    public function get_embedding_models($provider = null) {
        return $this->get_models($provider, self::TYPE_EMBEDDING);
    }

    
    public function get_models_for_dropdown($provider, $type = self::TYPE_CHAT) {
        $models = $this->get_models($provider, $type);

        $dropdown = array();
        foreach ($models as $model) {
            $label = $model->model_name;
            if ($model->is_recommended) {
                $label .= ' ⭐';
            }
            if (!empty($model->description)) {
                $label .= ' - ' . $model->description;
            }
            $dropdown[$model->model_id] = $label;
        }

        return $dropdown;
    }

    
    public function is_valid_model($model_id, $provider = null) {
        global $wpdb;

        $sql = "SELECT COUNT(*) FROM {$this->table_name} WHERE model_id = %s AND is_active = 1";
        $values = array($model_id);

        if ($provider !== null) {
            $sql .= " AND provider = %s";
            $values[] = $provider;
        }

        
        return $wpdb->get_var($wpdb->prepare($sql, $values)) > 0;
    }

    
    public function refresh_all_models() {
        
        
        
        
        $results = array(
            'anthropic' => $this->refresh_anthropic_models(),
            'voyage'    => $this->refresh_voyage_models(),
        );

        
        update_option('aieo_models_last_refresh', current_time('timestamp', true));

        return $results;
    }

    
    public function refresh_anthropic_models() {
        
        
        
        $rooster_token = (string) get_option('aieo_rooster_api_key', '');
        if (empty($rooster_token)) {
            return array('success' => false, 'message' => __('Rooster Content Connector token not configured — paste it in the Pro Panel.', 'ai-eshop-optimizer'), 'count' => 0);
        }
        $rooster_base = (string) get_option('aieo_rooster_hub_url', 'https://rooster.systems');
        if ('' === $rooster_base) $rooster_base = 'https://rooster.systems';
        $models_url = rtrim($rooster_base, '/') . '/wp-json/om-portal/v1/anthropic/models';

        $response = wp_remote_get($models_url, array(
            'timeout' => 30,
            'headers' => array(
                'X-OM-API-Key' => $rooster_token,
                'Accept'       => 'application/json',
            ),
        ));

        if (is_wp_error($response)) {
            if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) { error_log('AIEO Model Registry: rooster.systems unreachable - ' . $response->get_error_message()); }
            return array('success' => false, 'message' => $response->get_error_message(), 'count' => 0);
        }

        $code = wp_remote_retrieve_response_code($response);
        if ($code !== 200) {
            $body = wp_remote_retrieve_body($response);
            if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) { error_log('AIEO Model Registry: rooster.systems returned ' . $code . ' - ' . $body); }
            $parsed = json_decode($body, true);
            $msg = (is_array($parsed) && !empty($parsed['message'])) ? (string) $parsed['message'] : sprintf( __( 'Proxy returned code %d', 'ai-eshop-optimizer' ), $code );
            return array('success' => false, 'message' => $msg, 'count' => 0);
        }

        $body = wp_remote_retrieve_body($response);
        $data = json_decode($body, true);

        if (empty($data['data'])) {
            return array('success' => false, 'message' => __('No models returned', 'ai-eshop-optimizer'), 'count' => 0);
        }

        $count = 0;
        $sort = 10;

        foreach ($data['data'] as $model) {
            $id = $model['id'] ?? '';

            
            if (strpos($id, 'claude') !== 0) {
                continue;
            }

            $name = $this->format_model_name($id, 'anthropic');
            $max_tokens = $this->estimate_max_tokens($id);

            $this->insert_model(
                self::PROVIDER_ANTHROPIC,
                $id,
                $name,
                self::TYPE_CHAT,
                $model['description'] ?? '',
                $max_tokens,
                null,
                $sort === 10, 
                $sort
            );

            $sort += 10;
            $count++;
        }

        return array(
            'success' => true,
            
            'message' => sprintf(__('Fetched %d models', 'ai-eshop-optimizer'), $count),
            'count' => $count
        );
    }

    
    public function refresh_openai_models() {
        $api_key = get_option('aieo_chat_openai_api_key', '');
        if (empty($api_key)) {
            return array('success' => false, 'message' => __('No API key configured', 'ai-eshop-optimizer'), 'count' => 0);
        }

        $response = wp_remote_get(self::OPENAI_MODELS_URL, array(
            'timeout' => 30,
            'headers' => array(
                'Authorization' => 'Bearer ' . $api_key,
                'Content-Type' => 'application/json'
            )
        ));

        if (is_wp_error($response)) {
            if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) { error_log('AIEO Model Registry: OpenAI API error - ' . $response->get_error_message()); }
            return array('success' => false, 'message' => $response->get_error_message(), 'count' => 0);
        }

        $code = wp_remote_retrieve_response_code($response);
        if ($code !== 200) {
            
            return array('success' => false, 'message' => sprintf( __( 'API returned code %d', 'ai-eshop-optimizer' ), $code ), 'count' => 0);
        }

        $body = wp_remote_retrieve_body($response);
        $data = json_decode($body, true);

        if (empty($data['data'])) {
            return array('success' => false, 'message' => __('No models returned', 'ai-eshop-optimizer'), 'count' => 0);
        }

        $chat_count = 0;
        $embed_count = 0;
        $chat_sort = 10;
        $embed_sort = 10;

        
        $chat_prefixes = array('gpt-4', 'gpt-3.5', 'o1', 'o3', 'chatgpt');
        
        $embed_prefixes = array('text-embedding');
        
        $excluded = array('whisper', 'tts', 'dall-e', 'babbage', 'davinci', 'curie', 'instruct', 'search', 'similarity', 'code', 'edit', 'insert');

        foreach ($data['data'] as $model) {
            $id = $model['id'] ?? '';

            
            $skip = false;
            foreach ($excluded as $ex) {
                if (stripos($id, $ex) !== false) {
                    $skip = true;
                    break;
                }
            }
            if ($skip) continue;

            
            $is_chat = false;
            foreach ($chat_prefixes as $prefix) {
                if (strpos($id, $prefix) === 0) {
                    $is_chat = true;
                    break;
                }
            }

            
            $is_embed = false;
            foreach ($embed_prefixes as $prefix) {
                if (strpos($id, $prefix) === 0) {
                    $is_embed = true;
                    break;
                }
            }

            if ($is_chat) {
                $name = $this->format_model_name($id, 'openai');
                $this->insert_model(
                    self::PROVIDER_OPENAI,
                    $id,
                    $name,
                    self::TYPE_CHAT,
                    '',
                    $this->estimate_max_tokens($id),
                    null,
                    $chat_sort === 10,
                    $chat_sort
                );
                $chat_sort += 10;
                $chat_count++;
            } elseif ($is_embed) {
                $name = $this->format_model_name($id, 'openai');
                $dimensions = $this->estimate_dimensions($id);
                $this->insert_model(
                    self::PROVIDER_OPENAI,
                    $id,
                    $name,
                    self::TYPE_EMBEDDING,
                    '',
                    null,
                    $dimensions,
                    $embed_sort === 10,
                    $embed_sort
                );
                $embed_sort += 10;
                $embed_count++;
            }
        }

        $total = $chat_count + $embed_count;
        return array(
            'success' => true,
            
            'message' => sprintf(__('Fetched %1$d chat and %2$d embedding models', 'ai-eshop-optimizer'), $chat_count, $embed_count),
            'count' => $total
        );
    }

    
    public function refresh_voyage_models() {
        
        $voyage_catalog = array(
            
            array( 'voyage-3.5-large',       'Voyage 3.5 Large',       __( 'Newest generation, highest quality', 'ai-eshop-optimizer' ),    2048, false ),
            array( 'voyage-3.5',             'Voyage 3.5',             __( 'Newest generation', 'ai-eshop-optimizer' ),                    1024, false ),
            array( 'voyage-3.5-lite',        'Voyage 3.5 Lite',        __( 'Fast newest generation', 'ai-eshop-optimizer' ),               1024, false ),
            
            array( 'voyage-3-large',         'Voyage 3 Large',         __( 'Best quality, larger dimension', 'ai-eshop-optimizer' ),       2048, false ),
            array( 'voyage-3',               'Voyage 3',               __( 'Latest general-purpose model', 'ai-eshop-optimizer' ),         1024, true  ),
            array( 'voyage-3-lite',          'Voyage 3 Lite',          __( 'Faster, lower cost', 'ai-eshop-optimizer' ),                   512,  false ),
            
            array( 'voyage-multilingual-2',  'Voyage Multilingual 2',  __( 'Optimized for non-English', 'ai-eshop-optimizer' ),            1024, false ),
            array( 'voyage-finance-2',       'Voyage Finance 2',       __( 'Domain-tuned for financial text', 'ai-eshop-optimizer' ),      1024, false ),
            array( 'voyage-law-2',           'Voyage Law 2',           __( 'Domain-tuned for legal text', 'ai-eshop-optimizer' ),          1024, false ),
            array( 'voyage-code-2',          'Voyage Code 2',          __( 'Domain-tuned for code / docs', 'ai-eshop-optimizer' ),         1536, false ),
            
            array( 'voyage-large-2',         'Voyage Large 2',         __( 'High quality embeddings (legacy)', 'ai-eshop-optimizer' ),     1536, false ),
            array( 'voyage-2',               'Voyage 2',               __( 'Legacy model', 'ai-eshop-optimizer' ),                         1024, false ),
        );

        $count = 0;
        $sort  = 10;
        foreach ( $voyage_catalog as $row ) {
            list( $id, $name, $description, $dimensions, $recommended ) = $row;
            $this->insert_model(
                self::PROVIDER_VOYAGE,
                $id,
                $name,
                self::TYPE_EMBEDDING,
                $description,
                null,
                $dimensions,
                $recommended,
                $sort
            );
            $sort += 10;
            $count++;
        }

        return array(
            'success' => true,
            
            'message' => sprintf( __( 'Loaded %d Voyage models', 'ai-eshop-optimizer' ), $count ),
            'count'   => $count,
        );
    }

    
    private function format_model_name($id, $provider) {
        switch ($provider) {
            case 'anthropic':
                
                $name = str_replace('claude-', 'Claude ', $id);
                $name = preg_replace('/-\d{8}$/', '', $name); 
                $name = str_replace('-', ' ', $name);
                $name = preg_replace('/(\d)\s+(\d)/', '$1.$2', $name); 
                return ucwords($name);

            case 'openai':
                
                $name = strtoupper(substr($id, 0, 3)) . substr($id, 3);
                $name = str_replace('-', ' ', $name);
                $name = str_replace('text embedding', 'Text Embedding', $name);
                return ucwords($name);

            case 'voyage':
                
                $name = str_replace('-', ' ', $id);
                return ucwords($name);

            default:
                return $id;
        }
    }

    
    private function estimate_max_tokens($id) {
        if (strpos($id, 'opus-4-5') !== false || strpos($id, 'sonnet-4-5') !== false) {
            return 16384;
        }
        if (strpos($id, 'opus-4') !== false || strpos($id, 'sonnet-4') !== false) {
            return 8192;
        }
        if (strpos($id, 'o1') !== false || strpos($id, 'o3') !== false) {
            return 32768;
        }
        if (strpos($id, 'gpt-4o') !== false) {
            return 16384;
        }
        if (strpos($id, 'gpt-4') !== false) {
            return 8192;
        }
        return 4096;
    }

    
    private function estimate_dimensions($id) {
        if (strpos($id, '3-large') !== false) {
            return 3072;
        }
        if (strpos($id, '3-small') !== false || strpos($id, 'ada-002') !== false) {
            return 1536;
        }
        if (strpos($id, 'large') !== false) {
            return 1536;
        }
        if (strpos($id, 'lite') !== false) {
            return 512;
        }
        if (strpos($id, 'voyage-3.5') !== false || strpos($id, 'voyage-3') !== false) {
            return 1024;
        }
        return 1024;
    }

    
    public function get_last_refresh_info() {
        $timestamp = get_option('aieo_models_last_refresh', 0);

        return array(
            'timestamp' => $timestamp,
            'human' => $timestamp > 0
                ? human_time_diff($timestamp, current_time('timestamp', true)) . ' ' . __('ago', 'ai-eshop-optimizer')
                : __('Never', 'ai-eshop-optimizer'),
            'date' => $timestamp > 0
                ? wp_date(get_option('date_format') . ' ' . get_option('time_format'), $timestamp)
                : ''
        );
    }

    
    public function ajax_refresh_models() {
        check_ajax_referer('aieo_refresh_models', 'nonce');

        if (!current_user_can('manage_options')) {
            wp_send_json_error(array('message' => __('Insufficient permissions', 'ai-eshop-optimizer')), 403);
        }

        $results = $this->refresh_all_models();

        $total_success = 0;
        $total_count = 0;
        $messages = array();

        foreach ($results as $provider => $result) {
            if ($result['success']) {
                $total_success++;
                $total_count += $result['count'];
            }
            $messages[] = ucfirst($provider) . ': ' . $result['message'];
        }

        if ($total_success > 0) {
            wp_send_json_success(array(
                
                'message' => sprintf(__('Refreshed %1$d models from %2$d providers', 'ai-eshop-optimizer'), $total_count, $total_success),
                'details' => $messages,
                'results' => $results,
                'refresh_info' => $this->get_last_refresh_info()
            ));
        } else {
            wp_send_json_error(array(
                'message' => __('Failed to refresh models from any provider', 'ai-eshop-optimizer'),
                'details' => $messages,
                'results' => $results
            ));
        }
    }

    
    public function get_anthropic_models() {
        $models = $this->get_chat_models(self::PROVIDER_ANTHROPIC);
        $result = array();
        foreach ($models as $model) {
            $result[$model->model_id] = array(
                'name' => $model->model_name,
                'description' => $model->description,
                'max_tokens' => $model->max_tokens,
                'recommended' => (bool) $model->is_recommended
            );
        }
        return $result;
    }

    
    public function get_openai_models() {
        $models = $this->get_chat_models(self::PROVIDER_OPENAI);
        $result = array();
        foreach ($models as $model) {
            $result[$model->model_id] = array(
                'name' => $model->model_name,
                'description' => $model->description,
                'max_tokens' => $model->max_tokens,
                'recommended' => (bool) $model->is_recommended
            );
        }
        return $result;
    }

    
    public function ajax_validate_api_keys() {
        check_ajax_referer('aieo_validate_api_keys', 'nonce');

        if (!current_user_can('manage_options')) {
            wp_send_json_error(array('message' => __('Insufficient permissions', 'ai-eshop-optimizer')), 403);
        }

        $results = array(
            'anthropic' => $this->validate_anthropic_key(),
            'openai' => $this->validate_openai_key(),
            'voyage' => $this->validate_voyage_key()
        );

        wp_send_json_success($results);
    }

    
    private function validate_anthropic_key() {
        $api_key = get_option('aieo_chat_anthropic_api_key', '');

        if (empty($api_key)) {
            return array('not_configured' => true);
        }

        
        $response = wp_remote_post('https://api.anthropic.com/v1/messages', array(
            'timeout' => 15,
            'headers' => array(
                'Content-Type' => 'application/json',
                'x-api-key' => $api_key,
                'anthropic-version' => '2023-06-01'
            ),
            'body' => wp_json_encode(array(
                'model' => 'claude-3-haiku-20240307',
                'max_tokens' => 1,
                'messages' => array(
                    array('role' => 'user', 'content' => 'Hi')
                )
            ))
        ));

        if (is_wp_error($response)) {
            return array('valid' => false, 'error' => $response->get_error_message());
        }

        $code = wp_remote_retrieve_response_code($response);
        $body = json_decode(wp_remote_retrieve_body($response), true);

        
        if ($code === 400 || $code === 403 || $code === 429) {
            $error_type = isset($body['error']['type']) ? $body['error']['type'] : '';
            $error_message = isset($body['error']['message']) ? $body['error']['message'] : '';

            if (strpos($error_type, 'credit') !== false ||
                strpos($error_message, 'credit') !== false ||
                strpos($error_message, 'balance') !== false ||
                strpos($error_type, 'billing') !== false) {
                return array('valid' => true, 'credits_exhausted' => true);
            }

            
            if ($code === 429) {
                return array('valid' => true, 'credits_exhausted' => false);
            }
        }

        
        if ($code === 401) {
            return array('valid' => false, 'error' => __('Invalid API key', 'ai-eshop-optimizer'));
        }

        
        if ($code === 200) {
            return array('valid' => true, 'credits_exhausted' => false);
        }

        
        $error_msg = isset($body['error']['message']) ? $body['error']['message'] : __('Unknown error', 'ai-eshop-optimizer');
        return array('valid' => false, 'error' => $error_msg);
    }

    
    private function validate_openai_key() {
        $api_key = get_option('aieo_chat_openai_api_key', '');

        if (empty($api_key)) {
            return array('not_configured' => true);
        }

        
        $response = wp_remote_get('https://api.openai.com/v1/models', array(
            'timeout' => 15,
            'headers' => array(
                'Authorization' => 'Bearer ' . $api_key
            )
        ));

        if (is_wp_error($response)) {
            return array('valid' => false, 'error' => $response->get_error_message());
        }

        $code = wp_remote_retrieve_response_code($response);
        $body = json_decode(wp_remote_retrieve_body($response), true);

        
        if ($code === 429 || $code === 402) {
            $error_code = isset($body['error']['code']) ? $body['error']['code'] : '';
            $error_message = isset($body['error']['message']) ? $body['error']['message'] : '';

            if ($error_code === 'insufficient_quota' ||
                strpos($error_message, 'quota') !== false ||
                strpos($error_message, 'exceeded') !== false ||
                strpos($error_message, 'billing') !== false) {
                return array('valid' => true, 'credits_exhausted' => true);
            }

            
            if ($code === 429 && $error_code === 'rate_limit_exceeded') {
                return array('valid' => true, 'credits_exhausted' => false);
            }
        }

        
        if ($code === 401) {
            return array('valid' => false, 'error' => __('Invalid API key', 'ai-eshop-optimizer'));
        }

        
        if ($code === 200) {
            return array('valid' => true, 'credits_exhausted' => false);
        }

        
        $error_msg = isset($body['error']['message']) ? $body['error']['message'] : __('Unknown error', 'ai-eshop-optimizer');
        return array('valid' => false, 'error' => $error_msg);
    }

    
    private function validate_voyage_key() {
        $api_key = get_option('aieo_chat_voyage_api_key', '');

        if (empty($api_key)) {
            return array('not_configured' => true);
        }

        
        $response = wp_remote_post('https://api.voyageai.com/v1/embeddings', array(
            'timeout' => 15,
            'headers' => array(
                'Content-Type' => 'application/json',
                'Authorization' => 'Bearer ' . $api_key
            ),
            'body' => wp_json_encode(array(
                'model' => 'voyage-3-lite',
                'input' => 'test'
            ))
        ));

        if (is_wp_error($response)) {
            return array('valid' => false, 'error' => $response->get_error_message());
        }

        $code = wp_remote_retrieve_response_code($response);
        $body = json_decode(wp_remote_retrieve_body($response), true);

        
        if ($code === 402 || $code === 429) {
            $error_message = isset($body['detail']) ? $body['detail'] : (isset($body['error']['message']) ? $body['error']['message'] : '');

            if (strpos(strtolower($error_message), 'credit') !== false ||
                strpos(strtolower($error_message), 'quota') !== false ||
                strpos(strtolower($error_message), 'billing') !== false ||
                strpos(strtolower($error_message), 'payment') !== false) {
                return array('valid' => true, 'credits_exhausted' => true);
            }

            
            if ($code === 429) {
                return array('valid' => true, 'credits_exhausted' => false);
            }
        }

        
        if ($code === 401) {
            return array('valid' => false, 'error' => __('Invalid API key', 'ai-eshop-optimizer'));
        }

        
        if ($code === 200) {
            return array('valid' => true, 'credits_exhausted' => false);
        }

        
        $error_msg = isset($body['detail']) ? $body['detail'] : (isset($body['error']['message']) ? $body['error']['message'] : __('Unknown error', 'ai-eshop-optimizer'));
        return array('valid' => false, 'error' => $error_msg);
    }

    

    
    public function sampling_params() {
        return array('temperature', 'top_p', 'top_k');
    }

    
    public function get_unsupported_params($model_id) {
        global $wpdb;
        
        $meta = $wpdb->get_var($wpdb->prepare("SELECT metadata FROM {$this->table_name} WHERE model_id = %s LIMIT 1", $model_id));
        if (empty($meta)) {
            return array();
        }
        $decoded = json_decode($meta, true);
        if (!is_array($decoded) || empty($decoded['unsupported_params']) || !is_array($decoded['unsupported_params'])) {
            return array();
        }
        return array_values(array_unique(array_map('strval', $decoded['unsupported_params'])));
    }

    
    public function set_unsupported_params($model_id, array $params) {
        global $wpdb;
        
        $row = $wpdb->get_row($wpdb->prepare("SELECT id, metadata FROM {$this->table_name} WHERE model_id = %s LIMIT 1", $model_id));
        if (!$row) {
            return false;
        }
        $meta = array();
        if (!empty($row->metadata)) {
            $decoded = json_decode($row->metadata, true);
            if (is_array($decoded)) {
                $meta = $decoded;
            }
        }
        $meta['unsupported_params'] = array_values(array_unique(array_map('strval', $params)));
        return false !== $wpdb->update(
            $this->table_name,
            array('metadata' => wp_json_encode($meta)),
            array('id' => (int) $row->id),
            array('%s'),
            array('%d')
        );
    }

    
    public function mark_param_unsupported($model_id, $param) {
        $current = $this->get_unsupported_params($model_id);
        if (!in_array($param, $current, true)) {
            $current[] = $param;
            $this->set_unsupported_params($model_id, $current);
        }
    }

    
    public function detect_params($model_id) {
        if (!class_exists('AI_eShop_Chat_Anthropic_API')) {
            return array('error' => __('Anthropic API class not loaded', 'ai-eshop-optimizer'));
        }
        $api  = AI_eShop_Chat_Anthropic_API::get_instance();
        $msgs = array(array('role' => 'user', 'content' => 'Reply with exactly one word: hello'));
        $base = array('model' => $model_id, 'max_tokens' => 16, 'messages' => $msgs);

        
        $b = $api->raw_messages_probe($base);
        if (intval($b['code']) !== 200) {
            
            return array('error' => sprintf(__('Baseline call failed (HTTP %1$s): %2$s', 'ai-eshop-optimizer'), $b['code'], $b['error']));
        }

        $supported   = array();
        $unsupported = array();
        $probes      = array('temperature' => 0.5, 'top_p' => 0.9, 'top_k' => 40);
        foreach ($probes as $param => $val) {
            $body         = $base;
            $body[$param] = $val;
            $r            = $api->raw_messages_probe($body);
            if (intval($r['code']) === 200) {
                $supported[] = $param;
            } elseif (intval($r['code']) === 400 && stripos((string) $r['error'], 'deprecated') !== false) {
                $unsupported[] = $param;
            } else {
                
                
                $supported[] = $param;
            }
        }

        $this->set_unsupported_params($model_id, $unsupported);
        return array('supported' => $supported, 'unsupported' => $unsupported, 'base_ok' => true, 'error' => '');
    }

    
    public function ajax_model_test() {
        check_ajax_referer('aieo_chat_model_tester', 'nonce');
        if (!current_user_can('manage_options')) {
            wp_send_json_error(array('message' => __('Insufficient permissions', 'ai-eshop-optimizer')), 403);
        }

        $model   = isset($_POST['model']) ? sanitize_text_field(wp_unslash($_POST['model'])) : '';
        $message = isset($_POST['message']) ? sanitize_textarea_field(wp_unslash($_POST['message'])) : '';
        if ('' === $model) {
            wp_send_json_error(array('message' => __('No model selected', 'ai-eshop-optimizer')));
        }
        if ('' === $message) {
            $message = 'Reply with exactly one word: hello';
        }

        $max_tokens = isset($_POST['max_tokens']) ? max(1, min(2000, (int) $_POST['max_tokens'])) : 100;
        $body = array(
            'model'      => $model,
            'max_tokens' => $max_tokens,
            'messages'   => array(array('role' => 'user', 'content' => $message)),
        );
        if (isset($_POST['use_temperature']) && '1' === $_POST['use_temperature']) {
            $body['temperature'] = (float) wp_unslash($_POST['temperature']);
        }
        if (isset($_POST['use_top_p']) && '1' === $_POST['use_top_p']) {
            $body['top_p'] = (float) wp_unslash($_POST['top_p']);
        }
        if (isset($_POST['use_top_k']) && '1' === $_POST['use_top_k']) {
            $body['top_k'] = (int) wp_unslash($_POST['top_k']);
        }

        if (!class_exists('AI_eShop_Chat_Anthropic_API')) {
            wp_send_json_error(array('message' => __('Anthropic API class not loaded', 'ai-eshop-optimizer')));
        }
        $probe = AI_eShop_Chat_Anthropic_API::get_instance()->raw_messages_probe($body);
        $text  = isset($probe['json']['content'][0]['text']) ? $probe['json']['content'][0]['text'] : '';

        wp_send_json_success(array(
            'request'    => $body,
            'http_code'  => (int) $probe['code'],
            'latency_ms' => (int) $probe['latency_ms'],
            'error'      => (string) $probe['error'],
            'text'       => $text,
            'raw'        => (string) $probe['body'],
        ));
    }

    
    public function ajax_model_detect() {
        check_ajax_referer('aieo_chat_model_tester', 'nonce');
        if (!current_user_can('manage_options')) {
            wp_send_json_error(array('message' => __('Insufficient permissions', 'ai-eshop-optimizer')), 403);
        }
        $model = isset($_POST['model']) ? sanitize_text_field(wp_unslash($_POST['model'])) : '';
        if ('' === $model) {
            wp_send_json_error(array('message' => __('No model selected', 'ai-eshop-optimizer')));
        }
        $result = $this->detect_params($model);
        if (!empty($result['error'])) {
            wp_send_json_error(array('message' => $result['error']));
        }
        wp_send_json_success($result);
    }
}

AI_eShop_Chat_Model_Registry::get_instance();
