"""第三道防线：质量门控（QualityGate）.

综合 RuleValidator + LLMJudge 结果，决定内容是否通过：
  - 规则校验失败 → 直接拒绝
  - 规则通过 + LLM 评审通过 → 放行
  - 规则通过 + LLM 评审不通过 → 标记降级但仍返回（方案 B）
  - LLM 不可用 → 仅依据规则校验结果
"""

from dataclasses import dataclass, field

import structlog

from ...config import Settings
from .llm_judge import JudgeResult, LLMJudge
from .rule_validator import RuleValidator, ValidationResult

logger = structlog.get_logger()


@dataclass
class EvaluationResult:
    """综合评估结果."""

    passed: bool
    score: float
    rule_result: ValidationResult | None = None
    judge_result: JudgeResult | None = None
    errors: list[str] = field(default_factory=list)
    warnings: list[str] = field(default_factory=list)
    degraded: bool = False
    degraded_reason: str = ""


class QualityGate:
    """质量门控.

    权重配置：
      - rule_score 权重 0.4
      - llm_score 权重 0.6
      - LLM 不可用时 rule_score 权重 1.0
    """

    def __init__(
        self,
        rule_validator: RuleValidator | None = None,
        llm_judge: LLMJudge | None = None,
        pass_threshold: float = 0.7,
        excellent_threshold: float = 0.85,
    ) -> None:
        self._rule_validator = rule_validator or RuleValidator()
        self._llm_judge = llm_judge
        self._pass_threshold = pass_threshold
        self._excellent_threshold = excellent_threshold

    @classmethod
    def from_settings(cls, settings: Settings, llm_judge: LLMJudge | None = None) -> "QualityGate":
        """从 Settings 创建 QualityGate."""
        return cls(
            pass_threshold=settings.evaluation_pass_threshold,
            excellent_threshold=settings.evaluation_excellent_threshold,
            llm_judge=llm_judge,
        )

    async def evaluate(
        self,
        llm_output: str,
        expected_difficulty: str = "",
        expected_question_type: str = "",
        question: str = "",
        answer: str = "",
        explanation: str = "",
        subject: str = "",
    ) -> EvaluationResult:
        """执行三道防线评估.

        Args:
            llm_output: LLM 原始输出
            expected_difficulty: 期望难度
            expected_question_type: 期望题型
            question/answer/explanation/subject: 用于 LLM 评审的解析后内容

        Returns:
            EvaluationResult
        """
        result = EvaluationResult(passed=False, score=0.0)

        # 第一道：规则校验
        rule_result = self._rule_validator.validate(
            llm_output, expected_difficulty, expected_question_type,
        )
        result.rule_result = rule_result

        if not rule_result.passed:
            result.errors.extend(rule_result.errors)
            result.score = 0.0
            result.passed = False
            result.degraded = True
            result.degraded_reason = "rule validation failed"
            logger.warning(
                "quality_gate_rule_failed",
                errors=rule_result.errors,
            )
            return result

        result.warnings.extend(rule_result.warnings)

        # 第二道：LLM 评审
        if self._llm_judge is not None:
            # 使用规则校验解析的内容（如果未显式传入）
            parsed = rule_result.parsed or {}
            judge_result = await self._llm_judge.judge(
                question=question or str(parsed.get("question", "")),
                answer=answer or str(parsed.get("answer", "")),
                explanation=explanation or str(parsed.get("explanation", "")),
                difficulty=expected_difficulty,
                subject=subject,
            )
            result.judge_result = judge_result

            if not judge_result.available:
                # LLM 不可用，仅依据规则校验
                result.score = rule_result.score
                result.passed = rule_result.score >= self._pass_threshold
                if result.passed and rule_result.warnings:
                    result.degraded = True
                    result.degraded_reason = "rule warnings present, llm judge unavailable"
                logger.info(
                    "quality_gate_llm_unavailable",
                    rule_score=rule_result.score,
                    passed=result.passed,
                )
                return result

            # 综合评分
            result.score = self._combine_scores(rule_result.score, judge_result.score)
            result.passed = result.score >= self._pass_threshold

            if judge_result.issues:
                result.warnings.extend(judge_result.issues)

            if not result.passed:
                result.degraded = True
                result.degraded_reason = f"quality score {result.score:.2f} below threshold"
                logger.warning(
                    "quality_gate_score_below_threshold",
                    score=result.score,
                    threshold=self._pass_threshold,
                )
        else:
            # 无 LLM Judge，仅依据规则校验
            result.score = rule_result.score
            result.passed = rule_result.score >= self._pass_threshold
            if result.passed and rule_result.warnings:
                result.degraded = True
                result.degraded_reason = "rule warnings present, no llm judge"

        # 优秀标记
        if result.passed and result.score >= self._excellent_threshold:
            logger.info("quality_gate_excellent", score=result.score)

        return result

    def _combine_scores(self, rule_score: float, llm_score: float) -> float:
        """综合评分.

        权重：rule 0.4 + llm 0.6
        """
        return rule_score * 0.4 + llm_score * 0.6
