<?php
/**
 * OpenAI-compatible AI providers.
 */

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

if (!class_exists('AIAutotool_AI_Provider_OpenAI_Compatible')) {
    abstract class AIAutotool_AI_Provider_OpenAI_Compatible extends AIAutotool_AI_Provider_Base {
        protected $api_path = '/chat/completions';
        protected $models_path = '/models';
        protected $extra_headers = array();
        protected $requires_api_key = true;

        public function __construct($api_key = '') {
            parent::__construct($api_key);

            if (empty($this->api_key)) {
                $this->api_key = $this->get_rotated_key();
            }

            if (!$this->requires_api_key && empty($this->api_key)) {
                $this->api_key = 'unused';
            }
        }

        public function chat_completion($messages, $options = array()) {
            if (!$this->is_configured()) {
                return array(
                    'success' => false,
                    'error' => $this->name . ' API key not configured'
                );
            }

            $options = $this->parse_options($options);
            $body = array(
                'model' => $options['model'],
                'messages' => $messages,
                'temperature' => floatval($options['temperature']),
                'max_tokens' => intval($options['max_tokens']),
                'top_p' => floatval($options['top_p'])
            );

            if (!empty($options['stream'])) {
                $body['stream'] = (bool) $options['stream'];
            }

            $response = $this->make_request(
                rtrim($this->base_url, '/') . $this->api_path,
                $body,
                'POST',
                $this->get_request_headers(),
                array(
                    'timeout' => isset($options['timeout']) ? (int) $options['timeout'] : 60,
                    'connect_timeout' => isset($options['connect_timeout']) ? (int) $options['connect_timeout'] : 10,
                    'low_speed_time' => isset($options['low_speed_time']) ? (int) $options['low_speed_time'] : 30,
                )
            );

            if (!$response['success']) {
                return $response;
            }

            $data = $response['data'];
            if (!isset($data['choices'][0]['message']['content'])) {
                return array(
                    'success' => false,
                    'error' => 'Invalid response structure: missing message content'
                );
            }

            return array(
                'success' => true,
                'content' => $data['choices'][0]['message']['content'],
                'usage' => isset($data['usage']) ? $data['usage'] : null,
                'model' => isset($data['model']) ? $data['model'] : $options['model'],
                'finish_reason' => isset($data['choices'][0]['finish_reason']) ? $data['choices'][0]['finish_reason'] : null
            );
        }

        public function test_connection() {
            if (!$this->is_configured()) {
                return array(
                    'success' => false,
                    'message' => $this->name . ' API key not configured'
                );
            }

            $test_result = $this->chat_completion(
                array(
                    array(
                        'role' => 'user',
                        'content' => 'Reply with OK.'
                    )
                ),
                array(
                    'model' => $this->get_default_model(),
                    'temperature' => 0.2,
                    'max_tokens' => 32
                )
            );

            if ($test_result['success']) {
                $default_model = $this->get_default_model();
                $available_models = $this->get_available_models();

                return array(
                    'success' => true,
                    'message' => $this->name . ' API connection successful!',
                    'response' => isset($test_result['content']) ? trim($test_result['content']) : '',
                    'model' => isset($test_result['model']) ? $test_result['model'] : $default_model,
                    'model_name' => isset($available_models[$default_model]) ? $available_models[$default_model] : $default_model,
                    'usage' => isset($test_result['usage']) ? $test_result['usage'] : null
                );
            }

            return array(
                'success' => false,
                'message' => $this->name . ' API Error: ' . (isset($test_result['error']) ? $test_result['error'] : 'Unknown error'),
                'model' => $this->get_default_model()
            );
        }

        public function get_models() {
            if (!$this->is_configured()) {
                return array(
                    'success' => false,
                    'error' => $this->name . ' API key not configured'
                );
            }

            $response = $this->make_request(
                rtrim($this->base_url, '/') . $this->models_path,
                null,
                'GET',
                $this->get_request_headers()
            );

            if (!$response['success']) {
                return $response;
            }

            $models = array();
            if (isset($response['data']['data']) && is_array($response['data']['data'])) {
                foreach ($response['data']['data'] as $model) {
                    if (isset($model['id'])) {
                        $models[] = $model['id'];
                    }
                }
            }

            return array(
                'success' => true,
                'models' => $models
            );
        }

        protected function get_request_headers() {
            $headers = array(
                'Content-Type' => 'application/json'
            );

            if (!empty($this->api_key) && $this->api_key !== 'unused') {
                $headers['Authorization'] = 'Bearer ' . $this->api_key;
            }

            foreach ($this->extra_headers as $key => $value) {
                $headers[$key] = $value;
            }

            return $headers;
        }
    }
}

