#!/usr/bin/env python3
"""Ensayo local de Homelabista: sólo datos ficticios, sin rutas de entrada."""
import hashlib
import json
import os
from pathlib import Path
import secrets
import shutil
import subprocess
import sys
import tempfile


def main():
    if len(sys.argv) != 1:
        print("No admite argumentos ni rutas de datos. Ejecuta: python3 ensayo.py", file=sys.stderr)
        return 2
    restic = shutil.which("restic")
    if not restic:
        print("Falta Restic. Instálalo siguiendo https://restic.readthedocs.io/en/stable/020_installation.html", file=sys.stderr)
        return 2
    # Cada ejecución usa un directorio NUEVO, privado. Nunca recibe tu repositorio.
    lab = Path(tempfile.mkdtemp(prefix="homelabista-restic-"))
    print(f"Laboratorio nuevo: {lab}", flush=True)
    print("Datos ficticios. No prueba tus copias ni una recuperación de aplicaciones.", flush=True)
    env = {k: v for k, v in os.environ.items() if not k.upper().startswith("RESTIC_")}
    env["GOMAXPROCS"] = "2"
    password = lab / "clave-solo-del-ensayo.txt"
    password.write_text(secrets.token_urlsafe(32) + "\n", encoding="utf-8")
    password.chmod(0o600)
    command = [restic, "--repo", str(lab / "repositorio"),
               "--password-file", str(password), "--no-cache"]
    source = lab / "datos"
    source.mkdir()
    files = {
        "nota.txt": b"Esto es un documento ficticio para ensayar una restauracion.\n",
        "carpeta con espacios/recuerdo.txt": "Ejemplo, no una foto familiar: café y montaña.\n".encode("utf-8"),
        "vacio.txt": b"",
    }
    hashes = {}
    for name, data in files.items():
        file = source / name
        file.parent.mkdir(parents=True, exist_ok=True)
        file.write_bytes(data)
        hashes[name] = hashlib.sha256(data).hexdigest()
    (lab / "sha256-esperados.json").write_text(json.dumps(hashes, indent=2), encoding="utf-8")

    def run(*args):
        print("\nRestic: " + " ".join(args), flush=True)
        # No shell, no servidor, no credenciales heredadas de Restic.
        result = subprocess.run(command + list(args), cwd=lab, env=env,
                                stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
                                text=True, timeout=180)
        with (lab / "restic.log").open("a", encoding="utf-8") as log:
            log.write(result.stdout)
        if result.returncode:
            raise RuntimeError(f"Restic terminó con código {result.returncode}; consulta restic.log")
        return result.stdout

    try:
        run("init")
        run("backup", "datos", "--host", "laboratorio-ficticio", "--tag", "ensayo-homelabista")
        # Simula la ausencia del origen RENOMBRÁNDOLO; no elimina ningún archivo.
        source.rename(lab / "original-apartado")
        run("restore", "latest", "--target", str(lab / "restaurado"))
        restored = lab / "restaurado" / "datos"
        observed_names = {str(p.relative_to(restored)) for p in restored.rglob("*") if p.is_file()}
        if observed_names != set(hashes):
            raise RuntimeError("La lista de archivos restaurados no coincide")
        results = []
        for name, expected in hashes.items():
            actual = hashlib.sha256((restored / name).read_bytes()).hexdigest()
            if actual != expected:
                raise RuntimeError(f"El contenido restaurado no coincide: {name}")
            results.append({"archivo": name, "sha256_esperado": expected,
                            "sha256_restaurado": actual, "identico": True})
        receipt = {"alcance": "tres archivos ficticios; repositorio y destino en el mismo equipo",
                   "resultado": "PASS", "archivos": results,
                   "no_demuestra": ["backup del lector", "copia fuera de casa", "recuperación de una aplicación"]}
        (lab / "resultado.json").write_text(json.dumps(receipt, ensure_ascii=False, indent=2), encoding="utf-8")
        print("\nPASS: 3 de 3 archivos restaurados con SHA-256 idéntico.")
        print(f"Revisa resultado.json, restic.log y las carpetas dentro de {lab}")
        print("Todo se conserva para inspección. El sistema puede limpiar su carpeta temporal.")
        print("No uses la clave de demostración ni este laboratorio para tus copias reales.")
        return 0
    except (OSError, RuntimeError, subprocess.TimeoutExpired) as error:
        print(f"\nNO VERIFICADO: {error}\nArchivos conservados en {lab}", file=sys.stderr)
        return 1


if __name__ == "__main__":
    raise SystemExit(main())
