"""Tests for two-comment workflow validation (#507)."""
import sys
import unittest
from pathlib import Path

sys.path.insert(0, str(Path(__file__).resolve().parent.parent))

from thread_state_ledger_validator import (  # noqa: E402
    BLOCKER_CLASSIFICATIONS,
    assess_controller_handoff_comment,
    assess_thread_state_ledger_comment,
    assess_two_comment_workflow,
    assess_two_comment_pair,
)


def _minimal_handoff(**overrides):
    lines = [
        "[CONTROLLER HANDOFF] PR #203 / Issue #182 — review complete",
        "",
        "Identity/profile:",
        "- Active profile: prgs-reviewer",
        "- Authenticated identity: sysadmin",
        "",
        "Server-side mutation ledger:",
        "- gitea_submit_pr_review → APPROVED review posted to Gitea",
        "",
        "Blockers:",
        "- none",
    ]
    text = "\n".join(lines)
    for key, value in overrides.items():
        if f"{key}:" in text:
            text = text.replace(f"{key}:", f"{key}: {value}", 1)
    return text


def _minimal_ledger(**overrides):
    lines = [
        "[THREAD STATE LEDGER] PR #203 — APPROVED review posted to Gitea",
        "",
        "What is true now:",
        "- PR state: open",
        "- Current head SHA: 0fdc8f582026b72a229d59a172c0a63ac4aaeaf9",
        "- Server-side decision state: APPROVED review posted to Gitea",
        "- Local verdict/state: APPROVE verdict prepared locally",
        "- Latest known validation: tests passed locally",
        "",
        "What changed:",
        "- APPROVED review posted to Gitea at pinned head",
        "",
        "What is blocked:",
        "- Blocker classification: no blocker",
        "",
        "Who/what acts next:",
        "- Next actor: merger",
        "- Required action: merge on explicit operator command",
        "- Do not do: re-post APPROVE",
        "- Resume from: PR #203 review feedback",
    ]
    text = "\n".join(lines)
    for key, value in overrides.items():
        text = text.replace(f"- {key}:", f"- {key}: {value}")
    return text


class TestTwoCommentWorkflow(unittest.TestCase):
    def test_valid_combined_report_passes(self):
        report = _minimal_handoff() + "\n\n" + _minimal_ledger()
        result = assess_two_comment_workflow(report)
        self.assertTrue(result["proven"])
        self.assertFalse(result["block"])

    def test_missing_ledger_after_tagged_handoff_blocks(self):
        result = assess_two_comment_workflow(_minimal_handoff())
        self.assertTrue(result["block"])
        self.assertTrue(
            any("THREAD STATE LEDGER" in r for r in result["reasons"])
        )

    def test_legacy_controller_handoff_section_not_required_ledger(self):
        legacy = "## Controller Handoff\n\n- Task: work issue\n- Next: continue\n"
        result = assess_two_comment_workflow(legacy)
        self.assertFalse(result["block"])

    def test_ambiguous_approved_blocks(self):
        handoff = _minimal_handoff().replace(
            "APPROVED review posted to Gitea",
            "approved",
        )
        report = handoff + "\n\n" + _minimal_ledger()
        result = assess_two_comment_workflow(report)
        self.assertTrue(result["block"])
        self.assertTrue(any("approved" in r.lower() for r in result["reasons"]))

    def test_ambiguous_merged_blocks(self):
        handoff = _minimal_handoff() + "\n\n- Narrative: merged successfully"
        ledger = _minimal_ledger()
        report = handoff + "\n\n" + ledger
        result = assess_two_comment_workflow(report)
        self.assertTrue(result["block"])
        self.assertTrue(any("merge" in r.lower() for r in result["reasons"]))

    def test_blocked_without_gate_blocks(self):
        handoff = _minimal_handoff().replace("- none", "- blocked")
        ledger = _minimal_ledger().replace(
            "no blocker", "blocked but no gate named"
        )
        report = handoff + "\n\n" + ledger
        result = assess_two_comment_workflow(report)
        self.assertTrue(result["block"])

    def test_mutation_ledger_contradiction_blocks(self):
        handoff = _minimal_handoff().replace(
            "APPROVED review posted to Gitea",
            "none — no server-side state changed",
        )
        handoff += "\n- Narrative: APPROVED review posted to Gitea"
        report = handoff + "\n\n" + _minimal_ledger()
        result = assess_two_comment_workflow(report)
        self.assertTrue(result["block"])
        self.assertTrue(any("contradict" in r.lower() for r in result["reasons"]))

    def test_local_verdict_as_server_side_blocks(self):
        ledger = _minimal_ledger(
            **{
                "Server-side decision state": "APPROVE verdict prepared locally",
                "Local verdict/state": "none",
            }
        )
        report = _minimal_handoff() + "\n\n" + ledger
        result = assess_two_comment_workflow(report)
        self.assertTrue(result["block"])


class TestHandoffComment(unittest.TestCase):
    def test_handoff_comment_valid(self):
        result = assess_controller_handoff_comment(_minimal_handoff())
        self.assertTrue(result["proven"])

    def test_handoff_without_marker_skips(self):
        result = assess_controller_handoff_comment("casual comment")
        self.assertTrue(result["proven"])
        self.assertFalse(result["performed"])


class TestLedgerComment(unittest.TestCase):
    def test_ledger_requires_blocker_classification(self):
        ledger = _minimal_ledger().replace(
            "Blocker classification: no blocker",
            "something unclear",
        )
        result = assess_thread_state_ledger_comment(ledger)
        self.assertTrue(result["block"])

    def test_all_blocker_classifications_recognized(self):
        self.assertIn("no blocker", BLOCKER_CLASSIFICATIONS)
        self.assertIn("environment/tooling blocker", BLOCKER_CLASSIFICATIONS)


class TestPairedComments(unittest.TestCase):
    def test_pair_passes(self):
        result = assess_two_comment_pair(_minimal_handoff(), _minimal_ledger())
        self.assertTrue(result["proven"])

    def test_pair_missing_ledger_blocks(self):
        result = assess_two_comment_pair(_minimal_handoff(), "")
        self.assertTrue(result["block"])


class TestExamples(unittest.TestCase):
    """Smoke-test bundled examples from docs."""

    def test_examples_module_loads(self):
        from thread_state_ledger_examples import EXAMPLES  # noqa: E402

        self.assertGreaterEqual(len(EXAMPLES), 8)
        for name, handoff, ledger in EXAMPLES:
            result = assess_two_comment_pair(handoff, ledger)
            self.assertTrue(
                result["proven"],
                f"example '{name}' failed: {result['reasons']}",
            )


if __name__ == "__main__":
    unittest.main()