#!/usr/bin/env python3
import json
import time
import urllib.request
from pathlib import Path
import wave

PROJECT = Path('/data/video-pipeline/Youtube-Video-Maker/Project/26052026-001-Ngo-Quyen')
ENDPOINT = 'http://192.168.1.104:8005/compose-tts'
AUDIO_DIR = PROJECT / 'audio'
SCENES_DIR = AUDIO_DIR / 'scenes'
MASTER_AUDIO = AUDIO_DIR / 'master_narration.wav'
TIMELINE = AUDIO_DIR / 'master_narration_timeline.json'
MANIFEST = PROJECT / 'logs/step8_compose_tts_manifest.json'
PRE_HEADING_PAUSE = 1.0
POST_HEADING_PAUSE = 1.0


def log(msg):
    line = time.strftime('%Y-%m-%d %H:%M:%S ') + msg
    print(line, flush=True)


def wav_duration(path):
    with wave.open(str(path), 'rb') as wav:
        return wav.getnframes() / float(wav.getframerate())


def main():
    scenes = json.loads((PROJECT / 'script/scenes.json').read_text(encoding='utf-8'))['scenes']
    AUDIO_DIR.mkdir(parents=True, exist_ok=True)
    MANIFEST.parent.mkdir(parents=True, exist_ok=True)

    t = 0.0
    timeline = []
    segments = []
    missing = []

    for order, scene in enumerate(scenes, start=1):
        scene_id = scene['scene_id']
        audio_path = SCENES_DIR / f'{scene_id}.wav'
        if not audio_path.exists():
            missing.append(str(audio_path))
            continue

        scene_type = scene.get('scene_type') or scene.get('type', '')
        pre_pause = PRE_HEADING_PAUSE if scene_type == 'heading' else 0.0
        post_pause = POST_HEADING_PAUSE if scene_type == 'heading' else 0.0
        t += pre_pause

        duration = wav_duration(audio_path)
        start = round(t, 3)
        end = round(t + duration, 3)

        timeline_item = {
            'order': order,
            'scene_id': scene_id,
            'scene_type': scene_type,
            'audio_path': str(audio_path.relative_to(PROJECT)),
            'absolute_audio_path': str(audio_path),
            'start': start,
            'end': end,
            'duration': round(duration, 3),
            'pre_pause': pre_pause,
            'post_pause': post_pause,
            'narration': scene.get('narration', ''),
        }
        timeline.append(timeline_item)
        segments.append({
            'segment_index': order,
            'start': start,
            'end': end,
            'audio_path': str(audio_path),
            'source_text': scene.get('narration', ''),
            'translated_text': '',
            'status': 'ok',
        })
        t = end + post_pause

    if missing:
        raise SystemExit('Missing scene audio files: ' + json.dumps(missing[:10], ensure_ascii=False))

    payload = {
        'job_id': PROJECT.name + '_step8_master_narration',
        'work_dir': str(PROJECT),
        'output_audio_path': str(MASTER_AUDIO),
        'tts_segments': segments,
    }
    req = urllib.request.Request(
        ENDPOINT,
        data=json.dumps(payload, ensure_ascii=False).encode('utf-8'),
        headers={'Content-Type': 'application/json'},
        method='POST',
    )

    log(f'POST {ENDPOINT} segments={len(segments)} output={MASTER_AUDIO}')
    with urllib.request.urlopen(req, timeout=1800) as resp:
        worker_response = json.loads(resp.read().decode('utf-8'))

    total_duration = worker_response.get('duration')
    timeline_doc = {
        'project_id': PROJECT.name,
        'step': 8,
        'master_audio': str(MASTER_AUDIO.relative_to(PROJECT)),
        'master_audio_absolute': str(MASTER_AUDIO),
        'endpoint': ENDPOINT,
        'pause_rules': {
            'pre_heading_seconds': PRE_HEADING_PAUSE,
            'post_heading_seconds': POST_HEADING_PAUSE,
        },
        'total_scenes': len(timeline),
        'total_duration': total_duration,
        'timeline': timeline,
    }
    TIMELINE.write_text(json.dumps(timeline_doc, ensure_ascii=False, indent=2), encoding='utf-8')

    manifest = {
        'project_id': PROJECT.name,
        'step': 8,
        'status': 'completed',
        'endpoint': ENDPOINT,
        'request': {
            'job_id': payload['job_id'],
            'work_dir': payload['work_dir'],
            'output_audio_path': payload['output_audio_path'],
            'segments_count': len(segments),
        },
        'worker_response': worker_response,
        'timeline_path': str(TIMELINE),
        'master_audio_path': str(MASTER_AUDIO),
    }
    MANIFEST.write_text(json.dumps(manifest, ensure_ascii=False, indent=2), encoding='utf-8')
    log('DONE ' + json.dumps({'status': 'completed', 'segments': len(segments), 'duration_min': round((total_duration or 0) / 60, 2)}, ensure_ascii=False))


if __name__ == '__main__':
    main()
