"""Programmatic libvirt domain XML generation using xml.etree.ElementTree (D-06).

No Jinja2 or string templates — all XML built via ET for testability.
"""

from __future__ import annotations

import xml.etree.ElementTree as ET

from vmcluster_mcp.cluster.libvirt_client import domain_name
from vmcluster_mcp.topology.schema import NodeSpec


def build_domain_xml(
    cluster_name: str,
    node: NodeSpec,
    overlay_path: str,
    cidata_iso_path: str,
    bridge_name: str,
    mac_address: str,
) -> str:
    """Build a KVM domain XML string for the given node.

    Args:
        cluster_name: Cluster identifier (used for domain naming).
        node: Node specification with vcpus, memory_mb, extra_disks.
        overlay_path: Absolute path to the node's qcow2 overlay disk.
        cidata_iso_path: Absolute path to the cloud-init NoCloud ISO.
        bridge_name: Name of the libvirt bridge device.
        mac_address: Deterministic MAC address for the primary interface.

    Returns:
        XML string suitable for conn.defineXML().
    """
    root = ET.Element("domain", type="kvm")

    ET.SubElement(root, "name").text = domain_name(cluster_name, node.name)
    ET.SubElement(root, "memory", unit="MiB").text = str(node.memory_mb)
    ET.SubElement(root, "vcpu").text = str(node.vcpus)

    os_el = ET.SubElement(root, "os")
    ET.SubElement(os_el, "type", arch="x86_64").text = "hvm"
    ET.SubElement(os_el, "boot", dev="hd")

    features = ET.SubElement(root, "features")
    ET.SubElement(features, "acpi")

    devices = ET.SubElement(root, "devices")
    ET.SubElement(devices, "emulator").text = "/usr/bin/qemu-system-x86_64"

    # Primary overlay disk (vda virtio)
    disk_main = ET.SubElement(devices, "disk", type="file", device="disk")
    ET.SubElement(disk_main, "driver", name="qemu", type="qcow2")
    ET.SubElement(disk_main, "source", file=overlay_path)
    ET.SubElement(disk_main, "target", dev="vda", bus="virtio")

    # Cloud-init NoCloud ISO (sda sata, read-only)
    disk_cdrom = ET.SubElement(devices, "disk", type="file", device="cdrom")
    ET.SubElement(disk_cdrom, "driver", name="qemu", type="raw")
    ET.SubElement(disk_cdrom, "source", file=cidata_iso_path)
    ET.SubElement(disk_cdrom, "target", dev="sda", bus="sata")
    ET.SubElement(disk_cdrom, "readonly")

    # Extra disks from NodeSpec (vdb, vdc, ...)
    for i, extra in enumerate(node.extra_disks):
        dev_name = f"vd{chr(ord('b') + i)}"
        disk_extra = ET.SubElement(devices, "disk", type="file", device="disk")
        ET.SubElement(disk_extra, "driver", name="qemu", type="qcow2")
        ET.SubElement(disk_extra, "source", file=extra.path)
        ET.SubElement(disk_extra, "target", dev=dev_name, bus=extra.bus)

    # Primary network interface on cluster bridge
    iface = ET.SubElement(devices, "interface", type="bridge")
    ET.SubElement(iface, "source", bridge=bridge_name)
    ET.SubElement(iface, "mac", address=mac_address)
    ET.SubElement(iface, "model", type="virtio")

    # Serial console for debugging / cloud-init output
    serial = ET.SubElement(devices, "serial", type="pty")
    ET.SubElement(serial, "target", port="0")

    console = ET.SubElement(devices, "console", type="pty")
    ET.SubElement(console, "target", type="serial", port="0")

    return ET.tostring(root, encoding="unicode")
