from __future__ import annotations

import pytest

from src.domain.codegen.client_surface import resolve_client_surface
from src.domain.codegen.preflight import CodegenPreflightError, validate_codegen_preflight


def _plan(*, auth: bool = False) -> dict:
    return {
        "composition": {
            "primitive_ids": ["booking.reserve", "booking.cancel", "booking.availability"],
            "app_block_ids": [],
            "feature_pack_ids": [],
            "cloud_capability_ids": [],
        },
        "runtime": {"authentication_required": auth},
    }


def _ports() -> dict:
    return {
        "ports": [
            {"port_id": "bookings.list_resources", "bff": {"path": "/api/bookings/resources"}},
            {"port_id": "bookings.upsert_resource", "bff": {"path": "/api/bookings/resources"}},
            {"port_id": "bookings.availability", "bff": {"path": "/api/bookings/resources/:resource_key/availability"}},
            {"port_id": "bookings.reserve", "bff": {"path": "/api/bookings/reserve"}},
            {"port_id": "bookings.get", "bff": {"path": "/api/bookings/:reservation_id"}},
            {"port_id": "bookings.cancel", "bff": {"path": "/api/bookings/:reservation_id/cancel"}},
            {"port_id": "auth.me", "bff": {"path": "/api/auth/me"}},
            {"port_id": "auth.signin", "bff": {"path": "/api/auth/signin"}},
        ],
        "runtime_contract": {
            "routes": {"admin_panel_path": "/admin", "customer_login_path": "/login"},
            "capabilities": {"auth": {"magic_link": False}},
            "requirements": {"persistence_required": False, "admin_must_read_persisted": False},
        },
    }


def test_booking_surface_resolves_to_canonical_exports():
    surface = resolve_client_surface(_ports(), ["booking.reserve", "booking.availability"])
    assert surface["booking.reserve"]["call"] == "p2hs.reserveBooking(...)"
    assert surface["booking.availability"]["call"] == "p2hs.getBookingAvailability(...)"


def test_preflight_rejects_missing_booking_port_before_provider():
    ports = _ports()
    ports["ports"] = [item for item in ports["ports"] if item["port_id"] != "bookings.reserve"]
    with pytest.raises(CodegenPreflightError, match="unavailable_client_operations"):
        validate_codegen_preflight(
            generation_plan=_plan(),
            resolved_context={"app_blocks": [], "feature_packs": []},
            port_context=ports,
            runtime_invariants={
                "admin_panel_path": "/admin",
                "customer_login_path": "/login",
                "auth_modes": [],
                "persistence_required": False,
                "admin_must_read_persisted": False,
            },
        )


def test_preflight_accepts_resolved_booking_surface():
    report = validate_codegen_preflight(
        generation_plan=_plan(),
        resolved_context={"app_blocks": [], "feature_packs": []},
        port_context=_ports(),
        runtime_invariants={
            "admin_panel_path": "/admin",
            "customer_login_path": "/login",
            "auth_modes": [],
            "persistence_required": False,
            "admin_must_read_persisted": False,
        },
    )
    assert report["name"] == "P2HS_CODEGEN_PREFLIGHT"
