"""Shared evidence sufficiency check for the CODE_QA test pipeline."""

from __future__ import annotations

from dataclasses import dataclass, field

from app.modules.rag.code_qa_pipeline.contracts import EvidenceBundle


@dataclass(slots=True)
class EvidenceGateDecision:
    """Result of evidence sufficiency check."""

    passed: bool
    failure_reasons: list[str] = field(default_factory=list)
    degraded_message: str = ""


def evaluate_evidence(bundle: EvidenceBundle) -> EvidenceGateDecision:
    """Check evidence sufficiency by scenario; prevent confident answer without support."""
    sub = (bundle.resolved_sub_intent or "EXPLAIN").upper()
    reasons: list[str] = []

    if sub == "OPEN_FILE":
        if not bundle.resolved_target and not bundle.file_candidates:
            reasons.append("path_scope_empty")
        if bundle.evidence_count < 1:
            reasons.append("layer_c0_empty")
    elif sub == "EXPLAIN":
        if bundle.target_type == "symbol" and not bundle.resolved_target:
            reasons.append("target_not_resolved")
        if bundle.evidence_count < 2:
            reasons.append("insufficient_evidence")
        if bundle.target_type == "symbol" and not bundle.relations and bundle.evidence_count < 2:
            reasons.append("layer_c2_empty")
    elif sub == "FIND_TESTS":
        if not bundle.resolved_target and not bundle.target_symbol_candidates:
            reasons.append("target_not_resolved")
        if not bundle.test_evidence:
            reasons.append("tests_not_found")
    elif sub == "FIND_ENTRYPOINTS":
        if not bundle.entrypoints:
            reasons.append("entrypoints_not_found")
    else:
        if bundle.evidence_count < 1:
            reasons.append("insufficient_evidence")

    passed = len(reasons) == 0
    if not passed:
        bundle.failure_reasons = list(reasons)
        bundle.sufficient = False
    else:
        bundle.sufficient = True

    degraded = _degraded_message(bundle, reasons)
    return EvidenceGateDecision(passed=passed, failure_reasons=reasons, degraded_message=degraded)


def _degraded_message(bundle: EvidenceBundle, reasons: list[str]) -> str:
    if not reasons:
        return ""
    lines = ["Insufficient evidence for a confident answer."]
    if "target_not_resolved" in reasons:
        lines.append("Target symbol or file could not be resolved.")
    if "path_scope_empty" in reasons:
        lines.append("No matching path or file found.")
    if "layer_c0_empty" in reasons:
        lines.append("No code chunks retrieved.")
    if "tests_not_found" in reasons:
        lines.append("No test candidates found.")
    if "entrypoints_not_found" in reasons:
        lines.append("No entrypoints found.")
    if "insufficient_evidence" in reasons:
        lines.append(f"Evidence count: {bundle.evidence_count} (minimum required not met).")
    return " ".join(lines).strip()
