"""Tests for review_pr.py.

Mocks api_request and credentials.
"""
import io
import os
import sys
import unittest
from unittest.mock import patch

sys.path.insert(0, str(__import__("pathlib").Path(__file__).resolve().parent.parent))
import review_pr  # noqa: E402


FAKE_CREDS = "Basic dGVzdHVzZXI6dGVzdHBhc3M="
FAKE_PR_DATA = {
    "number": 81,
    "state": "open",
    "head": {
        "ref": "feature-branch",
        "sha": "abcdef1234567890"
    },
    "base": {
        "ref": "main"
    },
    "html_url": "https://gitea.example.com/pulls/81"
}


class TestArgParsing(unittest.TestCase):

    def setUp(self):
        self.exists_patcher = patch("os.path.exists", return_value=False)
        self.exists_patcher.start()
        self.addCleanup(self.exists_patcher.stop)

    def test_missing_pr_number_exits(self):
        with self.assertRaises(SystemExit):
            review_pr.main([])


class TestAPIPayload(unittest.TestCase):

    def setUp(self):
        self.exists_patcher = patch("os.path.exists", return_value=False)
        self.exists_patcher.start()
        self.addCleanup(self.exists_patcher.stop)

    def test_review_submission_fails_closed_without_api_call(self):
        # #211: live review submission must use gated MCP tools, not CLI POST.
        import io
        buf = io.StringIO()
        with patch.object(sys, "stderr", buf):
            rc = review_pr.main([
                "--pr-number", "81",
                "--event", "APPROVE",
                "--body", "Approved and ready to merge",
            ])
        self.assertEqual(rc, 2)
        self.assertIn("disabled", buf.getvalue().lower())
        self.assertIn("gitea_submit_pr_review", buf.getvalue())

    def test_merge_flag_fails_closed_without_api_call(self):
        # --merge is an ungated bypass and is disabled (#16). It must fail
        # closed BEFORE any API call — no review, no merge.
        rc = review_pr.main([
            "--pr-number", "81",
            "--event", "APPROVE",
            "--body", "Approved",
            "--merge",
            "--merge-method", "squash",
        ])
        self.assertEqual(rc, 2)

    def test_merge_flag_message_points_to_gated_workflow(self):
        import io
        buf = io.StringIO()
        with patch.object(sys, "stderr", buf):
            rc = review_pr.main([
                "--pr-number", "81", "--event", "APPROVE", "--merge",
            ])
        self.assertEqual(rc, 2)
        msg = buf.getvalue().lower()
        self.assertIn("disabled", msg)
        self.assertIn("gitea_merge_pr", msg)


class TestMutationAuthorityLock(unittest.TestCase):
    """#199 (refs #194): the CLI refuses to run under active MCP sessions."""

    def test_cli_disabled_on_session_lock(self):
        # When running inside an MCP session, direct review submission via CLI is disabled entirely.
        import io
        buf = io.StringIO()
        with patch.dict(os.environ,
                        {"GITEA_SESSION_PROFILE_LOCK": "prgs-author"}), \
             patch.object(sys, "stderr", buf):
            rc = review_pr.main([
                "--pr-number", "81", "--event", "APPROVE",
            ])
        self.assertEqual(rc, 2)
        msg = buf.getvalue().lower()
        self.assertIn("disabled", msg)
        self.assertIn("gitea_submit_pr_review", msg)

    def test_cli_disabled_even_without_session_lock(self):
        # #211: CLI review submission is fail-closed regardless of session lock.
        env = {k: v for k, v in os.environ.items()
               if k != "GITEA_SESSION_PROFILE_LOCK"}
        with patch.dict(os.environ, env, clear=True):
            rc = review_pr.main([
                "--pr-number", "81", "--event", "APPROVE",
            ])
        self.assertEqual(rc, 2)


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