class AIAutotool_AI_Provider_OpenRouter extends AIAutotool_AI_Provider_OpenAI_Compatible {
    protected $name = 'OpenRouter';
    protected $id = 'openrouter';
    protected $base_url = 'https://openrouter.ai/api/v1';
    protected $default_model = 'openai/gpt-4o-mini';
    protected $available_models = array(
        'openai/gpt-4o-mini' => 'OpenAI GPT-4o Mini',
        'openai/gpt-4o' => 'OpenAI GPT-4o',
        'anthropic/claude-sonnet-4.5' => 'Claude Sonnet 4.5',
        'google/gemini-2.5-flash' => 'Gemini 2.5 Flash',
        'deepseek/deepseek-chat' => 'DeepSeek Chat'
    );
    protected $extra_headers = array(
        'HTTP-Referer' => 'https://aiautotool.com',
        'X-Title' => 'AI Auto Tool'
    );
}

class AIAutotool_AI_Provider_9Router extends AIAutotool_AI_Provider_OpenAI_Compatible {
    protected $name = '9Router';
    protected $id = '9router';
    protected $base_url = 'https://api9.aiautotool.com/v1';
    protected $default_model = 'vkct';
    protected $requires_api_key = false;
    protected $available_models = array();

    public function __construct($api_key = '') {
        parent::__construct($api_key);
        $this->parse_router_config();
    }

    private function parse_router_config() {
        if (!is_string($this->api_key) || $this->api_key === '' || $this->api_key === 'unused') {
            return;
        }

        if (preg_match('#^https?://#i', $this->api_key)) {
            $this->base_url = rtrim($this->api_key, '/');
            $this->api_key = 'unused';
            return;
        }

        if (strpos($this->api_key, '|') === false) {
            return;
        }

        $parts = array_map('trim', explode('|', $this->api_key, 2));
        if (!empty($parts[0]) && preg_match('#^https?://#i', $parts[0])) {
            $this->base_url = rtrim($parts[0], '/');
        }

        $this->api_key = isset($parts[1]) ? $parts[1] : '';
        if ($this->api_key === '') {
            $this->api_key = 'unused';
        }
    }

    public function get_available_models() {
        $cache_key = $this->get_models_cache_key();
        if (function_exists('get_transient')) {
            $cached_models = get_transient($cache_key);
            if (is_array($cached_models) && !empty($cached_models)) {
                return $cached_models;
            }
        }

        $result = $this->get_models();
        if (empty($result['success']) || empty($result['models']) || !is_array($result['models'])) {
            return array();
        }

        $models = $this->normalize_models_for_select($result['models']);
        if (!empty($models) && function_exists('set_transient')) {
            set_transient($cache_key, $models, 30 * MINUTE_IN_SECONDS);
        }

        return $models;
    }

}

class AIAutotool_AI_Provider_Groq extends AIAutotool_AI_Provider_OpenAI_Compatible {
    protected $name = 'Groq';
    protected $id = 'groq';
    protected $base_url = 'https://api.groq.com/openai/v1';
    protected $default_model = 'llama-3.3-70b-versatile';
    protected $available_models = array(
        'llama-3.3-70b-versatile' => 'Llama 3.3 70B Versatile',
        'llama-3.1-8b-instant' => 'Llama 3.1 8B Instant',
        'openai/gpt-oss-120b' => 'GPT-OSS 120B',
        'openai/gpt-oss-20b' => 'GPT-OSS 20B'
    );
}

class AIAutotool_AI_Provider_DeepSeek extends AIAutotool_AI_Provider_OpenAI_Compatible {
    protected $name = 'DeepSeek';
    protected $id = 'deepseek';
    protected $base_url = 'https://api.deepseek.com';
    protected $default_model = 'deepseek-v4-flash';
    protected $available_models = array(
        'deepseek-v4-flash' => 'DeepSeek V4 Flash',
        'deepseek-v4-pro' => 'DeepSeek V4 Pro',
        'deepseek-chat' => 'DeepSeek Chat',
        'deepseek-reasoner' => 'DeepSeek Reasoner'
    );
}

class AIAutotool_AI_Provider_Mistral extends AIAutotool_AI_Provider_OpenAI_Compatible {
    protected $name = 'Mistral AI';
    protected $id = 'mistral';
    protected $base_url = 'https://api.mistral.ai/v1';
    protected $default_model = 'mistral-small-latest';
    protected $available_models = array(
        'mistral-small-latest' => 'Mistral Small Latest',
        'mistral-medium-latest' => 'Mistral Medium Latest',
        'mistral-large-latest' => 'Mistral Large Latest',
        'codestral-latest' => 'Codestral Latest'
    );
}

