"""Tests for :mod:`mgf.vm.core.security.isolation.checks.network` (MA-A2.1, Wave 1).

Six checks; each gets a passing fixture + a failing fixture. The
``analyze_static`` integration class from the original is NOT ported
(it parses/synthesises via defusedxml — DEFERRED to the adapter); the
per-check behaviour is asserted directly against an ``AnalysisContext``.
"""

from __future__ import annotations

from _isolation_xml import domain_with, parsed

from mgf.vm.core.security.isolation.checks.network import (
    net_no_dhcp,
    net_no_dns_forwarding,
    net_no_external_route,
    net_no_macvtap_bridge,
    net_no_passthrough_nic,
    net_quarantine_network_used,
)
from mgf.vm.core.security.isolation.context import (
    QUARANTINE_NETWORK_NAME,
    AnalysisContext,
)
from mgf.vm.core.security.isolation.types import FixKind, IsolationCategory


def _ctx(*body: str) -> AnalysisContext:
    return AnalysisContext(
        domain_xml=parsed(domain_with(*body)),
        vm_name="t",
    )


_QUARANTINE_IFACE = (
    f"<interface type='network'>"
    f"<source network='{QUARANTINE_NETWORK_NAME}'/>"
    f"<model type='virtio'/></interface>"
)
_DEFAULT_IFACE = (
    "<interface type='network'><source network='default'/><model type='virtio'/></interface>"
)
_MACVTAP_IFACE = (
    "<interface type='direct'><source dev='eth0' mode='bridge'/><model type='virtio'/></interface>"
)


class TestQuarantineNetworkUsed:
    def test_passes_when_quarantine_only(self) -> None:
        f = net_quarantine_network_used(_ctx(_QUARANTINE_IFACE))
        assert f.passing is True

    def test_fails_when_default_network_used(self) -> None:
        f = net_quarantine_network_used(_ctx(_DEFAULT_IFACE))
        assert f.passing is False
        assert f.category is IsolationCategory.BLOCKING
        assert f.fix_kind is FixKind.AUTO_FIX
        assert f.fix_executor == "network.swap_to_quarantine"

    def test_passes_when_no_interfaces(self) -> None:
        # An air-gap-style VM with no NICs declared.
        f = net_quarantine_network_used(_ctx())
        assert f.passing is True


class TestNoExternalRoute:
    def test_passes_for_quarantine_iface(self) -> None:
        f = net_no_external_route(_ctx(_QUARANTINE_IFACE))
        assert f.passing is True

    def test_fails_for_default_network(self) -> None:
        f = net_no_external_route(_ctx(_DEFAULT_IFACE))
        assert f.passing is False
        assert "default" in f.summary

    def test_passes_for_no_interfaces(self) -> None:
        f = net_no_external_route(_ctx())
        assert f.passing is True


class TestNoMacvtapBridge:
    def test_passes_when_no_macvtap(self) -> None:
        f = net_no_macvtap_bridge(_ctx(_QUARANTINE_IFACE))
        assert f.passing is True

    def test_fails_when_macvtap_present(self) -> None:
        f = net_no_macvtap_bridge(_ctx(_MACVTAP_IFACE))
        assert f.passing is False
        assert f.fix_executor == "strip.iface.macvtap"


class TestInterfaceSourceVariants:
    """Exercise the _network_interfaces source-extraction branches."""

    def test_bridge_iface_source_is_read(self) -> None:
        # type='bridge' reads the bridge name. It's not a 'network' NIC,
        # so there are no quarantine-eligible NICs but a non-network NIC
        # still exists, so the quarantine check fails (faithful to the
        # original: any declared NIC that isn't the quarantine network
        # is a leak path).
        body = "<interface type='bridge'><source bridge='br0'/></interface>"
        f = net_quarantine_network_used(_ctx(body))
        assert f.passing is False
        assert f.details["interfaces"] == [{"type": "bridge", "source": "br0"}]

    def test_iface_without_source_yields_none(self) -> None:
        body = "<interface type='user'><model type='virtio'/></interface>"
        f = net_quarantine_network_used(_ctx(body))
        assert f.details["interfaces"] == [{"type": "user", "source": None}]

    def test_unknown_iface_type_with_source_yields_none(self) -> None:
        body = "<interface type='vhostuser'><source path='/x'/></interface>"
        f = net_quarantine_network_used(_ctx(body))
        assert f.details["interfaces"] == [{"type": "vhostuser", "source": None}]


class TestNoPassthroughNic:
    def test_passes_when_no_hostdev(self) -> None:
        f = net_no_passthrough_nic(_ctx(_QUARANTINE_IFACE))
        assert f.passing is True

    def test_fails_for_pci_hostdev_with_net_alias(self) -> None:
        body = (
            "<hostdev mode='subsystem' type='pci'>"
            "<source><address bus='0x01' slot='0x00' function='0x0'/></source>"
            "<alias name='net0'/>"
            "</hostdev>"
        )
        f = net_no_passthrough_nic(_ctx(body))
        assert f.passing is False
        assert f.fix_executor == "strip.iface.passthrough"

    def test_ignores_non_pci_and_non_subsystem_hostdevs(self) -> None:
        # USB subsystem hostdev (wrong type) + a capabilities-mode
        # hostdev (wrong mode) are both skipped — neither is a PCI NIC.
        body = (
            "<hostdev mode='subsystem' type='usb'><alias name='net9'/></hostdev>"
            "<hostdev mode='capabilities' type='pci'><alias name='net8'/></hostdev>"
        )
        f = net_no_passthrough_nic(_ctx(body))
        assert f.passing is True

    def test_ignores_pci_hostdev_without_network_alias(self) -> None:
        body = "<hostdev mode='subsystem' type='pci'><alias name='hostdev0'/></hostdev>"
        f = net_no_passthrough_nic(_ctx(body))
        assert f.passing is True


class TestNoDhcp:
    def test_passes_for_quarantine_iface(self) -> None:
        f = net_no_dhcp(_ctx(_QUARANTINE_IFACE))
        assert f.passing is True
        assert f.category is IsolationCategory.ADVISORY

    def test_fails_for_default_network(self) -> None:
        f = net_no_dhcp(_ctx(_DEFAULT_IFACE))
        assert f.passing is False


class TestNoDnsForwarding:
    def test_passes_for_quarantine_iface(self) -> None:
        f = net_no_dns_forwarding(_ctx(_QUARANTINE_IFACE))
        assert f.passing is True

    def test_fails_for_default_network(self) -> None:
        f = net_no_dns_forwarding(_ctx(_DEFAULT_IFACE))
        assert f.passing is False
