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"
AUDIO_DIR = ASSETS_DIR / "audio"
EXPORTS_DIR = BASE_DIR / "06_Exports"
TEMP_DIR = ASSETS_DIR / "temp_prologue_flowkit"

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

# 1. Verify sources
shot01 = ARCHIVE_DIR / "prologue_shot_01_lang_que_198x_10s.mp4"
shot02 = ARCHIVE_DIR / "prologue_shot_02_ngam_kieu_10s.mp4"
shot03 = ARCHIVE_DIR / "prologue_shot_03_xuyen_khong_10s.mp4"
shot04 = ARCHIVE_DIR / "prologue_shot04_corrected.mp4"

for s in [shot01, shot02, shot03, shot04]:
    if not s.exists():
        print(f"Missing source: {s}")
        sys.exit(1)
    print(f"Source verified: {s.name}")

# 2. Extract clean audio stems and pre-condition to 48kHz stereo
print("\n--- Step 1: Pre-conditioning audio streams to 48kHz stereo ---")
for i, s in enumerate([shot01, shot02, shot03, shot04], 1):
    out_wav = TEMP_DIR / f"shot{i:02d}_48k_stereo.wav"
    cmd = [
        "ffmpeg", "-y",
        "-i", str(s),
        "-vn",
        "-af", "aresample=48000,aformat=sample_rates=48000:channel_layouts=stereo",
        str(out_wav)
    ]
    subprocess.run(cmd, check=True, capture_output=True)
    print(f"  [✓] Processed audio stem Shot {i} -> {out_wav.name}")

# Add festival ambience bed to Shot 4
shot04_ambience = AUDIO_DIR / "festival_crowd_ambience_bed.wav"
if shot04_ambience.exists():
    print("  [✓] Blending festival crowd ambience bed for Shot 4...")
    shot04_mixed = TEMP_DIR / "shot04_48k_mixed.wav"
    cmd_mix = [
        "ffmpeg", "-y",
        "-i", str(TEMP_DIR / "shot04_48k_stereo.wav"),
        "-i", str(shot04_ambience),
        "-filter_complex",
        "[0:a]volume=1.0[a0];"
        "[1:a]volume=0.30,afade=t=in:st=0:d=1.0,afade=t=out:st=8.5:d=1.5[a1];"
        "[a0][a1]amix=inputs=2:duration=first:dropout_transition=2[aout]",
        "-map", "[aout]",
        "-ar", "48000",
        str(shot04_mixed)
    ]
    subprocess.run(cmd_mix, check=True, capture_output=True)
    shutil.move(str(shot04_mixed), str(TEMP_DIR / "shot04_48k_stereo.wav"))
    print("  [✓] Blended high-end festival ambience into Shot 4 audio.")

# 3. Create Shot 4 video with 1.5s tail hold (tpad) so that total duration after 3x0.5s xfade is EXACTLY 40.00s
print("\n--- Step 2: Preparing Video Streams (1.5s Tail Pad for Shot 4) ---")
shot04_padded = TEMP_DIR / "shot04_padded_11s5.mp4"
cmd_pad_v = [
    "ffmpeg", "-y",
    "-i", str(shot04),
    "-filter_complex", "[0:v]tpad=stop_mode=clone:stop_duration=1.5[v]",
    "-map", "[v]",
    "-c:v", "libx264", "-crf", "18", "-preset", "fast", "-pix_fmt", "yuv420p",
    str(shot04_padded)
]
subprocess.run(cmd_pad_v, check=True, capture_output=True)
print(f"  [✓] Shot 4 padded video created: {shot04_padded.name}")

# Also pad Shot 4 audio by 1.5s with gentle natural fadeout
shot04_audio_padded = TEMP_DIR / "shot04_audio_padded_11s5.wav"
cmd_pad_a = [
    "ffmpeg", "-y",
    "-i", str(TEMP_DIR / "shot04_48k_stereo.wav"),
    "-af", "apad=pad_dur=1.5,afade=t=out:st=10.0:d=1.5",
    str(shot04_audio_padded)
]
subprocess.run(cmd_pad_a, check=True, capture_output=True)
print(f"  [✓] Shot 4 padded audio created: {shot04_audio_padded.name}")

# 4. Assemble each shot with its clean 48k stereo audio
prepared_shots = []
shot_inputs = [
    (shot01, TEMP_DIR / "shot01_48k_stereo.wav", TEMP_DIR / "prep_shot01.mp4"),
    (shot02, TEMP_DIR / "shot02_48k_stereo.wav", TEMP_DIR / "prep_shot02.mp4"),
    (shot03, TEMP_DIR / "shot03_48k_stereo.wav", TEMP_DIR / "prep_shot03.mp4"),
    (shot04_padded, shot04_audio_padded, TEMP_DIR / "prep_shot04.mp4")
]

