"""``configurator/metadata`` — domain title and description (pure planner).

Libvirt stores free-form metadata as ``<title>`` and ``<description>``
children directly under ``<domain>``. Changing either is always safe
against a running VM (it is a pure persistent-config edit), so the plan
never flags ``requires_shutdown``.

**Pure core.** :func:`plan` accepts an *already-parsed*
:class:`xml.etree.ElementTree.Element`; the ``apply()`` half stays in the
adapter (``mgf-vm``).
"""

from __future__ import annotations

from typing import TYPE_CHECKING

from mgf.vm.core.configurator.types import ConfigChange
from mgf.vm.core.configurator.xml_helpers import remove, serialize_domain_xml, set_text

if TYPE_CHECKING:
    import xml.etree.ElementTree as ET

SUBSYSTEM = "metadata"


def plan(
    domain: ET.Element,
    *,
    title: str | None = None,
    description: str | None = None,
) -> ConfigChange:
    """Produce a :class:`ConfigChange` for a title/description edit.

    ``domain`` is the parsed domain root element (injected by the
    adapter); it is mutated in place. Passing ``None`` for either field
    leaves it unchanged. Passing an empty string removes that element
    from the XML — the caller can "clear the title" by passing
    ``title=""``.
    """
    old_xml = serialize_domain_xml(domain)
    diffs: list[str] = []

    if title is not None:
        old_title = (domain.findtext("title") or "").strip()
        if title == "":
            if remove(domain, "title"):
                diffs.append(f"title {old_title!r} -> (cleared)")
        else:
            if old_title != title:
                diffs.append(f"title {old_title!r} -> {title!r}")
            set_text(domain, "title", title)

    if description is not None:
        old_desc = (domain.findtext("description") or "").strip()
        if description == "":
            if remove(domain, "description"):
                diffs.append("description (cleared)")
        else:
            if old_desc != description:
                diffs.append("description updated")
            set_text(domain, "description", description)

    summary = ", ".join(diffs) or "no change"
    return ConfigChange(
        subsystem=SUBSYSTEM,
        summary=summary,
        old_xml=old_xml,
        new_xml=serialize_domain_xml(domain),
        requires_shutdown=False,
    )


__all__ = ["SUBSYSTEM", "plan"]
