<?php
/**
 * Claude AI Provider.
 *
 * Implements the Anthropic Claude API.
 *
 * @package Inqyra
 */

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

/**
 * Claude Provider class.
 */
class Inqyra_Claude_Provider extends Inqyra_AI_Provider_Abstract {

    /**
     * API endpoint.
     */
    const API_URL = 'https://api.anthropic.com/v1/messages';

    /**
     * API version.
     */
    const API_VERSION = '2023-06-01';

    /**
     * Pricing per 1M tokens (input/output) by model.
     */
    const PRICING = [
        'claude-sonnet-4-20250514' => ['input' => 3.00, 'output' => 15.00],
        'claude-opus-4-20250514' => ['input' => 15.00, 'output' => 75.00],
        'claude-haiku-4-5-20251001' => ['input' => 1.00, 'output' => 5.00],
        'claude-3-5-sonnet-20241022' => ['input' => 3.00, 'output' => 15.00],
        'claude-3-5-haiku-20241022' => ['input' => 0.80, 'output' => 4.00],
        'claude-3-opus-20240229' => ['input' => 15.00, 'output' => 75.00],
        'claude-3-sonnet-20240229' => ['input' => 3.00, 'output' => 15.00],
        'claude-3-haiku-20240307' => ['input' => 0.25, 'output' => 1.25],
    ];

    /**
     * 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(__('Claude API key not configured.', 'inqyra')));
        }

        // Extract system message
        $system_prompt = '';
        $chat_messages = [];

        foreach ($messages as $message) {
            if ($message['role'] === 'system') {
                $system_prompt .= ($system_prompt ? "\n\n" : '') . $message['content'];
            } else {
                $chat_messages[] = [
                    'role' => $message['role'],
                    'content' => $message['content'],
                ];
            }
        }

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

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

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

        if ($system_prompt) {
            $request_data['system'] = $system_prompt;
        }

        $response = $this->make_request(
            self::API_URL,
            $request_data,
            [
                'x-api-key' => $this->api_key,
                'anthropic-version' => self::API_VERSION,
            ]
        );

        $content = $response['content'][0]['text'] ?? '';
        $tokens = [
            'input' => $response['usage']['input_tokens'] ?? 0,
            'output' => $response['usage']['output_tokens'] ?? 0,
        ];

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

        $this->log_api_call('claude', $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 'claude';
    }

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

    /**
     * Get hardcoded models - curated list of recommended chat models.
     *
     * @return array Model list with pricing.
     */
    public function get_hardcoded_models(): array {
        return [
            'claude-sonnet-4-20250514' => 'Claude Sonnet 4 ($3.00/$15.00 per 1M)',
            'claude-haiku-4-5-20251001' => 'Claude Haiku 4.5 ($1.00/$5.00 per 1M)',
            'claude-3-5-haiku-20241022' => 'Claude 3.5 Haiku ($0.80/$4.00 per 1M)',
        ];
    }

    /**
     * Get the default model.
     *
     * @return string Default model ID.
     */
    public function get_default_model(): string {
        return 'claude-sonnet-4-20250514';
    }

    /**
     * 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;
    }

    /**
     * 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];
        }

        // Default to Sonnet 4 pricing if unknown
        return self::PRICING['claude-sonnet-4-20250514'];
    }

    /**
     * Fetch available models from the Anthropic 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.anthropic.com/v1/models?limit=1000',
            [
                'x-api-key' => $this->api_key,
                'anthropic-version' => self::API_VERSION,
            ]
        );

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

        return $models;
    }
}
