from pathlib import Path
import subprocess

ROOT=Path('/home/spazio/cosmos-reels')
SRC=ROOT/'source'; TMP=ROOT/'tmp-v3'; OUT=ROOT/'out-v3'; SUB=ROOT/'subs-v3'
for p in (TMP,OUT,SUB): p.mkdir(parents=True,exist_ok=True)
FONTS='/home/spazio/cosmos-reels/fonts'

# V3 FACE-INTEGRITY EDIT:
# Close/selfie footage whose face was already cropped in-camera is excluded.
# Only landscapes, full-body/long shots, back/side creator shots, and macro process shots.
REELS={
'01_old_life_still_works_v3':{
 'clips':[('20261017_165151.mp4',3.2,3.2),('20261017_165151.mp4',6.5,3.2),('20261017_165151.mp4',9.5,3.2),('20261017_165151.mp4',12.2,3.5)],
 'events':[(0,3.0,'YOUR OLD LIFE\\NSTILL WORKS.','main'),(3.0,8.9,'IT SIMPLY CANNOT HOLD\\NWHO YOU ARE BECOMING.','main'),(8.9,12.8,'NOT FAILURE.\\NEXPANSION.','accent')]
},
'02_you_are_not_lost_v3':{
 'clips':[('20261017_165151.mp4',3.5,3.2),('20261017_165151.mp4',6.8,3.2),('20261017_165151.mp4',9.8,3.2),('20261017_165151.mp4',11.8,4.0)],
 'events':[(0,3.0,'YOU ARE NOT LOST.','accent'),(3.0,8.8,'YOU ARE BETWEEN\\NWHAT NO LONGER FITS','main'),(8.8,13.3,'AND WHAT HAS NOT\\NTAKEN SHAPE YET.','main')]
},
'03_choose_a_season_v3':{
 'clips':[('20261026_014149.mp4',150,3.2),('20261026_014149.mp4',160,3.2),('20261026_020000.mp4',22,3.2),('20261026_020000.mp4',33,3.5)],
 'events':[(0,4.2,'YOU DO NOT NEED\\NA SMALLER SELF.','main'),(4.2,8.7,'CHOOSE WHAT BECOMES REAL\\NIN THIS SEASON.','main'),(8.7,12.8,'CHOOSE A SEASON.\\NKEEP YOUR WHOLENESS.','accent')]
},
'04_visibility_before_confidence_v3':{
 'clips':[('20261026_014149.mp4',150,3.5),('20261026_014149.mp4',160,3.5),('20261017_165151.mp4',5.5,3.5),('20261017_165151.mp4',9.0,4.5)],
 'events':[(0,3.7,'YOU MAY NOT\\NFEEL READY.','main'),(3.7,7.4,'CONFIDENCE DOES NOT\\NCOME FIRST.','main'),(7.4,10.8,'VISIBILITY DOES.','accent'),(10.8,14.8,'BE SEEN BEFORE\\NIT IS PERFECT.','main')]
},
'05_intuition_without_fantasy_v3':{
 'clips':[('20261026_015152.mp4',408,3.5),('20261026_015152.mp4',422,3.5),('20261026_020000.mp4',99,4.0),('20261026_020000.mp4',110,4.5)],
 'events':[(0,5.0,'WHEN YOU STOP LYING\\NTO YOURSELF,','main'),(5.0,8.4,'INTUITION\\NGETS LOUDER.','accent'),(8.4,11.9,'THEN TEST IT\\NIN MATERIAL LIFE.','main'),(11.9,15.2,'HONESTY. ACTION. FEEDBACK.','accent')]
}}

def t(s):
 h=int(s//3600);m=int((s%3600)//60);q=s%60
 return f'{h}:{m:02d}:{q:05.2f}'

def make_ass(name,cfg,dur):
 hdr='''[Script Info]
ScriptType: v4.00+
PlayResX: 1080
PlayResY: 1920
WrapStyle: 2
ScaledBorderAndShadow: yes

[V4+ Styles]
Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding
Style: main,Cormorant Garamond,67,&H00F7F0E8,&H000000FF,&H700B0711,&H00000000,-1,0,0,0,100,100,2.2,0,1,2.2,0,8,130,130,1475,1
Style: accent,Cormorant Garamond,73,&H0064BDE1,&H000000FF,&H700B0711,&H00000000,-1,0,0,0,100,100,2.6,0,1,2.2,0,8,130,130,1475,1
Style: brand,Cormorant Garamond,31,&H00D0B46D,&H000000FF,&H600B0711,&H00000000,-1,0,0,0,100,100,6,0,1,1.5,0,2,120,120,315,1
Style: index,Cormorant Garamond,27,&H00D0B46D,&H000000FF,&H600B0711,&H00000000,-1,0,0,0,100,100,3,0,1,1.2,0,9,115,115,100,1

[Events]
Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
'''
 lines=[]
 for a,b,text,style in cfg['events']:
  lines.append(f'Dialogue: 1,{t(a)},{t(b)},{style},,0,0,0,,{{\\pos(540,350)\\fad(220,220)}}{text}')
 lines.append(f'Dialogue: 1,{t(0)},{t(dur)},brand,,0,0,0,,COSMOS LUMINOSITY')
 lines.append(f'Dialogue: 1,{t(0)},{t(dur)},index,,0,0,0,,BETWEEN IDENTITIES  ·  {name[:2]}')
 p=SUB/(name+'.ass');p.write_text(hdr+'\n'.join(lines)+'\n');return p

for name,cfg in REELS.items():
 parts=[]
 for i,(fn,start,dur) in enumerate(cfg['clips']):
  dst=TMP/f'{name}_{i}.mp4';parts.append(dst)
  # Full 16:9 source retained. Main image begins at y=590, far below text baseline y=350.
  fc=("color=c=0x0B0711:s=1080x1920:r=30[base];"
      "[0:v]scale=1000:563:flags=lanczos,eq=contrast=1.035:saturation=.88:brightness=-.01,unsharp=5:5:.3:5:5:0[fg];"
      "[base][fg]overlay=40:590:shortest=1,drawbox=x=39:y=589:w=1002:h=565:color=0xE1BD64@.62:t=2,"
      "drawbox=x=0:y=0:w=1080:h=1920:color=0x341355@.08:t=fill,fps=30,format=yuv420p")
  subprocess.run(['ffmpeg','-y','-hide_banner','-loglevel','error','-ss',str(start),'-t',str(dur),'-i',str(SRC/fn),'-filter_complex',fc,'-an','-c:v','libx264','-preset','veryfast','-crf','19',str(dst)],check=True)
 lst=TMP/f'{name}.txt';lst.write_text('\n'.join(f"file '{x}'" for x in parts)+'\n')
 base=TMP/f'{name}_base.mp4';subprocess.run(['ffmpeg','-y','-hide_banner','-loglevel','error','-f','concat','-safe','0','-i',str(lst),'-c','copy',str(base)],check=True)
 dur=sum(x[2] for x in cfg['clips']);sub=make_ass(name,cfg,dur);final=OUT/f'{name}.mp4'
 subprocess.run(['ffmpeg','-y','-hide_banner','-loglevel','error','-i',str(base),'-vf',f"subtitles='{sub}':fontsdir='{FONTS}'",'-an','-c:v','libx264','-preset','medium','-crf','20','-profile:v','high','-level','4.1','-pix_fmt','yuv420p','-movflags','+faststart',str(final)],check=True)
 print(final,final.stat().st_size)
