"""Tests for :mod:`mgf.vm.core.configurator.shares` (pure planners)."""

from __future__ import annotations

import xml.etree.ElementTree as ET

import pytest

from mgf.vm.core.configurator import shares
from mgf.vm.core.exceptions import SpecValidationError


def _dom(existing_targets: tuple[str, ...] = ()) -> ET.Element:
    fs = "".join(
        f"<filesystem type='mount'>"
        f"<driver type='virtiofs'/>"
        f"<source dir='/srv/{t}'/>"
        f"<target dir='{t}'/>"
        f"</filesystem>"
        for t in existing_targets
    )
    return ET.fromstring(f"<domain><name>web</name><uuid>u</uuid><devices>{fs}</devices></domain>")


class TestPlanAdd:
    def test_happy_path(self) -> None:
        change = shares.plan_add(_dom(), source="/srv/data", target="data")
        assert "share added" in change.summary
        assert change.requires_shutdown is True
        assert "virtiofs" in change.new_xml

    def test_9p_driver_accepted(self) -> None:
        change = shares.plan_add(_dom(), source="/srv/data", target="data", driver="9p")
        assert "9p" in change.new_xml

    def test_readonly(self) -> None:
        change = shares.plan_add(_dom(), source="/srv/data", target="data", readonly=True)
        assert "<readonly" in change.new_xml

    def test_bad_driver(self) -> None:
        with pytest.raises(SpecValidationError):
            shares.plan_add(_dom(), source="/s", target="t", driver="smb")

    def test_missing_source(self) -> None:
        with pytest.raises(SpecValidationError):
            shares.plan_add(_dom(), source="", target="t")

    def test_duplicate_target_rejected(self) -> None:
        with pytest.raises(SpecValidationError, match="already exists"):
            shares.plan_add(_dom(("data",)), source="/srv/data2", target="data")


class TestPlanRemove:
    def test_happy_path(self) -> None:
        change = shares.plan_remove(_dom(("data",)), target="data")
        assert "share removed" in change.summary
        assert "target dir" not in change.new_xml

    def test_missing_target(self) -> None:
        with pytest.raises(SpecValidationError):
            shares.plan_remove(_dom(), target="nope")

    def test_no_devices_element(self) -> None:
        dom = ET.fromstring("<domain><name>web</name></domain>")
        with pytest.raises(SpecValidationError, match="no <devices>"):
            shares.plan_remove(dom, target="data")
