"""Native vSphere console catalog tests."""

from app.vsphere.contracts.catalog import (
    _param_index,
    list_vsphere_majors,
    vsphere_catalog_payload,
    vsphere_method_payload,
)
from app.vsphere.rest.coverage import catalog_entries, is_implemented


def test_list_vsphere_majors() -> None:
    payload = list_vsphere_majors(runtime_version="8.0.2")
    series = {item["series"] for item in payload["majors"]}
    assert series == {
        "vSphere 7.0",
        "vSphere 7.0 U3",
        "vSphere 8.0",
        "vSphere 8.0 U2",
    }
    assert payload["plane"] == "vsphere-rest"


def test_vsphere_catalog_marks_implemented_methods() -> None:
    payload = vsphere_catalog_payload(9)
    assert payload["source_version"] == "8.0.2"
    assert payload["method_count"] == len(catalog_entries())
    assert is_implemented("GET", "/api/vcenter/vm")
    assert is_implemented("POST", "/api/cis/tagging/category")
    assert vsphere_catalog_payload(6)["method_count"] < payload["method_count"]
    # Methods for the same path must be merged (GET+POST+DELETE on one path entry).
    vm_paths = [
        p for cat in payload["categories"] for p in cat["paths"] if p["path"] == "/api/vcenter/vm"
    ]
    assert len(vm_paths) == 1
    assert {m["verb"] for m in vm_paths[0]["methods"]} >= {"GET", "POST"}


def test_vsphere_method_payload_extracts_path_fields() -> None:
    payload = vsphere_method_payload(
        major=9,
        path="/api/vcenter/vm/{vm}",
        verb="GET",
        runtime_version="8.0.2",
    )
    assert payload["implemented"] is True
    assert len(payload["path_fields"]) == 1
    assert payload["path_fields"][0]["name"] == "vm"
    assert payload["resolved_path"] == "/api/vcenter/vm/vm-101"


def test_param_index_loaded_from_openapi() -> None:
    _param_index.cache_clear()
    methods = _param_index()
    assert "GET /api/vcenter/vm" in methods
    assert "POST /api/vcenter/vm" in methods
    assert len(methods) > 500


def test_vsphere_method_payload_uses_openapi_query_filters() -> None:
    payload = vsphere_method_payload(
        major=9,
        path="/api/vcenter/vm",
        verb="GET",
        runtime_version="8.0.2",
    )
    assert payload["param_source"] == "openapi"
    query_names = {field["name"] for field in payload["query_fields"]}
    assert query_names >= {
        "vms",
        "names",
        "folders",
        "datacenters",
        "hosts",
        "clusters",
        "resource_pools",
        "power_states",
    }
    # GET has no JSON body in the real Automation API.
    assert payload["body_example"] == {}


def test_vsphere_method_payload_uses_openapi_create_spec() -> None:
    payload = vsphere_method_payload(
        major=9,
        path="/api/vcenter/vm",
        verb="POST",
        runtime_version="8.0.2",
    )
    assert payload["param_source"] == "openapi"
    assert payload["body_example"]["guest_os"] == "OTHER_GUEST_64"
    assert payload["body_example"]["name"] == "web-01"
    assert isinstance(payload["body_example"]["placement"], dict)
    assert payload["body_example"]["placement"]["host"] == "host-11"
    assert payload["body_example"]["cpu"]["count"] == 2
    assert payload["body_example"]["memory"]["size_mib"] == 2048
    body_names = {field["name"] for field in payload["body_fields"]}
    assert "guest_os" in body_names
    assert "name" in body_names
    assert "placement.host" in body_names
    assert "placement.folder" in body_names
    assert "cpu.count" in body_names
    assert "memory.size_mib" in body_names
    # Nested object keys themselves are not PARAM rows — only scalar leaves.
    assert "placement" not in body_names
    assert "cpu" not in body_names
    # Create must not inherit ?action=clone pollution.
    assert not any(field["name"] == "action" for field in payload["query_fields"])


def test_vsphere_method_payload_power_action_query() -> None:
    payload = vsphere_method_payload(
        major=9,
        path="/api/vcenter/vm/{vm}/power",
        verb="POST",
        runtime_version="8.0.2",
    )
    assert payload["param_source"] == "openapi"
    action = next(field for field in payload["query_fields"] if field["name"] == "action")
    assert action["optional"] is False
    assert set(action["enum"]) >= {"start", "stop", "reset", "suspend"}
    # Params drawer merges query into body_fields for editing.
    assert any(field["name"] == "action" for field in payload["body_fields"])
