<?php

/**
 * OpenRouter Provider Class
 *
 * Handles all OpenRouter API interactions for content generation
 * OpenRouter provides access to 400+ AI models through a unified API
 *
 * @link       https://insya.com/ai-magic
 * @since      2.2.0
 *
 * @package    Ai_Magic
 * @subpackage Ai_Magic/admin
 */

if (!class_exists('AI_Magic_OpenAI')) {
    require_once plugin_dir_path(__FILE__) . 'class-ai-magic-openai.php';
}

class AI_Magic_OpenRouter implements AI_Magic_Provider_Interface
{
    /**
     * API Key for OpenRouter
     *
     * @var string
     */
    private $api_key;

    /**
     * Model to use
     *
     * @var string
     */
    private $model;

    /**
     * Maximum tokens to generate
     *
     * @var int
     */
    private $max_tokens;

    /**
     * Temperature setting
     *
     * @var float
     */
    private $temperature;

    /**
     * Top P setting
     *
     * @var float
     */
    private $top_p;

    /**
     * Provider ID
     *
     * @var string
     */
    private $provider_id = 'openrouter';

    /**
     * API Base URL
     *
     * @var string
     */
    private $api_base = 'https://openrouter.ai/api/v1';

    /**
     * Constructor - Initialize OpenRouter provider with settings
     *
     * @since    2.2.0
     */
    public function __construct()
    {
        if (!interface_exists('AI_Magic_Provider_Interface')) {
            require_once plugin_dir_path(dirname(__FILE__)) . 'includes/interface-ai-magic-provider.php';
        }

        // Load provider-specific settings
        $this->load_provider_settings();
    }

    /**
     * Load provider-specific settings from database
     *
     * @since    2.2.0
     */
    private function load_provider_settings()
    {
        $this->api_key = get_option('ai_magic_api_key_openrouter', '');
        $this->model = get_option('ai_magic_openrouter_model', 'openai/gpt-4o');
        if ($this->model === 'custom') {
            $this->model = get_option('ai_magic_openrouter_custom_model', '');
        }
        $this->max_tokens = (int) get_option('ai_magic_openrouter_max_tokens', get_option('ai_magic_max_tokens', 4096));
        $this->temperature = (float) get_option('ai_magic_openrouter_temperature', get_option('ai_magic_temperature', 0.7));
        $this->top_p = (float) get_option('ai_magic_openrouter_top_p', 1.0);
    }

    /**
     * Get current provider settings
     *
     * @since    2.2.0
     * @return   array    Current settings
     */
    public function get_settings()
    {
        return array(
            'model' => $this->model,
            'max_tokens' => $this->max_tokens,
            'temperature' => $this->temperature,
            'top_p' => $this->top_p
        );
    }

    /**
     * Set API Key manually (e.g. for testing or fetching models before saving)
     *
     * @since    2.2.0
     * @param    string    $api_key    API Key
     */
    public function setApiKey($api_key)
    {
        $this->api_key = $api_key;
    }

    /**
     * Build the prompt string based on settings and input
     * 
     * @param string $title_text The user input/title
     * @param array $overrides Optional overrides for settings
     * @return string The constructed prompt
     */
    public function buildPrompt($title_text, $overrides = array())
    {
        // For now, reuse the same prompt logic as OpenAI
        // In a real implementation, we could move this to a shared utility
        $openai = new AI_Magic_OpenAI();
        return $openai->buildPrompt($title_text, $overrides);
    }

    /**
     * Parse structured content from AI response
     * 
     * @param string $text The raw text from AI
     * @return object Parsed data object
     */
    public function parseContent($text)
    {
        $fields = array("title", "slug", "excerpt", "tags", "content");
        $parsed_data = array();

        foreach ($fields as $field) {
            preg_match("/#\s*$field\s*:\s*(.*?)(?=#\s*\w+\s*:|$)/si", $text, $matches);
            $parsed_data[$field] = isset($matches[1]) ? trim($matches[1]) : "";
        }

        if (empty($parsed_data['content']) && empty($parsed_data['title'])) {
            $parsed_data['content'] = $text;
        }

        return (object) $parsed_data;
    }

