#!/usr/bin/env python3
import importlib.util, json, re, time
from pathlib import Path

PROJECT = Path('/data/video-pipeline/Youtube-Video-Maker/Project/02072026-001-Nha-Nguyen')
STEP06 = PROJECT / 'scripts_run_step_06_images.py'
LOG = PROJECT / 'logs/step06_missing_serial_auth_retry.log'
MANIFEST = PROJECT / 'logs/step06_missing_serial_auth_manifest.json'

spec = importlib.util.spec_from_file_location('step06_mod', STEP06)
step06 = importlib.util.module_from_spec(spec)
spec.loader.exec_module(step06)

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 reset_sleep_seconds(error):
    m = re.search(r'reset after (\d+)m\s*(\d+)s', error or '')
    if m:
        return int(m.group(1)) * 60 + int(m.group(2)) + 30
    m = re.search(r'reset after (\d+)s', error or '')
    if m:
        return int(m.group(1)) + 30
    if 'invalidated oauth token' in (error or '').lower() or '[401]' in (error or ''):
        return 120
    return 0

def main():
    LOG.write_text('', encoding='utf-8')
    refs = step06.load_refs()
    data = json.loads(step06.SCENES.read_text(encoding='utf-8'))
    scenes = data['scenes']
    results = []
    missing = [s for s in scenes if not (step06.OUT_SCENES / f"{s['scene_id']}.png").exists()]
    log(f'START missing serial auth-aware retry missing={len(missing)} total={len(scenes)}')
    for idx, scene in enumerate(missing, 1):
        scene_id = scene['scene_id']
        result = None
        for attempt in range(1, 5):
            log(f'RUN {scene_id} attempt={attempt} index={idx}/{len(missing)}')
            result = step06.run_one(scene, refs)
            if result.get('status') in ('ok', 'skipped_exists'):
                log(f"OK {scene_id} bytes={result.get('bytes')}")
                break
            err = result.get('error') or ''
            wait = reset_sleep_seconds(err)
            log(f"FAILED {scene_id} attempt={attempt} wait={wait}s error={err[:500].replace(chr(10), ' ')}")
            if not wait:
                break
            time.sleep(wait)
        results.append(result or {'scene_id': scene_id, 'status': 'failed', 'error': 'no_result'})
        done = len(list(step06.OUT_SCENES.glob('scene_*.png')))
        MANIFEST.write_text(json.dumps({'project_id': PROJECT.name, 'status': 'running', 'scenes_done': done, 'scenes_total': len(scenes), 'last_scene': scene_id, 'results': results}, ensure_ascii=False, indent=2), encoding='utf-8')
    done = len(list(step06.OUT_SCENES.glob('scene_*.png')))
    thumb_results = []
    status = 'completed' if done == len(scenes) else 'needs_retry'
    if status == 'completed':
        log('START thumbnails')
        step06.OUT_THUMBS.mkdir(parents=True, exist_ok=True)
        for kind, name in [('16x9', 'thumb_16x9_final.png'), ('9x16', 'thumb_9x16_final.png')]:
            tr = step06.gen_thumb(kind, step06.OUT_THUMBS / name, refs)
            thumb_results.append(tr)
            log(str(tr))
        if not all(t.get('status') in ('ok', 'skipped_exists') for t in thumb_results):
            status = 'needs_retry'
    final = {'project_id': PROJECT.name, 'status': status, 'scenes_done': done, 'scenes_total': len(scenes), 'results': results, 'thumbnail_results': thumb_results}
    MANIFEST.write_text(json.dumps(final, ensure_ascii=False, indent=2), encoding='utf-8')
    log('DONE ' + json.dumps({'status': status, 'scenes_done': done, 'scenes_total': len(scenes), 'thumbs': len(thumb_results)}, ensure_ascii=False))
    if status != 'completed':
        raise SystemExit('needs_retry')

if __name__ == '__main__':
    main()
