"""The hosting/runtime projection boundary: RuntimeProjectionAdapter turns a
project's merged, hosting-neutral CapabilityRuntimeRequirements into concrete
per-provider wiring. Proves the seam described in CLAUDE.md's Core<->Cloud contract
section works end to end without any capability needing to know which provider is
selected -- see test_capability_import_boundaries.py for the complementary
import-direction guarantee.
"""
from __future__ import annotations

from uuid import uuid4

from src.domain.capabilities.runtime import (
    CapabilityRuntimeRequirements,
    RuntimeConfigRequirement,
    RuntimeRouteRequirement,
    merge_runtime_requirements,
)
from src.domain.hosting.factory import get_runtime_projection_adapter
from src.domain.hosting.runtime_projection import (
    LegacyPagesRuntimeProjection,
    StubRuntimeProjection,
    W4PSharedBFFRuntimeProjection,
)


def _merged_auth_and_forms():
    auth = CapabilityRuntimeRequirements(
        capability_key="auth",
        capability_version=2,
        routes=(
            RuntimeRouteRequirement(
                path_prefix="/api/auth", purpose="auth_session_and_signin_routes"
            ),
        ),
        config=(
            RuntimeConfigRequirement(key="P2HS_AUTH_PUBLIC_KEY", visibility="public"),
            RuntimeConfigRequirement(key="P2HS_CLOUD_SERVICE_TOKEN", visibility="trusted"),
        ),
    )
    forms = CapabilityRuntimeRequirements(
        capability_key="forms",
        capability_version=1,
        routes=(
            RuntimeRouteRequirement(path_prefix="/api/forms", purpose="form_submission_routes"),
        ),
    )
    result = merge_runtime_requirements([auth, forms])
    assert result.ok
    return result.merged


def test_w4p_projects_every_route_as_a_bff_proxy():
    merged = _merged_auth_and_forms()
    plan = W4PSharedBFFRuntimeProjection().plan(uuid4(), merged)

    assert plan.ok
    assert {r.path_prefix: r.strategy for r in plan.routes} == {
        "/api/auth": "bff_proxy",
        "/api/forms": "bff_proxy",
    }
    assert all(r.target == "bff_origin" for r in plan.routes)


def test_legacy_pages_projects_routes_onto_functions_directories():
    merged = _merged_auth_and_forms()
    plan = LegacyPagesRuntimeProjection().plan(uuid4(), merged)

    assert plan.ok
    projected = {r.path_prefix: r.target for r in plan.routes}
    assert projected == {
        "/api/auth": "functions/api/auth",
        "/api/forms": "functions/api/forms",
    }


def test_public_and_trusted_config_stay_separated_across_providers():
    merged = _merged_auth_and_forms()

    for adapter in (W4PSharedBFFRuntimeProjection(), LegacyPagesRuntimeProjection()):
        plan = adapter.plan(uuid4(), merged)
        assert "P2HS_AUTH_PUBLIC_KEY" in plan.public_config
        assert "P2HS_AUTH_PUBLIC_KEY" not in plan.trusted_config
        assert "P2HS_CLOUD_SERVICE_TOKEN" in plan.trusted_config
        assert "P2HS_CLOUD_SERVICE_TOKEN" not in plan.public_config


def test_stub_adapter_reports_every_route_unresolved_rather_than_guessing():
    merged = _merged_auth_and_forms()
    plan = StubRuntimeProjection().plan(uuid4(), merged)

    assert plan.ok is False
    assert set(plan.unresolved) == {"/api/auth", "/api/forms"}


def test_factory_selects_adapter_by_hosting_provider_setting():
    from types import SimpleNamespace

    assert isinstance(
        get_runtime_projection_adapter(SimpleNamespace(hosting_provider="cloudflare_w4p_static")),
        W4PSharedBFFRuntimeProjection,
    )
    assert isinstance(
        get_runtime_projection_adapter(SimpleNamespace(hosting_provider="cloudflare_pages")),
        LegacyPagesRuntimeProjection,
    )
    assert isinstance(
        get_runtime_projection_adapter(SimpleNamespace(hosting_provider="anything_else")),
        StubRuntimeProjection,
    )


def test_projection_adapter_never_needs_a_capability_object():
    """The adapter's inputs are project_id (an opaque identifier) and the merged,
    hosting-neutral requirements -- never an AuthV2Provisioner/FormsProvisioner
    instance, and nothing that names a capability's internal state."""
    import inspect

    method_names = ("plan", "project_routes", "project_public_config", "project_trusted_config")
    for method_name in method_names:
        method = getattr(W4PSharedBFFRuntimeProjection, method_name)
        params = list(inspect.signature(method).parameters)
        assert params == ["self", "project_id", "requirements"]
