import os
import subprocess
import cv2
import numpy as np
from PIL import Image, ImageDraw, ImageFont, ImageFilter
from pathlib import Path

BASE_DIR = Path(__file__).resolve().parent.parent.parent
VIDEOS_DIR = BASE_DIR / "04_Assets" / "videos"

def generate_shot4_clean():
    src_video = r"C:\Users\Admin\Downloads\media-generation-prologue-shot-4-gia-tinh-revea-0-75a0f7f5-79b4-4888-afc1-d8ea3f51e23c.mp4"
    dst_video = VIDEOS_DIR / "prologue_shot_04_gia_tinh_trieu_minh_10s.mp4"

    if not os.path.exists(src_video):
        print(f"[!] File nguồn không tồn tại: {src_video}")
        return

    cap = cv2.VideoCapture(src_video)
    fps = cap.get(cv2.CAP_PROP_FPS) or 24.0
    w = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) or 1280
    h = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) or 720
    total = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))

    # Pre-render the full-opacity overlay
    overlay_full = Image.new('RGBA', (w, h), (0, 0, 0, 0))

    # Exact bounding box covering ONLY the old text lines (300 to 980, 530 to 678)
    rx1, ry1, rx2, ry2 = 300, 530, 980, 678
    pw, ph = rx2 - rx1, ry2 - ry1

    # Create antique lacquer gradient patch
    patch = Image.new('RGBA', (pw, ph), (0, 0, 0, 0))
    dp = ImageDraw.Draw(patch)

    for py in range(ph):
        for px in range(pw):
            nx = (px - pw/2) / (pw/2)
            ny = (py - ph/2) / (ph/2)
            dist = np.sqrt(nx**2 * 0.4 + ny**2 * 1.6)
            
            # Deep imperial maroon lacquer matching surrounding wood (R=38~58, G=3~9, B=5~11)
            vignette = max(0.0, 1.0 - 0.35 * dist)
            r = int(38 + 20 * vignette)
            g = int(3 + 6 * vignette)
            b = int(5 + 6 * vignette)
            dp.point((px, py), fill=(r, g, b, 255))

    # Soft feathered alpha mask to blend seamlessly into surrounding lacquer
    mask_shape = Image.new('L', (pw, ph), 0)
    dm = ImageDraw.Draw(mask_shape)
    dm.rounded_rectangle([(8, 8), (pw - 8, ph - 8)], radius=16, fill=255)
    mask_shape = mask_shape.filter(ImageFilter.GaussianBlur(radius=6))

    overlay_full.paste(patch, (rx1, ry1), mask=mask_shape)

    # Draw single line: 'Năm Gia Tĩnh, triều Minh'
    draw = ImageDraw.Draw(overlay_full)
    font = ImageFont.truetype('C:/Windows/Fonts/timesbd.ttf', 44)
    text = 'Năm Gia Tĩnh, triều Minh'

    bbox = draw.textbbox((0, 0), text, font=font)
    tw = bbox[2] - bbox[0]
    th = bbox[3] - bbox[1]

    # Center inside plaque: x center = 640, y center = 605
    tx = (w - tw) // 2
    ty = 605 - th // 2 - 2

    # Shadow & metallic gold styling
    for ox, oy in [(-2, 0), (2, 0), (0, -2), (0, 2), (-1, -1), (1, 1), (2, 3), (3, 4)]:
        draw.text((tx + ox, ty + oy), text, font=font, fill=(12, 2, 3, 240))

    for ox in [-1, 0, 1]:
        for oy in [-1, 0, 1]:
            draw.text((tx + ox, ty + oy), text, font=font, fill=(255, 195, 75, 90))

    draw.text((tx, ty), text, font=font, fill=(255, 230, 145, 255))

    fourcc = cv2.VideoWriter_fourcc(*'mp4v')
    temp_dst = VIDEOS_DIR / "temp_shot4_noaudio.mp4"
    out = cv2.VideoWriter(str(temp_dst), fourcc, fps, (w, h))

    print(f"Processing {total} frames for Shot 4...")
    for i in range(total):
        ret, frame = cap.read()
        if not ret:
            break

        # Calculate alpha based on frame index
        if i < 48:
            alpha = 0.0
        elif 48 <= i < 64:
            alpha = (i - 48) / 16.0
        elif 64 <= i <= 220:
            alpha = 1.0
        else: # 220 < i < 240
            alpha = max(0.0, 1.0 - (i - 220) / 19.0)

        if alpha > 0.0:
            pil_frame = Image.fromarray(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))
            if alpha < 1.0:
                # Scale alpha of overlay
                r, g, b, a = overlay_full.split()
                a_scaled = a.point(lambda p: int(p * alpha))
                overlay_cur = Image.merge('RGBA', (r, g, b, a_scaled))
            else:
                overlay_cur = overlay_full

            comp = Image.alpha_composite(pil_frame.convert('RGBA'), overlay_cur).convert('RGB')
            frame = cv2.cvtColor(np.array(comp), cv2.COLOR_RGB2BGR)

        out.write(frame)

    cap.release()
    out.release()

    # Mux patched video with original audio using ffmpeg
    cmd = [
        "ffmpeg", "-y",
        "-i", str(temp_dst),
        "-i", src_video,
        "-map", "0:v:0",
        "-map", "1:a:0",
        "-c:v", "libx264",
        "-crf", "18",
        "-pix_fmt", "yuv420p",
        "-c:a", "aac",
        "-b:a", "128k",
        str(dst_video)
    ]
    subprocess.run(cmd, check=True)
    if temp_dst.exists():
        temp_dst.unlink()
    print(f"Successfully generated clean Shot 4 with audio: {dst_video.name}")

if __name__ == "__main__":
    generate_shot4_clean()
