"""Tests for the confirm-verb gate in deploy_interactives.py --html-file mode.

Guardrail 2: gated interactive deploy.
- Missing --confirm-verb on non-dry-run refuses with SystemExit (argparse error).
- Ambiguous verb is rejected by argparse choices constraint.
- Valid verb (push, approved, deploy) proceeds to the actual deploy function.
- --dry-run does NOT require --confirm-verb and prints a dry-run message.
"""

import os
import sys
import pathlib
import tempfile
from unittest import mock

SCRIPTS_DIR = pathlib.Path(__file__).resolve().parents[1] / "scripts"
sys.path.insert(0, str(SCRIPTS_DIR))

import deploy_interactives as di  # noqa: E402


def _make_html_file(content="<html><body>test</body></html>"):
    """Create a temporary HTML file for testing; return its path."""
    tmp = tempfile.NamedTemporaryFile(suffix=".html", delete=False, mode="w")
    tmp.write(content)
    tmp.close()
    return tmp.name


class TestConfirmVerbGate:
    """confirm-verb gate for --html-file mode."""

    def _run(self, argv):
        """Run deploy_interactives.main(argv) and return exit code / exception."""
        with mock.patch("sys.argv", ["deploy_interactives"] + argv):
            try:
                di.main()
                return 0
            except SystemExit as exc:
                return exc.code

    def test_missing_confirm_verb_refuses(self, tmp_path):
        """Non-dry-run --html-file without --confirm-verb must refuse (exit non-zero)."""
        html_file = str(tmp_path / "interact.html")
        (tmp_path / "interact.html").write_text("<html></html>")
        rc = self._run(["--html-file", html_file, "--title", "Test Activity"])
        assert rc != 0, "Expected non-zero exit when --confirm-verb is missing"

    def test_ambiguous_verb_refused(self, tmp_path):
        """Argparse choices constraint must reject ambiguous verbs."""
        html_file = str(tmp_path / "interact.html")
        (tmp_path / "interact.html").write_text("<html></html>")
        for bad_verb in ("ok", "yes", "confirm", "sure", "yep"):
            rc = self._run([
                "--html-file", html_file, "--title", "Test",
                "--confirm-verb", bad_verb,
            ])
            assert rc != 0, f"Expected refusal for ambiguous verb '{bad_verb}'"

    def test_dry_run_no_confirm_verb_needed(self, tmp_path):
        """--dry-run mode must succeed without --confirm-verb."""
        html_file = str(tmp_path / "interact.html")
        (tmp_path / "interact.html").write_text("<html></html>")
        rc = self._run(["--html-file", html_file, "--title", "Test", "--dry-run"])
        assert rc == 0, f"--dry-run should not require --confirm-verb, got exit {rc}"

    def test_valid_verb_push_proceeds(self, tmp_path):
        """--confirm-verb push with mocked canvas calls should succeed."""
        html_file = str(tmp_path / "interact.html")
        (tmp_path / "interact.html").write_text("<html></html>")
        with mock.patch.object(di, "deploy_single_html",
                               return_value=("test-page-slug", 42)) as mock_deploy, \
             mock.patch("staging_manager.clear_staged", return_value={"ok": True}):
            rc = self._run([
                "--html-file", html_file, "--title", "Test Activity",
                "--confirm-verb", "push",
            ])
        mock_deploy.assert_called_once()
        assert rc == 0

    def test_valid_verb_approved_proceeds(self, tmp_path):
        """--confirm-verb approved should also be accepted."""
        html_file = str(tmp_path / "interact.html")
        (tmp_path / "interact.html").write_text("<html></html>")
        with mock.patch.object(di, "deploy_single_html",
                               return_value=("slug", 99)) as mock_deploy, \
             mock.patch("staging_manager.clear_staged", return_value={"ok": True}):
            rc = self._run([
                "--html-file", html_file, "--title", "Test",
                "--confirm-verb", "approved",
            ])
        mock_deploy.assert_called_once()
        assert rc == 0

    def test_valid_verb_deploy_proceeds(self, tmp_path):
        """--confirm-verb deploy should be accepted."""
        html_file = str(tmp_path / "interact.html")
        (tmp_path / "interact.html").write_text("<html></html>")
        with mock.patch.object(di, "deploy_single_html",
                               return_value=("slug", 7)) as mock_deploy, \
             mock.patch("staging_manager.clear_staged", return_value={"ok": True}):
            rc = self._run([
                "--html-file", html_file, "--title", "Test",
                "--confirm-verb", "deploy",
            ])
        mock_deploy.assert_called_once()
        assert rc == 0

    def test_staged_slug_cleared_on_success(self, tmp_path):
        """On success, the staged page must be cleared when --staged-slug is given."""
        html_file = str(tmp_path / "interact.html")
        (tmp_path / "interact.html").write_text("<html></html>")
        import staging_manager as sm
        with mock.patch.object(di, "deploy_single_html",
                               return_value=("slug", 1)), \
             mock.patch.object(sm, "clear_staged",
                               return_value={"ok": True}) as mock_clear, \
             mock.patch.dict("os.environ", {"CANVAS_COURSE_ID": "TEST123"}):
            rc = self._run([
                "--html-file", html_file, "--title", "Test",
                "--confirm-verb", "push",
                "--staged-slug", "m1-lesson",
            ])
        assert rc == 0
        mock_clear.assert_called_once()
        call_args = mock_clear.call_args
        # clear_staged(course_id, "pages", slug_to_clear)
        assert call_args[0][1] == "pages"
        assert call_args[0][2] == "m1-lesson"
