#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Kieu Story AI Film Production Pipeline Helper (v2.0)
Quản lý prompt, kiểm tra tài nguyên đa tầng nhân vật, và hỗ trợ xuất video.
"""

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

# Đảm bảo UTF-8 trên Windows console
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
PROMPTS_DIR = BASE_DIR / "02_AI_Prompts"
ASSETS_DIR = BASE_DIR / "04_Assets"
EXPORTS_DIR = BASE_DIR / "06_Exports"


def load_json(file_path):
    if not file_path.exists():
        print(f"[!] Không tìm thấy file: {file_path}")
        return None
    with open(file_path, "r", encoding="utf-8") as f:
        return json.load(f)


def list_prompts():
    banana_file = PROMPTS_DIR / "gemini_banana_prompts.json"
    muse_file = PROMPTS_DIR / "muse_ai_video_prompts.json"
    
    banana_data = load_json(banana_file)
    muse_data = load_json(muse_file)
    
    print("\n" + "=" * 65)
    print("🎬 KIEU STORY - DANH MỤC TÀI NGUYÊN PROMPT AI TOÀN DIỆN (V2.0)")
    print("=" * 65)
    
    if banana_data:
        print("\n[1] GEMINI BANANA (IMAGE GENERATION) - CÁC NHÓM NHÂN VẬT:")
        chars_group = banana_data.get("characters", {})
        total_chars = 0
        for group_key, chars_dict in chars_group.items():
            print(f"\n  📁 Nhóm [{group_key}]:")
            for char_id, char_val in chars_dict.items():
                total_chars += 1
                role = char_val.get("role_type", "Nhân vật")
                name = char_val.get("character_name", char_id)
                print(f"     • [{char_id}]: {name} ({role})")
        print(f"\n  👉 Tổng số tạo hình nhân vật thiết kế: {total_chars}")
        
        print("\n[2] BỐI CẢNH (ENVIRONMENTS):")
        for key, val in banana_data.get("environments", {}).items():
            print(f"  • [{key}]: {val.get('name')}")
            
        print("\n[3] KEYFRAMES TRỌNG ĐIỂM (CRITICAL KEYFRAMES):")
        for key, val in banana_data.get("critical_keyframes", {}).items():
            print(f"  • [{key}]: {val.get('scene')}")

    if muse_data:
        print("\n[4] MUSE.AI (VIDEO MOTION GENERATION):")
        for key, val in muse_data.get("motion_prompts", {}).items():
            print(f"  • [{key}]: {val.get('scene_title')} ({val.get('mode')}, {val.get('duration_sec')}s)")
    print("\n" + "=" * 65 + "\n")


def export_prompts_to_txt():
    banana_file = PROMPTS_DIR / "gemini_banana_prompts.json"
    muse_file = PROMPTS_DIR / "muse_ai_video_prompts.json"
    
    banana_data = load_json(banana_file)
    muse_data = load_json(muse_file)
    
    export_folder = PROMPTS_DIR / "exported_txt"
    export_folder.mkdir(parents=True, exist_ok=True)
    
    count = 0
    if banana_data:
        master_anchor = banana_data.get("master_style_anchor", "")
        chars_group = banana_data.get("characters", {})
        
        for group_key, chars_dict in chars_group.items():
            group_folder = export_folder / "characters" / group_key
            group_folder.mkdir(parents=True, exist_ok=True)
            
            for char_id, char_val in chars_dict.items():
                txt_path = group_folder / f"{char_id}.txt"
                content = f"--- {char_val.get('character_name')} ({char_val.get('role_type')}) ---\n"
                content += f"Nhóm thư mục: {group_key}\n\n"
                content += f"[16:9 Cinema Prompt]:\n{char_val.get('prompt_16x9')}\n\n"
                content += f"[9:16 Shorts Prompt]:\n{char_val.get('prompt_9x16')}\n\n"
                content += f"[Master Style Anchor]:\n{master_anchor}\n"
                txt_path.write_text(content, encoding="utf-8")
                count += 1

        # Export environments
        env_folder = export_folder / "environments"
        env_folder.mkdir(exist_ok=True)
        for key, val in banana_data.get("environments", {}).items():
            txt_path = env_folder / f"{key}.txt"
            content = f"--- Bối cảnh: {val.get('name')} ---\n\n"
            content += f"[16:9 Prompt]:\n{val.get('prompt_16x9')}\n"
            txt_path.write_text(content, encoding="utf-8")
            count += 1

    if muse_data:
        video_folder = export_folder / "video_motion"
        video_folder.mkdir(exist_ok=True)
        for key, val in muse_data.get("motion_prompts", {}).items():
            txt_path = video_folder / f"{key}.txt"
            content = f"--- {val.get('scene_title')} ---\n\n"
            content += f"Chế độ: {val.get('mode')}\n"
            content += f"Thời lượng: {val.get('duration_sec')} giây\n"
            content += f"Chuyển động camera: {val.get('camera_motion')}\n"
            if val.get('reference_start_frame'):
                content += f"Frame tham chiếu đầu vào (Start Frame): {val.get('reference_start_frame')}\n"
            if val.get('audio_prompt'):
                content += f"\n[Chỉ Thị Âm Thanh / Audio Directive]:\n{val.get('audio_prompt')}\n"
            content += f"\n[Motion & Audio Combined Prompt for Muse.ai]:\n{val.get('motion_prompt')}\n"
            txt_path.write_text(content, encoding="utf-8")
            count += 1

    print(f"[✓] Đã xuất thành công {count} prompt text files phân cấp ra: {export_folder}")


def check_status():
    print("\n" + "=" * 65)
    print("📊 KIEU STORY - TRẠNG THÁI DỰ ÁN & TÀI NGUYÊN (PHÂN TẦNG ĐẦY ĐỦ)")
    print("=" * 65)
    
    SCRIPTS_DIR = BASE_DIR / "01_Scripts_And_Episodes"
    print("\n[Văn bản Nguồn & Kịch bản 01_Scripts_And_Episodes/]:")
    if SCRIPTS_DIR.exists():
        for script_file in sorted(SCRIPTS_DIR.glob("*.*")):
            size_kb = script_file.stat().st_size / 1024
            print(f"  📜 {script_file.name:<48} : {size_kb:8.1f} KB")
    else:
        print("  [CHƯA TẠO]")

    char_base = ASSETS_DIR / "characters"
    print("\n[Thư mục Nhân vật 04_Assets/characters/]:")
    if char_base.exists():
        subdirs = sorted([d for d in char_base.iterdir() if d.is_dir()])
        for d in subdirs:
            files = list(d.glob("*.*"))
            print(f"  📁 {d.name:<32} : {len(files)} files")
    else:
        print("  [CHƯA TẠO]")

    print("\n[Thư mục Bối cảnh & Âm thanh]:")
    other_assets = [
        ("04_Assets/backgrounds", ASSETS_DIR / "backgrounds"),
        ("04_Assets/keyframes", ASSETS_DIR / "keyframes"),
        ("04_Assets/audio_sfx", ASSETS_DIR / "audio_sfx"),
    ]
    for name, path in other_assets:
        if path.exists():
            files = list(path.glob("*.*"))
            print(f"  📁 {name:<32} : {len(files)} files")
        else:
            print(f"  📁 {name:<32} : [CHƯA TẠO]")

    print("\n[Thư mục Xuất Bản Video 06_Exports/]:")
    export_dirs = [
        ("06_Exports/episodes_30m", EXPORTS_DIR / "episodes_30m"),
        ("06_Exports/shorts_5m", EXPORTS_DIR / "shorts_5m"),
        ("06_Exports/shorts_1m_9x16", EXPORTS_DIR / "shorts_1m_9x16"),
    ]
    for name, path in export_dirs:
        if path.exists():
            files = list(path.glob("*.*"))
            print(f"  🎬 {name:<32} : {len(files)} files")
        else:
            print(f"  🎬 {name:<32} : [CHƯA TẠO]")
            
    print("=" * 65 + "\n")


def make_short(input_video, output_video, start_time="00:00:00", duration="60"):
    ffmpeg_exe = Path(sys.executable).parent / "ffmpeg.exe"
    if not ffmpeg_exe.exists():
        ffmpeg_exe = "ffmpeg"

    filter_complex = (
        "[0:v]split=2[fg][bg];"
        "[bg]scale=1080:1920:force_original_aspect_ratio=increase,crop=1080:1920,boxblur=20:5[bg_blurred];"
        "[fg]scale=1080:1920:force_original_aspect_ratio=decrease[fg_scaled];"
        "[bg_blurred][fg_scaled]overlay=(W-w)/2:(H-h)/2[v]"
    )

    cmd = [
        str(ffmpeg_exe), "-y",
        "-ss", str(start_time),
        "-t", str(duration),
        "-i", str(input_video),
        "-filter_complex", filter_complex,
        "-map", "[v]",
        "-map", "0:a?",
        "-c:v", "h264_nvenc",
        "-preset", "p4",
        "-cq", "20",
        "-c:a", "aac",
        "-b:a", "192k",
        str(output_video)
    ]

    print(f"[*] Đang thực thi render Shorts 9:16 NVENC...")
    try:
        subprocess.run(cmd, check=True)
        print(f"[✓] Đã xuất thành công Short 9:16: {output_video}")
    except subprocess.CalledProcessError as e:
        print(f"[!] Lỗi khi chạy ffmpeg nvenc: {e}")
        print("[*] Thử lại với CPU libx264...")
        cmd[cmd.index("h264_nvenc")] = "libx264"
        cmd[cmd.index("-cq")] = "-crf"
        if "p4" in cmd:
            cmd[cmd.index("p4")] = "slow"
        subprocess.run(cmd, check=True)
        print(f"[✓] Xuất thành công (CPU fallback): {output_video}")


def reverse_video(input_video, output_video=None):
    """Đảo ngược 1 file video (hình ảnh + âm thanh) qua FFmpeg (-vf reverse -af areverse)."""
    in_path = Path(input_video).resolve()
    if not in_path.exists():
        print(f"[!] Không tìm thấy video: {in_path}")
        return False
    
    out_path = Path(output_video).resolve() if output_video else in_path
    temp_out = in_path.with_name(f"{in_path.stem}_rev_temp_{os.getpid()}{in_path.suffix}")

    ffmpeg_exe = Path(sys.executable).parent / "ffmpeg.exe"
    if not ffmpeg_exe.exists():
        ffmpeg_exe = "ffmpeg"

    cmd = [
        str(ffmpeg_exe), "-y",
        "-i", str(in_path),
        "-vf", "reverse",
        "-af", "areverse",
        "-c:v", "libx264",
        "-crf", "18",
        "-preset", "slow",
        "-c:a", "aac",
        "-b:a", "192k",
        "-ar", "48000",
        str(temp_out)
    ]
    print(f"[*] Đang thực thi Reverse Motion cho: {in_path.name}...")
    res = subprocess.run(cmd, capture_output=True, text=True)
    if res.returncode == 0 and temp_out.exists() and temp_out.stat().st_size > 1000:
        import shutil
        shutil.move(str(temp_out), str(out_path))
        print(f"[✓] Đã đảo ngược thành công: {out_path}")
        return True
    else:
        print(f"[!] Lỗi khi reverse video: {res.stderr}")
        if temp_out.exists():
            try:
                temp_out.unlink()
            except Exception:
                pass
        return False


def main():
    parser = argparse.ArgumentParser(description="Kieu Story Production Pipeline Helper v2.0")
    parser.add_argument("--list", action="store_true", help="Liệt kê danh sách prompt AI toàn diện")
    parser.add_argument("--export-prompts", action="store_true", help="Xuất prompt phân cấp ra các file txt tiện sử dụng")
    parser.add_argument("--status", action="store_true", help="Kiểm tra trạng thái tài nguyên dự án")
    parser.add_argument("--make-short", action="store_true", help="Cắt và tạo video ngắn dọc 9:16")
    parser.add_argument("--reverse-video", action="store_true", help="Đảo ngược video và âm thanh qua FFmpeg")
    parser.add_argument("--input", type=str, help="Đường dẫn video đầu vào")
    parser.add_argument("--output", type=str, help="Đường dẫn video đầu ra")
    parser.add_argument("--start", type=str, default="00:00:00", help="Thời điểm bắt đầu (HH:MM:SS)")
    parser.add_argument("--duration", type=str, default="58", help="Thời lượng (giây)")

    args = parser.parse_args()

    if args.list:
        list_prompts()
    elif args.export_prompts:
        export_prompts_to_txt()
    elif args.status:
        check_status()
    elif args.reverse_video:
        if not args.input:
            print("[!] Vui lòng chỉ định --input cho --reverse-video")
            return
        reverse_video(args.input, args.output)
    elif args.make_short:
        if not args.input or not args.output:
            print("[!] Vui lòng chỉ định --input và --output khi dùng --make-short")
            return
        make_short(args.input, args.output, args.start, args.duration)
    else:
        parser.print_help()


if __name__ == "__main__":
    main()
