"""Render every agent-produced barmodels.json for a level into PNGs and build
a DB-attach map.

Reads  P<LEVEL>/<folder>/barmodels.json  +  the sibling manifest.json
Writes _barmodel_<lvl>/<slug>-q<n>.png   (local, to be scp'd to prod
        storage/app/public/p<lvl>/solutions/)
Writes _barmodel_<lvl>_map.json          (list of {source, png, working})

Usage: python _barmodel_apply.py P6
"""
import json, glob, os, sys, re
from _barmodel import render

BASE = os.path.dirname(os.path.abspath(__file__))

def slugify(s):
    return re.sub(r'[^a-z0-9]+', '-', (s or '').lower()).strip('-')

def main(lvl):
    n = lvl[1:]  # "6"
    leveldir = os.path.join(BASE, lvl)
    outdir = os.path.join(BASE, "_barmodel_%s" % lvl.lower())
    os.makedirs(outdir, exist_ok=True)
    rows = []
    made = skipped_bad = papers = 0
    for bf in sorted(glob.glob(os.path.join(leveldir, "*", "barmodels.json"))):
        folder = os.path.dirname(bf)
        man = os.path.join(folder, "manifest.json")
        if not os.path.exists(man):
            continue
        try:
            B = json.load(open(bf, encoding="utf-8"))
            M = json.load(open(man, encoding="utf-8"))
        except Exception as e:
            print("skip", folder, e); continue
        papers += 1
        sp = (B.get("source_prefix") or (M.get("paper") or {}).get("source_prefix") or "")
        slug = slugify(sp)
        # n -> source string from the manifest (the DB key)
        nsource = {q.get("n"): q.get("source") for q in M.get("questions", [])}
        for mdl in B.get("models", []):
            qn = mdl.get("n")
            spec = mdl.get("spec")
            src = nsource.get(qn) or (sp + " Q" + str(qn))
            if not spec or not spec.get("bars"):
                skipped_bad += 1; continue
            png_rel = "p%s/solutions/%s-q%s.png" % (n, slug, qn)
            out_abs = os.path.join(outdir, "%s-q%s.png" % (slug, qn))
            try:
                render(spec, out_abs)
            except Exception as e:
                print("RENDER FAIL", src, e); skipped_bad += 1; continue
            rows.append({
                "source": src,
                "png": png_rel,
                "working": (mdl.get("working") or "").strip(),
                "answer": mdl.get("answer"),
                "answer_matches_key": mdl.get("answer_matches_key", True),
            })
            made += 1
    mapf = os.path.join(BASE, "_barmodel_%s_map.json" % lvl.lower())
    json.dump(rows, open(mapf, "w", encoding="utf-8"), ensure_ascii=False, indent=1)
    print("papers=%d rendered=%d skipped_bad=%d" % (papers, made, skipped_bad))
    print("pngs in", outdir)
    print("map   ->", mapf)
    flags = [r for r in rows if not r["answer_matches_key"]]
    if flags:
        print("ANSWER-KEY MISMATCHES (%d):" % len(flags))
        for r in flags[:30]:
            print("  ", r["source"], "->", r["answer"])

if __name__ == "__main__":
    main(sys.argv[1] if len(sys.argv) > 1 else "P6")
