"""Integration — real libvirt round-trip through the ASYNC SDK (B7).

Drives ``create → start → stop → delete`` against ``test:///default`` (the
libvirt in-tree test driver — no KVM, no root) via ``AsyncInProcessTransport`` +
``AsyncVmManagerClient``. Proves the async surface offloads the blocking libvirt
adapter to its thread pool and round-trips a *real* ``HypervisorBackend``.

Marked ``@pytest.mark.integration``; requires the ``[test-integration]`` extra
(``mgf-vm-libvirt`` + ``libvirt-python``). The libvirt import is guarded and the
whole module **skips gracefully** if the binding is missing or ``libvirt.open``
raises — a default ``uv run pytest`` (no extra, no daemon) stays green.
"""

from __future__ import annotations

import pytest

from mgf.vm.sdk.client import AsyncVmManagerClient
from mgf.vm.sdk.transport.async_inprocess import AsyncInProcessTransport

pytestmark = pytest.mark.integration

LibvirtHypervisorBackend = pytest.importorskip("mgf.vm.libvirt").LibvirtHypervisorBackend

_TEST_URI = "test:///default"


def _open_backend() -> object:
    """Open a backend against the test driver, or skip if libvirt is unavailable."""
    import libvirt

    try:
        libvirt.open(_TEST_URI).close()
    except libvirt.libvirtError as exc:  # pragma: no cover - env-dependent
        pytest.skip(f"libvirt unavailable ({_TEST_URI}): {exc}")
    return LibvirtHypervisorBackend(_TEST_URI)


async def test_real_libvirt_async_create_start_stop_delete() -> None:
    from mgf.vm.core.contracts import Vm, VmSpec, VmState
    from mgf.vm.core.exceptions import DomainNotFound

    backend = _open_backend()
    transport = AsyncInProcessTransport.from_adapters(backend)  # type: ignore[arg-type]
    async with AsyncVmManagerClient(transport) as client:
        spec = VmSpec(name="sdk-async-itest-vm", cpu=1, memory_bytes=128 * (1 << 20))
        vm = await client.create_vm(spec)
        assert isinstance(vm, Vm)
        assert vm.spec.name == "sdk-async-itest-vm"

        vm_id = vm.vm_id
        try:
            await client.start_vm(vm_id)
            assert (await client.get_vm(vm_id)).status.state is VmState.RUNNING

            await client.stop_vm(vm_id, force=True)
            assert (await client.get_vm(vm_id)).status.state is VmState.STOPPED
        finally:
            await client.delete_vm(vm_id)

        with pytest.raises(DomainNotFound):
            await client.get_vm(vm_id)
