"""
模型定义 - 结构化模型信息

所有支持的模型信息集中在此处，包括：
- provider: 提供商 (openai, anthropic, deepseek, glm, qwen, minimax)
- type: 模型类型 (chat, reasoning, code, vision 等)
- name: 模型名称
- context_window: 上下文窗口大小 (token 数)

注意：context_window 值基于官方 API 文档和网络搜索验证，
可能与实际 API 可用版本有差异，请以各 provider 官方文档为准。
"""

from dataclasses import dataclass
from typing import List, Dict, Any


@dataclass(frozen=True)
class ModelInfo:
    """模型信息"""
    provider: str      # 提供商
    type: str         # 模型类型: chat, reasoning, code, vision 等
    name: str         # 模型名称
    context_window: int  # 上下文窗口大小


# 结构化模型列表 (按 provider 分组)
# 注意：以下 context_window 值基于官方文档和 API 验证，可能存在版本差异
MODELS: List[ModelInfo] = [
    # ========== OpenAI ==========
    # GPT-5 系列 (2025)
    ModelInfo(provider="openai", type="chat", name="gpt-5.2", context_window=400000),
    ModelInfo(provider="openai", type="chat", name="gpt-5.1", context_window=400000),
    ModelInfo(provider="openai", type="chat", name="gpt-5", context_window=400000),
    ModelInfo(provider="openai", type="chat", name="gpt-5.2-chat-latest", context_window=400000),
    ModelInfo(provider="openai", type="chat", name="gpt-5.2-pro", context_window=400000),
    ModelInfo(provider="openai", type="code", name="gpt-5.2-codex", context_window=400000),
    ModelInfo(provider="openai", type="code", name="gpt-5-codex", context_window=400000),
    # ModelInfo(provider="openai", type="chat", name="gpt-5-pro", context_window=400000),
    # ModelInfo(provider="openai", type="chat", name="gpt-5-mini", context_window=400000),
    # ModelInfo(provider="openai", type="chat", name="gpt-5-nano", context_window=400000),

    # GPT-4.1 系列 (2024)
    # ModelInfo(provider="openai", type="chat", name="gpt-4.1", context_window=1048576),
    # ModelInfo(provider="openai", type="chat", name="gpt-4.1-mini", context_window=1048576),
    # ModelInfo(provider="openai", type="chat", name="gpt-4.1-nano", context_window=1048576),

    # GPT-4o 系列
    # ModelInfo(provider="openai", type="chat", name="gpt-4o", context_window=128000),
    # ModelInfo(provider="openai", type="chat", name="gpt-4o-mini", context_window=128000),
    # ModelInfo(provider="openai", type="chat", name="gpt-4-turbo", context_window=128000),
    # ModelInfo(provider="openai", type="chat", name="gpt-4", context_window=8192),
    # ModelInfo(provider="openai", type="chat", name="gpt-3.5-turbo", context_window=16385),

    # OpenAI o-series (reasoning)
    # ModelInfo(provider="openai", type="reasoning", name="o1-pro", context_window=200000),
    # ModelInfo(provider="openai", type="reasoning", name="o1", context_window=200000),
    # ModelInfo(provider="openai", type="reasoning", name="o1-mini", context_window=128000),
    # ModelInfo(provider="openai", type="reasoning", name="o3-pro", context_window=200000),
    # ModelInfo(provider="openai", type="reasoning", name="o3", context_window=200000),
    # ModelInfo(provider="openai", type="reasoning", name="o3-mini", context_window=200000),
    # ModelInfo(provider="openai", type="reasoning", name="o3-deep-research", context_window=200000),
    # ModelInfo(provider="openai", type="reasoning", name="o4-mini", context_window=200000),
    # ModelInfo(provider="openai", type="reasoning", name="o4-mini-deep-research", context_window=200000),
    # ModelInfo(provider="openai", type="code", name="codex-mini-latest", context_window=200000),

    # ========== Anthropic ==========
    # Claude 4 系列 (2025)
    ModelInfo(provider="anthropic", type="chat", name="claude-opus-4-6", context_window=200000),
    ModelInfo(provider="anthropic", type="chat", name="claude-sonnet-4-6", context_window=200000),
    # ModelInfo(provider="anthropic", type="chat", name="claude-opus-4-5-20250514", context_window=200000),
    # ModelInfo(provider="anthropic", type="chat", name="claude-sonnet-4-5-20250514", context_window=200000),
    # ModelInfo(provider="anthropic", type="chat", name="claude-opus-4-1-20250514", context_window=200000),
    # ModelInfo(provider="anthropic", type="chat", name="claude-sonnet-4-1-20250514", context_window=200000),
    # ModelInfo(provider="anthropic", type="chat", name="claude-opus-4", context_window=200000),
    # ModelInfo(provider="anthropic", type="chat", name="claude-sonnet-4", context_window=200000),

    # ========== DeepSeek ==========
    # DeepSeek V3 / R1 系列 (2024-2025)
    ModelInfo(provider="deepseek", type="chat", name="deepseek-chat", context_window=128000),
    ModelInfo(provider="deepseek", type="reasoning", name="deepseek-reasoner", context_window=128000),

    # ========== GLM / Zhipu ==========
    # GLM-5 系列 (2026)
    ModelInfo(provider="glm", type="chat", name="glm-5", context_window=200000),
    
    # GLM-4 系列 (2024-2025)
    ModelInfo(provider="glm", type="chat", name="glm-4.7", context_window=200000),
    ModelInfo(provider="glm", type="chat", name="glm-4.6", context_window=200000),

    # ========== Qwen ==========
    # Qwen3 系列 (2025) - 原生 32K，通过 YaRN 可扩展至 128K
    # 注：以下为 DashScope API 版本的 context_window
    # ModelInfo(provider="qwen", type="chat", name="qwen3-32b", context_window=32768),
    # ModelInfo(provider="qwen", type="chat", name="qwen3-14b", context_window=32768),
    # ModelInfo(provider="qwen", type="chat", name="qwen3-8b", context_window=32768),
    # ModelInfo(provider="qwen", type="chat", name="qwen3-4b", context_window=32768),
    # ModelInfo(provider="qwen", type="chat", name="qwen3-1.7b", context_window=32768),
    # ModelInfo(provider="qwen", type="chat", name="qwen3-0.6b", context_window=32768),
    # ModelInfo(provider="qwen", type="chat", name="qwen3-235b-a22b", context_window=128000),
    # ModelInfo(provider="qwen", type="chat", name="qwen3-30b-a3b", context_window=128000),

    # Qwen2.5 / Qwen2 系列 (DashScope API)
    # ModelInfo(provider="qwen", type="chat", name="qwen-long", context_window=1000000),
    # ModelInfo(provider="qwen", type="chat", name="qwen-long-latest", context_window=1000000),
    # ModelInfo(provider="qwen", type="chat", name="qwen-turbo-latest", context_window=1000000),
    # ModelInfo(provider="qwen", type="chat", name="qwen-plus-latest", context_window=1000000),
    # ModelInfo(provider="qwen", type="chat", name="qwen-turbo-2024-11-01", context_window=1000000),
    # ModelInfo(provider="qwen", type="chat", name="qwen-plus-2025-07-28", context_window=1000000),
    # ModelInfo(provider="qwen", type="chat", name="qwen-turbo", context_window=1000000),
    # ModelInfo(provider="qwen", type="chat", name="qwen-plus", context_window=1000000),
    # ModelInfo(provider="qwen", type="chat", name="qwen-plus-2025-07-14", context_window=131072),
    # ModelInfo(provider="qwen", type="chat", name="qwen-max-latest", context_window=131072),
    # ModelInfo(provider="qwen", type="chat", name="qwen-max-2025-01-25", context_window=131072),
    # ModelInfo(provider="qwen", type="chat", name="qwen-max", context_window=32768),

    # ========== Google Gemini ==========
    ModelInfo(provider="google", type="chat", name="gemini-3.1-pro-preview", context_window=1048576),
    ModelInfo(provider="google", type="chat", name="gemini-3-pro-preview", context_window=1048576),
    ModelInfo(provider="google", type="chat", name="gemini-3-flash-preview", context_window=1048576),
    ModelInfo(provider="google", type="chat", name="gemini-2.5-flash", context_window=1048576),

    # ========== MiniMax ==========
    # M2.5 系列 (2026)
    ModelInfo(provider="minimax", type="chat", name="MiniMax-M2.5", context_window=204800),
    ModelInfo(provider="minimax", type="chat", name="MiniMax-M2.5-highspeed", context_window=204800),
    # M2 / M1 系列
    ModelInfo(provider="minimax", type="chat", name="MiniMax-M2", context_window=204800),
    ModelInfo(provider="minimax", type="chat", name="MiniMax-M1", context_window=204800),
]

