"""Tests for MCP-native post-merge cleanup proof (#517)."""
import sys
import unittest
from pathlib import Path

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

from final_report_validator import assess_final_report_validator  # noqa: E402
from mcp_native_cleanup_proof import (  # noqa: E402
    assess_authorized_reconciler_cleanup_path,
    assess_mcp_native_cleanup_proof,
    assess_merger_cleanup_handoff_guidance,
    assess_raw_branch_delete_report,
    assess_raw_comment_delete_report,
)


def _authorized_cleanup_report(**overrides):
    fields = {
        "Merge mutations": "gitea_merge_pr on PR #100",
        "Cleanup mutations": (
            "gitea_reconcile_merged_cleanups deleted remote branch; "
            "gitea_cleanup_post_merge_moot_lease released lease"
        ),
        "Reconciler capability": "prgs-reconciler / gitea.branch.delete resolved",
        "Next actor": "reconciler session complete",
    }
    fields.update(overrides)
    lines = ["## Controller Handoff", ""]
    lines.extend(f"- {key}: {value}" for key, value in fields.items())
    return "\n".join(lines)


class TestRawBranchDeleteBlocked(unittest.TestCase):
    def test_git_branch_d_blocked(self):
        report = "Cleanup mutations: git branch -d feat/issue-1-x"
        result = assess_raw_branch_delete_report(report)
        self.assertTrue(result["block"])
        self.assertIn("git branch -d", result["commands"][0])

    def test_git_push_delete_in_ledger_blocked(self):
        report = "- Git ref mutations: git push origin --delete feat/x"
        result = assess_raw_branch_delete_report(report)
        self.assertTrue(result["block"])

    def test_narrative_git_push_delete_not_blocked(self):
        report = "\n".join([
            "## Validation",
            "Workflow §28B forbids raw git push --delete for cleanup.",
            "- Cleanup mutations: none",
            "- Git ref mutations: none",
            "- Worktree mutations: none",
        ])
        result = assess_raw_branch_delete_report(report)
        self.assertFalse(result["block"])

    def test_authorized_mcp_path_passes(self):
        report = _authorized_cleanup_report()
        result = assess_raw_branch_delete_report(report)
        self.assertFalse(result["block"])


class TestRawCommentDeleteBlocked(unittest.TestCase):
    def test_curl_delete_comment_in_ledger_blocked(self):
        report = (
            "- Cleanup mutations: curl -X DELETE https://gitea.example/api/v1/repos/o/r/"
            "issues/9/comments/42"
        )
        result = assess_raw_comment_delete_report(report)
        self.assertTrue(result["block"])

    def test_narrative_comment_delete_not_blocked(self):
        report = "\n".join([
            "Files reviewed: post_merge_cleanup_proof.py (raw comment delete patterns)",
            "Validation note: never use delete_issue_comment for lease cleanup.",
            "- Cleanup mutations: none",
            "- Git ref mutations: none",
            "- Worktree mutations: none",
        ])
        result = assess_raw_comment_delete_report(report)
        self.assertFalse(result["block"])

    def test_delete_issue_comment_helper_in_ledger_blocked(self):
        report = "- Cleanup mutations: delete_issue_comment purged lease comments"
        result = assess_raw_comment_delete_report(report)
        self.assertTrue(result["block"])

    def test_moot_lease_append_only_passes(self):
        report = _authorized_cleanup_report()
        result = assess_raw_comment_delete_report(report)
        self.assertFalse(result["block"])


class TestAuthorizedReconcilerPath(unittest.TestCase):
    def test_cleanup_without_mcp_tool_blocked(self):
        report = "\n".join([
            "## Controller Handoff",
            "- Cleanup mutations: removed branch manually after merge",
            "- Reconciler capability: prgs-reconciler",
        ])
        result = assess_authorized_reconciler_cleanup_path(report)
        self.assertTrue(result["block"])
        self.assertTrue(any("authorized MCP" in r for r in result["reasons"]))

    def test_authorized_cleanup_succeeds(self):
        result = assess_authorized_reconciler_cleanup_path(_authorized_cleanup_report())
        self.assertFalse(result["block"])

    def test_git_ref_cleanup_without_mcp_tool_blocked(self):
        report = "\n".join([
            "## Controller Handoff",
            "- Cleanup mutations: none",
            "- Git ref mutations: git branch -D feat/issue-517-test",
            "- Reconciler capability: prgs-reconciler",
        ])
        result = assess_authorized_reconciler_cleanup_path(report)
        self.assertTrue(result["block"])
        self.assertTrue(
            any("Git ref mutations cleanup must name" in r for r in result["reasons"])
        )

    def test_worktree_cleanup_without_mcp_tool_blocked(self):
        report = "\n".join([
            "## Controller Handoff",
            "- Cleanup mutations: none",
            "- Worktree mutations: git worktree remove branches/review-pr542",
            "- Reconciler capability: prgs-reconciler",
        ])
        result = assess_authorized_reconciler_cleanup_path(report)
        self.assertTrue(result["block"])
        self.assertTrue(
            any("Worktree mutations cleanup must name" in r for r in result["reasons"])
        )

    def test_git_fetch_in_git_ref_mutations_not_cleanup_claim(self):
        report = "\n".join([
            "## Controller Handoff",
            "- Cleanup mutations: none",
            "- Git ref mutations: git fetch prgs master",
        ])
        result = assess_authorized_reconciler_cleanup_path(report)
        self.assertFalse(result["block"])


