#!/usr/bin/env python3
import concurrent.futures, json, os, subprocess, sys, time, re, unicodedata
from pathlib import Path
PROJECT=Path('/data/video-pipeline/Youtube-Video-Maker/Project/02072026-002-Hot-Tat-Liet')
GEN_SCRIPT=Path('/home/hermes/.hermes/skills/media/gen-img-gpt/scripts/gen_img_gpt.py')
SCENES=PROJECT/'script/scenes.json'; PLAN=PROJECT/'script/character_reference_plan.json'
OUT_SCENES=PROJECT/'images/scenes'; OUT_THUMBS=PROJECT/'output/thumbnails'; LOG=PROJECT/'logs/step06_images_run.log'; MANIFEST=PROJECT/'logs/step06_images_manifest.json'
WORKERS=int(os.environ.get('STEP06_WORKERS','5'))
STYLE_SCENE='16:9 horizontal historical storytelling image, centered irregular ink-wash narrative window on warm antique cream paper, painted content occupies only about 65-70 percent of page with 30-35 percent clean antique paper negative space, handcrafted world-history manuscript feeling, muted brown black charcoal watercolor wash, not modern, not full-frame glossy digital poster, not fantasy splash art, no text, no watermark.'
STYLE_HEADING='16:9 horizontal old-world calligraphy title-card on warm antique paper, subtle ink wash, small red seal/stamp accent, airy text with breathing room, not heavy black title slam, not clean modern typography.'
NEG='Avoid modern objects, wrong culture, fantasy armor, samurai unless explicitly Japan context, Qing queue hairstyle, character sheet layout, model sheet, multiple views, floating costume parts, text labels, watermark, logo, glossy poster, edge-to-edge full-frame painting.'
def load_refs():
    refs={}
    if PLAN.exists():
        for r in json.loads(PLAN.read_text(encoding='utf-8')).get('references',[]): refs[r['character_id']]=Path(r['output_path'])
    return refs
def log(msg):
    line=time.strftime('%Y-%m-%d %H:%M:%S ')+msg; print(line,flush=True); LOG.parent.mkdir(parents=True,exist_ok=True)
    with LOG.open('a',encoding='utf-8') as f: f.write(line+'\n')
def scene_refs(text, refs):
    t=text.lower(); keys=[]
    mapping=[('hốt tất liệt','hot-tat-liet-kublai-khan'),('kublai','hot-tat-liet-kublai-khan'),('thành cát tư hãn','thanh-cat-tu-han'),('mông kha','mong-kha-dai-han'),('a lý bất ca','a-ly-bat-ca'),('phagpa','phagpa-va-tang-si-tay-tang'),('tây tạng','phagpa-va-tang-si-tay-tang'),('marco polo','marco-polo-va-thuong-nhan-phuong-tay')]
    for token,k in mapping:
        if token in t: keys.append(k)
    if any(x in t for x in ['mông cổ','đại hãn','thảo nguyên','kỵ binh','karakorum','vó ngựa','cung tên']): keys.append('quan-mong-co')
    if any(x in t for x in ['trung hoa','người hán','quan lại','nho giáo','đại đô','nhà nguyên','thuế','sổ thuế']): keys.append('quan-lai-va-hoc-gia-trung-hoa-thoi-nguyen')
    if any(x in t for x in ['nam tống','tương dương','phàn thành','lâm an','nhai sơn','lục tú phu']): keys.append('quan-nam-tong')
    if any(x in t for x in ['nhật bản','đại việt','chiêm thành','java','miến điện','bạch đằng','đông nam á','thần phong','kamikaze']): keys.append('doi-thu-bien-phuong-dong')
    out=[]
    for k in keys:
        p=refs.get(k)
        if p and p.exists() and p not in out: out.append(p)
    return out
def prompt_for(scene, refs):
    if scene.get('type')=='heading':
        return f"{STYLE_HEADING}\nVietnamese title card text to depict accurately if possible: {scene['narration']}\nSubtle motifs: Mongol steppe wind, horsehair banners, Yuan imperial seal, old Silk Road map, Dadu palace silhouette, antique paper. {NEG}"
    sr=scene_refs(scene.get('narration','')+' '+scene.get('summary',''), refs)
    ref_note='Use attached character reference image(s) only to keep identity, age, face, costume language, and temperament consistent. Do not reproduce a reference sheet. ' if sr else ''
    return f"{STYLE_SCENE}\nHistorical context: 13th century Mongol Empire and Yuan dynasty, Kublai Khan between Mongol steppe power and Chinese imperial administration, Song-Yuan war, Silk Road exchange, failed naval expeditions to Japan and Southeast Asia.\nNarration beat: {scene['narration']}\nVisual direction: {scene.get('visual_beat') or scene.get('visual_prompt')}\n{ref_note}One cinematic narrative scene, historically grounded Mongol, Yuan Chinese, Tibetan, Central Asian, Song, maritime or steppe setting as relevant.\nNegative exclusions: {NEG}"
