"""Tests for controller issue-acceptance gate (#500)."""
import sys
import unittest
from pathlib import Path

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

import issue_acceptance_gate  # noqa: E402
from final_report_validator import assess_final_report_validator  # noqa: E402


def _accepted_comment(**overrides):
    lines = [
        "## Controller Issue Acceptance",
        "",
        "STATE:",
        "accepted",
        "",
        "WHO_IS_NEXT:",
        "controller",
        "",
        "NEXT_ACTION:",
        "Close the tracker follow-up after verification.",
        "",
        "NEXT_PROMPT:",
        "Verify deployment checklist for issue #500 and post acceptance.",
        "",
        "ISSUE:",
        "#500",
        "",
        "MERGED_PR:",
        "#503",
        "",
        "MERGE_COMMIT:",
        "0fdc8f582026b72a229d59a172c0a63ac4aaeaf9",
        "",
        "ACCEPTANCE_CRITERIA_CHECKED:",
        "- [x] documentation added",
        "- [x] validator tests added",
        "",
        "VALIDATION_REVIEWED:",
        "pytest tests/test_issue_acceptance_gate.py -q",
        "",
        "CONTROLLER_DECISION:",
        "accepted",
        "",
        "WHY:",
        "All acceptance criteria satisfied with proof.",
        "",
        "MISSING_WORK:",
        "none",
        "",
        "FOLLOW_UP_ISSUES:",
        "none",
        "",
        "BLOCKERS:",
        "none",
        "",
        "LAST_UPDATED_BY:",
        "jcwalker3 / prgs-controller / 2026-07-08",
    ]
    text = "\n".join(lines)
    for key, value in overrides.items():
        text = text.replace(f"{key}:\n", f"{key}:\n{value}\n", 1)
    return text


def _rejection_comment(state="needs-tests"):
    text = _accepted_comment()
    text = text.replace("STATE:\naccepted", f"STATE:\n{state}")
    text = text.replace(
        "CONTROLLER_DECISION:\naccepted",
        "CONTROLLER_DECISION:\nrejected",
    )
    text = text.replace(
        "ACCEPTANCE_CRITERIA_CHECKED:\n- [x] documentation added\n- [x] validator tests added",
        "ACCEPTANCE_CRITERIA_CHECKED:\n- [ ] regression tests for rejection paths",
    )
    text = text.replace(
        "MISSING_WORK:\nnone",
        "MISSING_WORK:\nAdd regression tests for controller rejection paths.",
    )
    text = text.replace(
        "NEXT_PROMPT:\nVerify deployment checklist for issue #500 and post acceptance.",
        "NEXT_PROMPT:\nImplement the missing tests for issue #500 and reopen the PR.",
    )
    return text


class TestControllerAcceptanceComment(unittest.TestCase):
    def test_accepted_comment_valid(self):
        result = issue_acceptance_gate.validate_controller_acceptance_comment(
            _accepted_comment()
        )
        self.assertTrue(result["valid"], result["reasons"])

    def test_missing_who_is_next_rejected(self):
        text = _accepted_comment().replace("WHO_IS_NEXT:\ncontroller\n", "WHO_IS_NEXT:\n\n")
        result = issue_acceptance_gate.validate_controller_acceptance_comment(text)
        self.assertFalse(result["valid"])
        self.assertTrue(any("WHO_IS_NEXT" in r for r in result["reasons"]))

    def test_missing_next_prompt_on_rejection(self):
        text = _rejection_comment()
        text = text.replace(
            "NEXT_PROMPT:\nImplement the missing tests for issue #500 and reopen the PR.\n",
            "NEXT_PROMPT:\n\n",
        )
        result = issue_acceptance_gate.validate_controller_acceptance_comment(text)
        self.assertFalse(result["valid"])
        self.assertTrue(any("NEXT_PROMPT" in r for r in result["reasons"]))

    def test_vague_merge_only_completion_detected(self):
        text = "PR merged. Issue complete."
        self.assertTrue(issue_acceptance_gate.claims_merge_only_issue_complete(text))

    def test_rejection_paths_require_missing_work(self):
        for state in (
            "more-work-required",
            "needs-tests",
            "needs-docs",
            "needs-feature-enhancement",
            "needs-follow-up-issue",
        ):
            text = _rejection_comment(state=state).replace(
                "MISSING_WORK:\nAdd regression tests for controller rejection paths.\n",
                "MISSING_WORK:\n\n",
            )
            result = issue_acceptance_gate.validate_controller_acceptance_comment(text)
            self.assertFalse(result["valid"], state)
            self.assertTrue(any("MISSING_WORK" in r for r in result["reasons"]))

    def test_accepted_requires_checked_criteria(self):
        text = _accepted_comment().replace(
            "ACCEPTANCE_CRITERIA_CHECKED:\n- [x] documentation added\n- [x] validator tests added\n",
            "ACCEPTANCE_CRITERIA_CHECKED:\n- [ ] documentation added\n",
        )
        result = issue_acceptance_gate.validate_controller_acceptance_comment(text)
        self.assertFalse(result["valid"])
        self.assertTrue(any("checked acceptance criterion" in r for r in result["reasons"]))


class TestFinalReportIntegration(unittest.TestCase):
    def test_merge_only_complete_blocks_work_issue_report(self):
        report = (
            "## Controller Handoff\n\n"
            "- Task: work issue #500\n"
            "- Merge result: merged\n"
            "- Current status: PR merged; issue complete\n"
        )
        result = assess_final_report_validator(report, "work_issue")
        self.assertTrue(
            any(
                f["rule_id"] == "shared.issue_acceptance_gate"
                for f in result["findings"]
            ),
            result["findings"],
        )

    def test_pending_acceptance_allowed(self):
        report = (
            "## Controller Handoff\n\n"
            "- Task: work issue #500\n"
            "- Merge result: merged\n"
            "- Current status: controller acceptance pending\n"
        )
        result = assess_final_report_validator(report, "work_issue")
        self.assertFalse(
            any(
                f["rule_id"] == "shared.issue_acceptance_gate"
                for f in result["findings"]
            ),
            result["findings"],
        )

    def test_accepted_block_allows_complete_claim(self):
        report = _accepted_comment() + "\n\nIssue is complete."
        gate = issue_acceptance_gate.validate_final_report_issue_acceptance(report)
        self.assertTrue(gate["valid"], gate["reasons"])


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