"""Case judgement — the single authority for "did this case pass".

判定语义（CONTEXT.md / spec v0.5 / ADR-0002）：
    - 连通用例（无显式规则、无期望）：每轮收到回复即通过；缺回复=故障=不通过。
    - 显式规则按 rule_logic（ALL / ANY / WEIGHTED）组合；无显式规则时空真。
    - 期望派生的隐式规则是 rule_logic 之外的硬约束，任一失败则用例失败。

引擎执行时调用一次，结果写入 run.summary["case_outcomes"]，
报告 / 对比 / 渲染层只消费该权威值，不得各自重算。
"""

from dataclasses import dataclass
from typing import Optional, Sequence

from agenteval.models import RuleLogic


@dataclass(frozen=True)
class RuleOutcome:
    """单条规则的判定结果（引擎执行规则后规范化为此形状）。"""

    passed: bool
    score: Optional[float] = None
    weight: float = 1.0


@dataclass(frozen=True)
class CaseOutcome:
    """单个用例的权威判定结果。"""

    passed: bool
    connectivity: bool


def combine_case_outcome(
    *,
    all_replied: bool,
    explicit: Sequence[RuleOutcome] = (),
    implicit: Sequence[RuleOutcome] = (),
    rule_logic: RuleLogic = RuleLogic.ALL,
    threshold: float = 0.6,
) -> CaseOutcome:
    if not explicit and not implicit:
        # 连通用例：connectivity 标记仅在连通成功时为真
        ok = all_replied
        return CaseOutcome(passed=ok, connectivity=ok)

    if not explicit:
        explicit_ok = True
    elif rule_logic == RuleLogic.ANY:
        explicit_ok = any(r.passed for r in explicit)
    elif rule_logic == RuleLogic.WEIGHTED:
        total_weight = sum(r.weight for r in explicit)
        weighted_score = sum(
            (r.score if r.score is not None else (1.0 if r.passed else 0.0)) * r.weight
            for r in explicit
        )
        avg = weighted_score / total_weight if total_weight > 0 else 0.0
        explicit_ok = avg >= threshold
    else:  # ALL and fallback
        explicit_ok = all(r.passed for r in explicit)

    implicit_ok = all(r.passed for r in implicit)
    return CaseOutcome(passed=explicit_ok and implicit_ok, connectivity=False)
