from abc import ABC, abstractmethod
from typing import AsyncIterator
from dataclasses import dataclass, field


@dataclass
class LLMResponse:
    """LLM响应数据类"""

    content: str
    model: str
    usage: dict = field(
        default_factory=lambda: {
            "prompt_tokens": 0,
            "completion_tokens": 0,
            "total_tokens": 0,
        }
    )


class LLMError(Exception):
    """LLM调用异常"""

    def __init__(self, message: str, provider: str, status_code: int | None = None):
        self.provider = provider
        self.status_code = status_code
        super().__init__(f"[{provider}] {message}")


class LLMProvider(ABC):
    """LLM服务提供商抽象基类"""

    @property
    @abstractmethod
    def provider_name(self) -> str:
        """提供商名称"""
        ...

    @property
    @abstractmethod
    def model_name(self) -> str:
        """模型名称"""
        ...

    @property
    @abstractmethod
    def max_context_length(self) -> int:
        """最大上下文长度"""
        ...

    @abstractmethod
    async def chat(
        self,
        messages: list[dict],
        temperature: float = 0.7,
        max_tokens: int = 4096,
        stop: list[str] | None = None,
    ) -> LLMResponse:
        """
        同步聊天接口（非流式）

        Args:
            messages: 消息列表，格式 [{"role": "user"|"assistant"|"system", "content": "..."}]
            temperature: 采样温度
            max_tokens: 最大生成token数
            stop: 停止词列表

        Returns:
            LLMResponse
        """
        ...

    @abstractmethod
    async def chat_stream(
        self,
        messages: list[dict],
        temperature: float = 0.7,
        max_tokens: int = 4096,
    ) -> AsyncIterator[str]:
        """
        流式聊天接口

        Args:
            messages: 消息列表
            temperature: 采样温度
            max_tokens: 最大生成token数

        Yields:
            逐个token的文本片段
        """
        ...