class AIAutotool_AI_Provider_Together extends AIAutotool_AI_Provider_OpenAI_Compatible {
    protected $name = 'Together AI';
    protected $id = 'together';
    protected $base_url = 'https://api.together.xyz/v1';
    protected $default_model = 'meta-llama/Llama-3.3-70B-Instruct-Turbo';
    protected $available_models = array(
        'meta-llama/Llama-3.3-70B-Instruct-Turbo' => 'Llama 3.3 70B Instruct Turbo',
        'meta-llama/Llama-3.1-8B-Instruct-Turbo' => 'Llama 3.1 8B Instruct Turbo',
        'Qwen/Qwen2.5-72B-Instruct-Turbo' => 'Qwen 2.5 72B Instruct Turbo',
        'deepseek-ai/DeepSeek-R1' => 'DeepSeek R1'
    );
}

class AIAutotool_AI_Provider_Fireworks extends AIAutotool_AI_Provider_OpenAI_Compatible {
    protected $name = 'Fireworks AI';
    protected $id = 'fireworks';
    protected $base_url = 'https://api.fireworks.ai/inference/v1';
    protected $default_model = 'accounts/fireworks/models/llama-v3p1-8b-instruct';
    protected $available_models = array(
        'accounts/fireworks/models/llama-v3p1-8b-instruct' => 'Llama 3.1 8B Instruct',
        'accounts/fireworks/models/llama-v3p3-70b-instruct' => 'Llama 3.3 70B Instruct',
        'accounts/fireworks/models/deepseek-r1' => 'DeepSeek R1',
        'accounts/fireworks/models/qwen2p5-72b-instruct' => 'Qwen 2.5 72B Instruct'
    );
}

class AIAutotool_AI_Provider_Perplexity extends AIAutotool_AI_Provider_OpenAI_Compatible {
    protected $name = 'Perplexity';
    protected $id = 'perplexity';
    protected $base_url = 'https://api.perplexity.ai';
    protected $default_model = 'sonar';
    protected $available_models = array(
        'sonar' => 'Sonar',
        'sonar-pro' => 'Sonar Pro',
        'sonar-reasoning' => 'Sonar Reasoning',
        'sonar-reasoning-pro' => 'Sonar Reasoning Pro'
    );
}

class AIAutotool_AI_Provider_XAI extends AIAutotool_AI_Provider_OpenAI_Compatible {
    protected $name = 'xAI';
    protected $id = 'xai';
    protected $base_url = 'https://api.x.ai/v1';
    protected $default_model = 'grok-4';
    protected $available_models = array(
        'grok-4' => 'Grok 4',
        'grok-4-fast-reasoning' => 'Grok 4 Fast Reasoning',
        'grok-4-fast-non-reasoning' => 'Grok 4 Fast Non-Reasoning',
        'grok-3-mini' => 'Grok 3 Mini'
    );
}

class AIAutotool_AI_Provider_Ollama extends AIAutotool_AI_Provider_OpenAI_Compatible {
    protected $name = 'Ollama Local';
    protected $id = 'ollama';
    protected $base_url = 'http://localhost:11434/v1';
    protected $default_model = 'llama3.1';
    protected $requires_api_key = false;
    protected $available_models = array(
        'llama3.1' => 'Llama 3.1',
        'llama3.2' => 'Llama 3.2',
        'qwen2.5' => 'Qwen 2.5',
        'mistral' => 'Mistral',
        'gemma2' => 'Gemma 2'
    );
}

class AIAutotool_AI_Provider_GLM_Coding extends AIAutotool_AI_Provider_OpenAI_Compatible {
    protected $name = 'GLM Coding';
    protected $id = 'glm_coding';
    protected $base_url = 'https://open.bigmodel.cn/api/paas/v4';
    protected $default_model = 'glm-4.5';
    protected $available_models = array(
        'glm-4.5' => 'GLM 4.5',
        'glm-4.5-air' => 'GLM 4.5 Air',
        'glm-4.5-flash' => 'GLM 4.5 Flash',
        'glm-4-plus' => 'GLM 4 Plus'
    );
}

class AIAutotool_AI_Provider_GLM_China extends AIAutotool_AI_Provider_OpenAI_Compatible {
    protected $name = 'GLM China';
    protected $id = 'glm_china';
    protected $base_url = 'https://open.bigmodel.cn/api/paas/v4';
    protected $default_model = 'glm-4.5-air';
    protected $available_models = array(
        'glm-4.5-air' => 'GLM 4.5 Air',
        'glm-4.5' => 'GLM 4.5',
        'glm-4-flash' => 'GLM 4 Flash',
        'glm-4-plus' => 'GLM 4 Plus'
    );
}

