from __future__ import annotations

import logging
import os
from typing import Optional
from collections import deque

from config import settings

logger = logging.getLogger(__name__)


class LLMService:
    def __init__(self) -> None:
        self._ready = False
        self._error: Optional[str] = None
        self._client = None
        self._model = (settings.llm_model or "").strip()
        self._base_url = (settings.llm_base_url or "").strip()
        self._history: deque[dict] = deque(maxlen=12)  # 6 turns (user+assistant)
        self._system_prompt = "请用中文口语化简短回复，1-2句。"

        if not settings.llm_api_key:
            self._error = "missing LLM api key: set LLM_API_KEY or DEEPSEEK_API_KEY"
            return

        # If DeepSeek key is provided but no explicit base URL override,
        # route to DeepSeek-compatible OpenAI endpoint by default.
        if (
            os.getenv("DEEPSEEK_API_KEY")
            and not os.getenv("LLM_BASE_URL")
            and not os.getenv("DEEPSEEK_BASE_URL")
            and (self._base_url.lower() == "https://api.openai.com/v1" or not self._base_url)
        ):
            self._base_url = "https://api.deepseek.com/v1"

        if not self._model:
            base = self._base_url.lower()
            self._model = "deepseek-chat" if "deepseek" in base else "gpt-4o-mini"
        try:
            from openai import AsyncOpenAI

            self._client = AsyncOpenAI(
                api_key=settings.llm_api_key,
                base_url=self._base_url,
                timeout=settings.llm_timeout,
            )
            self._ready = True
            self._error = None
        except Exception as exc:  # pragma: no cover
            self._error = str(exc)
            logger.warning("LLM online mode unavailable: %s", exc)

    async def reply_with_meta(self, text: str) -> tuple[str, str]:
        if not self._ready or self._client is None:
            return f"收到：{text}。这是本地兜底回复。", "fallback"

        try:
            resp = await self._client.chat.completions.create(
                model=self._model,
                messages=[{"role": "system", "content": self._system_prompt}, *list(self._history), {"role": "user", "content": text}],
                max_tokens=settings.llm_max_tokens,
                temperature=0.7,
            )
            content = (resp.choices[0].message.content or "").strip()
            if content:
                self._history.append({"role": "user", "content": text})
                self._history.append({"role": "assistant", "content": content})
                return content, "online"
        except Exception as exc:  # pragma: no cover
            self._error = str(exc)
            logger.warning("LLM request failed, fallback used: %s", exc)

        return f"收到：{text}。这是本地兜底回复。", "fallback"

    async def reply(self, text: str) -> str:
        content, _ = await self.reply_with_meta(text)
        return content

    @property
    def health(self) -> dict:
        return {
            "ready": self._ready,
            "model": self._model,
            "base_url": self._base_url,
            "history_items": len(self._history),
            "error": self._error,
        }

    def clear_history(self) -> None:
        self._history.clear()
