#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
THẬP NGŨ NIÊN - Render full Scene 02 (Gia Trang Họ Vương) with Wan 2.2 and Concat to Master.
"""

import sys
import os
import json
import time
import shutil
import subprocess
from pathlib import Path

# Ensure UTF-8 console output
if sys.platform == "win32":
    try:
        sys.stdout.reconfigure(encoding="utf-8")
        sys.stderr.reconfigure(encoding="utf-8")
    except Exception:
        pass

BASE_DIR = Path(__file__).resolve().parent.parent
sys.path.insert(0, str(BASE_DIR))

from gradio_version.hf_client import HuggingFaceVideoClient

def get_ffmpeg():
    exe = Path(sys.executable).parent / "ffmpeg.exe"
    if exe.exists():
        return str(exe)
    return "ffmpeg"

SHOTS_TO_RENDER = [
    {
        "id": "ep01_scene02_shot01",
        "title": "Toàn cảnh sân trong Gia Trang họ Vương (Wide Establishing)",
        "image": "04_Assets/keyframes/ep01_scene02_shot01_start.jpg",
        "prompt": "Toàn cảnh sân trong gia trang họ Vương lát gạch Bát Tràng đỏ au, chậu cá gốm hoa súng xanh ngắt, hiên nhà gỗ lim chạm trổ rồng mây cổ kính, máy quay slow cinematic push-in êm ả, nắng sớm lung linh, 24fps cinematic.",
        "dest": "04_Assets/videos/ep01_scene02_shot01_wan22.mp4",
        "is_widescreen": True
    },
    {
        "id": "ep01_scene02_shot02",
        "title": "Nội cảnh phòng khách gia trang (Interior Medium Shot)",
        "image": "04_Assets/keyframes/ep01_scene02_shot02_start.jpg",
        "prompt": "Nội cảnh phòng khách thanh nhã ấm cúng gia trang họ Vương, ánh nắng sớm rọi qua rèm the mỏng tạo dải sáng vàng mềm mại, khói trầm từ lư đồng uốn lượn bay lên, Vương Ông ngồi bên bàn trà gỗ trắc tĩnh tại, 24fps cinematic.",
        "dest": "04_Assets/videos/ep01_scene02_shot02_wan22.mp4",
        "is_widescreen": True
    },
    {
        "id": "ep01_scene02_shot04",
        "title": "Vương Ông thưởng trà (MCU Father)",
        "image": "04_Assets/characters/02_Vuong_Family_And_Fate/vuong_ong_55yo/views/vuong_ong_55yo_portrait.png",
        "prompt": "Trung cận Vương Ông (55 tuổi) đạo mạo trong trang phục áo dài lụa màu sẫm, nét mặt đôn hậu, ngồi bên bàn trà gỗ trắc chậm rãi nâng chén trà sứ hoa lam, 24fps cinematic.",
        "dest": "04_Assets/videos/ep01_scene02_shot04_wan22.mp4",
        "existing": "gradio_version/outputs/ep01_scene02_shot04_wan22_5b.mp4",
        "is_widescreen": False
    },
    {
        "id": "ep01_scene02_shot06",
        "title": "Vương Bà vuốt nếp áo lụa du xuân (MCU Mother)",
        "image": "04_Assets/characters/02_Vuong_Family_And_Fate/vuong_ba_50yo/views/vuong_ba_50yo_portrait.png",
        "prompt": "Trung cận Vương Bà (50 tuổi) hiền từ phúc hậu trong chiếc áo tứ thân nền nã, tay âu yếm vuốt phẳng nếp áo lụa du xuân, nụ cười ấm áp đôn hậu, 24fps cinematic.",
        "dest": "04_Assets/videos/ep01_scene02_shot06_wan22.mp4",
        "existing": "gradio_version/outputs/ep01_scene02_shot06_wan22_5b.mp4",
        "is_widescreen": False
    },
    {
        "id": "ep01_scene02_shot07",
        "title": "Hai vợ chồng đàm đạo gia phong (Two-Shot Parents)",
        "image": "04_Assets/keyframes/ep01_scene02_shot07_start.jpg",
        "prompt": "Trung cảnh đôi Vương Ông và Vương Bà ngồi bên bàn trà gỗ trắc mỉm cười đôn hậu trò chuyện, ánh mắt mãn nguyện đàm đạo trong nắng mai, khói trầm uốn lượn, 24fps cinematic.",
        "dest": "04_Assets/videos/ep01_scene02_shot07_wan22.mp4",
        "is_widescreen": True
    },
    {
        "id": "ep01_scene02_shot08",
        "title": "Vương Quan bước vào bái chào cha mẹ (Entrance & Bow)",
        "image": "04_Assets/keyframes/ep01_scene02_shot08_start.jpg",
        "prompt": "Vương Quan thiếu niên thư sinh áo giao lĩnh lam nhạt bước qua ngưỡng cửa phòng khách, hai tay chắp bái chào cha mẹ với phong thái khiêm cung hiếu thảo, cha mẹ mỉm cười rạng rỡ đón con, 24fps cinematic.",
        "dest": "04_Assets/videos/ep01_scene02_shot08_wan22.mp4",
        "is_widescreen": True
    }
]

def render_all_shots():
    client = HuggingFaceVideoClient()
    rendered_files = []

    print("\n" + "=" * 75)
    print("🎬 [WAN 2.2 PIPELINE] BẮT ĐẦU SẢN XUẤT CẢNH 02 (TẬP 1) - GIA TRANG HỌ VƯƠNG")
    print(f"   • Tổng số shot cấu thành: {len(SHOTS_TO_RENDER)} shots")
    print("=" * 75)

    for idx, s in enumerate(SHOTS_TO_RENDER, 1):
        shot_id = s["id"]
        dest_p = BASE_DIR / s["dest"]
        print(f"\n--- [{idx}/{len(SHOTS_TO_RENDER)}] Xử lý {shot_id}: {s['title']} ---")

        # Check if already rendered
        if "existing" in s:
            exist_p = BASE_DIR / s["existing"]
            if exist_p.exists():
                print(f"    ✓ Đã có sẵn bản render Wan 2.2: {exist_p.name}")
                shutil.copy2(str(exist_p), str(dest_p))
                rendered_files.append((s, dest_p))
                continue

        if dest_p.exists() and dest_p.stat().st_size > 100000:
            print(f"    ✓ Đã tồn tại file render hợp lệ: {dest_p.name}")
            rendered_files.append((s, dest_p))
            continue

        img_p = BASE_DIR / s["image"]
        if not img_p.exists():
            print(f"    [!] Thiếu ảnh start frame: {img_p}")
            continue

        print(f"    🚀 Đang gọi Wan 2.2 sinh video ({img_p.name})...")
        t0 = time.time()
        ok, out_v = client.generate_i2v(
            image_path=str(img_p),
            prompt=s["prompt"],
            model_key="wan22",
            duration=4.0,
            output_filename=f"{shot_id}_wan22.mp4"
        )
        elapsed = time.time() - t0

        if ok and out_v and Path(out_v).exists():
            shutil.copy2(str(out_v), str(dest_p))
            print(f"    ✓ Render thành công trong {elapsed:.1f}s -> {dest_p.name}")
            rendered_files.append((s, dest_p))
        else:
            print(f"    [!] Thất bại khi sinh shot {shot_id}")

    return rendered_files

def standardize_clip(input_video: Path, output_video: Path, is_widescreen: bool = True):
    """Chuẩn hóa mọi clip về đúng tỷ lệ 16:9 1280x720 24fps kèm âm thanh câm stereo nếu chưa có."""
    ffmpeg = get_ffmpeg()
    
    if is_widescreen:
        # Scale to 1280x720 directly
        vf = "scale=1280:720:force_original_aspect_ratio=decrease,pad=1280:720:(ow-iw)/2:(oh-ih)/2:black,fps=24"
    else:
        # Blurred background for vertical portrait shots to look cinematic in widescreen
        vf = "[0:v]scale=1280:720:force_original_aspect_ratio=increase,crop=1280:720,boxblur=20:5[bg];" \
             "[0:v]scale=-1:720[fg];" \
             "[bg][fg]overlay=(W-w)/2:0,fps=24"

    cmd = [
        ffmpeg, "-y",
        "-i", str(input_video),
        "-filter_complex", vf,
        "-c:v", "libx264", "-preset", "fast", "-crf", "18",
        "-c:a", "aac", "-b:a", "192k", "-ar", "48000",
        "-movflags", "+faststart",
        str(output_video)
    ]
    
    # If source has no audio, add silent audio
    probe_cmd = ["ffprobe", "-v", "error", "-show_streams", "-select_streams", "a", str(input_video)]
    res_probe = subprocess.run(probe_cmd, capture_output=True, text=True)
    if not res_probe.stdout.strip():
        # Inject silent audio
        cmd = [
            ffmpeg, "-y",
            "-i", str(input_video),
            "-f", "lavfi", "-i", "anullsrc=channel_layout=stereo:sample_rate=48000",
            "-filter_complex", vf,
            "-c:v", "libx264", "-preset", "fast", "-crf", "18",
            "-c:a", "aac", "-b:a", "192k", "-shortest",
            "-movflags", "+faststart",
            str(output_video)
        ]

    subprocess.run(cmd, capture_output=True)
    return output_video.exists()

def build_scene_master(rendered_files):
    if not rendered_files:
        print("[!] Không có clip nào để ghép nối.")
        return None

    print("\n" + "=" * 75)
    print("🎬 [GHÉP MASTER CẢNH 02] Chuẩn hóa và nối chuỗi toàn bộ các shot...")
    print("=" * 75)

    temp_dir = BASE_DIR / "04_Assets" / "temp_scene02"
    temp_dir.mkdir(parents=True, exist_ok=True)

    std_clips = []
    for s_info, vid_path in rendered_files:
        std_out = temp_dir / f"std_{vid_path.name}"
        print(f"    • Chuẩn hóa 1280x720 24fps: {vid_path.name} (widescreen={s_info.get('is_widescreen', True)})")
        ok = standardize_clip(vid_path, std_out, s_info.get("is_widescreen", True))
        if ok:
            std_clips.append(std_out)

    if not std_clips:
        print("[!] Lỗi chuẩn hóa clip.")
        return None

    # Create concat list
    concat_list_file = temp_dir / "concat_list.txt"
    with open(concat_list_file, "w", encoding="utf-8") as f:
        for c in std_clips:
            clean_p = str(c).replace("\\", "/")
            f.write(f"file '{clean_p}'\n")

    raw_master = temp_dir / "scene02_raw_concat.mp4"
    ffmpeg = get_ffmpeg()
    cmd_concat = [
        ffmpeg, "-y",
        "-f", "concat", "-safe", "0",
        "-i", str(concat_list_file),
        "-c", "copy",
        str(raw_master)
    ]
    subprocess.run(cmd_concat, capture_output=True)

    if not raw_master.exists() or raw_master.stat().st_size < 10000:
        print("[!] Lỗi khi concat clip.")
        return None

    print(f"    ✓ Đã ghép nối liên hoàn các shot: {raw_master.stat().st_size / 1024 / 1024:.2f} MB")

    # Add BGM and Audio Normalization to -14.0 LUFS
    final_master_export = BASE_DIR / "06_Exports" / "ep01_scene02_wan22_cinematic_master.mp4"
    final_master_video = BASE_DIR / "04_Assets" / "videos" / "ep01_scene02_master_v1.mp4"
    
    bgm_file = BASE_DIR / "04_Assets" / "audio" / "scene01_bgm.m4a"

    if bgm_file.exists():
        print(f"    🎵 Đang hòa âm BGM cổ phong ({bgm_file.name}) và chuẩn hóa -14.0 LUFS...")
        cmd_master = [
            ffmpeg, "-y",
            "-i", str(raw_master),
            "-stream_loop", "-1", "-i", str(bgm_file),
            "-filter_complex",
            "[1:a]volume=0.35,afade=t=in:st=0:d=1.5[bgm];"
            "[0:a][bgm]amix=inputs=2:duration=first[a_mixed];"
            "[a_mixed]loudnorm=I=-14.0:LRA=7.0:TP=-1.5[a_out]",
            "-map", "0:v", "-map", "[a_out]",
            "-c:v", "copy",
            "-c:a", "aac", "-b:a", "192k", "-ar", "48000",
            "-shortest",
            str(final_master_export)
        ]
        res = subprocess.run(cmd_master, capture_output=True)
        if res.returncode != 0 or not final_master_export.exists():
            shutil.copy2(str(raw_master), str(final_master_export))
    else:
        shutil.copy2(str(raw_master), str(final_master_export))

    # Copy to 04_Assets/videos/ so Web Review indexes it
    shutil.copy2(str(final_master_export), str(final_master_video))

    print("\n" + "=" * 75)
    print(f"🎉 HOÀN TẤT XUẤT MASTER CẢNH 02 BẰNG WAN 2.2!")
    print(f"   • File Master Exports: {final_master_export}")
    print(f"   • File Master Web:     {final_master_video}")
    print("=" * 75)
    return final_master_export

if __name__ == "__main__":
    rendered = render_all_shots()
    master = build_scene_master(rendered)
    if master:
        print(f"\n[✓] Thành công! Kiểm tra ngay trên http://localhost:1515")