class AIAutotool_AI_Provider_Kimi extends AIAutotool_AI_Provider_OpenAI_Compatible {
    protected $name = 'Kimi';
    protected $id = 'kimi';
    protected $base_url = 'https://api.moonshot.cn/v1';
    protected $default_model = 'moonshot-v1-8k';
    protected $available_models = array(
        'moonshot-v1-8k' => 'Moonshot V1 8K',
        'moonshot-v1-32k' => 'Moonshot V1 32K',
        'moonshot-v1-128k' => 'Moonshot V1 128K',
        'kimi-k2-0711-preview' => 'Kimi K2 Preview'
    );
}

class AIAutotool_AI_Provider_Minimax_Coding extends AIAutotool_AI_Provider_OpenAI_Compatible {
    protected $name = 'Minimax Coding';
    protected $id = 'minimax_coding';
    protected $base_url = 'https://api.minimax.io/v1';
    protected $default_model = 'MiniMax-M1';
    protected $available_models = array(
        'MiniMax-M1' => 'MiniMax M1',
        'abab6.5s-chat' => 'ABAB 6.5s Chat',
        'abab6.5g-chat' => 'ABAB 6.5g Chat'
    );
}

class AIAutotool_AI_Provider_Minimax_China extends AIAutotool_AI_Provider_OpenAI_Compatible {
    protected $name = 'Minimax China';
    protected $id = 'minimax_china';
    protected $base_url = 'https://api.minimax.chat/v1';
    protected $default_model = 'MiniMax-M1';
    protected $available_models = array(
        'MiniMax-M1' => 'MiniMax M1',
        'abab6.5s-chat' => 'ABAB 6.5s Chat',
        'abab6.5g-chat' => 'ABAB 6.5g Chat'
    );
}

class AIAutotool_AI_Provider_Alibaba extends AIAutotool_AI_Provider_OpenAI_Compatible {
    protected $name = 'Alibaba';
    protected $id = 'alibaba';
    protected $base_url = 'https://dashscope.aliyuncs.com/compatible-mode/v1';
    protected $default_model = 'qwen-plus';
    protected $available_models = array(
        'qwen-plus' => 'Qwen Plus',
        'qwen-turbo' => 'Qwen Turbo',
        'qwen-max' => 'Qwen Max',
        'qwen3-coder-plus' => 'Qwen3 Coder Plus'
    );
}

class AIAutotool_AI_Provider_Alibaba_Intl extends AIAutotool_AI_Provider_OpenAI_Compatible {
    protected $name = 'Alibaba Intl';
    protected $id = 'alibaba_intl';
    protected $base_url = 'https://dashscope-intl.aliyuncs.com/compatible-mode/v1';
    protected $default_model = 'qwen-plus';
    protected $available_models = array(
        'qwen-plus' => 'Qwen Plus',
        'qwen-turbo' => 'Qwen Turbo',
        'qwen-max' => 'Qwen Max',
        'qwen3-coder-plus' => 'Qwen3 Coder Plus'
    );
}

class AIAutotool_AI_Provider_Volcengine_Ark extends AIAutotool_AI_Provider_OpenAI_Compatible {
    protected $name = 'Volcengine Ark';
    protected $id = 'volcengine_ark';
    protected $base_url = 'https://ark.cn-beijing.volces.com/api/v3';
    protected $default_model = 'doubao-seed-1-6';
    protected $available_models = array(
        'doubao-seed-1-6' => 'Doubao Seed 1.6',
        'doubao-seed-1-6-thinking' => 'Doubao Seed 1.6 Thinking',
        'doubao-1-5-pro-32k' => 'Doubao 1.5 Pro 32K'
    );
}

class AIAutotool_AI_Provider_BytePlus_ModelArk extends AIAutotool_AI_Provider_OpenAI_Compatible {
    protected $name = 'BytePlus ModelArk';
    protected $id = 'byteplus_modelark';
    protected $base_url = 'https://ark.ap-southeast.bytepluses.com/api/v3';
    protected $default_model = 'doubao-seed-1-6';
    protected $available_models = array(
        'doubao-seed-1-6' => 'Doubao Seed 1.6',
        'doubao-seed-1-6-thinking' => 'Doubao Seed 1.6 Thinking',
        'doubao-1-5-pro-32k' => 'Doubao 1.5 Pro 32K'
    );
}

