from types import SimpleNamespace
from uuid import uuid4

import pytest
from src.domain.edge_functions import cf_runtime


def test_compute_worker_name_is_safe_and_stable() -> None:
    project_id = uuid4()
    name = cf_runtime.compute_worker_name(project_id, "ledger-post-transaction")

    assert name == cf_runtime.compute_worker_name(project_id, "ledger-post-transaction")
    assert len(name) <= 63
    assert name.islower() or not name.isalpha()
    assert all(c.isalnum() or c == "-" for c in name)
    assert not name.startswith("-") and not name.endswith("-")


def test_compute_worker_name_differs_per_project_and_slug() -> None:
    a, b = uuid4(), uuid4()
    name_a = cf_runtime.compute_worker_name(a, "task-create")
    name_b = cf_runtime.compute_worker_name(b, "task-create")
    assert name_a != name_b
    assert name_a != cf_runtime.compute_worker_name(a, "task-list")


@pytest.mark.asyncio
async def test_deploy_function_script_rejects_non_js_runtime() -> None:
    with pytest.raises(cf_runtime.EdgeFunctionDeployError, match="Only 'js' is deployable"):
        await cf_runtime.deploy_function_script(
            project_id=uuid4(),
            workspace_id=uuid4(),
            slug="foo",
            runtime="ts",
            code="export default {}",
            gateway_base_url="https://gw.example.com",
            project_token="tok",
        )


@pytest.mark.asyncio
async def test_deploy_function_script_rejects_empty_code() -> None:
    with pytest.raises(cf_runtime.EdgeFunctionDeployError, match="no code"):
        await cf_runtime.deploy_function_script(
            project_id=uuid4(),
            workspace_id=uuid4(),
            slug="foo",
            runtime="js",
            code="   ",
            gateway_base_url="https://gw.example.com",
            project_token="tok",
        )


@pytest.mark.asyncio
async def test_deploy_function_script_uploads_expected_bindings(monkeypatch) -> None:
    settings = SimpleNamespace(
        cloudflare_api_token="cf-token",
        cloudflare_account_id="acct-123",
        cloudflare_functions_namespace="p2hs-cloud-functions",
        cloudflare_worker_compatibility_date="2026-01-01",
    )
    monkeypatch.setattr(cf_runtime, "get_settings", lambda: settings)

    captured = {}

    async def fake_request(method, path, *, files=None, expected=None):
        captured["method"] = method
        captured["path"] = path
        captured["files"] = files
        return {}

    monkeypatch.setattr(cf_runtime, "_cf_request", fake_request)

    project_id, workspace_id = uuid4(), uuid4()
    worker_name = await cf_runtime.deploy_function_script(
        project_id=project_id,
        workspace_id=workspace_id,
        slug="ledger-post-transaction",
        runtime="js",
        code="export default { fetch() {} };",
        gateway_base_url="https://gw.example.com",
        project_token="scoped-token",
    )

    assert worker_name == cf_runtime.compute_worker_name(project_id, "ledger-post-transaction")
    assert captured["method"] == "PUT"
    assert f"/scripts/{worker_name}" in captured["path"]
    assert "p2hs-cloud-functions" in captured["path"]

    metadata = captured["files"]["metadata"][1]
    assert '"PROJECT_ID"' in metadata
    assert str(project_id) in metadata
    assert '"secret_text"' in metadata
    assert "scoped-token" in metadata
    assert captured["files"]["worker.mjs"][1] == "export default { fetch() {} };"


@pytest.mark.asyncio
async def test_cf_request_raises_when_not_configured(monkeypatch) -> None:
    settings = SimpleNamespace(cloudflare_api_token="", cloudflare_account_id="")
    monkeypatch.setattr(cf_runtime, "get_settings", lambda: settings)

    with pytest.raises(cf_runtime.EdgeFunctionDeployError, match="not configured"):
        await cf_runtime._cf_request("GET", "/workers/scripts/foo")
