<?php

namespace XZD\AI\V5\Analytics;

use XZD\AI\V5\Core\Config;

/**
 * 成本追踪服务 — 记录每次 AI 调用的 Token 消耗和费用，写入 xzd_ai_cost_log 表。
 */
class CostTracker
{
    private static ?self $instance = null;

    // 厂商定价表 (RMB / 1M tokens)
    private array $pricing = [
        // DeepSeek V4 (2026-04-24+)
        'deepseek-v4-pro'   => ['input' => 3.0,  'output' => 6.0,  'cache' => 0.025],
        'deepseek-v4-flash' => ['input' => 1.0,  'output' => 2.0,  'cache' => 0.02],
        // SiliconFlow 代理的 DeepSeek V4
        'deepseek-ai/DeepSeek-V4-Pro'  => ['input' => 3.0,  'output' => 6.0,  'cache' => 0.025],
        'deepseek-ai/DeepSeek-V4-Flash' => ['input' => 1.0,  'output' => 2.0,  'cache' => 0.02],
        'deepseek-v3'       => ['input' => 2.0,  'output' => 8.0,  'cache' => 0.5],
        'deepseek-r1'       => ['input' => 4.0,  'output' => 16.0, 'cache' => 1.0],
        // OpenAI
        'gpt-4.1'           => ['input' => 14.0, 'output' => 56.0, 'cache' => 3.5],
        'gpt-4.1-mini'      => ['input' => 2.8,  'output' => 11.2, 'cache' => 0.7],
        'gpt-4o'            => ['input' => 17.5, 'output' => 70.0, 'cache' => 8.75],
        'gpt-4o-mini'       => ['input' => 1.05, 'output' => 4.2,  'cache' => 0.525],
        'o3'                => ['input' => 17.5, 'output' => 70.0, 'cache' => 8.75],
        'o4-mini'           => ['input' => 7.7,  'output' => 30.8, 'cache' => 3.85],
        // Anthropic
        'claude-opus-4-7'   => ['input' => 105.0,'output' => 525.0,'cache' => 10.5],
        'claude-sonnet-4-6' => ['input' => 21.0, 'output' => 105.0,'cache' => 2.1],
        'claude-haiku-4-5'  => ['input' => 7.0,  'output' => 35.0, 'cache' => 0.7],
        // Google
        'gemini-2.5-pro'    => ['input' => 8.75, 'output' => 43.75,'cache' => 1.75],
        'gemini-2.5-flash'  => ['input' => 1.05, 'output' => 5.25, 'cache' => 0.35],
        // Qwen
        'qwen-plus'         => ['input' => 2.8,  'output' => 8.4,  'cache' => 0],
        'qwen-max'          => ['input' => 14.0, 'output' => 42.0, 'cache' => 0],
        'qwen-turbo'        => ['input' => 0.35, 'output' => 1.4,  'cache' => 0],
        // Kimi
        'moonshot-v1-128k'  => ['input' => 2.8,  'output' => 8.4,  'cache' => 0],
        'moonshot-v1-32k'   => ['input' => 2.8,  'output' => 8.4,  'cache' => 0],
        // Zhipu
        'glm-4-plus'        => ['input' => 3.5,  'output' => 10.5, 'cache' => 0],
        'glm-4-flash'       => ['input' => 0.7,  'output' => 2.1,  'cache' => 0],
        // Doubao
        'doubao-pro-128k'   => ['input' => 0.56, 'output' => 2.8,  'cache' => 0],
        'doubao-lite-128k'  => ['input' => 0.28, 'output' => 1.4,  'cache' => 0],
        // MiMo (小米)
        'mimo-v2.5'         => ['input' => 1.0,  'output' => 2.0,  'cache' => 0],
    ];

    // 默认定价 (未知模型)
    private array $defaultPricing = ['input' => 1.0, 'output' => 2.0, 'cache' => 0.02];

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

    /**
     * 记录一次 AI 调用成本
     *
     * @return int|null 插入记录的ID
     */
    public function log(array $data): ?int
    {
        global $wpdb;
        $table = $wpdb->prefix . 'xzd_ai_cost_log';

        $model    = $data['model'] ?? '';
        $provider = $data['provider'] ?? '';
        $inputTokens  = $data['input_tokens'] ?? 0;
        $outputTokens = $data['output_tokens'] ?? 0;
        $cacheTokens  = $data['cache_read_tokens'] ?? 0;

        // 计算费用
        $cost = $this->calculateCost($model, $inputTokens, $outputTokens, $cacheTokens);

        $inserted = $wpdb->insert($table, [
            'provider'          => $provider,
            'model'             => $model,
            'tool_id'           => $data['tool_id'] ?? null,
            'operation_id'      => $data['operation_id'] ?? null,
            'input_tokens'      => $inputTokens,
            'output_tokens'     => $outputTokens,
            'cache_read_tokens' => $cacheTokens,
            'cost_rmb'          => round($cost, 6),
            'duration_ms'       => $data['duration_ms'] ?? 0,
            'created_at'        => current_time('mysql'),
        ]);

        if ($inserted === false) {
            error_log('[XZD-AI] 成本记录写入失败: ' . $wpdb->last_error);
            return null;
        }

        return $wpdb->insert_id;
    }

