"""Precise mutation category verifier for reviewer controller handoffs (#319)."""

from __future__ import annotations

import re
from typing import Any

_CONTROLLER_HANDOFF_RE = re.compile(r"controller handoff", re.IGNORECASE)
_WORKSPACE_MUTATIONS_RE = re.compile(
    r"^\s*[-*]?\s*workspace\s+mutations\s*:",
    re.IGNORECASE | re.MULTILINE,
)
_VAGUE_MUTATIONS_NONE_RE = re.compile(
    r"^\s*[-*]?\s*mutations\s*:\s*none\s*$",
    re.IGNORECASE | re.MULTILINE,
)

_REQUIRED_CATEGORIES = (
    "file edits by reviewer",
    "worktree/index mutations",
    "git ref mutations",
)
_WORKTREE_FIELD_ALIASES = (
    "worktree/index mutations",
    "worktree mutations",
)


def _has_category(text: str, category: str) -> bool:
    pattern = re.compile(
        rf"^\s*[-*]?\s*{re.escape(category)}\s*:",
        re.IGNORECASE | re.MULTILINE,
    )
    return bool(pattern.search(text))


def _has_worktree_category(text: str) -> bool:
    return any(_has_category(text, alias) for alias in _WORKTREE_FIELD_ALIASES)


def _normalize_for_consistency_check(text: str) -> str:
    """Map #319 precise labels to #313 field names for consistency delegation."""
    normalized = text
    if _has_category(text, "worktree/index mutations") and not _has_category(
        text, "worktree mutations"
    ):
        normalized = re.sub(
            r"(worktree/index mutations\s*:)",
            "Worktree mutations:",
            normalized,
            flags=re.IGNORECASE,
        )
    return normalized


def assess_mutation_categories_report(
    report_text: str,
    *,
    handoff_session: dict | None = None,
    observed_commands: list | None = None,
) -> dict[str, Any]:
    """Require precise mutation categories in reviewer controller handoffs (#319)."""
    text = report_text or ""
    session = dict(handoff_session or {})
    reasons: list[str] = []
    lower = text.lower()

    is_controller = bool(
        session.get("controller_handoff")
        or _CONTROLLER_HANDOFF_RE.search(text)
    )
    if not is_controller and not session.get("require_categories"):
        return {
            "proven": True,
            "block": False,
            "reasons": [],
            "controller_handoff": False,
            "safe_next_action": "proceed",
        }

    if _WORKSPACE_MUTATIONS_RE.search(text):
        reasons.append(
            "controller handoffs must not use legacy 'Workspace mutations'; "
            "use precise mutation category fields"
        )

    if _VAGUE_MUTATIONS_NONE_RE.search(text):
        reasons.append(
            "controller handoffs must not use vague 'Mutations: none'; "
            "report each precise category separately"
        )

    missing = [
        category
        for category in _REQUIRED_CATEGORIES
        if category != "worktree/index mutations" and not _has_category(text, category)
    ]
    if not _has_worktree_category(text):
        missing.append("worktree/index mutations")

    if missing:
        reasons.append(
            "controller handoff missing precise mutation categories: "
            + ", ".join(missing)
        )

    commands = observed_commands or session.get("observed_commands")
    if commands:
        from review_proofs import assess_workspace_mutation_consistency

        consistency = assess_workspace_mutation_consistency(
            _normalize_for_consistency_check(text),
            commands,
        )
        if not consistency.get("complete"):
            reasons.extend(consistency.get("reasons") or [])

    proven = not reasons
    return {
        "proven": proven,
        "block": not proven,
        "reasons": reasons,
        "controller_handoff": True,
        "safe_next_action": (
            "replace Workspace mutations with file edits, worktree/index, git ref, "
            "and other precise mutation category fields"
            if reasons
            else "proceed"
        ),
    }