#!/usr/bin/env python3
import concurrent.futures,json,subprocess,sys,time
from pathlib import Path
PROJECT=Path('/data/video-pipeline/Youtube-Video-Maker/Project/03072026-004-Phan-Dinh-Giot')
GEN_SCRIPT=Path('/home/hermes/.hermes/skills/media/gen-img-gpt/scripts/gen_img_gpt.py')
LOG=PROJECT/'logs/step06_images_run.log'; MANIFEST=PROJECT/'logs/step06_images_manifest.json'; WORKERS=5
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 ref_for(scene):
    txt=((scene.get('narration') or scene.get('text') or '')+' '+(scene.get('visual_beat') or '')).lower(); refs=[]
    def add(n):
        p=PROJECT/f'characters/{n}_ref.png'
        if p.exists() and p.stat().st_size>1000: refs.append(str(p))
    if 'lỗ châu mai' in txt or 'hỏa điểm' in txt or 'hy sinh' in txt: add('phan-dinh-giot-tai-lo-chau-mai')
    elif 'phan đình giót' in txt or 'anh' in txt: add('phan-dinh-giot-nguoi-linh')
    if any(w in txt for w in ['đồng đội','đại đoàn','bộ đội','xung phong','đơn vị']): add('bo-doi-dai-doan-312')
    if any(w in txt for w in ['pháp','lô cốt','cứ điểm','hàng rào','súng máy','châu mai']): add('quan-phap-trong-cu-diem-him-lam')
    if any(w in txt for w in ['dân công','kéo pháo','pháo binh','núi rừng']): add('dan-cong-va-phao-binh-dien-bien')
    return refs[:2]
def gen_one(scene):
    sid=scene['scene_id']; out=PROJECT/f'images/scenes/{sid}.png'
    if out.exists() and out.stat().st_size>1000: return {'scene_id':sid,'status':'exists','output':str(out)}
    prompt=scene.get('visual_prompt') or scene.get('visual_beat') or scene.get('text','')
    if scene.get('type')=='heading': prompt='Light Vietnamese old-calligraphy title-card on warm antique paper, subtle ink wash of Điện Biên mountains and red earth, airy text with breathing room. Title text: '+scene.get('text','')+'. No modern typography, no heavy black title slam.'
    cmd=[sys.executable,str(GEN_SCRIPT)]
    for r in ref_for(scene): cmd+=['--input-ref',r]
    cmd+=['--prompt',prompt,'--output',str(out),'--size','auto','--quality','auto','--background','auto','--image-detail','high','--output-format','png','--n','1']
    try:
        p=subprocess.run(cmd,text=True,capture_output=True,timeout=900)
        if p.returncode!=0: return {'scene_id':sid,'status':'failed','error':(p.stderr or p.stdout)[-2000:]}
        return {'scene_id':sid,'status':'generated','output':str(out),'bytes':out.stat().st_size if out.exists() else 0}
    except Exception as e: return {'scene_id':sid,'status':'failed','error':repr(e)}
def gen_thumb(name,prompt):
    out=PROJECT/f'output/thumbnails/{name}'
    if out.exists() and out.stat().st_size>1000: return {'name':name,'status':'exists','output':str(out)}
    cmd=[sys.executable,str(GEN_SCRIPT),'--prompt',prompt,'--output',str(out),'--size','auto','--quality','auto','--background','auto','--image-detail','high','--output-format','png','--n','1']
    p=subprocess.run(cmd,text=True,capture_output=True,timeout=900)
    return {'name':name,'status':'generated' if p.returncode==0 else 'failed','output':str(out),'error':None if p.returncode==0 else (p.stderr or p.stdout)[-2000:]}
def main():
    LOG.write_text('',encoding='utf-8')
    plan=json.loads((PROJECT/'script/character_reference_plan.json').read_text(encoding='utf-8'))
    if not plan.get('validation',{}).get('required_refs_exist'): raise SystemExit('Step 06 blocked: required Step 05 refs missing')
    scenes=json.loads((PROJECT/'script/dense_scene_plan.json').read_text(encoding='utf-8'))['scenes']; results=[]
    with concurrent.futures.ThreadPoolExecutor(max_workers=WORKERS) as ex:
        futs={ex.submit(gen_one,s):s['scene_id'] for s in scenes}
        for fut in concurrent.futures.as_completed(futs):
            res=fut.result(); results.append(res); log(json.dumps(res,ensure_ascii=False)); MANIFEST.write_text(json.dumps({'project_id':PROJECT.name,'step':6,'scene_results':results},ensure_ascii=False,indent=2),encoding='utf-8')
    failed=[r for r in results if r['status']=='failed']
    if failed:
        MANIFEST.write_text(json.dumps({'project_id':PROJECT.name,'step':6,'status':'needs_retry','failed':failed,'scene_results':results},ensure_ascii=False,indent=2),encoding='utf-8'); raise SystemExit('step06_scene_failures')
    tp='cinematic Vietnamese historical biography poster for Việt Sử Kể Lại, PHAN ĐÌNH GIÓT, heroic Viet Minh soldier at Him Lam Điện Biên Phủ 1954, warm antique parchment, smoky red-earth trench, barbed wire, mountains, solemn portrait, readable metallic-gold Vietnamese brush lettering title: PHAN ĐÌNH GIÓT, black ink-splash grunge title panel, no gore, no modern objects, no watermark.'
    thumbs=[gen_thumb('thumb_16x9_final.png',tp+' 16:9 horizontal 1920x1080 composition.'),gen_thumb('thumb_9x16_final.png',tp+' TikTok-safe SHORT portrait poster 1080x1280 4:5-ish composition, NOT full-height 9:16, keep face and title central.')]
    MANIFEST.write_text(json.dumps({'project_id':PROJECT.name,'step':6,'status':'completed','total_scenes':len(scenes),'scene_results':results,'thumbnails':thumbs},ensure_ascii=False,indent=2),encoding='utf-8'); log('DONE '+json.dumps({'status':'completed','scenes':len(scenes),'thumbnails':thumbs},ensure_ascii=False))
if __name__=='__main__': main()
