"""Tests for :mod:`mgf.vm.core.security.isolation.checks.disk` (MA-A2.2)."""

from __future__ import annotations

from typing import TYPE_CHECKING

import pytest
from _isolation_xml import domain_with, parsed

from mgf.vm.core.security.isolation.checks.disk import (
    disk_cache_safe,
    disk_discard_off,
    disk_in_quarantine_pool,
    disk_no_shared_backing,
)
from mgf.vm.core.security.isolation.context import AnalysisContext
from mgf.vm.core.security.isolation.types import (
    FixKind,
    IsolationCategory,
)

if TYPE_CHECKING:
    from pathlib import Path


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


def _disk(source_file: str, *, cache: str = "none", discard: str = "ignore") -> str:
    return (
        f"<disk type='file' device='disk'>"
        f"<driver name='qemu' type='qcow2' cache='{cache}' discard='{discard}'/>"
        f"<source file='{source_file}'/>"
        f"<target dev='vda' bus='virtio'/>"
        f"</disk>"
    )


@pytest.fixture
def quarantine_home(monkeypatch: pytest.MonkeyPatch, tmp_path: Path) -> Path:
    """Anchor a fake $HOME so the quarantine pool path is under tmp_path."""
    home = tmp_path / "home"
    home.mkdir()
    pool = home / ".local/share/vmanager/quarantine"
    pool.mkdir(parents=True)
    monkeypatch.setenv("HOME", str(home))
    return pool


class TestDiskInQuarantinePool:
    def test_passes_when_under_pool(
        self,
        quarantine_home: Path,
    ) -> None:
        path = quarantine_home / "demo.qcow2"
        path.touch()
        f = disk_in_quarantine_pool(_ctx(_disk(str(path))))
        assert f.passing is True

    def test_fails_when_outside_pool(self, quarantine_home: Path) -> None:
        del quarantine_home
        f = disk_in_quarantine_pool(_ctx(_disk("/var/lib/libvirt/images/x.qcow2")))
        assert f.passing is False
        assert f.category is IsolationCategory.BLOCKING
        assert f.fix_kind is FixKind.MANUAL  # disk move needs user judgement

    def test_passes_when_no_disks(self, quarantine_home: Path) -> None:
        del quarantine_home
        f = disk_in_quarantine_pool(_ctx())
        assert f.passing is True


class TestDiskNoSharedBacking:
    def test_passes_without_backing_chain(self, quarantine_home: Path) -> None:
        del quarantine_home
        f = disk_no_shared_backing(_ctx(_disk("/var/lib/libvirt/images/x.qcow2")))
        assert f.passing is True  # no backingStore element in fixture

    def test_fails_when_backing_outside_pool(
        self,
        quarantine_home: Path,
    ) -> None:
        del quarantine_home
        body = (
            "<disk type='file' device='disk'>"
            "<driver name='qemu' type='qcow2'/>"
            "<source file='/var/lib/libvirt/images/x.qcow2'>"
            "<backingStore type='file'>"
            "<source file='/srv/shared/base.qcow2'/>"
            "</backingStore>"
            "</source>"
            "<target dev='vda' bus='virtio'/>"
            "</disk>"
        )
        f = disk_no_shared_backing(_ctx(body))
        assert f.passing is False
        assert "shared" in f.summary or "outside" in f.summary


class TestDiskCacheSafe:
    def test_passes_when_cache_none(self) -> None:
        f = disk_cache_safe(_ctx(_disk("/x.qcow2", cache="none")))
        assert f.passing is True
        assert f.category is IsolationCategory.ADVISORY

    def test_fails_when_cache_writeback(self) -> None:
        f = disk_cache_safe(_ctx(_disk("/x.qcow2", cache="writeback")))
        assert f.passing is False
        assert f.fix_executor == "disk.set_cache_none"

    def test_fails_when_cache_default(self) -> None:
        # No cache attribute → libvirt default is not 'none'.
        body = (
            "<disk type='file' device='disk'>"
            "<driver name='qemu' type='qcow2'/>"
            "<source file='/x.qcow2'/>"
            "<target dev='vda' bus='virtio'/>"
            "</disk>"
        )
        f = disk_cache_safe(_ctx(body))
        assert f.passing is False


class TestDiskDiscardOff:
    def test_passes_when_discard_ignore(self) -> None:
        f = disk_discard_off(_ctx(_disk("/x.qcow2", discard="ignore")))
        assert f.passing is True

    def test_fails_when_discard_unmap(self) -> None:
        f = disk_discard_off(_ctx(_disk("/x.qcow2", discard="unmap")))
        assert f.passing is False
        assert f.fix_executor == "disk.set_discard_ignore"

    def test_passes_when_discard_absent(self) -> None:
        body = (
            "<disk type='file' device='disk'>"
            "<driver name='qemu' type='qcow2' cache='none'/>"
            "<source file='/x.qcow2'/>"
            "<target dev='vda' bus='virtio'/>"
            "</disk>"
        )
        f = disk_discard_off(_ctx(body))
        assert f.passing is True
