"""
audit_batch_sheets: genera las hojas de contacto de un batch de `batch_poses_chars`.

Lee `manifest_all.json` del lote y escribe en su raíz:

  audit_1.jpg, audit_2.jpg, ...   bloques de 3 personajes (3 columnas = 3 niveles)
  contact_all.jpg                 todos los personajes en una sola tira vertical

Se usa para auditar a ojo sin abrir 36 PNGs. No toca las imágenes originales.

    python Engine/audit_batch_sheets.py --run "Output/pilots/Diferent poses/BATCH_X"
    python Engine/audit_batch_sheets.py --run "..." --per-sheet 4 --thumb 300
"""
import argparse
import json
import sys
from pathlib import Path

from PIL import Image, ImageDraw

sys.stdout.reconfigure(encoding="utf-8", errors="backslashreplace")

BASE_DIR = Path(__file__).resolve().parent.parent


def load_records(run_dir):
    path = run_dir / "manifest_all.json"
    if not path.exists():
        raise SystemExit(f"[!] falta {path}")
    recs = json.loads(path.read_text(encoding="utf-8"))
    if not recs:
        raise SystemExit(f"[!] {path} está vacío")
    return recs


def group_by_char(recs):
    bychar = {}
    for r in recs:
        bychar.setdefault(r["char_dir"], []).append(r)
    for ch in bychar:
        bychar[ch].sort(key=lambda x: x["nivel"])
    return bychar


def make_sheet(run_dir, chars, bychar, thumb_w, out_path):
    thumb_h = int(thumb_w * 1.4625)          # 832x1216 ≈ 1:1,4625
    rows = len(chars)
    cols = max(len(bychar[ch]) for ch in chars)
    sheet = Image.new("RGB", (cols * thumb_w, rows * (thumb_h + 18)), "white")
    draw = ImageDraw.Draw(sheet)
    for ri, ch in enumerate(chars):
        for ci, r in enumerate(bychar[ch]):
            img_path = run_dir / r["file"]
            if not img_path.exists():
                raise SystemExit(f"[!] falta la imagen {img_path}")
            im = Image.open(img_path)
            im.thumbnail((thumb_w, thumb_h))
            x, y = ci * thumb_w, ri * (thumb_h + 18)
            sheet.paste(im.convert("RGB"), (x, y))
            draw.text((x + 6, y + thumb_h + 3),
                      "%s | %s %s" % (ch[:28], r["nivel"], r["pose_id"]),
                      fill="black")
    sheet.save(out_path, quality=90)
    print(out_path, sheet.size)


def main():
    p = argparse.ArgumentParser(description="Hojas de contacto de un batch")
    p.add_argument("--run", required=True, help="carpeta del batch (BATCH_...)")
    p.add_argument("--per-sheet", type=int, default=3,
                   help="personajes por hoja de auditoría (default 3)")
    p.add_argument("--thumb", type=int, default=400,
                   help="ancho de miniatura en px (default 400)")
    p.add_argument("--no-contact", action="store_true",
                   help="no generar contact_all.jpg")
    args = p.parse_args()

    run_dir = Path(args.run)
    if not run_dir.is_absolute():
        run_dir = BASE_DIR / run_dir
    recs = load_records(run_dir)
    bychar = group_by_char(recs)
    chars = list(bychar)

    n = 0
    for i in range(0, len(chars), args.per_sheet):
        n += 1
        make_sheet(run_dir, chars[i:i + args.per_sheet], bychar,
                   args.thumb, run_dir / f"audit_{n}.jpg")

    if not args.no_contact:
        make_sheet(run_dir, chars, bychar, args.thumb, run_dir / "contact_all.jpg")

    print(f"[OK] {len(recs)} imágenes | {len(chars)} personajes | {n} hoja(s)")


if __name__ == "__main__":
    main()
