"""Artefakt-Schicht: Scan-Fragmente je Quelldatei zusammensetzen und als
`.planer/`-Dateien ins Ziel-Repo schreiben. Merge arbeitet auf den ROHEN
Markdown-Blöcken (kein Grammatik-Roundtrip — nichts geht verloren).
"""
import re
from pathlib import Path

_ERGAENZE_RE = re.compile(r"^ergaenze-anker:\s*(\S+)\s+zu\s+(\S+)\s*$", re.M)


def datei_pfad(datei_rel: str) -> str:
    """Quelldatei → Pfad der Einheiten-Datei unter .planer/ (`/` → `__`).
    Bekannte v1-Schwäche: Quellnamen mit `__` können kollidieren."""
    return "einheiten/" + datei_rel.replace("/", "__") + ".md"


def _bloecke(text: str) -> dict[str, str]:
    """Fragment → {einheiten_id: roher_block}. Blöcke beginnen bei `## <id>`."""
    out: dict[str, str] = {}
    aktuelle_id = None
    zeilen: list[str] = []
    for zeile in text.splitlines():
        if zeile.startswith("## ") and ("::" in zeile or re.fullmatch(r"## \S+\.\w+", zeile.strip())):
            if aktuelle_id is not None:
                out[aktuelle_id] = "\n".join(zeilen).rstrip()
            aktuelle_id = zeile[3:].strip()
            zeilen = [zeile]
        elif aktuelle_id is not None and not _ERGAENZE_RE.match(zeile):
            zeilen.append(zeile)
    if aktuelle_id is not None:
        out[aktuelle_id] = "\n".join(zeilen).rstrip()
    return out


def merge_fragmente(fragmente: list[str]) -> str:
    """Fragmente EINER Quelldatei → Rumpf der Einheiten-Datei. Einheiten in Reihenfolge
    des ersten Auftretens, Dubletten (gleiche ID) fallen weg; `ergaenze-anker: X zu Y`
    aus Nachfass-Antworten wird als `anker: X` in den Block von Y eingefügt."""
    bloecke: dict[str, str] = {}
    ergaenzungen: list[tuple[str, str]] = []
    for frag in fragmente:
        ergaenzungen += _ERGAENZE_RE.findall(frag)
        for eid, block in _bloecke(frag).items():
            bloecke.setdefault(eid, block)
    for anker_id, ziel_id in ergaenzungen:
        block = bloecke.get(ziel_id)
        if block is None:
            continue  # Ziel existiert nicht — Gate hat das bereits als Fehler gemeldet
        kopf, _, rest = block.partition("\n")
        if f"anker: {anker_id}" not in block:
            bloecke[ziel_id] = f"{kopf}\nanker: {anker_id}\n{rest}"
    return "\n\n".join(bloecke.values())


def einheiten_datei(datei_rel: str, rumpf: str, stand: str) -> str:
    return f"# Einheiten: {datei_rel}\nstand: {stand}\n\n{rumpf}\n"


def lese_stand(text: str) -> str | None:
    m = re.search(r"^stand:\s*(\S+)", text, re.M)
    return m.group(1) if m else None


def alle_ids(text: str) -> set[str]:
    """Alle Einheiten-IDs + Zusatz-Anker einer Einheiten-Datei (für Referenz-Gates)."""
    ids = {m.group(1) for m in re.finditer(r"^## (\S+)$", text, re.M)}
    ids |= {m.group(1) for m in re.finditer(r"^anker:\s*(\S+)\s*$", text, re.M)}
    return ids


def schreibe_planer(ziel_repo: Path, dateien: dict[str, str]) -> list[Path]:
    """Schreibt {relativer_pfad_unter_.planer: inhalt} ins Ziel-Repo. → geschriebene Pfade."""
    geschrieben = []
    for rel, inhalt in sorted(dateien.items()):
        pfad = ziel_repo / ".planer" / rel
        pfad.parent.mkdir(parents=True, exist_ok=True)
        pfad.write_text(inhalt, encoding="utf-8")
        geschrieben.append(pfad)
    return geschrieben


def pruefung_geruest(wurzel: Path, projekt: str) -> str:
    """pruefung.md-Gerüst mit einfacher Erkennung (Makefile-Targets, pytest).
    Fehlt etwas, steht dort explizit '(keins vorhanden)' — Gates degradieren sichtbar."""
    tests = lint = start = "(keins vorhanden)"
    makefile = wurzel / "Makefile"
    if makefile.is_file():
        targets = set(re.findall(r"^([\w-]+):", makefile.read_text(encoding="utf-8"), re.M))
        if "test" in targets:
            tests = "make test"
        if "lint" in targets:
            lint = "make lint"
        for kandidat in ("dev", "run", "start"):
            if kandidat in targets:
                start = f"make {kandidat}"
                break
    elif list(wurzel.rglob("pytest.ini")) or list(wurzel.rglob("conftest.py")):
        tests = "pytest"
    return (f"# Prüfung: {projekt}\n"
            f"tests: {tests}\nlint: {lint}\nstart: {start}\n"
            f"hinweise:\n- (vom Scan erzeugtes Gerüst — bitte prüfen und ergänzen)\n")