    /**
     * Generate text using OpenRouter API
     *
     * @since    2.2.0
     * @param    string    $prompt    The prompt to send
     * @return   array                Response array
     */
    public function generateText($title_text)
    {
        if (empty($this->api_key)) {
            return array(
                'type' => 'error',
                'message' => __('OpenRouter API Key is missing. Please configure it in settings.', 'ai_magic')
            );
        }

        $start_time = microtime(true);
        $prompt = $this->buildPrompt($title_text);

        $url = $this->api_base . '/chat/completions';
        $headers = array(
            'Authorization' => 'Bearer ' . $this->api_key,
            'Content-Type' => 'application/json',
            'HTTP-Referer' => home_url(),
            'X-Title' => get_bloginfo('name')
        );

        $body = array(
            'model' => $this->model,
            'messages' => array(
                array('role' => 'user', 'content' => $prompt)
            ),
            'max_tokens' => $this->max_tokens,
            'temperature' => $this->temperature,
            'top_p' => $this->top_p
        );

        $args = array(
            'headers' => $headers,
            'body' => json_encode($body),
            'timeout' => 120,
            'method' => 'POST'
        );

        $response = wp_remote_post($url, $args);

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

        $response_code = wp_remote_retrieve_response_code($response);
        $response_body = wp_remote_retrieve_body($response);
        $data = json_decode($response_body, true);

        if ($response_code !== 200) {
            $error_msg = isset($data['error']['message']) ? $data['error']['message'] : 'Unknown error';
            return array('type' => 'error', 'message' => 'OpenRouter Error: ' . $error_msg);
        }

        if (isset($data['choices'][0]['message']['content'])) {
            $generated_text = $data['choices'][0]['message']['content'];
            $content = $this->parseContent($generated_text);

            $post_data = array(
                'post_title' => wp_strip_all_tags($content->title),
                'post_excerpt' => $content->excerpt,
                'post_content' => $content->content,
                'post_name' => $content->slug,
                'post_tags' => $content->tags,
                'post_status' => 'publish',
                'post_type' => 'ai_magic_logs',
                'post_author' => get_current_user_id()
            );

            $post_id = wp_insert_post($post_data);
            $end_time = microtime(true);
            $duration = ($end_time - $start_time) * 1000;

            update_post_meta($post_id, 'duration', $duration);
            update_post_meta($post_id, 'prompt', $title_text);
            update_post_meta($post_id, 'tags', $content->tags);
            update_post_meta($post_id, 'model', $data['model']);

            return array(
                'type' => 'success',
                'message' => 'Success',
                'data' => $post_data,
                'raw_text' => $generated_text
            );
        }

        return array('type' => 'error', 'message' => 'Invalid response from OpenRouter');
    }

    /**
     * Generate SEO meta description
     *
     * @param string $title Post title
     * @param string $content Post content
     * @param array $keywords Focus keywords
     * @return array Response
     */
    public function generateMetaDescription($title, $content = '', $keywords = array())
    {
        $keyword_text = !empty($keywords) ? implode(', ', $keywords) : '';
        $prompt = "Write a compelling SEO meta description for an article titled \"$title\".";
        if (!empty($content)) {
            $content_preview = substr(strip_tags($content), 0, 500);
            $prompt .= " The article is about: $content_preview";
        }
        if (!empty($keyword_text)) {
            $prompt .= " Include these keywords naturally: $keyword_text.";
        }
        $prompt .= " The meta description must be between 150-160 characters, engaging, and encourage clicks. Return only the meta description text, nothing else.";

        $response = $this->generateSimpleText($prompt);
        if ($response['type'] === 'success') {
            $response['length'] = strlen($response['data']);
        }
        return $response;
    }

    /**
     * Generate focus keywords from content
     *
     * @param string $content Post content
     * @param int $count Number of keywords to generate
     * @return array Response
     */
    public function generateFocusKeywords($content, $count = 5)
    {
        $content_preview = substr(strip_tags($content), 0, 1000);
        $prompt = "Analyze this content and extract the $count most important SEO keywords or key phrases. Return only a comma-separated list of keywords, nothing else:\n\n$content_preview";

        $response = $this->generateSimpleText($prompt);
        if ($response['type'] === 'success') {
            $keywords = array_map('trim', explode(',', $response['data']));
            $response['data'] = array_filter($keywords);
        }
        return $response;
    }

    /**
     * Internal helper to generate a simple text response without structured parsing
     * 
     * @param string $prompt
     * @return array
     */
    private function generateSimpleText($prompt)
    {
        if (empty($this->api_key)) {
            return array('type' => 'error', 'message' => 'API Key missing');
        }

        $url = $this->api_base . '/chat/completions';
        $body = array(
            'model' => $this->model,
            'messages' => array(array('role' => 'user', 'content' => $prompt)),
            'max_tokens' => 200,
            'temperature' => 0.7
        );

        $response = wp_remote_post($url, array(
            'headers' => array(
                'Authorization' => 'Bearer ' . $this->api_key,
                'Content-Type' => 'application/json'
            ),
            'body' => json_encode($body),
            'timeout' => 30
        ));

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

        $data = json_decode(wp_remote_retrieve_body($response), true);
        if (isset($data['choices'][0]['message']['content'])) {
            return array(
                'type' => 'success',
                'data' => trim($data['choices'][0]['message']['content'])
            );
        }

        return array('type' => 'error', 'message' => 'Invalid response');
    }

