"""Shared pytest fixtures for mgf-vm-libvirt.

Per TESTING.md:
  * tier 1 (unit) — pure functions only; XML rendering, error
    translation. No libvirt connection.
  * tier 2 (integration) — against a real libvirtd in a privileged
    container. Opt in with ``-m integration``. Fixtures live in
    ``tests/integration/conftest.py``.

The conformance suite runs at tier 2 against the same containerized
libvirtd, importing ``mgf.vm.core.conformance``.

Tier-1 helpers below let the unit suite mock ``libvirt.libvirtError``
(an integer error code + ``get_error_code()``) and a ``virConnect``
double without the real binding installed.
"""

from __future__ import annotations

from typing import Any

import pytest


class FakeLibvirtError(Exception):
    """Stand-in for ``libvirt.libvirtError`` for tier-1 tests.

    The real binding exposes ``get_error_code() -> int``; that is the
    only surface the translation seam reads, so this double implements
    exactly that. A ``code=None`` simulates an error with no code.
    """

    def __init__(self, code: int | None, message: str = "libvirt failure") -> None:
        super().__init__(message)
        self._code = code

    def get_error_code(self) -> int | None:
        return self._code


class FakeConn:
    """A minimal ``virConnect`` double that records ``close()`` calls."""

    def __init__(self, *, close_raises: BaseException | None = None) -> None:
        self.close_calls = 0
        self._close_raises = close_raises

    def close(self) -> int:
        self.close_calls += 1
        if self._close_raises is not None:
            raise self._close_raises
        return 0

    # A representative native call the wrapper might serialize.
    def listAllDomains(self) -> list[Any]:  # noqa: N802 - mirror libvirt naming
        return []


@pytest.fixture
def fake_conn() -> FakeConn:
    return FakeConn()