class AIAutotool_AI_Provider_Cerebras extends AIAutotool_AI_Provider_OpenAI_Compatible {
    protected $name = 'Cerebras';
    protected $id = 'cerebras';
    protected $base_url = 'https://api.cerebras.ai/v1';
    protected $default_model = 'llama-3.3-70b';
    protected $available_models = array(
        'llama-3.3-70b' => 'Llama 3.3 70B',
        'qwen-3-235b-a22b' => 'Qwen 3 235B A22B',
        'gpt-oss-120b' => 'GPT-OSS 120B'
    );
}

class AIAutotool_AI_Provider_Cohere extends AIAutotool_AI_Provider_OpenAI_Compatible {
    protected $name = 'Cohere';
    protected $id = 'cohere';
    protected $base_url = 'https://api.cohere.com/compatibility/v1';
    protected $default_model = 'command-a-03-2025';
    protected $available_models = array(
        'command-a-03-2025' => 'Command A',
        'command-r-plus' => 'Command R Plus',
        'command-r' => 'Command R'
    );
}

class AIAutotool_AI_Provider_Nebius extends AIAutotool_AI_Provider_OpenAI_Compatible {
    protected $name = 'Nebius AI';
    protected $id = 'nebius';
    protected $base_url = 'https://api.studio.nebius.com/v1';
    protected $default_model = 'meta-llama/Meta-Llama-3.1-70B-Instruct';
    protected $available_models = array(
        'meta-llama/Meta-Llama-3.1-70B-Instruct' => 'Llama 3.1 70B Instruct',
        'meta-llama/Meta-Llama-3.1-8B-Instruct' => 'Llama 3.1 8B Instruct',
        'Qwen/Qwen2.5-72B-Instruct' => 'Qwen 2.5 72B Instruct'
    );
}

class AIAutotool_AI_Provider_SiliconFlow extends AIAutotool_AI_Provider_OpenAI_Compatible {
    protected $name = 'SiliconFlow';
    protected $id = 'siliconflow';
    protected $base_url = 'https://api.siliconflow.cn/v1';
    protected $default_model = 'deepseek-ai/DeepSeek-V3';
    protected $available_models = array(
        'deepseek-ai/DeepSeek-V3' => 'DeepSeek V3',
        'deepseek-ai/DeepSeek-R1' => 'DeepSeek R1',
        'Qwen/Qwen2.5-72B-Instruct' => 'Qwen 2.5 72B Instruct'
    );
}

class AIAutotool_AI_Provider_Hyperbolic extends AIAutotool_AI_Provider_OpenAI_Compatible {
    protected $name = 'Hyperbolic';
    protected $id = 'hyperbolic';
    protected $base_url = 'https://api.hyperbolic.xyz/v1';
    protected $default_model = 'meta-llama/Meta-Llama-3.1-70B-Instruct';
    protected $available_models = array(
        'meta-llama/Meta-Llama-3.1-70B-Instruct' => 'Llama 3.1 70B Instruct',
        'meta-llama/Meta-Llama-3.1-8B-Instruct' => 'Llama 3.1 8B Instruct',
        'deepseek-ai/DeepSeek-V3' => 'DeepSeek V3'
    );
}

class AIAutotool_AI_Provider_Chutes extends AIAutotool_AI_Provider_OpenAI_Compatible {
    protected $name = 'Chutes AI';
    protected $id = 'chutes';
    protected $base_url = 'https://llm.chutes.ai/v1';
    protected $default_model = 'deepseek-ai/DeepSeek-V3';
    protected $available_models = array(
        'deepseek-ai/DeepSeek-V3' => 'DeepSeek V3',
        'deepseek-ai/DeepSeek-R1' => 'DeepSeek R1',
        'Qwen/Qwen2.5-72B-Instruct' => 'Qwen 2.5 72B Instruct'
    );
}

class AIAutotool_AI_Provider_NVIDIA_NIM extends AIAutotool_AI_Provider_OpenAI_Compatible {
    protected $name = 'NVIDIA NIM';
    protected $id = 'nvidia_nim';
    protected $base_url = 'https://integrate.api.nvidia.com/v1';
    protected $default_model = 'meta/llama-3.1-70b-instruct';
    protected $available_models = array(
        'meta/llama-3.1-70b-instruct' => 'Llama 3.1 70B Instruct',
        'meta/llama-3.1-8b-instruct' => 'Llama 3.1 8B Instruct',
        'mistralai/mixtral-8x7b-instruct-v0.1' => 'Mixtral 8x7B Instruct'
    );
}
