"""
WiX ProductFiles.wxs Generator

Generiert automatisch eine WXS-Datei mit allen Dateien aus dist/DocuMentor.
Ersetzt die veraltete 'wix heat' Funktionalität für WiX v6.
"""

import uuid
from pathlib import Path
from xml.etree import ElementTree as ET


def generate_guid() -> str:
    """Generiert eine neue GUID."""
    return str(uuid.uuid4()).upper()


def sanitize_id(name: str) -> str:
    """
    Macht einen String WiX-konform für IDs.

    WiX erlaubt nur: A-Z, a-z, 0-9, _, .
    Darf nicht mit Zahl beginnen.
    """
    # Ersetze illegale Zeichen
    sanitized = name.replace("-", "_").replace(" ", "_").replace(".", "_")

    # Entferne alle anderen nicht erlaubten Zeichen
    allowed = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_"
    sanitized = "".join(c if c in allowed else "_" for c in sanitized)

    # Darf nicht mit Zahl beginnen
    if sanitized and sanitized[0].isdigit():
        sanitized = f"_{sanitized}"

    return sanitized


def create_wix_fragment(dist_dir: Path) -> ET.Element:
    """
    Erstellt ein WiX Fragment mit allen Dateien aus dem dist Verzeichnis.

    Args:
        dist_dir: Pfad zum dist/DocuMentor Verzeichnis

    Returns:
        ET.Element: Wix Root-Element mit Fragment
    """
    # Namespace (WiX v4+)
    ns = "http://wixtoolset.org/schemas/v4/wxs"
    ET.register_namespace("", ns)

    # Root Element
    wix = ET.Element(f"{{{ns}}}Wix")
    fragment = ET.SubElement(wix, f"{{{ns}}}Fragment")
    component_group = ET.SubElement(
        fragment, f"{{{ns}}}ComponentGroup", {"Id": "ProductComponents", "Directory": "INSTALLFOLDER"}
    )

    # Sammle alle Dateien
    all_files = sorted(dist_dir.rglob("*"))
    files_only = [f for f in all_files if f.is_file()]

    print(f"Gefunden: {len(files_only)} Dateien")

    # Gruppiere nach Verzeichnis
    dirs_dict: dict[Path, list[Path]] = {}
    for file in files_only:
        rel_dir = file.parent.relative_to(dist_dir)
        if rel_dir not in dirs_dict:
            dirs_dict[rel_dir] = []
        dirs_dict[rel_dir].append(file)

    # Erstelle Directory Fragments
    dir_fragment = ET.SubElement(wix, f"{{{ns}}}Fragment")

    # INSTALLFOLDER ist bereits in DocuMentor.wxs definiert
    directory_ref = ET.SubElement(dir_fragment, f"{{{ns}}}DirectoryRef", {"Id": "INSTALLFOLDER"})

    # Erstelle Verzeichnisstruktur
    created_dirs = {"INSTALLFOLDER": directory_ref}

    for rel_dir in sorted(dirs_dict.keys()):
        if rel_dir == Path("."):
            continue

        parts = rel_dir.parts
        parent_id = "INSTALLFOLDER"

        for i, part in enumerate(parts):
            current_path = Path(*parts[: i + 1])
            dir_id = f"Dir_{sanitize_id(current_path.as_posix().replace('/', '_'))}"

            if dir_id not in created_dirs:
                parent_elem = created_dirs[parent_id]
                new_dir = ET.SubElement(parent_elem, f"{{{ns}}}Directory", {"Id": dir_id, "Name": part})
                created_dirs[dir_id] = new_dir
                parent_id = dir_id
            else:
                parent_id = dir_id

    # Füge Komponenten hinzu
    component_counter = 0

    for rel_dir, files in sorted(dirs_dict.items()):
        if rel_dir == Path("."):
            dir_id = "INSTALLFOLDER"
        else:
            dir_id = f"Dir_{sanitize_id(rel_dir.as_posix().replace('/', '_'))}"

        # Erstelle eine Komponente pro Verzeichnis
        component_id = f"Component_{sanitize_id(dir_id)}"
        component_counter += 1

        component = ET.SubElement(
            component_group, f"{{{ns}}}Component", {"Id": component_id, "Directory": dir_id, "Guid": generate_guid()}
        )

        # Füge alle Dateien des Verzeichnisses hinzu
        for idx, file in enumerate(files):
            file_id = f"File_{sanitize_id(component_id)}_{idx}"
            # Absoluter Pfad für WiX
            source_path = str(file).replace("/", "\\")

            file_attribs = {"Id": file_id, "Source": source_path, "Name": file.name}

            # Erste Datei ist KeyPath
            if idx == 0:
                file_attribs["KeyPath"] = "yes"

            ET.SubElement(component, f"{{{ns}}}File", file_attribs)

    print(f"Erstellt: {component_counter} Komponenten")

    return wix


def format_xml(element: ET.Element, level: int = 0) -> None:
    """Formatiert XML mit Einrückungen (in-place)."""
    indent = "  "
    i = f"\n{indent * level}"

    if len(element):
        if not element.text or not element.text.strip():
            element.text = i + indent
        if not element.tail or not element.tail.strip():
            element.tail = i
        last_child = None
        for child in element:
            format_xml(child, level + 1)
            last_child = child
        if last_child is not None and (not last_child.tail or not last_child.tail.strip()):
            last_child.tail = i
    else:
        if level and (not element.tail or not element.tail.strip()):
            element.tail = i


def main():
    """Hauptfunktion."""
    dist_dir = Path("dist/DocuMentor")
    output_file = Path("ProductFiles.wxs")

    if not dist_dir.exists():
        print(f"FEHLER: {dist_dir} existiert nicht!")
        print("Führe zuerst 'uv run pyinstaller DocuMentor.spec' aus.")
        return

    print(f"Generiere ProductFiles.wxs aus {dist_dir}...")

    wix_root = create_wix_fragment(dist_dir)
    format_xml(wix_root)

    # Schreibe XML
    tree = ET.ElementTree(wix_root)
    tree.write(output_file, encoding="utf-8", xml_declaration=True)

    print(f"[OK] {output_file} erfolgreich erstellt!")
    print(f"\nNaechste Schritte:")
    print(f"1. wix build DocuMentor.wxs ProductFiles.wxs -o DocuMentor.msi")


if __name__ == "__main__":
    main()
