#!/usr/bin/env python3
"""Inventory an EmuDeck/RetroArch-style emulation tree: per-system ROM counts +
sizes, a BIOS listing, and a full game list per system.

Designed to run ON the device (or against a mounted SD card) against local paths,
so it's re-runnable whenever the collection changes.

Usage:
  inventory.py --roms <roms_dir> --bios <bios_dir> --out <out_dir> [--device NAME]

Writes:
  <out>/inventory.md            summary table + BIOS section (scannable)
  <out>/lists/<system>.txt      full sorted filename list per system
  <out>/bios.txt                full BIOS file listing

Counting: everything under each system folder except metadata/db/gamelist files
and media/artwork subfolders. Uses os.walk (never `ls` — see [[env-ls-quotes-filenames]]).
"""
import os, sys, argparse, datetime

SKIP_NAMES = {"metadata.txt", "systeminfo.txt", "desktop.ini", "gamelist.xml"}
SKIP_EXTS = {".db", ".xml", ".cache"}
SKIP_DIRS = {"media", "images", "imgs", "downloaded_media", "boxart", "snaps",
             "videos", "manuals", "covers", ".media", "images_cache"}

def is_rom(name):
    if name.startswith("."):
        return False
    if name in SKIP_NAMES:
        return False
    ext = os.path.splitext(name)[1].lower()
    return ext not in SKIP_EXTS

def count_system(path):
    files, size = [], 0
    for dp, dns, fns in os.walk(path):
        dns[:] = [d for d in dns if d.lower() not in SKIP_DIRS]
        for f in fns:
            if is_rom(f):
                fp = os.path.join(dp, f)
                try:
                    size += os.path.getsize(fp)
                except OSError:
                    pass
                # store path relative to the system dir (handles subfolders)
                files.append(os.path.relpath(fp, path))
    return sorted(files), size

def human(n):
    for u in ("B", "KB", "MB", "GB", "TB"):
        if n < 1024:
            return f"{n:.0f} {u}" if u == "B" else f"{n:.1f} {u}"
        n /= 1024
    return f"{n:.1f} PB"

def main():
    ap = argparse.ArgumentParser()
    ap.add_argument("--roms", required=True)
    ap.add_argument("--bios", required=True)
    ap.add_argument("--out", required=True)
    ap.add_argument("--device", default="device")
    a = ap.parse_args()

    os.makedirs(os.path.join(a.out, "lists"), exist_ok=True)
    rows, total_files, total_size = [], 0, 0
    for sysname in sorted(os.listdir(a.roms)):
        sp = os.path.join(a.roms, sysname)
        if not os.path.isdir(sp):
            continue
        files, size = count_system(sp)
        if not files:
            continue
        rows.append((sysname, len(files), size))
        total_files += len(files); total_size += size
        with open(os.path.join(a.out, "lists", f"{sysname}.txt"), "w", encoding="utf-8") as fh:
            fh.write("\n".join(files) + "\n")

    # BIOS
    bios_files = []
    for dp, dns, fns in os.walk(a.bios):
        for f in fns:
            fp = os.path.join(dp, f)
            try:
                bios_files.append((os.path.relpath(fp, a.bios), os.path.getsize(fp)))
            except OSError:
                pass
    bios_files.sort()
    with open(os.path.join(a.out, "bios.txt"), "w", encoding="utf-8") as fh:
        for name, sz in bios_files:
            fh.write(f"{sz:>10d}  {name}\n")

    rows.sort(key=lambda r: -r[1])
    md = []
    md.append(f"# {a.device} — emulation inventory\n")
    md.append(f"_Generated {datetime.date.today().isoformat()} by inventory.py_\n")
    md.append(f"- ROMs dir: `{a.roms}`")
    md.append(f"- BIOS dir: `{a.bios}`")
    md.append(f"- **{len(rows)} systems, {total_files} ROMs, {human(total_size)} total**\n")
    md.append("Full game lists per system are in `lists/<system>.txt`; BIOS files in `bios.txt`.\n")
    md.append("| System | ROMs | Size |")
    md.append("|---|---:|---:|")
    for name, n, sz in rows:
        md.append(f"| {name} | {n} | {human(sz)} |")
    md.append(f"\n**BIOS folder:** {len(bios_files)} files, "
              f"{human(sum(s for _, s in bios_files))} (see `bios.txt`).")
    with open(os.path.join(a.out, "inventory.md"), "w", encoding="utf-8") as fh:
        fh.write("\n".join(md) + "\n")

    print(f"{len(rows)} systems, {total_files} ROMs, {human(total_size)} -> {a.out}/inventory.md")

if __name__ == "__main__":
    main()
