"""Tests for non-mergeable skip conflict-proof verifier (#322)."""
import sys
import unittest
from pathlib import Path

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

from reviewer_mergeability_skip import assess_non_mergeable_skip_proof  # noqa: E402

HEAD_A = "0fdc8f582026b72a229d59a172c0a63ac4aaeaf9"
HEAD_B = "1111111111111111111111111111111111111111"


def _good_skip_report(pr_number: int, head: str, files: str = "review_proofs.py") -> str:
    return "\n".join([
        f"Skipped PR #{pr_number} (non-mergeable).",
        f"- PR number: #{pr_number}",
        f"- Current head SHA: {head}",
        "- Mergeability result: false",
        "- Conflict proof command: git merge-tree $(git merge-base prgs/master prgs/feat) prgs/master prgs/feat",
        f"- Conflicting files: {files}",
        "- Head unchanged since prior blocker",
        "- Blocking category: merge conflict",
    ])


class TestNonMergeableSkipProof(unittest.TestCase):
    def test_no_skips_passes(self):
        report = "Selected PR #203 for review. No earlier PRs skipped."
        result = assess_non_mergeable_skip_proof(report, skipped_prs=[])
        self.assertTrue(result["proven"])
        self.assertFalse(result["block"])

    def test_documented_non_mergeable_skip_passes(self):
        report = _good_skip_report(282, HEAD_A)
        result = assess_non_mergeable_skip_proof(
            report,
            skipped_prs=[{
                "pr_number": 282,
                "mergeable": False,
                "head_sha": HEAD_A,
                "mergeability_verified": True,
                "conflicting_files": ["review_proofs.py"],
                "head_changed_since_prior_blocker": False,
            }],
        )
        self.assertTrue(result["proven"])

    def test_skip_without_conflict_proof_blocks(self):
        report = "\n".join([
            "Skipped PR #284 because it was not mergeable.",
            f"Head SHA: {HEAD_B}",
        ])
        result = assess_non_mergeable_skip_proof(
            report,
            skipped_prs=[{
                "pr_number": 284,
                "mergeable": False,
                "head_sha": HEAD_B,
                "mergeability_verified": True,
            }],
        )
        self.assertFalse(result["proven"])
        self.assertTrue(result["block"])
        self.assertTrue(any("conflict proof" in r for r in result["reasons"]))

    def test_missing_head_sha_blocks(self):
        report = _good_skip_report(282, HEAD_A).replace(HEAD_A, "")
        result = assess_non_mergeable_skip_proof(
            report,
            skipped_prs=[{
                "pr_number": 282,
                "mergeable": False,
                "head_sha": HEAD_A,
                "mergeability_verified": True,
            }],
        )
        self.assertFalse(result["proven"])

    def test_mergeability_unverified_classification_passes(self):
        report = "\n".join([
            "Skipped PR #282.",
            "Classification: MERGEABILITY_UNVERIFIED",
            "Conflict proof could not be retrieved in this session.",
        ])
        result = assess_non_mergeable_skip_proof(
            report,
            skipped_prs=[{
                "pr_number": 282,
                "mergeable": False,
                "mergeability_verified": False,
            }],
        )
        self.assertTrue(result["proven"])

    def test_unverified_without_classification_blocks(self):
        report = "Skipped PR #282 due to conflicts."
        result = assess_non_mergeable_skip_proof(
            report,
            skipped_prs=[{
                "pr_number": 282,
                "mergeable": False,
                "mergeability_verified": False,
            }],
        )
        self.assertFalse(result["proven"])
        self.assertTrue(any("MERGEABILITY_UNVERIFIED" in r for r in result["reasons"]))

    def test_non_mergeable_without_file_details_still_passes_with_command(self):
        report = _good_skip_report(284, HEAD_B, files="not available")
        result = assess_non_mergeable_skip_proof(
            report,
            skipped_prs=[{
                "pr_number": 284,
                "mergeable": False,
                "head_sha": HEAD_B,
                "mergeability_verified": True,
                "conflicting_files": [],
            }],
        )
        self.assertTrue(result["proven"])

    def test_stale_head_requires_head_change_field(self):
        report = _good_skip_report(282, HEAD_A).replace(
            "- Head unchanged since prior blocker",
            "",
        )
        result = assess_non_mergeable_skip_proof(
            report,
            skipped_prs=[{
                "pr_number": 282,
                "mergeable": False,
                "head_sha": HEAD_A,
                "mergeability_verified": True,
                "head_changed_since_prior_blocker": True,
            }],
        )
        self.assertFalse(result["proven"])
        self.assertTrue(any("head-changed" in r for r in result["reasons"]))


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

        self.assertTrue(callable(exported))


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