from PIL import Image, ImageDraw, ImageFont, ImageFilter
from pathlib import Path
import subprocess, math, os, textwrap, shutil

BASE = Path('/root/life-rpg-validation')
OUT = BASE / 'videos'
FRAMES = BASE / 'tmp_frames'
OUT.mkdir(parents=True, exist_ok=True)
FRAMES.mkdir(parents=True, exist_ok=True)
W, H = 1080, 1920
FPS = 30
DURATION = 12

FONT_BOLD = '/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf'
FONT_REG = '/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf'

def font(size, bold=False):
    return ImageFont.truetype(FONT_BOLD if bold else FONT_REG, size)

def wrap(draw, text, fnt, max_width):
    lines=[]
    for para in text.split('\n'):
        if not para:
            lines.append('')
            continue
        words=para.split(' ')
        line=''
        for w in words:
            test=(line+' '+w).strip()
            if draw.textbbox((0,0), test, font=fnt)[2] <= max_width:
                line=test
            else:
                if line: lines.append(line)
                line=w
        if line: lines.append(line)
    return lines

def rounded(draw, xy, r, fill, outline=None, width=1):
    draw.rounded_rectangle(xy, radius=r, fill=fill, outline=outline, width=width)

def gradient_bg(t, accent=(139,92,246)):
    img = Image.new('RGB', (W,H), (7,10,18))
    pix = img.load()
    for y in range(H):
        k = y/H
        base = (int(7*(1-k)+2*k), int(10*(1-k)+3*k), int(18*(1-k)+10*k))
        for x in range(W):
            pix[x,y] = base
    overlay = Image.new('RGBA',(W,H),(0,0,0,0))
    d=ImageDraw.Draw(overlay)
    cx = int(W*(0.18+0.06*math.sin(t*2)))
    cy = int(H*(0.08+0.03*math.cos(t*3)))
    for rad, alpha in [(520,70),(360,55),(210,45)]:
        d.ellipse((cx-rad,cy-rad,cx+rad,cy+rad), fill=(*accent,alpha))
    cx2 = int(W*(0.88+0.03*math.cos(t*2)))
    cy2 = int(H*(0.35+0.04*math.sin(t*2)))
    for rad, alpha in [(430,45),(260,38)]:
        d.ellipse((cx2-rad,cy2-rad,cx2+rad,cy2+rad), fill=(34,211,238,alpha))
    overlay = overlay.filter(ImageFilter.GaussianBlur(70))
    img = Image.alpha_composite(img.convert('RGBA'), overlay)
    d=ImageDraw.Draw(img)
    for x in range(0,W,72):
        d.line((x,0,x,H), fill=(255,255,255,12), width=1)
    for y in range(0,H,72):
        d.line((0,y,W,y), fill=(255,255,255,10), width=1)
    return img

def draw_centered(draw, text, y, fnt, fill=(249,250,251), max_width=900, spacing=8):
    lines=wrap(draw,text,fnt,max_width)
    total=sum(draw.textbbox((0,0),ln,font=fnt)[3]-draw.textbbox((0,0),ln,font=fnt)[1] for ln in lines)+spacing*(len(lines)-1)
    yy=y-total/2
    for ln in lines:
        bb=draw.textbbox((0,0),ln,font=fnt)
        x=(W-(bb[2]-bb[0]))/2
        draw.text((x,yy),ln,font=fnt,fill=fill)
        yy += (bb[3]-bb[1])+spacing

def draw_badge(draw, text, y):
    f=font(34, True)
    bb=draw.textbbox((0,0), text, font=f)
    tw,th=bb[2]-bb[0],bb[3]-bb[1]
    x=(W-tw-54)/2
    rounded(draw,(x,y,x+tw+54,y+th+30),32,(139,92,246,44),(196,181,253,90),2)
    draw.text((x+27,y+13),text,font=f,fill=(221,214,254))

def draw_card(draw, y, title, sub, accent=(139,92,246), progress=None):
    x=96; w=W-192; h=178
    rounded(draw,(x,y,x+w,y+h),32,(17,24,39,235),(139,92,246,120),2)
    draw.text((x+34,y+28),title,font=font(44, True),fill=(255,255,255))
    draw.text((x+34,y+88),sub,font=font(30),fill=(203,213,225))
    if progress is not None:
        rounded(draw,(x+34,y+132,x+w-34,y+148),8,(255,255,255,55))
        rounded(draw,(x+34,y+132,x+34+(w-68)*progress,y+148),8,accent)

