"""Tests for canonical review-workflow citation and version proof (#296).

PR review/merge reports must prove they loaded the canonical workflow
(workflows/review-merge-pr.md) and cite the workflow version/hash used;
a stale or missing hash fails so prompt drift is caught.
"""
import sys
import unittest
from pathlib import Path

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

from review_proofs import (  # noqa: E402
    assess_review_workflow_source,
    compute_workflow_hash,
)


CANONICAL_TEXT = "# review-merge-pr workflow v1\nstep one\n"
CANONICAL_HASH = compute_workflow_hash(CANONICAL_TEXT)


def _report(citation=True, version=CANONICAL_HASH):
    lines = ["Task: review next eligible PR"]
    if citation:
        lines.append(
            "Workflow source: skills/llm-project-workflow/"
            "workflows/review-merge-pr.md (loaded via mcp_get_skill_guide)"
        )
    if version is not None:
        lines.append(f"- Workflow version: {version}")
    return "\n".join(lines) + "\n"


class TestComputeWorkflowHash(unittest.TestCase):
    def test_deterministic(self):
        self.assertEqual(
            compute_workflow_hash(CANONICAL_TEXT),
            compute_workflow_hash(CANONICAL_TEXT),
        )

    def test_changes_with_content(self):
        self.assertNotEqual(
            compute_workflow_hash(CANONICAL_TEXT),
            compute_workflow_hash(CANONICAL_TEXT + "extra rule\n"),
        )

    def test_short_hex(self):
        h = compute_workflow_hash(CANONICAL_TEXT)
        self.assertEqual(len(h), 12)
        int(h, 16)  # raises if not hex


class TestReviewWorkflowSource(unittest.TestCase):
    def test_citation_and_matching_hash_passes(self):
        result = assess_review_workflow_source(
            _report(), canonical_hash=CANONICAL_HASH
        )
        self.assertTrue(result["complete"])
        self.assertEqual(result["reasons"], [])

    def test_missing_citation_fails(self):
        result = assess_review_workflow_source(
            _report(citation=False), canonical_hash=CANONICAL_HASH
        )
        self.assertFalse(result["complete"])
        self.assertTrue(
            any("review-merge-pr" in r.lower() for r in result["reasons"])
        )

    def test_missing_version_field_fails(self):
        result = assess_review_workflow_source(
            _report(version=None), canonical_hash=CANONICAL_HASH
        )
        self.assertFalse(result["complete"])
        self.assertTrue(
            any("workflow version" in r.lower() for r in result["reasons"])
        )

    def test_stale_hash_fails(self):
        result = assess_review_workflow_source(
            _report(version="deadbeef0000"), canonical_hash=CANONICAL_HASH
        )
        self.assertFalse(result["complete"])
        self.assertTrue(
            any("stale" in r.lower() or "does not match" in r.lower()
                for r in result["reasons"])
        )

    def test_version_none_fails(self):
        result = assess_review_workflow_source(
            _report(version="none"), canonical_hash=CANONICAL_HASH
        )
        self.assertFalse(result["complete"])

    def test_without_canonical_hash_field_still_required(self):
        # No canonical hash supplied (e.g. offline validation): citation
        # and a populated version field are still required.
        self.assertTrue(
            assess_review_workflow_source(_report())["complete"]
        )
        self.assertFalse(
            assess_review_workflow_source(_report(version=None))["complete"]
        )


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