for v_in, a_in, out_p in shot_inputs:
    cmd_mux = [
        "ffmpeg", "-y",
        "-i", str(v_in),
        "-i", str(a_in),
        "-map", "0:v", "-map", "1:a",
        "-c:v", "copy",
        "-c:a", "aac", "-b:a", "256k", "-ar", "48000",
        str(out_p)
    ]
    subprocess.run(cmd_mux, check=True, capture_output=True)
    prepared_shots.append(out_p)
    print(f"  [✓] Prepared: {out_p.name}")

# 5. Build FlowKit Seamless xfade filter complex
print("\n--- Step 3: Executing FlowKit Seamless Multi-Shot Stitching ---")
raw_stitched = TEMP_DIR / "prologue_stitched_raw.mp4"

filter_complex = (
    # Video crossfades:
    # Shot 1 dur = 10.0s -> offset 9.5s
    "[0:v][1:v]xfade=transition=fade:duration=0.5:offset=9.5[v01];"
    # v01 dur = 19.5s -> offset 19.0s
    "[v01][2:v]xfade=transition=fade:duration=0.5:offset=19.0[v02];"
    # v02 dur = 29.0s -> offset 28.5s
    "[v02][3:v]xfade=transition=fade:duration=0.5:offset=28.5[vmaster];"
    # Audio crossfades (identical offsets and duration):
    "[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 = [
    "ffmpeg", "-y",
    "-i", str(prepared_shots[0]),
    "-i", str(prepared_shots[1]),
    "-i", str(prepared_shots[2]),
    "-i", str(prepared_shots[3]),
    "-filter_complex", filter_complex,
    "-map", "[vmaster]",
    "-map", "[amaster]",
    "-c:v", "libx264", "-crf", "18", "-preset", "slow", "-pix_fmt", "yuv420p",
    "-c:a", "aac", "-b:a", "256k", "-ar", "48000",
    str(raw_stitched)
]

print("Running FFmpeg stitch...")
res = subprocess.run(cmd_stitch, capture_output=True, text=True)
if res.returncode != 0:
    print("[!] Stitch failed:", res.stderr)
    sys.exit(1)
print(f"  [✓] Raw stitch completed: {raw_stitched.name}")

# 6. Two-Pass EBU R128 Loudness Normalization to -14.0 LUFS
print("\n--- Step 4: Two-Pass EBU R128 Loudness Normalization (-14.0 LUFS) ---")
sys.path.append("05_Production_Pipeline")
from audio_continuity_engine import AudioContinuityEngine
ace = AudioContinuityEngine()

final_master = EXPORTS_DIR / "thap_ngu_nien_prologue_master_40s.mp4"
norm_ok = ace.normalize_loudness(
    str(raw_stitched),
    str(final_master),
    target_lufs=-14.0,
    two_pass=True
)

if not norm_ok:
    print("[!] Loudness normalization failed!")
    sys.exit(1)

# Also sync to 04_Assets/videos
video_dest = VIDEOS_DIR / "prologue_hoai_niem_198x_to_gia_tinh_40s.mp4"
shutil.copy2(final_master, video_dest)
print(f"  [✓] Master video synced to: {video_dest}")
print(f"  [✓] Master video exported to: {final_master}")

# 7. Verification & Probe
print("\n--- Step 5: Final Quality Verification ---")
c_probe = [
    "ffprobe", "-v", "quiet", "-print_format", "json",
    "-show_format", "-show_streams", str(final_master)
]
p_res = subprocess.run(c_probe, capture_output=True, text=True)
p_data = json.loads(p_res.stdout)
dur = float(p_data["format"].get("duration", 0))
size_mb = int(p_data["format"].get("size", 0)) / (1024 * 1024)

v_stream = next(s for s in p_data["streams"] if s["codec_type"] == "video")
a_stream = next(s for s in p_data["streams"] if s["codec_type"] == "audio")

loud_metrics = ace.measure_loudness(str(final_master))

print("=" * 60)
print(f"🎬 KẾT QUẢ SẢN XUẤT PROLOGUE 40S FLOWKIT MASTER:")
print(f"  Thời lượng: {dur:.2f} giây (Chuẩn 40s điện ảnh)")
print(f"  Dung lượng: {size_mb:.2f} MB")
print(f"  Hình ảnh:   {v_stream.get('width')}x{v_stream.get('height')} @ {v_stream.get('r_frame_rate')} {v_stream.get('codec_name')} (CRF 18 slow)")
print(f"  Âm thanh:   {a_stream.get('codec_name')} {a_stream.get('sample_rate')}Hz {a_stream.get('channels')}ch (Stereo 256kbps)")
print(f"  Loudness:   {loud_metrics.get('input_i')} LUFS (Chuẩn EBU R128: -14.0 LUFS)")
print(f"  True Peak:  {loud_metrics.get('input_tp')} dBTP (Trần chuẩn: -1.0 dBTP)")
print(f"  LRA:        {loud_metrics.get('input_lra')} LU")
print("=" * 60)