# 默认上下文窗口大小
DEFAULT_CONTEXT_WINDOW = 128000

# ============================================================================
# 内置默认 Provider 连接配置
# 配置文件中同名的会覆盖这里的默认值
# ============================================================================

DEFAULT_PROVIDERS: Dict[str, Dict[str, Any]] = {
    "openai": {
        "type": "openai",
        "base_url": "https://api.openai.com/v1",
    },
    "anthropic": {
        "type": "anthropic",
        "base_url": "https://api.anthropic.com",
    },
    "glm": {
        "type": "glm",
        "base_url": "https://open.bigmodel.cn/api/coding/paas/v4",
    },
    "minimax": {
        "type": "minimax",
        "base_url": "https://api.minimaxi.com/anthropic",
    },
    "google": {
        "type": "google",
    },
}


def get_default_models() -> Dict[str, Dict[str, Any]]:
    """
    从 MODELS 列表生成默认模型配置字典

    格式: {"provider/model_name": {"provider": "...", "model": "..."}}
    """
    return {
        f"{m.provider}/{m.name}": {"provider": m.provider, "model": m.name}
        for m in MODELS
    }


def get_model_info(model_name: str) -> ModelInfo | None:
    """
    根据模型名称获取模型信息

    Args:
        model_name: 模型名称

    Returns:
        ModelInfo 或 None (未找到时返回 None)
    """
    # 精确匹配
    for model in MODELS:
        if model.name == model_name:
            return model
    return None


