#!/usr/bin/env python3
from __future__ import annotations

import datetime, json, os, subprocess, sys, re
from pathlib import Path

PROJECT=Path('/data/video-pipeline/Youtube-Video-Maker/Project/28052026-001-Tay-Son-That-Ho-Tuong')
GEN_SCRIPT=Path('/home/hermes/.hermes/skills/media/gen-img-gpt/scripts/gen_img_gpt.py')
SCENES_PATH=PROJECT/'script/scenes.json'
PLAN_PATH=PROJECT/'script/character_reference_plan.json'
LOG_PATH=PROJECT/'logs/step_06_images_run.log'
STATE_PATH=PROJECT/'logs/step_06_generation_state.json'
MANIFEST_PATH=PROJECT/'logs/step_06_scene_images_manifest.json'

STYLE_SCENE='Vietnamese historical ink-wash storytelling illustration, 16:9 horizontal canvas, centered irregular ink-wash narrative window on warm antique cream paper; painted content occupies only 65-70 percent of page, remaining 30-35 percent is clean antique paper negative space; soft brown-black ink lines, transparent watercolor wash, muted earthy sepia/ochre/charcoal palette, handcrafted historical documentary mood.'
NEG='No modern objects, no watermark, no logo, no text labels unless this is a heading title card, no glossy full-frame poster, no 3D/game art, no fantasy armor, no character sheet, no concept board, no multiple views, no lineup, no model sheet.'

def log(s):
    LOG_PATH.parent.mkdir(parents=True, exist_ok=True)
    line=datetime.datetime.now().isoformat(timespec='seconds')+' '+s
    print(line, flush=True)
    LOG_PATH.open('a',encoding='utf-8').write(line+'\n')

def load_env():
    ep=Path('/home/hermes/.hermes/.env')
    if ep.exists():
        for raw in ep.read_text(encoding='utf-8').splitlines():
            if raw.strip() and not raw.strip().startswith('#') and '=' in raw:
                k,v=raw.strip().split('=',1); os.environ.setdefault(k,v)

def relevant_refs(text, plan):
    names=[]
    tl=text.lower()
    for it in plan.get('items',[]):
        parts=[it['name'].lower(), it['name'].split(' - ')[0].lower()]
        if any(p and p in tl for p in parts):
            names.append(it)
    return names[:2]

def prompt_for_scene(scene, refs):
    if scene.get('type')=='heading':
        title=scene.get('narration') or scene.get('summary') or scene['scene_id']
        return f"Light Vietnamese old-calligraphy title-card on warm antique paper. Exact Vietnamese title text: {title}. Airy composition with breathing room, subtle ink wash, small red seal accent, elegant historical manuscript feeling. 16:9 horizontal. No extra words, no watermark, no logo, correct Vietnamese diacritics."
    ref_txt=''
    if refs:
        ref_txt='Use attached character reference image(s) only to preserve identity, face, age, hair, costume language and temperament. Do not reproduce the ref sheet. '
    return '\n'.join([
        STYLE_SCENE,
        ref_txt + 'Create one cinematic narrative scene matching this narration beat, with clear environment, action, framing, focal point, and historical grounding in late 18th century Đại Việt / Tây Sơn era.',
        'Narration beat: '+scene.get('narration',''),
        'Scene visual prompt: '+scene.get('visual_prompt', scene.get('visual_beat','')),
        'Historical grounding: Vietnamese Tay Son period, villages, citadels, rivers, battle camps, practical Vietnamese clothing/armor/weapons appropriate to the scene.',
        NEG,
    ])

def run_gen(prompt, out, refs=None, timeout=420):
    cmd=[sys.executable,str(GEN_SCRIPT),'--prompt',prompt,'--output',str(out),'--size','auto','--quality','auto','--background','auto','--image-detail','high','--output-format','png']
    for r in refs or []:
        cmd += ['--input-ref', str(r)]
    return subprocess.run(cmd,cwd=str(PROJECT),text=True,capture_output=True,timeout=timeout)

