"""Infra-stop repair handoff verifier for blocked reviewer workflows (#289)."""

from __future__ import annotations

import re
from typing import Any

from capability_stop_terminal import (
    TERMINAL_REPORT_HEADING,
    assess_capability_stop_report,
)

_REPAIR_HANDOFF_RE = re.compile(
    r"repair handoff|control-checkout repair mode",
    re.IGNORECASE,
)
_CONTROL_REPAIR_RE = re.compile(r"control-checkout repair mode", re.IGNORECASE)
_PR_QUEUE_ADVANCE_RE = re.compile(
    r"(?:selected pr|pr #\d+ (?:to review|selected)|eligible pr|"
    r"next (?:eligible )?pr(?: to review)?|oldest eligible pr|pinned (?:review )?head)",
    re.IGNORECASE,
)
_REVIEW_MUTATION_RE = re.compile(
    r"(?:gitea_review_pr|gitea_merge_pr|request_changes|submitted\s+approve|"
    r"merge result|review decision\s*:\s*approve)",
    re.IGNORECASE,
)
_BACKGROUND_TOOL_RE = re.compile(r"\b(?:schedule|manage_task)\b", re.IGNORECASE)
_PR_REVIEW_REPORT_RE = re.compile(
    r"(?:review summary|merge recommendation|validation result\s*:\s*pass|"
    r"queue status report with selected pr)",
    re.IGNORECASE,
)

_DIAGNOSTIC_FIELDS = {
    "mcp process root": re.compile(r"mcp process root\s*:", re.IGNORECASE),
    "inspected git root": re.compile(r"inspected git root\s*:", re.IGNORECASE),
    "conflict marker path": re.compile(
        r"(?:conflict marker path|exact conflict marker path)\s*:",
        re.IGNORECASE,
    ),
    "merge/rebase control path": re.compile(
        r"(?:merge/rebase control path|exact merge/rebase control path)\s*:",
        re.IGNORECASE,
    ),
    "safe next repair action": re.compile(
        r"safe next (?:repair )?action\s*:",
        re.IGNORECASE,
    ),
}


def assess_infra_stop_handoff_report(
    report_text: str,
    *,
    stop_session: dict | None = None,
) -> dict[str, Any]:
    """Validate repair handoff purity when infra_stop blocks reviewer capability (#289)."""
    text = report_text or ""
    session = dict(stop_session or {})
    reasons: list[str] = []

    infra_stop = bool(
        session.get("infra_stop")
        or session.get("infra_stop_blocked")
        or session.get("route_result") == "infra_stop"
    )
    if not infra_stop:
        return {
            "proven": True,
            "block": False,
            "reasons": [],
            "infra_stop": False,
            "safe_next_action": "proceed",
        }

    lower = text.lower()
    repair_handoff = bool(
        _REPAIR_HANDOFF_RE.search(text)
        or TERMINAL_REPORT_HEADING.lower() in lower
    )
    if not repair_handoff:
        reasons.append(
            "infra_stop requires a repair handoff, not a PR review report"
        )

    if _PR_REVIEW_REPORT_RE.search(text) and not _REPAIR_HANDOFF_RE.search(text):
        reasons.append(
            "final output must be a repair handoff instead of stale PR review state"
        )

    if _PR_QUEUE_ADVANCE_RE.search(text):
        reasons.append(
            "infra_stop blocks PR queue advancement; do not select or advance next PR"
        )

    if _REVIEW_MUTATION_RE.search(text):
        reasons.append(
            "review, approval, request-changes, merge, or comment mutations "
            "forbidden while infra_stop is active"
        )

    if session.get("pinned_head_sha") or re.search(
        r"pinned (?:review )?head sha\s*:", text, re.IGNORECASE
    ):
        if session.get("capability_cleared") is not True:
            reasons.append(
                "cannot pin PR head SHA while review capability never cleared"
            )

    if session.get("main_checkout_diagnostics") and not _CONTROL_REPAIR_RE.search(text):
        reasons.append(
            "main-checkout diagnostics must be labeled CONTROL-CHECKOUT REPAIR MODE"
        )

    if _BACKGROUND_TOOL_RE.search(text):
        reasons.append(
            "background schedule/manage_task tools must not be used during "
            "blocked infra_stop recovery"
        )

    assessment = session.get("infra_stop_assessment") or {}
    if assessment.get("infra_stop") or infra_stop:
        missing = [
            label
            for label, pattern in _DIAGNOSTIC_FIELDS.items()
            if not pattern.search(text)
        ]
        if missing and session.get("require_infra_diagnostics", True):
            reasons.append(
                "infra_stop repair handoff missing diagnostic fields: "
                + ", ".join(missing)
            )
        conflict_file = assessment.get("conflict_file")
        if conflict_file and conflict_file.lower() not in lower:
            reasons.append(
                f"infra_stop assessment conflict file {conflict_file!r} "
                "not reflected in repair handoff"
            )

    capability = assess_capability_stop_report(
        text,
        trust_gate_status=session.get("trust_gate_status"),
        capability_denied=True,
    )
    if not capability.get("pure"):
        reasons.extend(capability.get("reasons") or [])

    proven = not reasons
    return {
        "proven": proven,
        "block": not proven,
        "reasons": list(dict.fromkeys(reasons)),
        "infra_stop": True,
        "repair_handoff": repair_handoff,
        "safe_next_action": (
            "stop PR queue work; emit CONTROL-CHECKOUT REPAIR MODE handoff "
            "with infra diagnostics and safe next repair action"
            if reasons
            else "proceed"
        ),
    }