"""vSphere seed profile shape tests (no database)."""

from app.vsphere.profiles import (
    PROFILE_SIZES,
    big_vsphere_profile,
    build_vsphere_profile,
    infer_profile_hint,
    large_vsphere_profile,
    minimal_vsphere_profile,
    small_vsphere_profile,
)
from app.vsphere.security.authz import has_privilege, privileges_for_roles


def test_profile_sizes_table() -> None:
    assert PROFILE_SIZES["minimal"].vm_count == 5
    assert PROFILE_SIZES["small"].host_count == 3
    assert PROFILE_SIZES["small"].vm_count == 50
    assert PROFILE_SIZES["large"].host_count == 10
    assert PROFILE_SIZES["large"].vm_count == 1000
    assert PROFILE_SIZES["big"].host_count == 20
    assert PROFILE_SIZES["big"].vm_count == 2000


def test_minimal_profile() -> None:
    profile = minimal_vsphere_profile()
    assert profile.name == "minimal"
    assert profile.vm_count == 5
    assert profile.host_count == 3
    assert len([o for o in profile.objects if o.type == "Datastore"]) == 1
    assert len([o for o in profile.objects if o.type == "Network"]) == 1


def test_small_profile_has_named_vms_and_scale() -> None:
    profile = small_vsphere_profile()
    assert profile.vm_count == 50
    assert profile.host_count == 3
    assert profile.extras_scale == 1
    names = {obj.name for obj in profile.objects if obj.type == "VirtualMachine"}
    assert {"web-01", "app-01", "db-01"} <= names
    datastores = [obj for obj in profile.objects if obj.type == "Datastore"]
    assert len(datastores) == 2
    ds_ids = {d.moid for d in datastores}
    for vm in profile.objects:
        if vm.type != "VirtualMachine":
            continue
        assert vm.props.get("datastore") in ds_ids


def test_large_profile_1000_vms() -> None:
    profile = large_vsphere_profile(host_count=10, vm_count=1000)
    assert profile.vm_count == 1000
    assert profile.host_count == 10
    assert profile.extras_scale == 2
    vms = [obj for obj in profile.objects if obj.type == "VirtualMachine"]
    hosts = [obj for obj in profile.objects if obj.type == "HostSystem"]
    folders = [obj for obj in profile.objects if obj.type == "Folder"]
    assert len(vms) == 1000
    assert len(hosts) == 10
    assert len(folders) == 10  # 8 spine + 2 scaled
    assert any(obj.name == "web-01" for obj in vms)
    by_host: dict[str, int] = {}
    for vm in vms:
        host = str(vm.props.get("host"))
        by_host[host] = by_host.get(host, 0) + 1
    assert len(by_host) == 10
    assert min(by_host.values()) >= 90
    assert max(by_host.values()) <= 110


def test_big_profile_2000_vms() -> None:
    profile = big_vsphere_profile()
    assert profile.name == "big"
    assert profile.vm_count == 2000
    assert profile.host_count == 20
    assert profile.extras_scale == 4
    datastores = [obj for obj in profile.objects if obj.type == "Datastore"]
    networks = [
        obj
        for obj in profile.objects
        if obj.type in {"Network", "DistributedVirtualPortgroup"}
    ]
    folders = [obj for obj in profile.objects if obj.type == "Folder"]
    assert len(datastores) == 8
    assert len(networks) == 8
    assert len(folders) == 14  # 8 spine + 6 scaled
    ds_ids = {d.moid for d in datastores}
    for vm in profile.objects:
        if vm.type != "VirtualMachine":
            continue
        assert vm.props.get("datastore") in ds_ids


def test_demo_cluster_aliases_big() -> None:
    profile = build_vsphere_profile("demo-cluster")
    assert profile.name == "big"
    assert profile.vm_count == 2000
    assert profile.host_count == 20


def test_infer_profile_hint() -> None:
    assert infer_profile_hint(hosts=3, vms=5, datastores=1) == "minimal"
    assert infer_profile_hint(hosts=3, vms=50, datastores=2) == "small"
    assert infer_profile_hint(hosts=10, vms=1000, datastores=4) == "large"
    assert infer_profile_hint(hosts=20, vms=2000, datastores=8) == "big"


def test_lab_credentials_include_readonly() -> None:
    users = {c.username: c.roles for c in large_vsphere_profile().credentials}
    assert "readonly@vsphere.local" in users
    assert "ReadOnly" in users["readonly@vsphere.local"]
    assert "Administrator" in users["administrator@vsphere.local"]


def test_readonly_cannot_power() -> None:
    assert has_privilege(["ReadOnly"], "System.Read")
    assert not has_privilege(["ReadOnly"], "VirtualMachine.Interact.PowerOn")
    assert has_privilege(["VirtualMachinePowerUser"], "VirtualMachine.Interact.PowerOn")
    assert "*" not in privileges_for_roles(["Administrator"])
    assert "Authorization.ModifyPermissions" in privileges_for_roles(["Administrator"])