def main():
    load_env()
    if not os.environ.get('GEN_IMG_API_KEY'):
        log('BLOCKED missing GEN_IMG_API_KEY'); return 2
    scenes=json.loads(SCENES_PATH.read_text(encoding='utf-8'))['scenes']
    plan=json.loads(PLAN_PATH.read_text(encoding='utf-8'))
    scene_dir=PROJECT/'images/scenes'; scene_dir.mkdir(parents=True,exist_ok=True)
    done=[]; failed=[]
    for i,scene in enumerate(scenes,1):
        out=scene_dir/(scene['scene_id']+'.png')
        if out.exists() and out.stat().st_size>1000:
            done.append(scene['scene_id']); continue
        refs=relevant_refs((scene.get('narration','')+' '+scene.get('summary','')+' '+scene.get('section','')), plan)
        ref_paths=[Path(r['output_path']) for r in refs if Path(r['output_path']).exists()]
        log(f'generate scene {i}/{len(scenes)} {scene["scene_id"]} refs={len(ref_paths)} -> {out}')
        pr=prompt_for_scene(scene, refs)
        try:
            proc=run_gen(pr,out,ref_paths)
        except Exception as e:
            failed.append({'scene_id':scene['scene_id'],'error':str(e)}); log(f'failed {scene["scene_id"]}: {e}'); break
        if proc.returncode==0 and out.exists() and out.stat().st_size>1000:
            done.append(scene['scene_id']); log(f'done {scene["scene_id"]} bytes={out.stat().st_size}')
        else:
            err=(proc.stderr or proc.stdout or 'unknown')[-2000:]
            failed.append({'scene_id':scene['scene_id'],'error':err}); log(f'failed {scene["scene_id"]}: {err}'); break
        STATE_PATH.write_text(json.dumps({'step':6,'phase':'scenes','done':len(done),'total_scenes':len(scenes),'failed':failed,'updated_at':datetime.datetime.now().isoformat(timespec='seconds')},ensure_ascii=False,indent=2),encoding='utf-8')
    thumb_dir=PROJECT/'output/thumbnails'; thumb_dir.mkdir(parents=True,exist_ok=True)
    thumbs=[]
    if not failed and len(done)==len(scenes):
        title=json.loads(SCENES_PATH.read_text(encoding='utf-8')).get('title','Tây Sơn Thất Hổ Tướng')
        for name,desc in [('thumb_16x9_final.png','16:9 horizontal 1920x1080-style YouTube thumbnail'),('thumb_9x16_final.png','9:16 vertical 1080x1920-style short video thumbnail')]:
            out=thumb_dir/name
            if out.exists() and out.stat().st_size>1000:
                thumbs.append(str(out)); continue
            prompt=f"Epic dark Vietnamese historical biography poster thumbnail, {desc}. Subject: {title}. Large central/left Tay Son warrior-general portrait group, smoky battlefield and political conflict background, dark sepia bronze black gold palette, gritty parchment texture, black ink splash/grunge title panel, large readable metallic-gold Vietnamese brush-calligraphy title: Tây Sơn Thất Hổ Tướng. GPT-generated final thumbnail, not crop, not scene image, no watermark."
            log(f'generate thumbnail {name}')
            proc=run_gen(prompt,out,timeout=420)
            if proc.returncode==0 and out.exists() and out.stat().st_size>1000:
                thumbs.append(str(out)); log(f'done thumbnail {name} bytes={out.stat().st_size}')
            else:
                failed.append({'thumbnail':name,'error':(proc.stderr or proc.stdout or 'unknown')[-2000:]}); break
    status='completed' if not failed and len(done)==len(scenes) and len(thumbs)==2 else 'partial_failed'
    manifest={'project_id':PROJECT.name,'step':6,'status':status,'provider':'gen-img-gpt','model':'cx/gpt-5.5-image','scene_done':len(done),'total_scenes':len(scenes),'thumbnails':thumbs,'failed':failed,'updated_at':datetime.datetime.now().isoformat(timespec='seconds')}
    MANIFEST_PATH.parent.mkdir(parents=True,exist_ok=True)
    MANIFEST_PATH.write_text(json.dumps(manifest,ensure_ascii=False,indent=2),encoding='utf-8')
    STATE_PATH.write_text(json.dumps(manifest,ensure_ascii=False,indent=2),encoding='utf-8')
    log('DONE '+json.dumps({'status':status,'scene_done':len(done),'total_scenes':len(scenes),'thumbs':len(thumbs)},ensure_ascii=False))
    return 0 if status=='completed' else 1
if __name__=='__main__': raise SystemExit(main())
