"""check-audit-bundle-filled.py — verifiziert deterministisch, ob ein Audit-
Präsentations-Bundle tatsächlich mit Audit-Daten befüllt ist oder noch die
generischen Template-Defaults aus `Praesentation Template.html` trägt.

Hintergrund: `neue-praesentation.py` kopiert das Master-Template ungefiltert.
Wenn der Modus-Audit-Flow danach das Bundle NICHT mit Manifest-Daten befüllt,
liegt eine fingierte Financial-Navigator-Pitch-Präsentation im Audit-Ordner —
genau das ist in Session 33 (brayht.com_2026-05-15_v4) passiert. Dieser
Helper macht den Bug strukturell sichtbar: er sucht in den JSX-Quellen nach
einer Liste typischer Template-Default-Marker-Strings. Treffer = Bundle ist
noch leer.

Aufruf:
    python check-audit-bundle-filled.py "<pfad/zum/bundle-zielordner>"

Erwartete Struktur: `<bundle>/_runtime/src/{slides-a.jsx, slides-b.jsx, app.jsx}`.

Exit-Codes:
    0 — Bundle ist befüllt (kein Template-Default-Marker gefunden) und das
        erzeugte app.jsx trägt alle Mount-Bausteine.
    7 — Bundle ist noch leer (mindestens ein Marker-String gefunden) oder
        app.jsx trägt keinen Audit-Marker. Stdout listet pro Marker die
        Treffer-Datei und Treffer-Zahl.
    8 — v2.4-70-Renderability-Wand: Bundle ist befüllt, aber app.jsx fehlen
        ein oder mehrere Mount-Bausteine (function App, function DeckPortal,
        function OverviewModal, ReactDOM.createRoot, const TEMPLATES =
        window.TEMPLATES). Browser würde weiße Seite zeigen.
    1 — Bundle-Struktur unvollständig (keine JSX-Quellen gefunden).
    2 — Argument-Fehler.

Verwendung als Pflicht-Gate im Modus-Audit-Flow:

    python "<BUNDLE_ROOT>/.skills/neue-praesentation/scripts/check_audit_bundle_filled.py" \
      "<audit_dir>/Praesentation"
    if [ $? -ne 0 ]; then echo "Bundle nicht befüllt — Modus-Audit unvollständig"; exit 7; fi

So lässt sich der Drift „Template kopiert, aber kein Befüllen passiert"
nicht mehr stillschweigend in einen Audit-Ordner schmuggeln.
"""

# --- Bundle-Pflicht-Sätze §1 (Wave I v0.17.0, Phase A) ---
# Pfad-Resolver-Standard (analog _cross_skill_evals/run_linkedin_wave_h_evals.py):
#   BUNDLE_ROOT = Path(__file__).resolve().parent.parent.parent.parent
#     # .skills/neue-praesentation/scripts/file.py -> Repo-Root
#   SKILL_ROOT = BUNDLE_ROOT / ".skills" / "neue-praesentation"
#   FOUNDATION = BUNDLE_ROOT / "_lib" / "designsystem" / "templates" / "praesentation"
# Echte Umlaute (ä ö ü ß) durchgehend, keine ae/oe/ue/ss-Substitutionen.


from __future__ import annotations

import argparse
import sys
from pathlib import Path


TEMPLATE_DEFAULT_MARKERS: tuple[str, ...] = (
    # Strings aus dem Master-Template (Financial-Navigator-Demo)
    "Kapitalmarktrauschen",
    "Independent Financial Navigator",
    "Vermögen entsteht selten durch Brillanz",
    "Familie M.",
    "Mareike Sander",
    "Jonas Pfaff",
    "Ines Voß",
    "Reaktiv vs. Navigiert",
    "Vier Schichten",
    "Hafen Hamburg",
    "Wer den Hafen kennt",
    "Zehn Jahre an der Schnittstelle",
    "+49 40 555 09 84",
    "Dalbar",
    "Vier Prinzipien — Klarheit, Struktur, Transparenz, Konsequenz",
)


def find_jsx_sources(bundle_dir: Path) -> list[Path]:
    src_dir = bundle_dir / "_runtime" / "src"
    if not src_dir.is_dir():
        return []
    return [src_dir / name for name in ("app.jsx", "slides-a.jsx", "slides-b.jsx") if (src_dir / name).is_file()]


def scan_for_markers(paths: list[Path]) -> dict[str, list[tuple[str, int]]]:
    treffer: dict[str, list[tuple[str, int]]] = {}
    for marker in TEMPLATE_DEFAULT_MARKERS:
        for p in paths:
            text = p.read_text(encoding="utf-8", errors="replace")
            count = text.count(marker)
            if count > 0:
                treffer.setdefault(marker, []).append((p.name, count))
    return treffer


# v2.4-69: Audit-Marker-Negativ-Wand. fill_audit_slides.py schreibt in app.jsx
# IMMER `window.AUDIT_DATA = {...}` plus den Generator-Kommentar
# `audit-app.jsx — generated by fill_audit_slides.py`. Wenn das Bundle frei von
# Template-Default-Markern ist, aber app.jsx KEINEN dieser Audit-Marker trägt,
# wurde fill_audit_slides.py nie aufgerufen (Schritt 2 des Modus-Audit-Flows
# übersprungen). Ohne diese Wand bleibt der Marker-Gate-Exit-0 ambivalent:
# „leer" und „bereits umsortiert ohne Audit-Daten" sind nicht unterscheidbar.
# Heilung: Brille A Achse A3 + Brille C1 Multi-Reviewer Session 40.
AUDIT_MARKER_CANDIDATES: tuple[str, ...] = (
    "window.AUDIT_DATA",
    "audit-app.jsx — generated by fill_audit_slides.py",
)