    /**
     * 记录流式调用的成本（静态入口，供 StreamEngine 使用）
     *
     * 流式聊天之前从不记录成本，此方法与 instance()->log() 等价但提供静态调用便利。
     */
    public static function recordStreamCall(string $model, int $inputTokens, int $outputTokens, int $cacheTokens, string $streamId): ?int
    {
        try {
            return self::instance()->log([
                'model'             => $model,
                'provider'          => 'stream',
                'tool_id'           => 'chat_stream',
                'operation_id'      => $streamId,
                'input_tokens'      => $inputTokens,
                'output_tokens'     => $outputTokens,
                'cache_read_tokens' => $cacheTokens,
            ]);
        } catch (\Throwable $e) {
            error_log("[XZD-AI] recordStreamCall failed: {$e->getMessage()}");
            return null;
        }
    }

    /**
     * 计算费用 (RMB)
     *
     * 缓存命中的 token 从 input 全价中扣除，改按 cache 折扣价计费。
     */
    public function calculateCost(string $model, int $inputTokens, int $outputTokens, int $cacheTokens = 0): float
    {
        $pricing = $this->pricing[$model] ?? $this->defaultPricing;

        // 缓存命中的token从input全价中扣除，改用cache折扣价
        $nonCacheInput = max(0, $inputTokens - $cacheTokens);

        $cost = 0;
        if ($nonCacheInput > 0) {
            $cost += ($nonCacheInput / 1_000_000) * $pricing['input'];
        }
        if ($outputTokens > 0) {
            $cost += ($outputTokens / 1_000_000) * $pricing['output'];
        }
        if ($cacheTokens > 0) {
            $cost += ($cacheTokens / 1_000_000) * $pricing['cache'];
        }

        return $cost;
    }

    /**
     * 获取成本统计
     */
    public function getStats(array $filters = []): array
    {
        global $wpdb;
        $table = $wpdb->prefix . 'xzd_ai_cost_log';

        $where = ['1=1'];
        $binds = [];

        if (!empty($filters['date_from'])) {
            $where[] = 'created_at >= %s';
            $binds[] = $filters['date_from'];
        }
        if (!empty($filters['date_to'])) {
            $where[] = 'created_at <= %s';
            $binds[] = $filters['date_to'];
        }
        if (!empty($filters['provider'])) {
            $where[] = 'provider = %s';
            $binds[] = $filters['provider'];
        }
        if (!empty($filters['model'])) {
            $where[] = 'model = %s';
            $binds[] = $filters['model'];
        }

        $whereSql = implode(' AND ', $where);

        $query = fn(string $sql) => empty($binds)
            ? $wpdb->get_results($sql, ARRAY_A)
            : $wpdb->get_results($wpdb->prepare($sql, $binds), ARRAY_A);

        // 总计
        $total = $query("SELECT COUNT(*) as calls, COALESCE(SUM(cost_rmb), 0) as total_cost,
                COALESCE(SUM(input_tokens), 0) as total_input,
                COALESCE(SUM(output_tokens), 0) as total_output,
                COALESCE(SUM(cache_read_tokens), 0) as total_cache
         FROM {$table} WHERE {$whereSql}");
        $total = $total[0] ?? null;

        // 按日期分组
        $byDate = $query("SELECT DATE(created_at) as date, COUNT(*) as calls, COALESCE(SUM(cost_rmb), 0) as cost
         FROM {$table} WHERE {$whereSql}
         GROUP BY DATE(created_at) ORDER BY date DESC LIMIT 30");

        // 按模型分组
        $byModel = $query("SELECT model, COUNT(*) as calls, COALESCE(SUM(cost_rmb), 0) as cost,
                COALESCE(SUM(input_tokens), 0) as input_tokens,
                COALESCE(SUM(output_tokens), 0) as output_tokens
         FROM {$table} WHERE {$whereSql}
         GROUP BY model ORDER BY cost DESC LIMIT 20");

        // 按厂商分组
        $byProvider = $query("SELECT provider, COUNT(*) as calls, COALESCE(SUM(cost_rmb), 0) as cost
         FROM {$table} WHERE {$whereSql}
         GROUP BY provider ORDER BY cost DESC");

        return [
            'total'        => $total,
            'by_date'      => $byDate,
            'by_model'     => $byModel,
            'by_provider'  => $byProvider,
            'pricing'      => $this->pricing,
        ];
    }

    /**
     * 获取本月成本摘要
     */
    public function getMonthSummary(): array
    {
        global $wpdb;
        $table = $wpdb->prefix . 'xzd_ai_cost_log';
        $monthStart = date('Y-m-01');

        $row = $wpdb->get_row($wpdb->prepare(
            "SELECT COALESCE(SUM(cost_rmb), 0) as total_cost,
                    COALESCE(SUM(input_tokens), 0) as total_input,
                    COALESCE(SUM(output_tokens), 0) as total_output,
                    COUNT(*) as calls
             FROM {$table} WHERE created_at >= %s",
            $monthStart
        ), ARRAY_A);

        $budget = (float) Config::instance()->get('cost.monthly_budget', 0);
        $remaining = $budget > 0 ? max(0, $budget - (float) ($row['total_cost'] ?? 0)) : 0;

        return [
            'month_cost'       => (float) ($row['total_cost'] ?? 0),
            'month_input'      => (int) ($row['total_input'] ?? 0),
            'month_output'     => (int) ($row['total_output'] ?? 0),
            'month_calls'      => (int) ($row['calls'] ?? 0),
            'budget'           => $budget,
            'budget_remaining' => round($remaining, 4),
            'budget_pct'       => $budget > 0 ? round((float) ($row['total_cost'] ?? 0) / $budget * 100, 1) : 0,
        ];
    }

    /**
     * 获取模型定价表
     */
    public function getPricing(): array
    {
        return $this->pricing;
    }
}