    /**
     * Get available models from OpenRouter API
     *
     * @since    2.2.0
     * @return   array    List of models
     */
    /**
     * Get available models from OpenRouter API
     *
     * @since    2.2.0
     * @return   array    List of models
     */
    public function getModels()
    {
        // Try to fetch from API first
        $api_models = $this->fetchModelsFromAPI();

        if (!empty($api_models)) {
            return $api_models;
        }

        // Fallback to curated list if API fails or returns empty
        return array(
            // OpenAI Models
            array('id' => 'openai/gpt-4o', 'name' => 'GPT-4o (OpenAI)'),
            array('id' => 'openai/gpt-4o-mini', 'name' => 'GPT-4o Mini (OpenAI)'),
            array('id' => 'openai/gpt-4-turbo', 'name' => 'GPT-4 Turbo (OpenAI)'),
            array('id' => 'openai/o1-preview', 'name' => 'O1 Preview (OpenAI)'),
            array('id' => 'openai/o1-mini', 'name' => 'O1 Mini (OpenAI)'),

            // Anthropic Models
            array('id' => 'anthropic/claude-3.5-sonnet', 'name' => 'Claude 3.5 Sonnet'),
            array('id' => 'anthropic/claude-3-opus', 'name' => 'Claude 3 Opus'),
            array('id' => 'anthropic/claude-3-haiku', 'name' => 'Claude 3 Haiku'),

            // Google Models
            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 Models
            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'),
            array('id' => 'meta-llama/llama-3.1-70b-instruct', 'name' => 'Llama 3.1 70B'),

            // Mistral Models
            array('id' => 'mistralai/mistral-large', 'name' => 'Mistral Large'),
            array('id' => 'mistralai/mixtral-8x22b-instruct', 'name' => 'Mixtral 8x22B'),
            array('id' => 'mistralai/mistral-7b-instruct', 'name' => 'Mistral 7B'),

            // DeepSeek Models
            array('id' => 'deepseek/deepseek-chat', 'name' => 'DeepSeek Chat'),
            array('id' => 'deepseek/deepseek-coder', 'name' => 'DeepSeek Coder'),

            // Qwen Models
            array('id' => 'qwen/qwen-2.5-72b-instruct', 'name' => 'Qwen 2.5 72B'),
            array('id' => 'qwen/qwen-2.5-coder-32b-instruct', 'name' => 'Qwen 2.5 Coder 32B'),

            // 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)'),
        );
    }

    /**
     * Fetch all models from OpenRouter API (dynamic)
     *
     * @since    2.2.0
     * @return   array    List of all models from API
     */
    public function fetchModelsFromAPI()
    {
        $url = $this->api_base . '/models';

        $response = wp_remote_get($url, array(
            'timeout' => 30,
            'headers' => array(
                'Authorization' => 'Bearer ' . $this->api_key
            )
        ));

        if (is_wp_error($response)) {
            return array();
        }

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

        if (!isset($data['data']) || !is_array($data['data'])) {
            return array();
        }

        $models = array();
        foreach ($data['data'] as $model) {
            $models[] = array(
                'id' => $model['id'],
                'name' => isset($model['name']) ? $model['name'] : $model['id'],
                'context_length' => isset($model['context_length']) ? $model['context_length'] : null,
                'pricing' => isset($model['pricing']) ? $model['pricing'] : null
            );
        }

        return $models;
    }

    /**
     * Validate API Key
     *
     * @since    2.2.0
     * @return   bool|WP_Error    True if valid, WP_Error otherwise
     */
    public function validateApiKey()
    {
        if (empty($this->api_key)) {
            return new WP_Error('missing_key', __('API Key is missing', 'ai_magic'));
        }

        // Test API key by fetching models
        $url = $this->api_base . '/models';

        $response = wp_remote_get($url, array(
            'timeout' => 15,
            'headers' => array(
                'Authorization' => 'Bearer ' . $this->api_key
            )
        ));

        if (is_wp_error($response)) {
            return $response;
        }

        $response_code = wp_remote_retrieve_response_code($response);
        if ($response_code !== 200) {
            return new WP_Error('invalid_key', __('Invalid API Key', 'ai_magic'));
        }

        return true;
    }
}