def verify_audit_marker(paths: list[Path]) -> tuple[bool, str]:
    """Prüft, ob app.jsx mindestens einen der bekannten Audit-Marker enthält.

    Rückgabe: (gefunden, app_jsx_name_oder_fehlertext).
    """
    app_jsx = next((p for p in paths if p.name == "app.jsx"), None)
    if app_jsx is None:
        return False, "app.jsx nicht unter _runtime/src/ gefunden"
    text = app_jsx.read_text(encoding="utf-8", errors="replace")
    for marker in AUDIT_MARKER_CANDIDATES:
        if marker in text:
            return True, app_jsx.name
    return False, app_jsx.name


# v2.4-70: Renderability-Wand. fill_audit_slides.py::_build_app_jsx muss in
# das erzeugte app.jsx die Mount-Bausteine aus dem Master-Footer-Block
# einsetzen — sonst rendert React nichts und der Browser zeigt eine weiße
# Seite (Live-Test blnkr.de am 2026-05-17 / Spec v2.4-70 K-1). Diese fünf
# Marker müssen byte-gleich im erzeugten app.jsx auftauchen.
MOUNT_MARKERS: tuple[str, ...] = (
    "function App",
    "function DeckPortal",
    "function OverviewModal",
    "ReactDOM.createRoot",
    "const TEMPLATES = window.TEMPLATES",
)


def verify_mount_markers(paths: list[Path]) -> int:
    """v2.4-70: prüft, dass das erzeugte app.jsx alle fünf Mount-Bausteine
    enthält. Verhindert die weiße-Seite-Klasse von Bugs aus v2.4-69.

    Rückgabe: Exit-Code (0 = alle Marker vorhanden, 8 = Marker fehlen,
    1 = app.jsx nicht gefunden — Aufrufer entscheidet, wie er 1 propagiert).
    """
    app_jsx = next((p for p in paths if p.name == "app.jsx"), None)
    if app_jsx is None:
        print("FEHLER: app.jsx nicht unter _runtime/src/ gefunden — Mount-Marker-Wand kann nicht greifen.", file=sys.stderr)
        return 1
    text = app_jsx.read_text(encoding="utf-8", errors="replace")
    fehlend = [m for m in MOUNT_MARKERS if m not in text]
    if fehlend:
        print(
            "FEHLER: Mount-Bausteine fehlen im erzeugten app.jsx (Browser würde weiße Seite zeigen):",
            file=sys.stderr,
        )
        for m in fehlend:
            print(f"  - {m!r}", file=sys.stderr)
        print(
            f"\nGeprüft: {app_jsx.name}. Erwartete Marker stammen aus Master-Footer-Block "
            f"(_lib/designsystem/templates/praesentation/src/app.jsx Z 39–218).\n"
            f"Heilung: fill_audit_slides.py::_build_app_jsx muss _MASTER_FOOTER_BLOCK plus "
            f"`const TEMPLATES = window.TEMPLATES;` ans Ende des f-Strings setzen (Spec v2.4-70 K-1).",
            file=sys.stderr,
        )
        return 8
    return 0


def main() -> int:
    parser = argparse.ArgumentParser(description="Prüft, ob ein Audit-Präsentations-Bundle befüllt ist.")
    parser.add_argument("bundle_dir", help="Pfad zum Bundle-Zielordner (enthält _runtime/src/)")
    args = parser.parse_args()

    bundle_dir = Path(args.bundle_dir).resolve()
    if not bundle_dir.is_dir():
        print(f"FEHLER: Bundle-Ordner nicht gefunden: {bundle_dir}", file=sys.stderr)
        return 1

    sources = find_jsx_sources(bundle_dir)
    if not sources:
        print(f"FEHLER: keine JSX-Quellen unter {bundle_dir}/_runtime/src/", file=sys.stderr)
        return 1

    treffer = scan_for_markers(sources)

    if not treffer:
        # Default-Marker frei — aber zweite Wand: app.jsx muss Audit-Marker tragen.
        marker_ok, marker_target = verify_audit_marker(sources)
        if not marker_ok:
            print(
                "FEHLER: Bundle frei von Template-Default-Markern, aber app.jsx trägt "
                f"keinen Audit-Marker. fill_audit_slides.py wurde vermutlich nie aufgerufen.\n"
                f"  - geprüft: {marker_target}\n"
                f"  - erwartet einer der Marker: {', '.join(repr(m) for m in AUDIT_MARKER_CANDIDATES)}",
                file=sys.stderr,
            )
            return 7
        # Dritte Wand (v2.4-70): app.jsx muss die Mount-Bausteine tragen, sonst
        # rendert React nichts und Browser zeigt weiße Seite (Spec v2.4-70 K-1).
        mount_exit = verify_mount_markers(sources)
        if mount_exit != 0:
            return mount_exit
        print(
            f"OK: Bundle befüllt — kein Template-Default-Marker in {len(sources)} JSX-Datei(en), "
            f"Audit-Marker in {marker_target}, Mount-Bausteine vollständig."
        )
        return 0

    print("FEHLER: Bundle enthält noch Template-Default-Marker (Audit-Befüllung fehlt):", file=sys.stderr)
    for marker, hits in treffer.items():
        hit_str = ", ".join(f"{name}:{count}" for name, count in hits)
        print(f"  - '{marker}' -> {hit_str}", file=sys.stderr)
    total = sum(c for hits in treffer.values() for _, c in hits)
    print(
        f"\nGesamtreffer: {total} in {len(sources)} JSX-Datei(en). Befüllung aus Audit-Manifest fehlt.",
        file=sys.stderr,
    )
    return 7


if __name__ == "__main__":
    sys.exit(main())
