"""Tests for web UI deployment and auth boundary (#435)."""
import os
import subprocess
import sys
import unittest
from pathlib import Path

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

from starlette.testclient import TestClient

from webui.app import create_app
from webui.deployment_boundary import (
    assess_bind_host,
    runtime_assumptions,
    scan_text_for_client_secrets,
)


class TestBindAssessment(unittest.TestCase):
    def test_loopback_is_safe(self):
        for host in ("127.0.0.1", "localhost", "::1"):
            with self.subTest(host=host):
                result = assess_bind_host(host)
                self.assertEqual(result.disposition, "safe")

    def test_all_interfaces_refused_by_default(self):
        for host in ("0.0.0.0", "::", "*"):
            with self.subTest(host=host):
                result = assess_bind_host(host)
                self.assertEqual(result.disposition, "refuse")

    def test_all_interfaces_allowed_with_override(self):
        prior = os.environ.pop("WEBUI_ALLOW_PUBLIC_BIND", None)
        try:
            os.environ["WEBUI_ALLOW_PUBLIC_BIND"] = "1"
            result = assess_bind_host("0.0.0.0")
            self.assertEqual(result.disposition, "warn")
        finally:
            os.environ.pop("WEBUI_ALLOW_PUBLIC_BIND", None)
            if prior is not None:
                os.environ["WEBUI_ALLOW_PUBLIC_BIND"] = prior

    def test_non_loopback_warns_without_override(self):
        prior = os.environ.pop("WEBUI_ALLOW_REMOTE_BIND", None)
        try:
            os.environ.pop("WEBUI_ALLOW_REMOTE_BIND", None)
            result = assess_bind_host("192.168.1.10")
            self.assertEqual(result.disposition, "warn")
        finally:
            if prior is not None:
                os.environ["WEBUI_ALLOW_REMOTE_BIND"] = prior

    def test_runtime_assumptions_exclude_secrets(self):
        assumptions = runtime_assumptions()
        blob = " ".join(str(v) for v in assumptions.values())
        self.assertNotIn("GITEA_TOKEN", blob)
        self.assertIn("internal-operator-console", assumptions["deployment_mode"])


class TestDeploymentRoutes(unittest.TestCase):
    def setUp(self):
        self.client = TestClient(create_app(bind_host="127.0.0.1"))

    def test_health_includes_deployment_metadata(self):
        response = self.client.get("/health")
        self.assertEqual(response.status_code, 200)
        data = response.json()
        self.assertIn("deployment", data)
        deployment = data["deployment"]
        self.assertEqual(deployment["mode"], "internal-operator-console")
        self.assertEqual(deployment["mvp_auth"], "none")
        self.assertEqual(deployment["bind"]["disposition"], "safe")
        self.assertIn("runtime_assumptions", deployment)

    def test_rendered_pages_contain_no_embedded_secrets(self):
        for path in ("/", "/projects", "/prompts", "/queue"):
            with self.subTest(path=path):
                text = self.client.get(path).text
                self.assertEqual(scan_text_for_client_secrets(text), [])


class TestStartupRefusal(unittest.TestCase):
    def test_refuses_all_interface_bind(self):
        env = {**os.environ, "WEBUI_HOST": "0.0.0.0"}
        env.pop("WEBUI_ALLOW_PUBLIC_BIND", None)
        repo_root = Path(__file__).resolve().parent.parent
        result = subprocess.run(
            [sys.executable, "-m", "webui"],
            cwd=repo_root,
            env=env,
            capture_output=True,
            text=True,
            timeout=3,
        )
        self.assertEqual(result.returncode, 1)


class TestClientSecretScanner(unittest.TestCase):
    def test_detects_token_like_content(self):
        findings = scan_text_for_client_secrets("var x = GITEA_TOKEN_PRGS")
        self.assertTrue(findings)


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