# -*- coding: utf-8 -*-
"""Generate vocabulary pictures with the local Thinkera Image Studio (http://localhost:8879).

The studio only knows courses under F:/Solutions/Thinkera/Thinkera/<course>/ with a 01-Storyboards/_images/images_tool.py,
so this script creates a tiny stand-alone course «Yaseen-French2» (never touching the real ones), writes one prompt per
vocabulary word (words.W with img=True), starts a batch job, and later copies the finished PNGs into static/vocab/.

  python tools/gen_images.py prepare     # write course folder + prompts
  python tools/gen_images.py start       # start the batch job (returns job id)
  python tools/gen_images.py status      # job progress
  python tools/gen_images.py collect     # copy generated PNGs -> static/vocab/<key>.png (512px)
"""
import json, os, sys, time
import requests

ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.insert(0, ROOT)
from curriculum import words as WD

STUDIO = "http://localhost:8879"
COURSE = "Yaseen-French2"
COURSE_DIR = os.path.join("F:/Solutions/Thinkera/Thinkera", COURSE)
KEY = "VOCAB"
OUT = os.path.join(ROOT, "static", "vocab")
JOB_FILE = os.path.join(ROOT, "tools", "image_job.json")

TOOL = '''"""Minimal images_tool for the Yaseen-French2 vocabulary course (read by the Image Studio)."""
import json
from pathlib import Path
HERE = Path(__file__).resolve().parent
SB = HERE.parent
ASPECTS = {"16:9", "4:3", "1:1", "3:4"}
CAST = {}
def storyboards():
    return sorted(SB.glob("Unit-*/*.md"))
def lesson_folder(md):
    return md.stem
def file_names(sid, n):
    return [f"{sid}.png"] if n == 1 else [f"{sid}-{i:02d}.png" for i in range(1, n + 1)]
def load(md):
    p = HERE / f"{md.stem}.images.json"
    return json.loads(p.read_text(encoding="utf-8")) if p.exists() else None
def check(md, data):
    return []
def insert(md, data):
    pass
'''

STYLE = ("Children's picture-dictionary illustration for a French textbook for 8-year-olds: {desc}. "
         "A single clear subject centred on a plain soft cream background, flat vector cartoon style with rounded shapes, "
         "thick clean outlines and bright cheerful colours, friendly and simple. This image must be a cartoon illustration, "
         "not a photograph and not realistic. No text, no letters, no numbers anywhere.")


def prepare():
    os.makedirs(os.path.join(COURSE_DIR, "01-Storyboards", "_images"), exist_ok=True)
    os.makedirs(os.path.join(COURSE_DIR, "01-Storyboards", "Unit-Vocab"), exist_ok=True)
    os.makedirs(os.path.join(COURSE_DIR, "02-Production", "assets", "Unit-Vocab", KEY, "images", "generated"), exist_ok=True)
    with open(os.path.join(COURSE_DIR, "01-Storyboards", "_images", "images_tool.py"), "w", encoding="utf-8") as f:
        f.write(TOOL)
    data, md = {}, ["# Yaseen French 2 – vocabulary pictures", ""]
    for key, w in WD.W.items():
        if not w.get("img"):
            continue
        data[key] = {"images": [{"title": w["fr"], "use": "illustration", "aspect": "1:1", "cast": [],
                                 "prompt": STYLE.format(desc=w["desc"])}]}
        md.append(f"### {key} · {w['fr']}")
        md.append("")
    with open(os.path.join(COURSE_DIR, "01-Storyboards", "_images", f"{KEY}.images.json"), "w", encoding="utf-8") as f:
        json.dump(data, f, ensure_ascii=False, indent=1)
    with open(os.path.join(COURSE_DIR, "01-Storyboards", "Unit-Vocab", f"{KEY}.md"), "w", encoding="utf-8") as f:
        f.write("\n".join(md))
    print("prepared", len(data), "prompts in", COURSE_DIR)
    r = requests.get(f"{STUDIO}/api/lessons", params={"course": COURSE}, timeout=30)
    print(r.status_code, r.text[:300])


def start():
    r = requests.post(f"{STUDIO}/api/batch", json={"keys": [KEY], "course": COURSE, "overwrite": False}, timeout=60)
    print(r.status_code, r.text[:500])
    r.raise_for_status()
    with open(JOB_FILE, "w", encoding="utf-8") as f:
        f.write(r.text)


def status():
    jid = json.load(open(JOB_FILE, encoding="utf-8")).get("id") or json.load(open(JOB_FILE, encoding="utf-8")).get("jid")
    r = requests.get(f"{STUDIO}/api/jobs/{jid}", timeout=30)
    d = r.json()
    short = {k: v for k, v in d.items() if k not in ("log", "items", "results")}
    print(json.dumps(short, ensure_ascii=False)[:1500])
    for line in (d.get("log") or [])[-8:]:
        print("  ", line)


FORCE = "--force" in sys.argv


def collect():
    from PIL import Image
    src = os.path.join(COURSE_DIR, "02-Production", "assets", "Unit-Vocab", KEY, "images", "generated")
    os.makedirs(OUT, exist_ok=True)
    n = 0
    for key, w in WD.W.items():
        if not w.get("img"):
            continue
        p = os.path.join(src, f"{key}.png")
        dst = os.path.join(OUT, f"{key}.png")
        if os.path.exists(p) and (FORCE or not os.path.exists(dst) or os.path.getmtime(p) > os.path.getmtime(dst)):
            im = Image.open(p).convert("RGB")
            im.thumbnail((400, 400), Image.LANCZOS)
            # flat cartoons: a 128-colour palette keeps them sharp at a fraction of the size
            im.quantize(colors=128, method=Image.Quantize.MEDIANCUT, dither=Image.Dither.NONE).save(dst, "PNG", optimize=True)
            n += 1
    have = sum(1 for k, w in WD.W.items() if w.get("img") and os.path.exists(os.path.join(OUT, f"{k}.png")))
    want = sum(1 for w in WD.W.values() if w.get("img"))
    print(f"copied {n}; {have}/{want} pictures in static/vocab")


if __name__ == "__main__":
    {"prepare": prepare, "start": start, "status": status, "collect": collect}[sys.argv[1]]()
