"""Cloudflare end-to-end tests — mirrors cloudflare.e2e.test.ts.

Uses HTTP proxy pattern: POSTs exec() calls to a deployed Cloudflare Worker.
Skips .env deny, env, printenv tests (Firecracker kernel limitation).
"""

from __future__ import annotations

import time

import httpx
import pytest

from tests.e2e.conftest import ENV, skip_no_cloudflare

from agentsh_secure_sandbox import SecuredSandbox, secure_sandbox
from agentsh_secure_sandbox.adapters import cloudflare

pytestmark = [pytest.mark.e2e, pytest.mark.timeout(300), skip_no_cloudflare]

# ─── Module-scoped setup / teardown ────────────────────────


class _CloudflareSandboxProxy:
    """HTTP proxy that forwards exec() calls to the deployed Worker."""

    def __init__(self, base_url: str, token: str, sandbox_id: str) -> None:
        self._base_url = base_url
        self._token = token
        self._sandbox_id = sandbox_id
        self._client = httpx.AsyncClient(timeout=120)

    async def exec(
        self, command: str, *, cwd: str | None = None
    ) -> dict[str, object]:
        res = await self._client.post(
            f"{self._base_url}/exec",
            params={"id": self._sandbox_id},
            headers={
                "Content-Type": "application/json",
                "Authorization": f"Bearer {self._token}",
            },
            json={"command": command, "cwd": cwd},
        )
        if res.status_code >= 400:
            raise RuntimeError(f"Worker returned {res.status_code}: {res.text}")
        return res.json()  # type: ignore[no-any-return]

    async def close(self) -> None:
        await self._client.aclose()


@pytest.fixture(scope="module")
async def secured() -> SecuredSandbox:  # type: ignore[misc]
    sandbox_id = f"e2e-{int(time.time() * 1000)}"
    proxy = _CloudflareSandboxProxy(
        base_url=ENV["CLOUDFLARE_WORKER_URL"],
        token=ENV["CLOUDFLARE_API_TOKEN"],
        sandbox_id=sandbox_id,
    )
    adapter = cloudflare(proxy)
    sec = await secure_sandbox(adapter)

    yield sec  # type: ignore[misc]

    await sec.stop()
    await proxy.close()


# ─── Smoke tests ──────────────────────────────────────────


class TestCloudflareSmoke:
    async def test_provisions_session_id(self, secured: SecuredSandbox) -> None:
        assert secured.session_id
        assert isinstance(secured.session_id, str)

    async def test_reports_valid_security_mode(self, secured: SecuredSandbox) -> None:
        assert secured.security_mode in ("full", "landlock", "landlock-only", "minimal")

    async def test_exec_simple_command(self, secured: SecuredSandbox) -> None:
        result = await secured.exec("echo hello")
        assert result.exit_code == 0
        assert result.stdout.strip() == "hello"

    async def test_write_read_roundtrip(self, secured: SecuredSandbox) -> None:
        path = "/workspace/e2e-test-file.txt"
        content = f"e2e-roundtrip-{int(time.time() * 1000)}"

        write_result = await secured.write_file(path, content)
        assert write_result.success is True

        read_result = await secured.read_file(path)
        assert read_result.success is True
        if read_result.success:
            assert read_result.content.strip() == content


# ─── Policy enforcement ───────────────────────────────────
# Note: Cloudflare Containers run in Firecracker VMs whose custom kernel
# reports 'full' security mode but may lack actual seccomp_user_notify
# and FUSE support.  Tests for .env file deny, env/printenv blocking are
# skipped here and covered by the Vercel E2E tests instead.


class TestCloudflarePolicy:
    async def test_allows_workspace_write(self, secured: SecuredSandbox) -> None:
        result = await secured.write_file("/workspace/allowed-file.txt", "allowed")
        assert result.success is True

    async def test_blocks_sudo(self, secured: SecuredSandbox) -> None:
        result = await secured.exec("sudo whoami")
        assert result.exit_code != 0

    async def test_allows_npm_registry(self, secured: SecuredSandbox) -> None:
        result = await secured.exec(
            'curl -s -o /dev/null -w "%{http_code}" https://registry.npmjs.org/'
            ' || echo "no-curl"'
        )
        if "no-curl" not in result.stdout:
            assert result.stdout.strip() == "200"

    async def test_blocks_unauthorized_network(self, secured: SecuredSandbox) -> None:
        result = await secured.exec(
            "curl -s -o /dev/null -w '%{http_code}' --connect-timeout 5"
            " https://evil.example.com 2>&1"
        )
        assert result.stdout.strip() != "200"

    async def test_filters_sensitive_env_vars(self, secured: SecuredSandbox) -> None:
        result = await secured.exec('bash -c "echo $SECRET_KEY"')
        assert result.stdout.strip() == ""
