"""Tests for linked-issue consistency verifier (#314).

Reviewer reports must verify the linked issue live for the selected PR;
stale issue numbers from a previous PR must not leak into the final
report, and linked-issue status must never be claimed without live proof.
"""
import sys
import unittest
from pathlib import Path

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

from review_proofs import assess_linked_issue_consistency  # noqa: E402


class TestCorrectLinkedIssue(unittest.TestCase):
    def test_matching_linked_issue_passes(self):
        report = (
            "Selected PR: 280\n"
            "Linked issue status: Issue #275 open, closes on merge\n"
        )
        result = assess_linked_issue_consistency(
            report, selected_pr=280, linked_issues=[275]
        )
        self.assertTrue(result["complete"])
        self.assertFalse(result["downgraded"])
        self.assertEqual(result["reasons"], [])

    def test_multiple_linked_issues_all_reported_passes(self):
        report = (
            "Linked issue status: Issue #275 and Issue #276 both open\n"
        )
        result = assess_linked_issue_consistency(
            report, selected_pr=280, linked_issues=[275, 276]
        )
        self.assertTrue(result["complete"])

    def test_multiple_linked_issues_one_missing_fails(self):
        report = "Linked issue status: Issue #275 open\n"
        result = assess_linked_issue_consistency(
            report, selected_pr=280, linked_issues=[275, 276]
        )
        self.assertFalse(result["complete"])
        self.assertTrue(
            any("276" in r for r in result["reasons"])
        )


class TestStaleIssueLeak(unittest.TestCase):
    def test_stale_issue_in_status_field_fails(self):
        # #314 observed behavior: PR #280 links Issue #275 but the report
        # carries Issue #260 from the previous PR.
        report = "Linked issue status: Issue #260 open\n"
        result = assess_linked_issue_consistency(
            report, selected_pr=280, linked_issues=[275]
        )
        self.assertFalse(result["complete"])
        self.assertTrue(any("260" in r for r in result["reasons"]))

    def test_stale_issue_in_diagnostics_fails(self):
        report = (
            "Linked issue status: Issue #275 open\n"
            "Read-only diagnostics: viewed Issue #260 status\n"
        )
        result = assess_linked_issue_consistency(
            report, selected_pr=280, linked_issues=[275]
        )
        self.assertFalse(result["complete"])
        self.assertTrue(
            any("stale" in r.lower() and "260" in r for r in result["reasons"])
        )

    def test_selected_pr_number_mention_is_not_stale(self):
        # "PR #280" mentions must not be confused with issue mentions.
        report = (
            "Selected PR: 280\n"
            "Validation: ran tests at PR #280 head\n"
            "Linked issue status: Issue #275 open\n"
        )
        result = assess_linked_issue_consistency(
            report, selected_pr=280, linked_issues=[275]
        )
        self.assertTrue(result["complete"])


class TestMissingProof(unittest.TestCase):
    def test_status_claim_without_live_proof_fails(self):
        report = "Linked issue status: Issue #275 open\n"
        result = assess_linked_issue_consistency(
            report, selected_pr=280, linked_issues=None
        )
        self.assertFalse(result["complete"])
        self.assertTrue(
            any("live proof" in r.lower() for r in result["reasons"])
        )

    def test_unverified_wording_without_proof_passes(self):
        report = (
            "Linked issue status: not verified in this session\n"
        )
        result = assess_linked_issue_consistency(
            report, selected_pr=280, linked_issues=None
        )
        self.assertTrue(result["complete"])

    def test_missing_field_fails(self):
        report = "Selected PR: 280\n"
        result = assess_linked_issue_consistency(
            report, selected_pr=280, linked_issues=[275]
        )
        self.assertFalse(result["complete"])
        self.assertTrue(
            any("linked issue status" in r.lower() for r in result["reasons"])
        )


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