"""git-Helfer (nackte CLI, keine Bibliothek): Anker-Stände und Diff fürs Re-Scannen."""
import subprocess
from pathlib import Path


def _git(wurzel: Path, *args: str) -> str:
    res = subprocess.run(["git", "-C", str(wurzel), *args],
                         capture_output=True, text=True, timeout=30)
    if res.returncode != 0:
        raise RuntimeError(f"git {' '.join(args)}: {res.stderr.strip() or res.stdout.strip()}")
    return res.stdout


def ist_repo(wurzel: Path) -> bool:
    try:
        _git(wurzel, "rev-parse", "--git-dir")
        return True
    except (RuntimeError, FileNotFoundError):
        return False


def head_hash(wurzel: Path) -> str:
    return _git(wurzel, "rev-parse", "--short=12", "HEAD").strip()


def working_tree_sauber(wurzel: Path) -> bool:
    """False bei uncommitteten Änderungen (inkl. untracked) — Scan/Board arbeiten nur
    auf sauberem Tree, sonst vermischen sich Stände. AUSNAHME `.planer/`: die eigenen
    Artefakte (z. B. aus einem Teillauf) dürfen den Folgelauf nicht blockieren."""
    for zeile in _git(wurzel, "status", "--porcelain").splitlines():
        pfad = zeile[3:].split(" -> ")[-1].strip().strip('"')
        if not pfad.startswith(".planer/"):
            return False
    return True


def geaenderte_dateien(wurzel: Path, alt: str, neu: str = "HEAD") -> tuple[set[str], set[str]]:
    """(geändert_oder_neu, gelöscht) zwischen `alt` und `neu`, `.planer/` ausgefiltert.
    Renames (R) = alt gelöscht + neu geändert (v1: kein Anker-Matching über Renames)."""
    geaendert: set[str] = set()
    geloescht: set[str] = set()
    for zeile in _git(wurzel, "diff", "--name-status", f"{alt}..{neu}").splitlines():
        teile = zeile.split("\t")
        status = teile[0]
        if status.startswith("R") and len(teile) == 3:
            geloescht.add(teile[1])
            geaendert.add(teile[2])
        elif status == "D":
            geloescht.add(teile[1])
        elif len(teile) >= 2:
            geaendert.add(teile[1])
    kein_planer = lambda s: not s.startswith(".planer/")  # noqa: E731
    return set(filter(kein_planer, geaendert)), set(filter(kein_planer, geloescht))
