"""
Kimi (月之暗面) 平台适配器 - 使用 Moonshot AI API 获取真实AI回答

API文档: https://platform.moonshot.cn/docs
使用 Moonshot v1 chat completion API
"""

import asyncio
import logging
import time
from typing import Optional

import httpx

from app.config import settings
from app.workers.platforms.base import BasePlatformAdapter
from app.workers.platforms.search_engine import fetch_search_content

logger = logging.getLogger(__name__)

# 模块级频率限制器
_last_request_time: float = 0.0
_min_interval: float = 6.0  # 每分钟10次 -> 6秒间隔


async def _rate_limit_wait():
    """确保请求间隔不低于最小间隔"""
    global _last_request_time
    now = time.monotonic()
    elapsed = now - _last_request_time
    if elapsed < _min_interval:
        wait_time = _min_interval - elapsed
        logger.debug(f"Kimi 频率限制等待 {wait_time:.1f}s")
        await asyncio.sleep(wait_time)
    _last_request_time = time.monotonic()


class KimiAdapter(BasePlatformAdapter):
    """Kimi 平台适配器 - 使用 Moonshot AI API 获取真实AI回答"""

    platform_name = "kimi"
    platform_url = "https://kimi.moonshot.cn"
    _api_base = "https://api.moonshot.cn/v1"
    _model = "moonshot-v1-8k"

    def __init__(self):
        self._api_key: Optional[str] = None
        self._client: Optional[httpx.AsyncClient] = None

    @property
    def api_key(self) -> Optional[str]:
        if self._api_key is None:
            self._api_key = settings.MOONSHOT_API_KEY
        return self._api_key

    @property
    def is_configured(self) -> bool:
        return bool(self.api_key and self.api_key.strip())

    def _get_client(self) -> httpx.AsyncClient:
        if self._client is None or self._client.is_closed:
            self._client = httpx.AsyncClient(
                timeout=httpx.Timeout(60.0, connect=10.0),
                headers={
                    "Content-Type": "application/json",
                    "Authorization": f"Bearer {self.api_key}",
                },
            )
        return self._client

    async def query(self, keyword: str) -> str:
        """在 Kimi 查询关键词，返回原始响应文本"""
        last_error = None
        for attempt in range(3):
            try:
                return await self._do_query(keyword)
            except Exception as e:
                last_error = e
                logger.warning(f"Kimi 查询第 {attempt + 1} 次尝试失败: {e}")
                if attempt < 2:
                    await asyncio.sleep(2 ** attempt)

        # 所有尝试失败后回退到搜索引擎
        logger.warning(f"Kimi API 调用全部失败，回退到搜索引擎: {last_error}")
        return await self._fallback_search(keyword)

    async def _do_query(self, keyword: str) -> str:
        """通过 Moonshot API 获取真实AI回答"""
        if not self.is_configured:
            logger.warning("Kimi API Key 未配置，回退到搜索引擎")
            return await self._fallback_search(keyword)

        await _rate_limit_wait()

        client = self._get_client()
        payload = {
            "model": self._model,
            "messages": [
                {
                    "role": "system",
                    "content": (
                        "你是一个专业的AI搜索助手。请基于你的知识，"
                        "详细回答用户的问题。如果引用了外部来源，"
                        "请在回答中标注来源URL或出处名称。"
                    ),
                },
                {
                    "role": "user",
                    "content": keyword,
                },
            ],
            "temperature": 0.7,
            "max_tokens": 2000,
        }

        response = await client.post(
            f"{self._api_base}/chat/completions",
            json=payload,
        )

        if response.status_code == 429:
            retry_after = int(response.headers.get("Retry-After", "10"))
            logger.warning(f"Kimi API 限流，等待 {retry_after}s 后重试")
            await asyncio.sleep(retry_after)
            raise RuntimeError(f"Kimi API 限流，等待 {retry_after}s")

        if response.status_code != 200:
            error_body = response.text[:500]
            raise RuntimeError(
                f"Kimi API 返回错误 {response.status_code}: {error_body}"
            )

        data = response.json()
        choices = data.get("choices", [])
        if not choices:
            raise RuntimeError("Kimi API 返回空 choices")

        content = choices[0].get("message", {}).get("content", "")
        if not content:
            raise RuntimeError("Kimi API 返回空内容")

        # 标记数据来源为AI平台
        result = f"[data_source: ai_platform]\n{content}"
        logger.info(f"Kimi API 调用成功，返回 {len(content)} 字符")
        return result

    async def _fallback_search(self, keyword: str) -> str:
        """回退到搜索引擎模式，标记数据来源"""
        content = await fetch_search_content(self.platform_name, keyword)
        return f"[data_source: search_engine]\n{content}"

    async def close(self):
        """清理资源"""
        if self._client and not self._client.is_closed:
            await self._client.aclose()
            self._client = None