def render_video(name, frames_fn):
    vdir=FRAMES/name
    if vdir.exists(): shutil.rmtree(vdir)
    vdir.mkdir(parents=True)
    total=FPS*DURATION
    for i in range(total):
        t=i/FPS
        img=frames_fn(t)
        img.save(vdir/f'frame_{i:04d}.png')
    out=OUT/f'{name}.mp4'
    cmd=['ffmpeg','-y','-framerate',str(FPS),'-i',str(vdir/'frame_%04d.png'),'-c:v','libx264','-pix_fmt','yuv420p','-movflags','+faststart',str(out)]
    subprocess.run(cmd,check=True,stdout=subprocess.DEVNULL,stderr=subprocess.DEVNULL)
    return out

def video_core(t):
    img=gradient_bg(t)
    d=ImageDraw.Draw(img)
    draw_badge(d,'LifeQuest concept',92)
    if t<2.4:
        draw_centered(d,'What if your\nreal life was an RPG?',590,font(86,True),max_width=900,spacing=16)
        draw_centered(d,'Building an AI-powered Life RPG',860,font(34),fill=(203,213,225))
    elif t<8.9:
        items=[('Workout','+25 Strength XP'),('Deep work','Boss HP -30'),('Read 10 pages','+15 Intelligence'),('Sleep on time','Recovery bonus')]
        draw_centered(d,'Real actions become progression',250,font(52,True))
        for idx,(a,b) in enumerate(items):
            appear=2.7+idx*1.35
            if t>=appear:
                draw_card(d,400+idx*220,a,b,accent=(34,211,238))
    else:
        draw_centered(d,'AI Game Master\ncreates your daily quests.',590,font(72,True),max_width=900,spacing=12)
        draw_centered(d,'Join the beta waitlist',870,font(44,True),fill=(196,181,253))
    return img

def video_adhd(t):
    img=gradient_bg(t,accent=(34,211,238))
    d=ImageDraw.Draw(img)
    draw_badge(d,'For gamer brains',92)
    if t<3:
        draw_centered(d,'My brain ignores reminders.\nIt understands quests.',590,font(72,True),max_width=900,spacing=14)
    elif t<8.5:
        lines=['No boring streaks.','No guilt dashboard.','No 47 checkboxes.','Just quests, XP, boss fights.']
        draw_centered(d,'A habit tracker for people\nwho hate habit trackers',260,font(54,True),spacing=8)
        for idx,line in enumerate(lines):
            if t>3.2+idx*1.1:
                draw_card(d,470+idx*205,line,'',accent=(139,92,246))
    else:
        draw_centered(d,'Missed a day?\nRecovery quest unlocked.',615,font(72,True),max_width=900,spacing=12)
        draw_centered(d,'Would this help you?',900,font(44,True),fill=(125,211,252))
    return img

def video_boss(t):
    img=gradient_bg(t,accent=(239,68,68))
    d=ImageDraw.Draw(img)
    draw_badge(d,'Weekly boss fight',92)
    if t<2.5:
        draw_centered(d,'What if doomscrolling\nwas a weekly boss?',610,font(74,True),max_width=900,spacing=12)
    else:
        draw_centered(d,'Doomscrolling Hydra',240,font(64,True),fill=(254,215,170))
        hp=max(0.12,1-(t-2.5)/10)
        draw_card(d,360,'Boss HP',f'{int(hp*100)}/100 remaining',accent=(239,68,68),progress=hp)
        actions=[('30 min deep work','-30 HP'),('No phone before bed','-25 HP'),('Read 10 pages','-15 HP')]
        for idx,(a,b) in enumerate(actions):
            if t>3.5+idx*1.6:
                draw_card(d,610+idx*210,a,b,accent=(245,158,11))
        if t>9.5:
            draw_centered(d,'Your real blockers\nbecome beatable.',1480,font(56,True),max_width=900)
    return img

if __name__=='__main__':
    outs=[]
    outs.append(render_video('01_core_fantasy_life_rpg', video_core))
    outs.append(render_video('02_adhd_gamer_brain_quests', video_adhd))
    outs.append(render_video('03_doomscrolling_hydra_boss', video_boss))
    for o in outs: print(o)
