import json, os, subprocess, time, concurrent.futures, datetime, traceback
P='/data/video-pipeline/Youtube-Video-Maker/Project/24052026-001-Ly-Thuong-Kiet'
SCRIPT='/home/onepiece/.openclaw/workspace/skills/gen-img-gpt/scripts/gen_img_gpt.py'
STYLE='/data/video-pipeline/Youtube-Video-Maker/data/ref-img/template1/ref1.png'
OUT=P+'/images/scenes'; LOGD=P+'/logs'; TMP=P+'/tmp/image_prompts'
os.makedirs(OUT,exist_ok=True); os.makedirs(LOGD,exist_ok=True); os.makedirs(TMP,exist_ok=True)
scenes=json.load(open(P+'/script/scenes.json'))
progress_path=LOGD+'/image_generation_progress.json'

def now(): return datetime.datetime.utcnow().isoformat()+'Z'
def save(extra=None):
    done=len([f for f in os.listdir(OUT) if f.startswith('scene_') and f.endswith('.png')])
    data={'updated_utc':now(),'project_id':'24052026-001-Ly-Thuong-Kiet','total':len(scenes),'done':done,'remaining':len(scenes)-done,'max_workers':6,'status':'running'}
    if extra: data.update(extra)
    open(progress_path,'w').write(json.dumps(data,ensure_ascii=False,indent=2))

def one(s):
    sid=s['scene_id']; out=f'{OUT}/scene_{sid:03d}.png'; ptxt=f'{TMP}/scene_{sid:03d}_prompt.txt'
    if os.path.exists(out) and os.path.getsize(out)>10000: return {'scene_id':sid,'status':'exists'}
    prompt=s['visual_prompt'] + ' Production scene image for approved story video. Keep exact locked mực loang kể chuyện layout: 16:9 horizontal, warm antique cream paper, central irregular ink-wash window about 65 percent canvas with clear filled composition, no huge blank space, no pure white, no full bleed, no text, no watermark. Historically grounded Đại Việt Lý dynasty 11th century, Vietnamese faces/costumes; Song troops distinct only if present.'
    open(ptxt,'w').write(prompt)
    last=''
    for attempt in range(1,4):
        try:
            cmd=['python3',SCRIPT,'--prompt',prompt,'--input-ref',STYLE,'--output',out,'--size','auto','--quality','auto','--background','auto','--image-detail','high','--output-format','png']
            r=subprocess.run(cmd,stdout=subprocess.PIPE,stderr=subprocess.PIPE,text=True,timeout=480)
            last=(r.stdout+'\n'+r.stderr)[-2000:]
            if r.returncode==0 and os.path.exists(out) and os.path.getsize(out)>10000:
                open(f'{LOGD}/scene_{sid:03d}_image.log','w').write(last)
                return {'scene_id':sid,'status':'ok','attempt':attempt}
        except Exception as e:
            last=traceback.format_exc()[-2000:]
        time.sleep(10*attempt)
    open(f'{LOGD}/scene_{sid:03d}_image.ERROR.log','w').write(last)
    return {'scene_id':sid,'status':'failed','error':last[-500:]}

save({'note':'started'})
failed=[]
with concurrent.futures.ThreadPoolExecutor(max_workers=6) as ex:
    futs={ex.submit(one,s):s for s in scenes}
    for fut in concurrent.futures.as_completed(futs):
        res=fut.result();
        if res['status']=='failed': failed.append(res)
        save({'last_result':res,'failed_count':len(failed)})
status='completed' if not failed else 'completed_with_failures'
save({'status':status,'failed_count':len(failed),'failed':failed[:20]})
