<?php
/**
 * DeepSeek AI Provider.
 *
 * Implements the DeepSeek API (OpenAI-compatible).
 *
 * @package Inqyra
 */

// If this file is called directly, abort.
if (!defined('WPINC')) {
    die;
}

/**
 * DeepSeek Provider class.
 */
class Inqyra_DeepSeek_Provider extends Inqyra_AI_Provider_Abstract {

    /**
     * API endpoint.
     */
    const API_URL = 'https://api.deepseek.com/v1/chat/completions';

    /**
     * Pricing per 1M tokens (input/output) by model.
     * Input price uses cache-miss rate (conservative estimate).
     */
    const PRICING = [
        'deepseek-chat'     => ['input' => 0.28, 'output' => 0.42],
        'deepseek-reasoner' => ['input' => 0.28, 'output' => 0.42],
    ];

    /**
     * Send a chat completion request.
     *
     * @param array $messages Array of messages with 'role' and 'content'.
     * @param array $options  Additional options.
     * @return array Response with 'content', 'tokens', and 'model'.
     * @throws Exception On API error.
     */
    public function chat(array $messages, array $options = []): array {
        if (!$this->is_configured()) {
            throw new Exception(esc_html(__('DeepSeek API key not configured.', 'inqyra')));
        }

        $model = $options['model'] ?? $this->get_default_model();
        $max_tokens = $options['max_tokens'] ?? 4096;

        $request_data = [
            'model' => $model,
            'messages' => $messages,
            'max_tokens' => $max_tokens,
        ];

        if (isset($options['temperature'])) {
            $request_data['temperature'] = (float) $options['temperature'];
        }

        $response = $this->make_request(
            self::API_URL,
            $request_data,
            [
                'Authorization' => 'Bearer ' . $this->api_key,
            ]
        );

        $content = $response['choices'][0]['message']['content'] ?? '';
        $tokens = [
            'input' => $response['usage']['prompt_tokens'] ?? 0,
            'output' => $response['usage']['completion_tokens'] ?? 0,
        ];

        $cost = $this->calculate_cost($tokens['input'], $tokens['output'], $model);

        $this->log_api_call('deepseek', $model, $tokens, $cost);

        return [
            'content' => $content,
            'tokens' => $tokens,
            'model' => $response['model'] ?? $model,
            'cost' => $cost,
        ];
    }

    /**
     * Get the provider identifier.
     *
     * @return string Provider ID.
     */
    public function get_id(): string {
        return 'deepseek';
    }

    /**
     * Get the provider name.
     *
     * @return string Provider name.
     */
    public function get_name(): string {
        return 'DeepSeek';
    }

    /**
     * Get hardcoded models - curated list of recommended chat models.
     *
     * @return array Model list with pricing.
     */
    public function get_hardcoded_models(): array {
        return [
            'deepseek-chat'     => 'DeepSeek Chat V3 ($0.28/$0.42 per 1M)',
            'deepseek-reasoner' => 'DeepSeek Reasoner R1 ($0.28/$0.42 per 1M)',
        ];
    }

    /**
     * Get the default model.
     *
     * @return string Default model ID.
     */
    public function get_default_model(): string {
        return 'deepseek-chat';
    }

    /**
     * Calculate cost for token usage.
     *
     * @param int    $input_tokens  Number of input tokens.
     * @param int    $output_tokens Number of output tokens.
     * @param string $model         Model identifier.
     * @return float Cost in USD.
     */
    public function calculate_cost(int $input_tokens, int $output_tokens, string $model): float {
        $pricing = $this->get_model_pricing($model);

        $input_cost = ($input_tokens / 1000000) * $pricing['input'];
        $output_cost = ($output_tokens / 1000000) * $pricing['output'];

        return $input_cost + $output_cost;
    }

    /**
     * Fetch available models from the DeepSeek API.
     *
     * @return array Associative array of model_id => display_name.
     */
    public function fetch_available_models(): array {
        if (!$this->is_configured()) {
            return [];
        }

        $response = $this->make_get_request(
            'https://api.deepseek.com/v1/models',
            [
                'Authorization' => 'Bearer ' . $this->api_key,
            ]
        );

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

        return $models;
    }

    /**
     * Get pricing for a specific model.
     *
     * @param string $model Model identifier.
     * @return array Pricing with 'input' and 'output' per 1M tokens.
     */
    protected function get_model_pricing(string $model): array {
        if (isset(self::PRICING[$model])) {
            return self::PRICING[$model];
        }

        // Check for partial matches
        foreach (self::PRICING as $price_model => $pricing) {
            if (strpos($model, $price_model) !== false) {
                return $pricing;
            }
        }

        // Default to chat model pricing
        return self::PRICING['deepseek-chat'];
    }
}
