"""Tests for merge-simulation worktree mutation verifier (#317)."""
import sys
import unittest
from pathlib import Path

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

from reviewer_merge_simulation import (  # noqa: E402
    assess_merge_simulation_report,
    merge_simulation_commands,
)


def _good_simulation_report(**overrides) -> str:
    lines = [
        "Worktree/index mutations: merge simulation in branches/review-pr281",
        "Worktree path: branches/review-pr281",
        "Pre-simulation clean status: clean (git status --porcelain empty)",
        "Merge result: conflicts in review_proofs.py",
        "Abort command: git merge --abort",
        "Post-abort clean status: clean after abort (git status --porcelain empty)",
    ]
    text = "\n".join(lines)
    for key, value in overrides.items():
        text = text.replace(f"{key}:", f"{key}: {value}")
    return text


class TestMergeSimulationDetection(unittest.TestCase):
    def test_detects_no_commit_merge(self):
        commands = merge_simulation_commands([
            "git merge prgs/master --no-commit --no-ff",
            "git status",
        ])
        self.assertEqual(commands, ["git merge prgs/master --no-commit --no-ff"])

    def test_detects_merge_abort(self):
        commands = merge_simulation_commands([
            "git merge prgs/master --no-commit --no-ff",
            "git merge --abort",
        ])
        self.assertIn("git merge --abort", commands)


class TestMergeSimulationReport(unittest.TestCase):
    def test_no_simulation_passes(self):
        result = assess_merge_simulation_report(
            "Review complete. Worktree/index mutations: none",
            command_log=["git status --porcelain", "git diff prgs/master...HEAD"],
        )
        self.assertTrue(result["proven"])

    def test_documented_simulation_passes(self):
        report = _good_simulation_report()
        result = assess_merge_simulation_report(
            report,
            command_log=[
                "git merge prgs/master --no-commit --no-ff",
                "git merge --abort",
            ],
        )
        self.assertTrue(result["proven"], result["reasons"])

    def test_readonly_classification_blocks(self):
        report = "\n".join([
            "Read-only diagnostics: git merge prgs/master --no-commit --no-ff, git status",
            "Worktree/index mutations: none",
        ])
        result = assess_merge_simulation_report(
            report,
            command_log=["git merge prgs/master --no-commit --no-ff"],
        )
        self.assertFalse(result["proven"])
        self.assertTrue(result["block"])
        self.assertTrue(any("read-only" in r.lower() for r in result["reasons"]))

    def test_missing_worktree_field_blocks(self):
        report = "Merge simulation ran but only noted in prose."
        result = assess_merge_simulation_report(
            report,
            command_log=["git merge prgs/master --no-commit --no-ff"],
        )
        self.assertFalse(result["proven"])
        self.assertTrue(any("worktree/index mutations" in r.lower() for r in result["reasons"]))

    def test_conflict_simulation_requires_merge_result(self):
        report = _good_simulation_report().replace(
            "Merge result: conflicts in review_proofs.py",
            "",
        )
        result = assess_merge_simulation_report(
            report,
            command_log=["git merge prgs/master --no-commit --no-ff"],
        )
        self.assertFalse(result["proven"])
        self.assertTrue(any("merge result" in r.lower() for r in result["reasons"]))

    def test_aborted_simulation_requires_post_clean_proof(self):
        report = _good_simulation_report().replace(
            "Post-abort clean status: clean after abort (git status --porcelain empty)",
            "",
        )
        result = assess_merge_simulation_report(
            report,
            command_log=[
                "git merge prgs/master --no-commit --no-ff",
                "git merge --abort",
            ],
        )
        self.assertFalse(result["proven"])
        self.assertTrue(any("post-abort" in r.lower() for r in result["reasons"]))

    def test_successful_simulation_without_abort_omits_abort_fields(self):
        report = "\n".join([
            "Worktree/index mutations: merge simulation completed cleanly",
            "Worktree path: branches/review-pr281",
            "Pre-simulation clean status: clean before simulation",
            "Merge result: clean fast-forward simulation",
        ])
        result = assess_merge_simulation_report(
            report,
            command_log=["git merge prgs/master --no-commit --no-ff"],
        )
        self.assertTrue(result["proven"], result["reasons"])


class TestExport(unittest.TestCase):
    def test_review_proofs_reexport(self):
        from review_proofs import assess_merge_simulation_report as exported

        self.assertTrue(callable(exported))


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