"""第二道防线：LLM 质量评审.

使用 LLM 对生成内容进行语义层面评估：
  - 知识点准确性
  - 题目清晰度
  - 答案正确性
  - 解析完整性
  - 难度适当性

返回 0.0-1.0 的质量评分。
"""

import json
from dataclasses import dataclass

import structlog

from ...errors import AILLMUnavailableError
from ...providers import LLMProvider, LLMResponse

logger = structlog.get_logger()

JUDGE_SYSTEM_PROMPT = """你是一个教育内容质量评审专家。
请对以下题目进行质量评估，从 5 个维度打分（每项 0-1 分）：
1. accuracy: 知识点准确性
2. clarity: 题目表述清晰度
3. correctness: 答案正确性
4. completeness: 解析完整性
5. difficulty_match: 难度匹配度

请严格按以下 JSON 格式输出（不要包含其他内容）：
{
  "accuracy": 0.9,
  "clarity": 0.8,
  "correctness": 0.9,
  "completeness": 0.7,
  "difficulty_match": 0.8,
  "overall": 0.82,
  "issues": ["如有问题简要描述"]
}"""


@dataclass
class JudgeResult:
    """LLM 评审结果."""

    score: float
    accuracy: float = 0.0
    clarity: float = 0.0
    correctness: float = 0.0
    completeness: float = 0.0
    difficulty_match: float = 0.0
    issues: list[str] | None = None
    available: bool = True  # False 表示 LLM 不可用，降级跳过

    @property
    def passed(self) -> bool:
        """是否通过评审."""
        return self.available and self.score >= 0.6


class LLMJudge:
    """LLM 质量评审器."""

    def __init__(
        self,
        provider: LLMProvider | None = None,
        model: str = "gpt-4o-mini",
    ) -> None:
        self._provider = provider
        self._model = model

    async def judge(
        self,
        question: str,
        answer: str,
        explanation: str = "",
        difficulty: str = "",
        subject: str = "",
    ) -> JudgeResult:
        """评审题目质量.

        Args:
            question: 题目内容
            answer: 答案
            explanation: 解析
            difficulty: 难度
            subject: 学科

        Returns:
            JudgeResult（LLM 不可用时返回 available=False 的降级结果）
        """
        if self._provider is None or not self._provider.is_available():
            logger.debug("llm_judge_skipped_no_provider")
            return JudgeResult(score=0.7, available=False)

        user_prompt = self._build_user_prompt(
            question, answer, explanation, difficulty, subject,
        )
        messages = [
            {"role": "system", "content": JUDGE_SYSTEM_PROMPT},
            {"role": "user", "content": user_prompt},
        ]

        try:
            response: LLMResponse = await self._provider.chat(
                messages=messages,
                model=self._model,
                temperature=0.3,
            )
        except AILLMUnavailableError as exc:
            logger.warning("llm_judge_failed_degraded", error=str(exc))
            return JudgeResult(score=0.7, available=False)

        return self._parse_judge_response(response.content)

    def _build_user_prompt(
        self,
        question: str,
        answer: str,
        explanation: str,
        difficulty: str,
        subject: str,
    ) -> str:
        """构建评审 user prompt."""
        return f"""请评审以下题目：

【学科】{subject or "未指定"}
【难度】{difficulty or "未指定"}

【题目】
{question}

【答案】
{answer}

【解析】
{explanation or "无解析"}
"""

    def _parse_judge_response(self, response: str) -> JudgeResult:
        """解析 LLM 评审响应."""
        response = response.strip()
        # 去除 markdown 代码块
        if response.startswith("```"):
            lines = response.split("\n")[1:]
            if lines and lines[-1].strip() == "```":
                lines = lines[:-1]
            response = "\n".join(lines)

        try:
            data = json.loads(response)
        except json.JSONDecodeError:
            logger.warning("llm_judge_response_not_json", response=response[:200])
            return JudgeResult(score=0.5, available=False)

        return JudgeResult(
            score=float(data.get("overall", 0.5)),
            accuracy=float(data.get("accuracy", 0.0)),
            clarity=float(data.get("clarity", 0.0)),
            correctness=float(data.get("correctness", 0.0)),
            completeness=float(data.get("completeness", 0.0)),
            difficulty_match=float(data.get("difficulty_match", 0.0)),
            issues=data.get("issues"),
        )