class TestMergerHandoffGuidance(unittest.TestCase):
    def test_merger_cleanup_without_handoff_blocked(self):
        report = "Merger deleted remote branch and removed worktree after merge"
        result = assess_merger_cleanup_handoff_guidance(report)
        self.assertTrue(result["block"])

    def test_merger_cleanup_with_reconciler_handoff_passes(self):
        report = (
            "Merger deleted remote branch; next actor: reconciler for worktree audit"
        )
        result = assess_merger_cleanup_handoff_guidance(report)
        self.assertFalse(result["block"])


class TestCompositeVerifier(unittest.TestCase):
    def test_full_authorized_report_passes(self):
        result = assess_mcp_native_cleanup_proof(_authorized_cleanup_report())
        self.assertFalse(result["block"], result["reasons"])

    def test_raw_bypasses_fail_composite(self):
        report = "\n".join([
            "## Controller Handoff",
            "- Merge mutations: gitea_merge_pr",
            "- Cleanup mutations: git branch -D feat/x; curl -X DELETE .../comments/1",
        ])
        result = assess_mcp_native_cleanup_proof(report)
        self.assertTrue(result["block"])
        self.assertGreaterEqual(len(result["reasons"]), 2)

    def test_narrative_cleanup_mentions_pass_when_ledgers_none(self):
        report = "\n".join([
            "## Review summary",
            "Validated workflow §28B MCP-native cleanup guidance.",
            "Files reviewed describe raw git branch -d and delete_issue_comment blocks.",
            "",
            "## Controller Handoff",
            "- Cleanup mutations: none",
            "- Git ref mutations: none",
            "- Worktree mutations: none",
        ])
        result = assess_mcp_native_cleanup_proof(report)
        self.assertFalse(result["block"], result["reasons"])

    def test_git_ref_cleanup_bypass_blocked_in_composite(self):
        report = "\n".join([
            "## Controller Handoff",
            "- Cleanup mutations: none",
            "- Git ref mutations: git branch -D feat/issue-517-test",
            "- Reconciler capability: prgs-reconciler",
        ])
        result = assess_mcp_native_cleanup_proof(report)
        self.assertTrue(result["block"])
        self.assertTrue(
            any("Git ref mutations cleanup must name" in r for r in result["reasons"])
        )


class TestFinalReportValidatorIntegration(unittest.TestCase):
    def test_validator_blocks_raw_branch_delete_in_review_report(self):
        report = "\n".join([
            "## Controller Handoff",
            "- Cleanup mutations: git branch -d feat/issue-517-test",
        ])
        result = assess_final_report_validator(report, "review_pr")
        rules = {f["rule_id"] for f in result["findings"]}
        self.assertIn("shared.mcp_native_cleanup_proof", rules)

    def test_validator_passes_authorized_cleanup_report(self):
        result = assess_final_report_validator(_authorized_cleanup_report(), "review_pr")
        blocked = [f for f in result["findings"] if f.get("severity") == "block"]
        mcp_blocks = [
            f for f in blocked if f.get("rule_id") == "shared.mcp_native_cleanup_proof"
        ]
        self.assertEqual(mcp_blocks, [])

    def test_validator_passes_narrative_cleanup_mentions_with_none_ledgers(self):
        report = "\n".join([
            "## Review summary",
            "Workflow §28B documents raw git push --delete and delete_issue_comment blocks.",
            "",
            "## Controller Handoff",
            "- Cleanup mutations: none",
            "- Git ref mutations: none",
            "- Worktree mutations: none",
        ])
        result = assess_final_report_validator(report, "review_pr")
        mcp_blocks = [
            f for f in result["findings"]
            if f.get("rule_id") == "shared.mcp_native_cleanup_proof"
            and f.get("severity") == "block"
        ]
        self.assertEqual(mcp_blocks, [])

    def test_validator_blocks_git_ref_cleanup_bypass(self):
        report = "\n".join([
            "## Controller Handoff",
            "- Cleanup mutations: none",
            "- Git ref mutations: git branch -D feat/issue-517-test",
            "- Reconciler capability: prgs-reconciler",
        ])
        result = assess_final_report_validator(report, "reconcile_already_landed")
        rules = {f["rule_id"] for f in result["findings"] if f.get("severity") == "block"}
        self.assertIn("shared.mcp_native_cleanup_proof", rules)


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