"""Tests for canonical state comment validation (#495)."""
import sys
import unittest
from pathlib import Path

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

from canonical_state_comments import (  # noqa: E402
    validate_canonical_state_comment,
    validate_final_report_state_update,
)


GOOD_ISSUE_STATE = """## Canonical Issue State

STATE:
ready-for-author

WHO_IS_NEXT:
author

NEXT_ACTION:
Implement the focused validator and open a PR.

NEXT_PROMPT:
Find issue #495, load the work-issue workflow, implement the validator, and open a PR.

WHAT_HAPPENED:
Controller selected the canonical tracking issue.

WHY:
The duplicate issue points here as canonical.

RELATED_PRS:
none

BRANCH:
none

HEAD_SHA:
none

VALIDATION:
none

BLOCKERS:
none
"""


class TestCanonicalStateComments(unittest.TestCase):
    def test_good_issue_state_validates(self):
        result = validate_canonical_state_comment(GOOD_ISSUE_STATE)
        self.assertTrue(result["valid"])
        self.assertEqual(result["reasons"], [])

    def test_missing_next_actor_is_rejected(self):
        result = validate_canonical_state_comment(
            GOOD_ISSUE_STATE.replace("WHO_IS_NEXT:\nauthor", "WHO_IS_NEXT:\n")
        )
        self.assertFalse(result["valid"])
        self.assertIn("WHO_IS_NEXT", " ".join(result["reasons"]))

    def test_missing_next_prompt_is_rejected(self):
        result = validate_canonical_state_comment(
            GOOD_ISSUE_STATE.replace(
                "NEXT_PROMPT:\nFind issue #495, load the work-issue workflow, implement the validator, and open a PR.",
                "NEXT_PROMPT:\n",
            )
        )
        self.assertFalse(result["valid"])
        self.assertIn("NEXT_PROMPT", " ".join(result["reasons"]))

    def test_vague_next_action_is_rejected(self):
        result = validate_canonical_state_comment(
            GOOD_ISSUE_STATE.replace(
                "NEXT_ACTION:\nImplement the focused validator and open a PR.",
                "NEXT_ACTION:\ncontinue",
            )
        )
        self.assertFalse(result["valid"])
        self.assertIn("too vague", " ".join(result["reasons"]))

    def test_ready_to_merge_requires_approval_and_head_sha(self):
        text = """## Canonical PR State

STATE:
ready-to-merge

WHO_IS_NEXT:
merger

NEXT_ACTION:
Merge PR #12 after checking the current head.

NEXT_PROMPT:
Load the merge workflow and merge PR #12 if gates pass.

ISSUE:
#11

HEAD_SHA:
abc123

REVIEW_STATUS:
none

MERGE_READY:
yes
"""
        result = validate_canonical_state_comment(text)
        self.assertFalse(result["valid"])
        reasons = " ".join(result["reasons"])
        self.assertIn("approved REVIEW_STATUS", reasons)
        self.assertIn("full HEAD_SHA", reasons)

    def test_superseded_requires_canonical_item(self):
        text = GOOD_ISSUE_STATE.replace("STATE:\nready-for-author", "STATE:\nsuperseded")
        result = validate_canonical_state_comment(text)
        self.assertFalse(result["valid"])
        self.assertIn("canonical item", " ".join(result["reasons"]))

    def test_blocked_requires_unblock_condition(self):
        text = GOOD_ISSUE_STATE.replace("STATE:\nready-for-author", "STATE:\nblocked")
        text = text.replace("BLOCKERS:\nnone", "BLOCKERS:\n")
        result = validate_canonical_state_comment(text)
        self.assertFalse(result["valid"])
        self.assertIn("BLOCKERS", " ".join(result["reasons"]))

    def test_final_report_claim_without_block_is_rejected(self):
        report = "Posted canonical state comment on issue #495."
        result = validate_final_report_state_update(report)
        self.assertTrue(result["applicable"])
        self.assertFalse(result["valid"])

    def test_final_report_without_state_claim_not_applicable(self):
        result = validate_final_report_state_update("ordinary final report")
        self.assertFalse(result["applicable"])
        self.assertTrue(result["valid"])


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