#!/usr/bin/env python3
import concurrent.futures, json, os, subprocess, sys, time
from pathlib import Path
PROJECT = Path('/data/video-pipeline/Youtube-Video-Maker/Project/05062026-001-Phung-Hung')
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', '7'))
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 Vietnamese co phong feeling, muted brown black charcoal watercolor wash, not modern, not full-frame glossy digital poster, not fantasy splash art, not 3D game key art, no text, no watermark.'
STYLE_HEADING = '16:9 horizontal light Vietnamese old-calligraphy title-card on warm antique paper, subtle ink wash and 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, Qing/Ming costume drift, Chinese opera costume, European armor, fantasy armor, samurai, guns, character sheet layout, model sheet, multiple views, floating costume parts, text labels, watermark, logo, glossy poster, edge-to-edge full-frame painting.'
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'])
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):
    t=text.lower(); keys=[]
    if 'phùng hưng' in t or 'bố cái' in t or 'đường lâm' in t: keys.append('phung-hung-bo-cai-dai-vuong')
    if 'phùng hải' in t or 'phùng dĩnh' in t or 'ba anh em' in t: keys.append('phung-hai-va-phung-dinh')
    if 'cao chính bình' in t or 'đô hộ' in t or 'quan nhà đường' in t: keys.append('cao-chinh-binh-quan-do-ho-nha-duong')
    if 'nghĩa quân' in t or 'dân giao châu' in t or 'dân chúng' in t or 'làng' in t or 'khởi nghĩa' in t: keys.append('nghia-quan-duong-lam-va-dan-giao-chau')
    if 'quân lính' in t or 'nhà đường' in t or 'tống bình' in t or 'phủ thành' in t: keys.append('quan-linh-nha-duong-o-an-nam')
    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):
    if scene.get('type')=='heading':
        return f"{STYLE_HEADING}\nVietnamese chapter title card text to depict accurately if possible: {scene['narration']}\nSubtle 8th-century Giao Châu motifs, Đường Lâm stone village, Tống Bình citadel silhouette, rebel flag, antique paper. {NEG}"
    text=scene.get('narration','')+' '+scene.get('summary','')
    refs=scene_refs(text)
    ref_note='Use attached reference image(s) only to keep identity, age, face, costume language, and temperament consistent. Do not reproduce a reference sheet. ' if refs else ''
    return f"{STYLE_SCENE}\nHistorical context: late 8th-century Giao Châu under Tang domination, Đường Lâm villages, Tống Bình citadel, local Vietnamese hào trưởng networks, Tang protectorate officials, rebel uprising atmosphere.\nNarration beat: {scene['narration']}\nVisual direction: {scene.get('visual_beat') or scene.get('visual_prompt')}\n{ref_note}One cinematic narrative scene, historically grounded Vietnamese local clothing, Tang frontier officials/soldiers where appropriate, spears, village roads, riverlands, citadel gates, rebel banners, oppressive colonial administration atmosphere.\nNegative exclusions: {NEG}"
def run_one(scene):
    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),'--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',''))[: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 Vietnamese historical biography poster for 'PHÙNG HƯNG - BỐ CÁI ĐẠI VƯƠNG'. Large dramatic bust portrait of Phùng Hưng, strong Vietnamese rebel leader from Đường Lâm, beside a dark rebel flag; Tống Bình citadel siege, Tang officials and Giao Châu villagers in smoky background; manuscript parchment texture, dark sepia bronze black palette, large readable metallic-gold Vietnamese brush lettering over irregular black ink-splash title panel. Keep hands hidden or out of frame; no malformed fingers, no close-up gripping gesture. Historically grounded late 8th-century Giao Châu, not modern, not fantasy, no watermark."
def gen_thumb(kind,out):
    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('phung-hung-bo-cai-dai-vuong')
    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')
    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):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')}")
    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); 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()
