"""
LLM工厂类 - 统一创建和管理LLM适配器

使用 LiteLLM 作为主要适配器，支持大多数 LLM 提供商。
对于 API 格式特殊的提供商（百度、MiniMax、豆包），使用原生适配器。
"""

from typing import Dict, List
from .types import LLMConfig, LLMProvider, DEFAULT_MODELS
from .base_adapter import BaseLLMAdapter
from .adapters import (
    LiteLLMAdapter,
    BaiduAdapter,
    MinimaxAdapter,
    DoubaoAdapter,
)


# 必须使用原生适配器的提供商（API 格式特殊）
NATIVE_ONLY_PROVIDERS = {
    LLMProvider.BAIDU,
    LLMProvider.MINIMAX,
    LLMProvider.DOUBAO,
}


class LLMFactory:
    """LLM工厂类"""

    _adapters: Dict[str, BaseLLMAdapter] = {}

    @classmethod
    def create_adapter(cls, config: LLMConfig) -> BaseLLMAdapter:
        """创建LLM适配器实例"""
        cache_key = cls._get_cache_key(config)

        # 从缓存中获取
        if cache_key in cls._adapters:
            return cls._adapters[cache_key]

        # 创建新的适配器实例
        adapter = cls._instantiate_adapter(config)

        # 缓存实例
        cls._adapters[cache_key] = adapter

        return adapter

    @classmethod
    def _instantiate_adapter(cls, config: LLMConfig) -> BaseLLMAdapter:
        """根据提供商类型实例化适配器"""
        # 如果未指定模型，使用默认模型
        if not config.model:
            config.model = DEFAULT_MODELS.get(config.provider, "gpt-4o-mini")

        # 对于必须使用原生适配器的提供商
        if config.provider in NATIVE_ONLY_PROVIDERS:
            return cls._create_native_adapter(config)

        # 其他提供商使用 LiteLLM
        if LiteLLMAdapter.supports_provider(config.provider):
            return LiteLLMAdapter(config)

        # 不支持的提供商
        raise ValueError(f"不支持的LLM提供商: {config.provider}")

    @classmethod
    def _create_native_adapter(cls, config: LLMConfig) -> BaseLLMAdapter:
        """创建原生适配器（仅用于 API 格式特殊的提供商）"""
        native_adapter_map = {
            LLMProvider.BAIDU: BaiduAdapter,
            LLMProvider.MINIMAX: MinimaxAdapter,
            LLMProvider.DOUBAO: DoubaoAdapter,
        }

        adapter_class = native_adapter_map.get(config.provider)
        if not adapter_class:
            raise ValueError(f"不支持的原生适配器提供商: {config.provider}")

        return adapter_class(config)

    @classmethod
    def _get_cache_key(cls, config: LLMConfig) -> str:
        """生成缓存键"""
        api_key_prefix = config.api_key[:8] if config.api_key else "no-key"
        return f"{config.provider.value}:{config.model}:{api_key_prefix}"

    @classmethod
    def clear_cache(cls) -> None:
        """清除缓存"""
        cls._adapters.clear()

    @classmethod
    def get_supported_providers(cls) -> List[LLMProvider]:
        """获取支持的提供商列表"""
        return list(LLMProvider)

    @classmethod
    def get_default_model(cls, provider: LLMProvider) -> str:
        """获取提供商的默认模型"""
        return DEFAULT_MODELS.get(provider, "gpt-4o-mini")

    @classmethod
    def get_available_models(cls, provider: LLMProvider) -> List[str]:
        """获取提供商的可用模型列表 (2025年最新)"""
        models = {
            LLMProvider.GEMINI: [
                "gemini-3-pro",
                "gemini-3.0-deep-think",
                "gemini-2.5-flash",
                "gemini-2.5-pro",
                "gemini-2.5-flash-lite",
                "gemini-2.5-flash-live-api",
                "veo-3.1",
                "veo-3.1-fast",
            ],
            LLMProvider.OPENAI: [
                "gpt-5",
                "gpt-5.1",
                "gpt-5.1-instant",
                "gpt-5.1-codex-max",
                "gpt-4o",
                "gpt-4o-mini",
                "gpt-4.5",
                "o4-mini",
                "o3",
                "o3-mini",
                "gpt-oss-120b",
                "gpt-oss-20b",
            ],
            LLMProvider.CLAUDE: [
                "claude-opus-4.5",
                "claude-sonnet-4.5",
                "claude-haiku-4.5",
                "claude-sonnet-4",
                "claude-opus-4",
                "claude-3.7-sonnet",
                "claude-3.5-sonnet",
                "claude-3.5-haiku",
                "claude-3-opus",
            ],
            LLMProvider.QWEN: [
                "qwen3-max-instruct",
                "qwen3-235b-a22b",
                "qwen3-turbo",
                "qwen3-32b",
                "qwen3-4b",
                "qwen3-embedding-8b",
                "qwen-image",
                "qwen-vl",
                "qwen-audio",
            ],
            LLMProvider.DEEPSEEK: [
                "deepseek-v3.1-terminus",
                "deepseek-r1-70b",
                "deepseek-r1-zero",
                "deepseek-v3.2-exp",
                "deepseek-chat",
                "deepseek-reasoner",
                "deepseek-ocr",
            ],
            LLMProvider.ZHIPU: [
                "glm-4.6",
                "glm-4.6-reap-218b",
                "glm-4.5",
                "glm-4.5v",
                "glm-4.5-air-106b",
                "glm-4-flash",
                "glm-4v-flash",
                "glm-4.1v-thinking",
            ],
            LLMProvider.MOONSHOT: [
                "kimi-k2",
                "kimi-k2-thinking",
                "kimi-k2-instruct-0905",
                "kimi-k1.5",
                "kimi-vl",
                "kimi-dev-72b",
                "kimi-researcher",
                "kimi-linear",
            ],
            LLMProvider.BAIDU: [
                "ernie-4.5",
                "ernie-4.5-21b-a3b-thinking",
                "ernie-4.0-8k",
                "ernie-3.5-8k",
                "ernie-vl",
            ],
            LLMProvider.MINIMAX: [
                "minimax-m2",
                "minimax-01-text",
                "minimax-01-vl",
                "minimax-m1",
                "speech-2.6",
                "hailuo-02",
                "music-1.5",
            ],
            LLMProvider.DOUBAO: [
                "doubao-1.6-pro",
                "doubao-1.5-pro",
                "doubao-seed-code",
                "doubao-seed-1.6",
                "doubao-vision-language",
            ],
            LLMProvider.OLLAMA: [
                "llama3.3-70b",
                "qwen3-8b",
                "gemma3-27b",
                "dolphin-3.0-llama3.1-8b",
                "cogito-v1",
                "deepseek-r1",
                "gpt-oss-120b",
                "llama3.1-405b",
                "mistral-nemo",
                "phi-3",
            ],
        }
        return models.get(provider, [])
