"""
模型客户端工厂类

通过注册表机制动态创建客户端实例，新增 provider 只需在注册表中添加映射。
"""

import os
from typing import Dict, Type

from core.config import AppConfig, ProviderConfig
from .base import BaseModelClient
from .openai_client import OpenAIClient
from .anthropic_client import AnthropicClient
from .minimax_client import MinimaxClient
from .glm_client import GLMClient
from .google_client import GoogleClient


class ModelClientFactory:
    """模型客户端工厂类，根据配置创建对应的客户端实例"""

    # provider_type → 客户端类 映射
    _CLIENT_REGISTRY: Dict[str, Type[BaseModelClient]] = {
        "openai": OpenAIClient,
        "anthropic": AnthropicClient,
        "minimax": MinimaxClient,
        "glm": GLMClient,
        "google": GoogleClient,
    }

    @staticmethod
    def create_client_from_model(
        model_name: str,
        config: AppConfig,
    ) -> BaseModelClient:
        """
        根据模型名称和配置创建客户端实例

        Args:
            model_name: 模型名称，如 "anthropic/claude-opus-4-6"
            config: 应用配置

        Returns:
            BaseModelClient 实例

        Raises:
            ValueError: 模型或 provider 未定义
        """
        provider_section = config.provider

        if "/" not in model_name:
            raise ValueError(f"模型名称必须是 provider/model 格式: {model_name}")

        provider_name, actual_model = model_name.split("/", 1)

        # 查找 provider 配置
        provider_config = provider_section.providers.get(provider_name)
        if not provider_config:
            available = ", ".join(provider_section.providers.keys())
            raise ValueError(
                f"未找到 provider 配置: {provider_name}\n"
                f"可用 provider: {available}"
            )

        return ModelClientFactory._create_client(
            provider_name=provider_name,
            provider_config=provider_config,
            model=actual_model,
        )

    @staticmethod
    def _create_client(
        provider_name: str,
        provider_config: ProviderConfig,
        model: str,
    ) -> BaseModelClient:
        """
        根据 provider 类型创建具体客户端

        Args:
            provider_config: Provider 连接配置
            model: 实际模型名称（不含 provider 前缀）

        Returns:
            BaseModelClient 实例
        """
        provider_type = provider_config.type.lower()

        # Build kwargs via ProviderManager (API key + context_window)
        try:
            from provider.provider_manager import ProviderManager

            pm = ProviderManager.get()
            kwargs = pm.get_client_kwargs(
                provider_name=provider_name,
                model=model,
                provider_config=provider_config,
            )
            # keep factory-specific params policy here
            kwargs.update({
                # temperature/max_tokens 不再走 provider.models(dict) 单模型配置，
                # 由各 client 内部默认值/调用方参数决定。
            })
        except Exception as e:
            # Do not silently swallow errors; this makes config/schema mistakes hard to detect.
            from core.telemetry import TelemetryManager

            TelemetryManager.get().error(
                "provider_kwargs_resolve_failed",
                e,
                provider=provider_name,
                model=model,
                provider_type=provider_type,
            )
            kwargs = {
                "model": model,
                "api_key": provider_config.api_key,
                "base_url": provider_config.base_url,
                "context_window": None,
            }

        client_cls = ModelClientFactory._CLIENT_REGISTRY.get(provider_type)
        if not client_cls:
            supported = ", ".join(ModelClientFactory._CLIENT_REGISTRY.keys())
            raise ValueError(
                f"不支持的 provider 类型: {provider_type}\n"
                f"支持的类型: {supported}"
            )

        return client_cls(**kwargs)
