"""实现层 - 大模型API客户端基类"""
import aiohttp
from typing import Dict, Any
from ...interfaces.llm_client import LLMClient


class BaseLLMClient(LLMClient):
    """大模型API客户端基类"""

    def __init__(
        self,
        server_url: str,
        model_id: str,
        api_key: str,
        timeout: int = 30,
        max_retries: int = 2
    ):
        """
        初始化客户端

        Args:
            server_url: 服务器URL
            model_id: 模型ID
            api_key: API密钥
            timeout: 超时时间（秒）
            max_retries: 最大重试次数
        """
        self.server_url = server_url.rstrip("/")
        self.model_id = model_id
        self.api_key = api_key
        self.timeout = timeout
        self.max_retries = max_retries

    def get_model_id(self) -> str:
        """获取模型ID"""
        return self.model_id

    def get_server_url(self) -> str:
        """获取服务器URL"""
        return self.server_url

    def _get_headers(self) -> Dict[str, str]:
        """获取请求头"""
        return {
            "Content-Type": "application/json",
            "Authorization": f"Bearer {self.api_key}"
        }

    def _build_request_body(
        self,
        messages: list[Dict[str, str]],
        **kwargs
    ) -> Dict[str, Any]:
        """
        构建请求体

        Args:
            messages: 消息列表
            **kwargs: 额外参数

        Returns:
            请求体字典
        """
        body = {
            "model": self.model_id,
            "messages": messages
        }

        # 添加可选参数
        if "temperature" in kwargs:
            body["temperature"] = kwargs["temperature"]
        if "max_tokens" in kwargs:
            body["max_tokens"] = kwargs["max_tokens"]
        if "stream" in kwargs:
            body["stream"] = kwargs["stream"]

        return body

    async def chat_completion(
        self,
        messages: list[Dict[str, str]],
        **kwargs
    ) -> Dict[str, Any]:
        """
        异步调用聊天补全API

        Args:
            messages: 消息列表
            **kwargs: 额外参数

        Returns:
            API响应结果
        """
        url = f"{self.server_url}/chat/completions"
        headers = self._get_headers()
        body = self._build_request_body(messages, **kwargs)

        timeout = aiohttp.ClientTimeout(total=self.timeout)

        for attempt in range(self.max_retries + 1):
            try:
                async with aiohttp.ClientSession(timeout=timeout) as session:
                    async with session.post(url, json=body, headers=headers) as response:
                        response.raise_for_status()
                        data = await response.json()

                        # 解析响应
                        if "choices" in data and len(data["choices"]) > 0:
                            content = data["choices"][0].get("message", {}).get("content", "")
                            return {
                                "content": content,
                                "usage": data.get("usage", {}),
                                "model": data.get("model", self.model_id),
                                "raw_response": data
                            }
                        else:
                            return {
                                "content": "",
                                "usage": {},
                                "model": self.model_id,
                                "raw_response": data
                            }

            except aiohttp.ClientError as e:
                if attempt == self.max_retries:
                    raise RuntimeError(f"API调用失败（重试{self.max_retries}次后）: {e}")
                continue
            except Exception as e:
                raise RuntimeError(f"API调用异常: {e}")
