import requests
from typing import List, Dict, Generator
import json
import logging

from models.base import LLMProvider

logger = logging.getLogger(__name__)


class OpenAICompatibleProvider(LLMProvider):
    """OpenAI 兼容接口适配器

    支持任何兼容 OpenAI API 格式的服务：
    - 通义千问 (DashScope)
    - DeepSeek
    - Moonshot
    - 本地 Ollama
    - 其他 OpenAI 兼容服务
    """

    def __init__(
        self,
        api_key: str,
        base_url: str = "https://api.openai.com/v1",
        model: str = "gpt-3.5-turbo"
    ):
        self.api_key = api_key
        self.base_url = base_url.rstrip('/')
        self.model = model
        self.endpoint = f"{self.base_url}/chat/completions"
        self._validate_connection()

    def _validate_connection(self):
        """验证连接配置"""
        logger.info(f"Initialized LLM Provider: {self.base_url} with model {self.model}")

    def validate_config(self) -> bool:
        """验证配置是否有效"""
        try:
            response = requests.get(
                self.base_url,
                headers={"Authorization": f"Bearer {self.api_key}"},
                timeout=5
            )
            # 大多数 API 会返回 404 但说明服务在线
            return response.status_code in [200, 404, 405]
        except Exception:
            return False

    def _build_headers(self) -> Dict:
        """构建请求头"""
        return {
            "Authorization": f"Bearer {self.api_key}",
            "Content-Type": "application/json",
        }

    def _build_payload(self, messages: List[Dict], **kwargs) -> Dict:
        """构建请求负载"""
        return {
            "model": kwargs.get("model", self.model),
            "messages": messages,
            "temperature": kwargs.get("temperature", 0.7),
            "max_tokens": kwargs.get("max_tokens", 2000),
            "top_p": kwargs.get("top_p", 0.9),
        }

    def generate(self, messages: List[Dict], **kwargs) -> str:
        """同步生成内容

        Args:
            messages: 消息列表，格式 [{"role": "user", "content": "..."}]
            **kwargs: 额外参数 (temperature, max_tokens, top_p 等)

        Returns:
            生成的文本内容
        """
        try:
            response = requests.post(
                self.endpoint,
                headers=self._build_headers(),
                json=self._build_payload(messages, **kwargs),
                timeout=kwargs.get("timeout", 60)
            )
            response.raise_for_status()
            return response.json()['choices'][0]['message']['content']
        except requests.exceptions.HTTPError as e:
            logger.error(f"HTTP Error: {e.response.text}")
            raise
        except Exception as e:
            logger.error(f"Generation failed: {e}")
            raise

    def stream_generate(self, messages: List[Dict], **kwargs) -> Generator[str, None, None]:
        """流式生成内容

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

        Yields:
            生成的文本片段
        """
        payload = self._build_payload(messages, **kwargs)
        payload["stream"] = True

        try:
            response = requests.post(
                self.endpoint,
                headers=self._build_headers(),
                json=payload,
                stream=True,
                timeout=kwargs.get("timeout", 120)
            )
            response.raise_for_status()

            for line in response.iter_lines():
                if line:
                    line = line.decode('utf-8')
                    if line.startswith('data: '):
                        data = line[6:]
                        if data == '[DONE]':
                            break
                        try:
                            chunk = json.loads(data)
                            delta = chunk['choices'][0].get('delta', {})
                            content = delta.get('content', '')
                            if content:
                                yield content
                        except json.JSONDecodeError:
                            continue
        except Exception as e:
            logger.error(f"Stream generation failed: {e}")
            raise


# 工厂函数：根据配置创建不同的 Provider
def create_provider(
    provider_type: str = "openai_compatible",
    **kwargs
) -> LLMProvider:
    """创建 LLM Provider 工厂函数

    Args:
        provider_type: Provider 类型
        **kwargs: Provider 配置参数

    Returns:
        LLMProvider 实例
    """
    providers = {
        "openai_compatible": OpenAICompatibleProvider,
    }

    provider_class = providers.get(provider_type)
    if not provider_class:
        raise ValueError(f"Unknown provider type: {provider_type}")

    return provider_class(**kwargs)
