"""
Voll-Zustands-Backup (mem0 + Hermes-Configs/Secrets + llama-swap config).
Delegiert an deploy/backup.sh (eine Quelle der Wahrheit, identisch zum systemd-Timer);
Restore läuft bewusst nur per CLI (deploy/restore.sh) — siehe docs/BACKUP.md.
"""

import subprocess
import tarfile
from pathlib import Path

from config import MODELS_DIR

BACKUP_DIR = Path(MODELS_DIR) / "mc2-backups"
SRC_ROOT = Path(__file__).resolve().parents[2]
BACKUP_SH = SRC_ROOT / "deploy" / "backup.sh"


def _ts(p: Path) -> str:
    """Zeitstempel aus 'mc2-state-<ts>.tar.gz' (Path.stem ließe '.tar' stehen)."""
    return p.name[len("mc2-state-"):-len(".tar.gz")]


def _latest() -> Path | None:
    if not BACKUP_DIR.exists():
        return None
    snaps = sorted(BACKUP_DIR.glob("mc2-state-*.tar.gz"), reverse=True)
    return snaps[0] if snaps else None


def snapshot_components(tarball: Path) -> list[str]:
    """Öffentliche Sicht auf die Snapshot-Komponenten (Zeitmaschine-Detail in der UI)."""
    return _components(tarball)


def _components(tarball: Path) -> list[str]:
    """Top-Level-Einträge im Tarball (zur Anzeige im UI)."""
    try:
        with tarfile.open(tarball, "r:gz") as t:
            top = {m.name.split("/")[1] for m in t.getmembers()
                   if m.name.startswith("./") and "/" in m.name[2:]}
            top |= {m.name[2:] for m in t.getmembers()
                    if m.name.startswith("./") and "/" not in m.name[2:] and m.isfile()}
        return sorted(x for x in top if x)
    except Exception:
        return []


def backup_now() -> dict:
    """Erstellt einen Voll-Zustands-Snapshot via deploy/backup.sh."""
    try:
        r = subprocess.run(["/bin/bash", str(BACKUP_SH)], capture_output=True, text=True, timeout=180)
        if r.returncode != 0:
            return {"ok": False, "snapshot": "", "files": [], "error": (r.stderr or r.stdout).strip()[-300:]}
    except Exception as exc:  # noqa: BLE001
        return {"ok": False, "snapshot": "", "files": [], "error": str(exc)}

    latest = _latest()
    if not latest:
        return {"ok": False, "snapshot": "", "files": [], "error": "Kein Backup erzeugt"}
    return {
        "ok": True,
        "snapshot": _ts(latest),
        "files": _components(latest),
        "size_mb": round(latest.stat().st_size / 1_000_000, 2),
    }


def list_backups() -> list[dict]:
    if not BACKUP_DIR.exists():
        return []
    out = []
    for p in sorted(BACKUP_DIR.glob("mc2-state-*.tar.gz"), reverse=True):
        out.append({
            "snapshot": _ts(p),
            "file": p.name,
            "size_mb": round(p.stat().st_size / 1_000_000, 2),
        })
    return out
