"""Version matrix and hot-swap gating."""

from httpx import ASGITransport, AsyncClient

from app.config import Settings
from app.main import create_app
from app.vsphere.contracts.matrix import (
    VERSIONS,
    available_for_request,
    catalog_entries_for_major,
    methods_for_major,
)
from tests.unit.test_health import FakeDatabase


def test_major_6_smaller_than_major_9() -> None:
    assert len(methods_for_major(6)) < len(methods_for_major(9))
    assert len(methods_for_major(7)) <= len(methods_for_major(8))
    assert len(methods_for_major(8)) <= len(methods_for_major(9))


def test_runtime_serves_all_registered_regardless_of_major() -> None:
    """Catalog floors remain for browse; runtime never 501s known paths."""

    assert available_for_request("POST", "/api/cis/tagging/category", 6) is True
    assert available_for_request("GET", "/api/content/library", 6) is True
    assert available_for_request("POST", "/api/appliance/networking/dns/hostname", 6) is True


def test_catalog_floor_still_shrinks_browse_list() -> None:
    from app.vsphere.contracts.matrix import methods_for_major

    assert ("POST", "/api/cis/tagging/category") not in methods_for_major(6)
    assert ("POST", "/api/cis/tagging/category") in methods_for_major(7)
    assert ("GET", "/api/content/library") not in methods_for_major(7)
    assert ("GET", "/api/content/library") in methods_for_major(8)


def test_literal_path_beats_param_template() -> None:
    """`/api/content/library/item` must not resolve as `/{library_id}`."""
    from app.vsphere.contracts.matrix import resolve_template

    assert resolve_template("GET", "/api/content/library/item") == "/api/content/library/item"
    assert available_for_request("GET", "/api/content/library/item", 8) is True


def test_catalog_entries_match_version() -> None:
    for major in VERSIONS:
        entries = catalog_entries_for_major(major)
        assert all(e["status"] in {"implemented", "stub"} for e in entries)
        assert len(entries) == len(methods_for_major(major))


async def test_hot_swap_does_not_501_registered_paths() -> None:
    app = create_app(
        settings=Settings(enable_pve_stub=False),
        database_factory=lambda _settings: FakeDatabase(True),
        worker_factories=(),
    )
    async with app.router.lifespan_context(app):
        async with AsyncClient(transport=ASGITransport(app=app), base_url="http://test") as client:
            apply = await client.post("/ui/api/contract/apply", params={"major": 6})
            assert apply.status_code == 200
            assert apply.json()["runtime_version"] == "7.0.0"
            # Session required for library — but must not be version-gated 501.
            library = await client.get("/api/content/library")
            assert library.status_code != 501
            restore = await client.post("/ui/api/contract/apply", params={"major": 9})
            assert restore.status_code == 200
