"""判定组合器（judgement）单元测试 — 纯函数，无通道无 DB。

语义来源：CONTEXT.md（连通用例/通过率）、ADR-0002（故障=不通过）、
spec v0.5（期望叠加：隐式规则是 rule_logic 之外的硬约束）。
"""

from agenteval.evaluation.judgement import CaseOutcome, RuleOutcome, combine_case_outcome
from agenteval.models import RuleLogic


def _r(passed: bool, score: float | None = None, weight: float = 1.0) -> RuleOutcome:
    return RuleOutcome(passed=passed, score=score, weight=weight)


# ── 连通用例（无任何判定标准） ──────────────────────────────────────


def test_connectivity_case_all_replied_passes():
    outcome = combine_case_outcome(all_replied=True)
    assert outcome == CaseOutcome(passed=True, connectivity=True)


def test_connectivity_case_missing_reply_fails():
    # 无回复=故障=不通过（ADR-0002 服务视角），且不再标注为连通
    outcome = combine_case_outcome(all_replied=False)
    assert outcome == CaseOutcome(passed=False, connectivity=False)


# ── 显式规则组合（rule_logic） ─────────────────────────────────────


def test_all_logic_every_rule_passes():
    outcome = combine_case_outcome(all_replied=True, explicit=[_r(True), _r(True)])
    assert outcome == CaseOutcome(passed=True, connectivity=False)


def test_all_logic_single_failure_fails():
    outcome = combine_case_outcome(all_replied=True, explicit=[_r(True), _r(False)])
    assert outcome.passed is False


def test_any_logic_single_pass_suffices():
    outcome = combine_case_outcome(
        all_replied=True, explicit=[_r(False), _r(True)], rule_logic=RuleLogic.ANY
    )
    assert outcome.passed is True


def test_any_logic_no_pass_fails():
    outcome = combine_case_outcome(
        all_replied=True, explicit=[_r(False), _r(False)], rule_logic=RuleLogic.ANY
    )
    assert outcome.passed is False


def test_weighted_logic_above_threshold_passes():
    outcome = combine_case_outcome(
        all_replied=True,
        explicit=[_r(True, score=0.9, weight=2.0), _r(False, score=0.3, weight=1.0)],
        rule_logic=RuleLogic.WEIGHTED,
        threshold=0.6,
    )
    # (0.9*2 + 0.3*1) / 3 = 0.7 >= 0.6
    assert outcome.passed is True


def test_weighted_logic_below_threshold_fails():
    outcome = combine_case_outcome(
        all_replied=True,
        explicit=[_r(True, score=0.9, weight=1.0), _r(False, score=0.1, weight=2.0)],
        rule_logic=RuleLogic.WEIGHTED,
        threshold=0.6,
    )
    # (0.9 + 0.1*2) / 3 ≈ 0.367 < 0.6
    assert outcome.passed is False


def test_weighted_logic_scoreless_rule_uses_binary_score():
    # 无 score 的规则按通过=1.0 / 失败=0.0 计（与引擎既有口径一致）
    outcome = combine_case_outcome(
        all_replied=True,
        explicit=[_r(True, score=None, weight=1.0)],
        rule_logic=RuleLogic.WEIGHTED,
        threshold=0.6,
    )
    assert outcome.passed is True


# ── 期望叠加（隐式规则是硬约束） ───────────────────────────────────


def test_implicit_failure_vetoes_explicit_pass():
    outcome = combine_case_outcome(
        all_replied=True, explicit=[_r(True)], implicit=[_r(False)]
    )
    assert outcome.passed is False


def test_implicit_failure_vetoes_even_any_logic():
    # 隐式规则不参与 rule_logic 组合：any 满足也救不回隐式失败
    outcome = combine_case_outcome(
        all_replied=True,
        explicit=[_r(True), _r(False)],
        implicit=[_r(False)],
        rule_logic=RuleLogic.ANY,
    )
    assert outcome.passed is False


def test_implicit_only_case_passes_when_implicit_pass():
    # 仅期望无显式规则：显式组合空真
    outcome = combine_case_outcome(all_replied=True, implicit=[_r(True)])
    assert outcome == CaseOutcome(passed=True, connectivity=False)


def test_explicit_failure_not_saved_by_implicit_pass():
    outcome = combine_case_outcome(
        all_replied=True, explicit=[_r(False)], implicit=[_r(True)]
    )
    assert outcome.passed is False


# ── 有规则用例的回复缺失：判定权在规则 ─────────────────────────────


def test_ruled_case_judged_by_rules_even_with_missing_reply():
    # 有判定标准时由规则说了算（规则自身会因无回复而失败），不因缺回复直接判死
    outcome = combine_case_outcome(all_replied=False, explicit=[_r(True)])
    assert outcome == CaseOutcome(passed=True, connectivity=False)