def get_context_window(model_name: str) -> int:
    """
    根据模型名称获取上下文窗口大小

    匹配策略：先精确匹配，再前缀匹配（取最长前缀）。

    Args:
        model_name: 模型名称

    Returns:
        上下文窗口大小 (token 数)
    """
    # 精确匹配
    for model in MODELS:
        if model.name == model_name:
            return model.context_window

    # 前缀匹配 (取最长匹配的 key)
    best_match: ModelInfo | None = None
    best_match_len = 0
    for model in MODELS:
        if model_name.startswith(model.name) and len(model.name) > best_match_len:
            best_match = model
            best_match_len = len(model.name)

    if best_match:
        return best_match.context_window

    return DEFAULT_CONTEXT_WINDOW


def get_models_by_provider(provider: str) -> List[ModelInfo]:
    """
    获取指定提供商的所有模型

    Args:
        provider: 提供商名称

    Returns:
        模型列表
    """
    return [m for m in MODELS if m.provider == provider]


def get_all_providers() -> List[str]:
    """
    获取所有提供商列表

    Returns:
        提供商列表
    """
    return sorted(list({m.provider for m in MODELS}))


def get_model_list() -> List[dict]:
    """
    获取模型列表 (用于 WebSocket 传输)

    Returns:
        模型列表 (dict 格式)
    """
    return [
        {
            "provider": m.provider,
            "type": m.type,
            "name": m.name,
            "context_window": m.context_window,
        }
        for m in MODELS
    ]
