"""Tests for exact per-mutation capability proof in reviewer reports (#405)."""

import sys
import unittest
from pathlib import Path

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

from reviewer_mutation_capability_proof import assess_mutation_capability_proof
from review_proofs import assess_mutation_capability_proof as proofs_assess
from final_report_validator import assess_final_report_validator


REVIEW_ONLY = """
Review decision: approved
Mutation capability table:
- gitea_submit_pr_review | review_pr (gitea.pr.review) | submitted | resolved before review
"""

MERGE_PROVEN = """
Review decision: approved
Merge result: merged 0123456789ab
Mutation capability table:
- gitea_submit_pr_review | review_pr (gitea.pr.review) | submitted | before review
- gitea_merge_pr | merge_pr (gitea.pr.merge) | merged | resolved before merge
"""

MERGE_AND_DELETE_PROVEN = """
Review decision: approved
Merge result: merged 0123456789ab
Remote branch deleted: feat/issue-x
Mutation capability table:
- gitea_submit_pr_review | review_pr (gitea.pr.review) | submitted | before review
- gitea_merge_pr | merge_pr (gitea.pr.merge) | merged | before merge
- gitea_delete_branch | delete_branch (gitea.branch.delete) | deleted | before delete
"""


class TestModule(unittest.TestCase):
    def test_review_only_with_capability_passes(self):
        r = assess_mutation_capability_proof(REVIEW_ONLY)
        self.assertTrue(r["proven"], r["reasons"])

    def test_merge_with_exact_capability_passes(self):
        r = assess_mutation_capability_proof(MERGE_PROVEN)
        self.assertTrue(r["proven"], r["reasons"])

    def test_merge_and_delete_fully_proven_passes(self):
        r = assess_mutation_capability_proof(MERGE_AND_DELETE_PROVEN)
        self.assertTrue(r["proven"], r["reasons"])

    def test_review_pr_does_not_authorize_merge(self):
        report = """
Review decision: approved
Merge result: merged 0123456789ab
Mutation capability table:
- gitea_submit_pr_review | review_pr (gitea.pr.review) | submitted | before review
"""
        r = assess_mutation_capability_proof(report)
        self.assertFalse(r["proven"])
        self.assertTrue(any("merge" in x.lower() for x in r["reasons"]), r["reasons"])

    def test_merge_pr_does_not_authorize_branch_deletion(self):
        report = """
Review decision: approved
Merge result: merged 0123456789ab
Remote branch deleted: feat/issue-x
Mutation capability table:
- gitea_submit_pr_review | review_pr (gitea.pr.review) | submitted | before review
- gitea_merge_pr | merge_pr (gitea.pr.merge) | merged | before merge
"""
        r = assess_mutation_capability_proof(report)
        self.assertFalse(r["proven"])
        self.assertTrue(any("delet" in x.lower() for x in r["reasons"]), r["reasons"])

    def test_delete_skipped_when_capability_missing_passes(self):
        report = """
Review decision: approved
Merge result: merged 0123456789ab
Branch deletion: skipped — delete_branch capability not available
Mutation capability table:
- gitea_submit_pr_review | review_pr (gitea.pr.review) | submitted | before review
- gitea_merge_pr | merge_pr (gitea.pr.merge) | merged | before merge
"""
        r = assess_mutation_capability_proof(report)
        self.assertTrue(r["proven"], r["reasons"])

    def test_missing_table_when_merging_blocks(self):
        report = """
Review decision: approved
Merge result: merged 0123456789ab
merge_pr gitea.pr.merge resolved
"""
        r = assess_mutation_capability_proof(report)
        self.assertFalse(r["proven"])
        self.assertTrue(any("table" in x.lower() for x in r["reasons"]), r["reasons"])

    def test_post_hoc_proof_blocks(self):
        report = """
Review decision: approved
Merge result: merged 0123456789ab
Mutation capability table:
- gitea_merge_pr | merge_pr (gitea.pr.merge) | merged | capability resolved after merge
"""
        r = assess_mutation_capability_proof(report)
        self.assertFalse(r["proven"])
        self.assertTrue(any("after" in x.lower() for x in r["reasons"]), r["reasons"])

    def test_review_without_capability_blocks(self):
        report = "Review decision: approved\nreview submitted\n"
        r = assess_mutation_capability_proof(report)
        self.assertFalse(r["proven"])

    def test_no_mutation_no_requirement(self):
        r = assess_mutation_capability_proof("Selected PR: #1\nSkipped, no action.")
        self.assertTrue(r["proven"], r["reasons"])


class TestWiring(unittest.TestCase):
    def test_review_proofs_wrapper_matches_module(self):
        self.assertEqual(
            proofs_assess(MERGE_PROVEN)["proven"],
            assess_mutation_capability_proof(MERGE_PROVEN)["proven"],
        )

    def test_final_report_validator_flags_nearby_capability_merge(self):
        report = """
## Controller Handoff
- Task: review_pr
Review decision: approved
Merge result: merged 0123456789ab
Mutation capability table:
- gitea_submit_pr_review | review_pr (gitea.pr.review) | submitted | before review
"""
        result = assess_final_report_validator(report, "review_pr")
        rule_ids = [f["rule_id"] for f in result.get("findings", [])]
        self.assertIn("reviewer.mutation_capability_proof", rule_ids)


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