#!/usr/bin/env python3
import json
import os
import subprocess
import sys
import time
from datetime import datetime
from pathlib import Path

PROJECT = Path('/data/video-pipeline/Youtube-Video-Maker/Project/31052026-001-Nguyen-Hue-Quang-Trung')
GEN_SCRIPT = Path('/home/hermes/.hermes/skills/media/gen-img-gpt/scripts/gen_img_gpt.py')
LOG = PROJECT / 'logs/step06_first50_images_run.log'
MAN = PROJECT / 'logs/step06_first50_until_done_manifest.json'
LIMIT = 50


def log(msg):
    LOG.parent.mkdir(parents=True, exist_ok=True)
    line = f"[{datetime.now().isoformat(timespec='seconds')}] {msg}"
    print(line, flush=True)
    with LOG.open('a', encoding='utf-8') as f:
        f.write(line + '\n')


def scene_path(scene_id):
    return PROJECT / 'images/scenes' / f'{scene_id}.png'


def build_prompt(scene):
    n = scene.get('narration') or scene.get('text', '')
    if scene.get('type') == 'heading':
        return f"Vietnamese old-calligraphy chapter title card, 16:9 horizontal, warm antique paper, subtle ink wash, small seal stamp accent, airy breathing room. Exact title: {n}. No modern typography, no logo, no watermark."
    return f"Vietnamese historical ink-wash storytelling illustration, 16:9 horizontal canvas, centered irregular ink-wash window on warm antique cream paper, painted content only 65-70 percent of page with 30-35 percent antique paper negative space. Late 18th-century Dai Viet, Tay Son era, historically grounded Vietnamese clothing, terrain, villages, courts, armies, river geography. One cinematic narrative scene matching this narration beat: {n}. Clear focal action, environment, emotional staging. Not character sheet, not multiple views, not modern, not logo, not watermark, not text, not edge-to-edge, not glossy 3D."


def generate(scene):
    sid = scene['scene_id']
    out = scene_path(sid)
    if out.exists() and out.stat().st_size > 1000:
        return {'scene_id': sid, 'status': 'exists', 'bytes': out.stat().st_size}
    cmd = [sys.executable, str(GEN_SCRIPT), '--prompt', build_prompt(scene), '--output', str(out), '--size', 'auto', '--quality', 'auto', '--background', 'auto', '--image-detail', 'high', '--output-format', 'png', '--n', '1']
    proc = subprocess.run(cmd, text=True, capture_output=True, timeout=420)
    if proc.returncode != 0:
        return {'scene_id': sid, 'status': 'failed', 'error': (proc.stderr or proc.stdout)[-2000:]}
    if not out.exists() or out.stat().st_size < 1000:
        return {'scene_id': sid, 'status': 'failed_empty'}
    return {'scene_id': sid, 'status': 'generated', 'bytes': out.stat().st_size}


def backoff_seconds(error, attempt):
    err = (error or '').lower()
    if '429' in err or 'too many requests' in err:
        return min(900, 240 + attempt * 90)
    if 'terminated' in err:
        return min(420, 90 + attempt * 45)
    return min(300, 60 + attempt * 30)


def write_manifest(status, results, attempts, scenes):
    remaining = [s['scene_id'] for s in scenes if not scene_path(s['scene_id']).exists()]
    MAN.write_text(json.dumps({
        'project_id': '31052026-001-Nguyen-Hue-Quang-Trung',
        'step': '6_limited_first50_until_done',
        'status': status,
        'generated_count': LIMIT - len(remaining),
        'remaining_missing': remaining,
        'attempts': attempts,
        'results': results[-100:]
    }, ensure_ascii=False, indent=2), encoding='utf-8')
    return remaining


def main():
    if not os.environ.get('GEN_IMG_API_KEY'):
        raise SystemExit('GEN_IMG_API_KEY missing')
    scenes = json.loads((PROJECT / 'script/scenes.json').read_text(encoding='utf-8'))['scenes'][:LIMIT]
    results = []
    attempts = {}
    log('Start until-done v2 for scene_001..scene_050; no thumbnails, no scene_051')
    while True:
        remaining = [s for s in scenes if not scene_path(s['scene_id']).exists()]
        if not remaining:
            write_manifest('completed_limited_50_pending_review', results, attempts, scenes)
            log('Reached 50/50 images. Stopping before thumbnails and scene_051.')
            return 0
        s = remaining[0]
        sid = s['scene_id']
        attempts[sid] = attempts.get(sid, 0) + 1
        log(f'Until-done v2 retry {sid} attempt {attempts[sid]}')
        res = generate(s)
        results.append(res)
        log(f"Until-done v2 {sid} {res['status']}")
        write_manifest('running', results, attempts, scenes)
        if res['status'].startswith('failed'):
            wait = backoff_seconds(res.get('error', ''), attempts[sid])
            log(f'Backoff {wait}s then retry {sid}')
            time.sleep(wait)
        else:
            time.sleep(5)

if __name__ == '__main__':
    raise SystemExit(main())
