"""Render Balimentari Monday Motivation video.
Generates frames with Pillow, encodes with FFmpeg, adds narration audio.
"""
import subprocess
import os
import math
from PIL import Image, ImageDraw, ImageFont

OUT_DIR = "/app/working/workspaces/default/OpenMontage/pipeline/balimentari-senin"
NARRATION = os.path.join(OUT_DIR, "narration.wav")
FRAMES_DIR = os.path.join(OUT_DIR, "frames")
OUTPUT = os.path.join(OUT_DIR, "balimentari_senin.mp4")
FONT_BOLD = "/usr/share/fonts/truetype/quicksand/Quicksand-Bold.ttf"
FONT_REGULAR = "/usr/share/fonts/truetype/quicksand/Quicksand-Regular.ttf"

W, H = 1080, 1920
FPS = 24

# Get narration duration
dur_cmd = ["ffprobe", "-v", "error", "-show_entries", "format=duration",
           "-of", "default=noprint_wrappers=1:nokey=1", NARRATION]
narration_dur = float(subprocess.run(dur_cmd, capture_output=True, text=True).stdout.strip())
total_dur = narration_dur + 1.5
total_frames = int(total_dur * FPS)
print(f"Narration: {narration_dur:.1f}s, Total: {total_dur:.1f}s, Frames: {total_frames}")

os.makedirs(FRAMES_DIR, exist_ok=True)

# Scene definitions with timing
scenes = [
    # (text_line1, text_line2, start_sec, end_sec, font_size1, font_size2, y_offset)
    ("The holiday", "is over.", 0.3, 2.5, 72, 88, 0.30),
    ("But today...", "is your fresh start.", 2.6, 5.5, 60, 72, 0.38),
    ("Your new", "beginning.", 5.6, 8.0, 64, 80, 0.44),
    ("The world", "is waiting.", 8.1, 10.5, 60, 68, 0.50),
    ("Take that", "first step.", 10.6, 12.8, 56, 72, 0.56),
]

# Color palette - warm sunrise gradient
bg_top = (26, 10, 46)     # dark purple
bg_bot = (180, 60, 40)    # warm orange-red
accent = (255, 180, 100)  # golden accent
text_color = (255, 255, 255)

def lerp_color(c1, c2, t):
    return tuple(int(c1[i] + (c2[i] - c1[i]) * t) for i in range(3))

print("Generating frames...")
for frame_idx in range(total_frames):
    t = frame_idx / FPS
    progress = t / total_dur
    
    # Create gradient background
    img = Image.new('RGB', (W, H))
    for y in range(H):
        y_ratio = y / H
        color = lerp_color(bg_top, bg_bot, y_ratio)
        # Slight warm pulse over time
        pulse = 1 + 0.05 * math.sin(t * 0.5 + y_ratio * 2)
        r = min(255, int(color[0] * pulse))
        g = min(255, int(color[1] * pulse))
        b = min(255, int(color[2] * pulse))
        for x in range(W):
            img.putpixel((x, y), (r, g, b))
    
    draw = ImageDraw.Draw(img)
    
    # Draw scene text
    for scene in scenes:
        text1, text2, s_start, s_end, fs1, fs2, y_off = scene
        if t < s_start - 0.3 or t > s_end + 0.3:
            continue
        
        # Calculate alpha (fade in/out)
        fade_dur = 0.35
        if t < s_start:
            alpha = 0
        elif t < s_start + fade_dur:
            alpha = (t - s_start) / fade_dur
        elif t < s_end - fade_dur:
            alpha = 1.0
        elif t < s_end:
            alpha = (s_end - t) / fade_dur
        else:
            alpha = 0
        
        if alpha <= 0:
            continue
        
        # Apply alpha to color
        c = tuple(int(255 * alpha + tc * (1 - alpha)) for tc in text_color)
        # Actually let's do proper alpha blending with bg
        bg_sample = img.getpixel((W//2, int(H * y_off)))
        c = tuple(int(bg_sample[i] * (1-alpha) + text_color[i] * alpha) for i in range(3))
        
        # Draw text
        y_center = int(H * y_off)
        
        font1 = ImageFont.truetype(FONT_BOLD, fs1)
        font2 = ImageFont.truetype(FONT_BOLD, fs2)
        
        # Line 1
        bbox1 = draw.textbbox((0, 0), text1, font=font1)
        tw1 = bbox1[2] - bbox1[0]
        th1 = bbox1[3] - bbox1[1]
        y1 = y_center - th1 - 10
        
        # Line 2  
        bbox2 = draw.textbbox((0, 0), text2, font=font2)
        tw2 = bbox2[2] - bbox2[0]
        th2 = bbox2[3] - bbox2[1]
        y2 = y_center + 10
        
        # Slight upward drift animation
        drift_y = 5 * math.sin(t * 1.5 + hash(text1) % 100)
        
        draw.text(((W - tw1) // 2, y1 + drift_y), text1, fill=c, font=font1)
        draw.text(((W - tw2) // 2, y2 + drift_y), text2, fill=c, font=font2)
    
    # Balimentari watermark - appears gradually
    if t > total_dur - 2.0:
        wm_alpha = min(1.0, (t - (total_dur - 2.0)) / 1.0)
        wm_font = ImageFont.truetype(FONT_BOLD, 36)
        wm_text = "Balimentari"
        wm_bbox = draw.textbbox((0, 0), wm_text, font=wm_font)
        wm_w = wm_bbox[2] - wm_bbox[0]
        bg_sample = img.getpixel((W//2, H - 120))
        wm_c = tuple(int(bg_sample[i] * (1-wm_alpha) + 255 * wm_alpha) for i in range(3))
        draw.text(((W - wm_w) // 2, H - 120), wm_text, fill=wm_c, font=wm_font)
    
    img.save(os.path.join(FRAMES_DIR, f"frame_{frame_idx:05d}.png"))
    
    if frame_idx % 50 == 0 or frame_idx == total_frames - 1:
        print(f"  Frame {frame_idx+1}/{total_frames} ({100*(frame_idx+1)/total_frames:.0f}%)")

print("Encoding video...")
# Encode frames to video with ffmpeg
encode_cmd = [
    "ffmpeg", "-y",
    "-framerate", str(FPS),
    "-i", os.path.join(FRAMES_DIR, "frame_%05d.png"),
    "-i", NARRATION,
    "-c:v", "libx264",
    "-preset", "fast",
    "-crf", "20",
    "-c:a", "aac",
    "-b:a", "128k",
    "-pix_fmt", "yuv420p",
    "-shortest",
    OUTPUT
]
proc = subprocess.run(encode_cmd, capture_output=True, text=True, timeout=120)

if proc.returncode == 0:
    size_mb = os.path.getsize(OUTPUT) / 1024 / 1024
    print(f"\n✅ VIDEO BERHASIL DIRENDER!")
    print(f"   Output: {OUTPUT}")
    print(f"   Size: {size_mb:.1f} MB")
    print(f"   Duration: {total_dur:.1f}s")
else:
    print("❌ Encode failed!")
    print("STDERR:", proc.stderr[-1500:])