def run_one(scene, refs):
    out=OUT_SCENES/f"{scene['scene_id']}.png"
    if out.exists() and out.stat().st_size>1000: return {'scene_id':scene['scene_id'],'status':'skipped_exists','output':str(out),'bytes':out.stat().st_size}
    cmd=[sys.executable,str(GEN_SCRIPT),'--prompt',prompt_for(scene, refs),'--output',str(out),'--size','auto','--quality','auto','--background','auto','--image-detail','high','--output-format','png','--n','1']
    for ref in scene_refs(scene.get('narration','')+' '+scene.get('summary',''), refs)[:2]: cmd += ['--input-ref',str(ref)]
    p=subprocess.run(cmd,text=True,capture_output=True,timeout=1200)
    if p.returncode!=0: return {'scene_id':scene['scene_id'],'status':'failed','output':str(out),'error':(p.stderr or p.stdout)[-2000:]}
    return {'scene_id':scene['scene_id'],'status':'ok','output':str(out),'bytes':out.stat().st_size if out.exists() else 0}
def thumb_prompt(kind):
    aspect='16:9 YouTube thumbnail, 1920x1080' if kind=='16x9' else 'TikTok-safe vertical thumbnail/poster, 1080x1280 preferred composition'
    return f"{aspect}. Cinematic world-history poster for 'HỐT TẤT LIỆT - ĐẠI HÃN GIỮA HAI THẾ GIỚI'. Large dramatic Kublai Khan seated between Mongol steppe horse banners and Yuan imperial palace at Dadu, Silk Road map glowing behind, storm clouds over Japan sea and Song war silhouettes, parchment texture, dark sepia bronze black palette, large readable metallic-gold Vietnamese brush lettering over irregular black ink-splash title panel. Historically grounded, not modern, not fantasy, no watermark."
def gen_thumb(kind,out,refs):
    if out.exists() and out.stat().st_size>1000: return {'kind':kind,'status':'skipped_exists','output':str(out),'bytes':out.stat().st_size}
    cmd=[sys.executable,str(GEN_SCRIPT),'--prompt',thumb_prompt(kind),'--output',str(out),'--size','auto','--quality','auto','--background','auto','--image-detail','high','--output-format','png','--n','1']
    p=refs.get('hot-tat-liet-kublai-khan')
    if p and p.exists(): cmd += ['--input-ref',str(p)]
    r=subprocess.run(cmd,text=True,capture_output=True,timeout=1200)
    if r.returncode!=0: return {'kind':kind,'status':'failed','output':str(out),'error':(r.stderr or r.stdout)[-2000:]}
    return {'kind':kind,'status':'ok','output':str(out),'bytes':out.stat().st_size if out.exists() else 0}
def main():
    OUT_SCENES.mkdir(parents=True,exist_ok=True); OUT_THUMBS.mkdir(parents=True,exist_ok=True); LOG.parent.mkdir(parents=True,exist_ok=True); LOG.write_text('',encoding='utf-8')
    refs=load_refs(); scenes=json.loads(SCENES.read_text(encoding='utf-8'))['scenes']; results=[]; log(f'START step6 scenes={len(scenes)} workers={WORKERS}')
    with concurrent.futures.ThreadPoolExecutor(max_workers=WORKERS) as ex:
        futs={ex.submit(run_one,s,refs):s for s in scenes}
        for fut in concurrent.futures.as_completed(futs):
            r=fut.result(); results.append(r); log((f"{r['status']} {r.get('scene_id')} bytes={r.get('bytes')}" if 'scene_id' in r else str(r)))
    thumb_results=[]
    if not any(r['status']=='failed' for r in results):
        log('START thumbnails')
        for kind,name in [('16x9','thumb_16x9_final.png'),('9x16','thumb_9x16_final.png')]:
            tr=gen_thumb(kind,OUT_THUMBS/name,refs); thumb_results.append(tr); log(str(tr))
    status='completed' if all(r['status'] in ('ok','skipped_exists') for r in results) and len(thumb_results)==2 and all(r['status'] in ('ok','skipped_exists') for r in thumb_results) else 'needs_retry'
    MANIFEST.write_text(json.dumps({'project_id':PROJECT.name,'step':6,'status':status,'workers':WORKERS,'total_scenes':len(scenes),'scene_results':results,'thumbnail_results':thumb_results},ensure_ascii=False,indent=2),encoding='utf-8')
    log('DONE '+json.dumps({'status':status,'scenes_done':sum(1 for r in results if r['status'] in ('ok','skipped_exists')),'scenes_total':len(scenes),'thumbs':len(thumb_results)},ensure_ascii=False))
    if status!='completed': raise SystemExit('needs_retry')
if __name__=='__main__': main()
