#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
=============================================================================
THẬP NGŨ NIÊN — PURE NATIVE AUDIO INTRO (20S) & PROLOGUE (40S) MASTERING
=============================================================================
Quy chuẩn sản xuất không ghép nhạc nền nhân tạo (No External BGM):
- GIỮ NGUYÊN 100% âm thanh gốc sinh ra từ shot (foley, tiếng ngâm thơ, âm cảnh tự nhiên).
- Intro (20s): Nối kết 2 shot Intro bằng âm thanh gốc của shot (aac 48kHz stereo).
- Prologue (40s): Nối kết 4 shot Prologue với giọng ngâm thơ Kiều nguyên bản của cụ già
  và tiếng động môi trường tự nhiên (tiếng ve hè, quạt mo cau, xoáy mây xuyên không,
  khí sắc cung đình Gia Tĩnh), không pha tạp nhạc nền điện tử.
- Điểm giao cắt: Equal-Power acrossfade (qsin) triệt tiêu tiếng click/pop.
- Tiêu chuẩn xuất bản: EBU R128 (-14.0 LUFS, True Peak <= -1.0 dBTP, Stereo 48kHz).
=============================================================================
"""

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

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

BASE_DIR = Path("c:/Projects/KieuStory")
ASSETS_DIR = BASE_DIR / "04_Assets"
VIDEOS_DIR = ASSETS_DIR / "videos"
ARCHIVE_DIR = ASSETS_DIR / "archive" / "prologue_pre_fix"
EXPORTS_DIR = BASE_DIR / "06_Exports"
TEMP_DIR = ASSETS_DIR / "temp_pure_native_audio"

TEMP_DIR.mkdir(parents=True, exist_ok=True)
EXPORTS_DIR.mkdir(parents=True, exist_ok=True)

sys.path.append("05_Production_Pipeline")
from audio_continuity_engine import AudioContinuityEngine
ace = AudioContinuityEngine()


# =============================================================================
# PART 1: INTRO (20S) WITH PURE NATIVE AUDIO
# =============================================================================
def produce_pure_native_intro():
    print("\n" + "=" * 70)
    print("🎬 SẢN XUẤT INTRO 20S VỚI ÂM THANH GỐC NGUYÊN BẢN CỦA SHOT (NO BGM)")
    print("=" * 70)

    in_shot01 = VIDEOS_DIR / "thap_ngu_nien_intro_shot01_10s_raw.mp4"
    in_shot02 = VIDEOS_DIR / "thap_ngu_nien_intro_shot02_10s_raw.mp4"

    if not in_shot01.exists() or not in_shot02.exists():
        print(f"[!] Không tìm thấy video raw intro: {in_shot01}, {in_shot02}")
        return False

    # 1. Chuẩn hóa mỗi shot intro về đúng 10.00s và stereo 48kHz
    prep_intro_01 = TEMP_DIR / "intro_shot01_prep.mp4"
    prep_intro_02 = TEMP_DIR / "intro_shot02_prep.mp4"

    cmd1 = [
        "ffmpeg", "-y",
        "-ss", "0.0", "-t", "10.0", "-i", str(in_shot01),
        "-c:v", "libx264", "-crf", "18", "-preset", "slow", "-pix_fmt", "yuv420p",
        "-af", "aresample=48000,aformat=sample_rates=48000:channel_layouts=stereo",
        "-c:a", "aac", "-b:a", "256k", "-ar", "48000",
        str(prep_intro_01)
    ]
    subprocess.run(cmd1, check=True, capture_output=True)
    print("  [✓] Intro Shot 1 chuẩn hóa video & audio gốc 48k stereo.")

    cmd2 = [
        "ffmpeg", "-y",
        "-ss", "0.0", "-t", "10.0", "-i", str(in_shot02),
        "-c:v", "libx264", "-crf", "18", "-preset", "slow", "-pix_fmt", "yuv420p",
        "-af", "aresample=48000,aformat=sample_rates=48000:channel_layouts=stereo",
        "-c:a", "aac", "-b:a", "256k", "-ar", "48000",
        str(prep_intro_02)
    ]
    subprocess.run(cmd2, check=True, capture_output=True)
    print("  [✓] Intro Shot 2 chuẩn hóa video & audio gốc 48k stereo.")

    # 2. Ghép nối 2 shot intro liên hoàn bằng xfade 0.5s (offset 9.5s)
    # Để giữ chính xác 20.0s sau xfade 0.5s, Shot 2 được tpad 0.5s ở cuối
    prep_intro_02_padded = TEMP_DIR / "intro_shot02_padded.mp4"
    cmd_pad = [
        "ffmpeg", "-y",
        "-i", str(prep_intro_02),
        "-filter_complex",
        "[0:v]tpad=stop_mode=clone:stop_duration=0.5[v];"
        "[0:a]apad=pad_dur=0.5,afade=t=out:st=10.0:d=0.5[a]",
        "-map", "[v]", "-map", "[a]",
        "-c:v", "libx264", "-crf", "18", "-preset", "fast", "-pix_fmt", "yuv420p",
        "-c:a", "aac", "-b:a", "256k", "-ar", "48000",
        str(prep_intro_02_padded)
    ]
    subprocess.run(cmd_pad, check=True, capture_output=True)

    # 3. Stitch với xfade 0.5s và acrossfade 0.5s
    raw_intro = TEMP_DIR / "intro_stitched_raw.mp4"
    filter_intro = (
        "[0:v][1:v]xfade=transition=fade:duration=0.5:offset=9.5[v];"
        "[0:a][1:a]acrossfade=d=0.5:c1=qsin:c2=qsin[a]"
    )
    cmd_stitch = [
        "ffmpeg", "-y",
        "-i", str(prep_intro_01),
        "-i", str(prep_intro_02_padded),
        "-filter_complex", filter_intro,
        "-map", "[v]", "-map", "[a]",
        "-c:v", "libx264", "-crf", "18", "-preset", "slow", "-pix_fmt", "yuv420p",
        "-c:a", "aac", "-b:a", "256k", "-ar", "48000",
        str(raw_intro)
    ]
    subprocess.run(cmd_stitch, check=True, capture_output=True)

    # 4. Chuẩn hóa EBU R128 (-14.0 LUFS)
    intro_master_export = EXPORTS_DIR / "thap_ngu_nien_intro_master_20s.mp4"
    ace.normalize_loudness(str(raw_intro), str(intro_master_export), target_lufs=-14.0, two_pass=True)

    # Đồng bộ các tài nguyên
    shutil.copy2(intro_master_export, VIDEOS_DIR / "thap_ngu_nien_intro_complete_20s.mp4")
    shutil.copy2(prep_intro_01, VIDEOS_DIR / "ep01_intro_shot01_10s_master.mp4")
    shutil.copy2(prep_intro_02, VIDEOS_DIR / "ep01_intro_shot02_10s_master.mp4")

    # Đo kiểm
    loud_intro = ace.measure_loudness(str(intro_master_export))
    print(f"  [✓] Hoàn tất Intro 20s Master (100% âm thanh gốc của shot):")
    print(f"      Lưu tại: {intro_master_export}")
    print(f"      Loudness: {loud_intro.get('input_i')} LUFS | True Peak: {loud_intro.get('input_tp')} dBTP | LRA: {loud_intro.get('input_lra')} LU")
    return True


# =============================================================================
# PART 2: PROLOGUE (40S) WITH PURE NATIVE AUDIO & VO (NO BGM)
# =============================================================================
def produce_pure_native_prologue():
    print("\n" + "=" * 70)
    print("🎬 SẢN XUẤT PROLOGUE 40S VỚI ÂM THANH GỐC & THOẠI NGUYÊN BẢN (NO BGM)")
    print("=" * 70)

    shot01_src = ARCHIVE_DIR / "prologue_shot_01_lang_que_198x_10s.mp4"
    shot02_src = ARCHIVE_DIR / "prologue_shot_02_ngam_kieu_10s.mp4"
    shot03_src = ARCHIVE_DIR / "prologue_shot_03_xuyen_khong_10s.mp4"
    shot04_src = ARCHIVE_DIR / "prologue_shot04_corrected.mp4"

    # Trích xuất audio gốc của từng shot và resample 48kHz stereo sạch sẽ
    shots = [shot01_src, shot02_src, shot03_src, shot04_src]
    prep_shots = []

    for i, s in enumerate(shots, 1):
        out_shot = TEMP_DIR / f"prologue_shot{i:02d}_prep.mp4"
        cmd = [
            "ffmpeg", "-y",
            "-ss", "0.0", "-t", "10.0", "-i", str(s),
            "-c:v", "libx264", "-crf", "18", "-preset", "slow", "-pix_fmt", "yuv420p",
            "-af", "aresample=48000,aformat=sample_rates=48000:channel_layouts=stereo",
            "-c:a", "aac", "-b:a", "256k", "-ar", "48000",
            str(out_shot)
        ]
        subprocess.run(cmd, check=True, capture_output=True)
        prep_shots.append(out_shot)
        print(f"  [✓] Shot {i} đã chuẩn hóa video & audio gốc không nhạc nền: {out_shot.name}")

    # Shot 4 padded 1.5s cuối để tổng 4 shots sau 3 xfade 0.5s đạt đúng 40.00s
    shot04_padded = TEMP_DIR / "prologue_shot04_padded.mp4"
    cmd_pad4 = [
        "ffmpeg", "-y",
        "-i", str(prep_shots[3]),
        "-filter_complex",
        "[0:v]tpad=stop_mode=clone:stop_duration=1.5[v];"
        "[0:a]apad=pad_dur=1.5,afade=t=out:st=10.0:d=1.5[a]",
        "-map", "[v]", "-map", "[a]",
        "-c:v", "libx264", "-crf", "18", "-preset", "fast", "-pix_fmt", "yuv420p",
        "-c:a", "aac", "-b:a", "256k", "-ar", "48000",
        str(shot04_padded)
    ]
    subprocess.run(cmd_pad4, check=True, capture_output=True)

    # Ghép 4 shots với xfade 0.5s và acrossfade 0.5s (hoàn toàn là âm thanh gốc & ngâm thơ)
    raw_prologue = TEMP_DIR / "prologue_pure_native_stitched_raw.mp4"
    filter_prologue = (
        "[0:v][1:v]xfade=transition=fade:duration=0.5:offset=9.5[v01];"
        "[v01][2:v]xfade=transition=fade:duration=0.5:offset=19.0[v02];"
        "[v02][3:v]xfade=transition=fade:duration=0.5:offset=28.5[vmaster];"
        "[0:a][1:a]acrossfade=d=0.5:c1=qsin:c2=qsin[a01];"
        "[a01][2:a]acrossfade=d=0.5:c1=qsin:c2=qsin[a02];"
        "[a02][3:a]acrossfade=d=0.5:c1=qsin:c2=qsin[amaster]"
    )
    cmd_stitch_p = [
        "ffmpeg", "-y",
        "-i", str(prep_shots[0]),
        "-i", str(prep_shots[1]),
        "-i", str(prep_shots[2]),
        "-i", str(shot04_padded),
        "-filter_complex", filter_prologue,
        "-map", "[vmaster]",
        "-map", "[amaster]",
        "-c:v", "libx264", "-crf", "18", "-preset", "slow", "-pix_fmt", "yuv420p",
        "-c:a", "aac", "-b:a", "256k", "-ar", "48000",
        str(raw_prologue)
    ]
    subprocess.run(cmd_stitch_p, check=True, capture_output=True)

    # Chuẩn hóa EBU R128 (-14.0 LUFS)
    prologue_master_export = EXPORTS_DIR / "thap_ngu_nien_prologue_master_40s.mp4"
    ace.normalize_loudness(str(raw_prologue), str(prologue_master_export), target_lufs=-14.0, two_pass=True)

    # Đồng bộ sang các vị trí khác
    shutil.copy2(prologue_master_export, EXPORTS_DIR / "prologue_master_40s.mp4")
    shutil.copy2(prologue_master_export, VIDEOS_DIR / "prologue_hoai_niem_198x_to_gia_tinh_40s.mp4")
    for idx, p in enumerate(prep_shots, 1):
        shutil.copy2(p, VIDEOS_DIR / f"prologue_shot{idx:02d}_10s_v1.mp4")

    # Đo kiểm
    loud_prologue = ace.measure_loudness(str(prologue_master_export))
    print(f"  [✓] Hoàn tất Prologue 40s Master (100% âm thanh gốc, không BGM):")
    print(f"      Lưu tại: {prologue_master_export}")
    print(f"      Loudness: {loud_prologue.get('input_i')} LUFS | True Peak: {loud_prologue.get('input_tp')} dBTP | LRA: {loud_prologue.get('input_lra')} LU")
    return True


# =============================================================================
# PART 3: CONTINUOUS INTRO + PROLOGUE (60S) MASTER
# =============================================================================
def produce_continuous_60s_cut():
    print("\n" + "=" * 70)
    print("🎬 GHÉP NỐI BẢN LIÊN HOÀN 60S (INTRO 20S + PROLOGUE 40S - NO BGM)")
    print("=" * 70)

    intro_file = EXPORTS_DIR / "thap_ngu_nien_intro_master_20s.mp4"
    prologue_file = EXPORTS_DIR / "thap_ngu_nien_prologue_master_40s.mp4"
    out_60s = EXPORTS_DIR / "thap_ngu_nien_intro_prologue_continuous_60s.mp4"

    # Nối với micro-fade 30ms giữa Intro và Prologue
    cmd_concat = [
        "ffmpeg", "-y",
        "-i", str(intro_file),
        "-i", str(prologue_file),
        "-filter_complex",
        "[0:v][1:v]concat=n=2:v=1:a=0[v];"
        "[0:a]afade=t=out:st=19.97:d=0.03[a0];"
        "[1:a]afade=t=in:st=0:d=0.03[a1];"
        "[a0][a1]concat=n=2:v=0:a=1[a]",
        "-map", "[v]", "-map", "[a]",
        "-c:v", "libx264", "-crf", "18", "-preset", "slow", "-pix_fmt", "yuv420p",
        "-c:a", "aac", "-b:a", "256k", "-ar", "48000",
        str(out_60s)
    ]
    subprocess.run(cmd_concat, check=True, capture_output=True)
    shutil.copy2(out_60s, VIDEOS_DIR / "thap_ngu_nien_ep01_intro_prologue_60s.mp4")

    loud_60s = ace.measure_loudness(str(out_60s))
    print(f"  [✓] Đã tạo thành công bản liên hoàn 60s:")
    print(f"      Lưu tại: {out_60s}")
    print(f"      Loudness: {loud_60s.get('input_i')} LUFS | True Peak: {loud_60s.get('input_tp')} dBTP")
    return True


if __name__ == "__main__":
    produce_pure_native_intro()
    produce_pure_native_prologue()
    produce_continuous_60s_cut()
    print("\n" + "=" * 70)
    print("🎉 HOÀN TẤT 100%: CẢ INTRO VÀ PROLOGUE ĐÃ ĐƯỢC CHUẨN HÓA VỚI ÂM THANH GỐC NGUYÊN BẢN!")
    print("=" * 70)
