from __future__ import annotations

import json
from pathlib import Path
from uuid import uuid4

from src.domain.capabilities.runtime import (
    CapabilityRuntimeRequirements,
    RuntimePortRequirement,
    merge_runtime_requirements,
)
from src.domain.hosting.runtime_projection import (
    LegacyPagesRuntimeProjection,
    W4PSharedBFFRuntimeProjection,
)


AUTH_PORTS = {
    "auth.magic_link_request": ("POST", "/api/auth/magic-link/request", "public"),
    "auth.magic_link_consume": ("GET", "/api/auth/magic-link/consume", "public"),
    "auth.me": ("GET", "/api/auth/me", "session"),
    "auth.signout": ("POST", "/api/auth/signout", "session"),
    "auth.permissions_check": ("POST", "/api/auth/permissions/check", "session"),
}

FORMS_PORTS = {
    "forms.submit": ("POST", "/api/forms/:form_key/submissions", "public"),
    "forms.file_upload": ("POST", "/api/forms/:form_key/files", "public"),
}


def _auth_requirements():
    return CapabilityRuntimeRequirements(
        capability_key="auth",
        capability_version=2,
        ports=tuple(
            RuntimePortRequirement(
                port_id=port_id,
                capability="auth",
                capability_version=2,
                method=method,
                public_path=path,
                auth=auth,
            )
            for port_id, (method, path, auth) in AUTH_PORTS.items()
        ),
    )


def test_auth_logical_ports_are_in_the_canonical_catalog():
    catalog = json.loads(
        (Path(__file__).parents[1] / "src/integrations/contracts/platform-port-catalog.json")
        .read_text(encoding="utf-8")
    )
    ports = {item["port_id"]: item for item in catalog["ports"]}
    for port_id, (method, path, auth) in AUTH_PORTS.items():
        assert ports[port_id]["bff"] == {
            "method": method,
            "path": path,
            "files": ports[port_id]["bff"]["files"],
            "adapter": "generic",
            "auth": auth,
        }


def test_w4p_and_pages_project_the_same_logical_auth_ports():
    merged = merge_runtime_requirements([_auth_requirements()]).merged
    assert merged is not None
    expected = tuple(AUTH_PORTS)
    assert tuple(port.port_id for port in merged.ports) == expected
    assert W4PSharedBFFRuntimeProjection().plan(uuid4(), merged).ports == expected
    assert LegacyPagesRuntimeProjection().plan(uuid4(), merged).ports == expected


def test_forms_logical_ports_are_in_the_canonical_catalog_and_provider_parity():
    catalog = json.loads(
        (Path(__file__).parents[1] / "src/integrations/contracts/platform-port-catalog.json")
        .read_text(encoding="utf-8")
    )
    ports = {item["port_id"]: item for item in catalog["ports"]}
    requirement = CapabilityRuntimeRequirements(
        capability_key="forms",
        capability_version=1,
        ports=tuple(
            RuntimePortRequirement(
                port_id=port_id,
                capability="forms",
                capability_version=1,
                method=method,
                public_path=path,
                auth=auth,
            )
            for port_id, (method, path, auth) in FORMS_PORTS.items()
        ),
    )
    for port_id, (method, path, auth) in FORMS_PORTS.items():
        assert ports[port_id]["bff"]["method"] == method
        assert ports[port_id]["bff"]["path"] == path
        assert ports[port_id]["bff"]["auth"] == auth
    merged = merge_runtime_requirements([requirement]).merged
    assert merged is not None
    expected = tuple(FORMS_PORTS)
    assert W4PSharedBFFRuntimeProjection().plan(uuid4(), merged).ports == expected
    assert LegacyPagesRuntimeProjection().plan(uuid4(), merged).ports == expected


def test_unknown_logical_port_blocks_projection_even_when_prefix_is_valid():
    requirement = CapabilityRuntimeRequirements(
        capability_key="auth",
        capability_version=2,
        ports=(RuntimePortRequirement(
            port_id="auth.not_implemented",
            capability="auth",
            capability_version=2,
            method="GET",
            public_path="/api/auth/not-implemented",
            auth="public",
        ),),
    )
    merged = merge_runtime_requirements([requirement]).merged
    assert merged is not None
    plan = W4PSharedBFFRuntimeProjection().plan(uuid4(), merged)
    assert plan.ok is False
    assert plan.missing_ports == ("auth.not_implemented",)
    assert plan.unresolved == ("port:auth.not_implemented",)
