from pathlib import Path
import subprocess, os

ROOT=Path('/home/spazio/cosmos-reels')
SRC=ROOT/'source'; TMP=ROOT/'tmp'; OUT=ROOT/'out'; SUB=ROOT/'subs'
for p in (TMP,OUT,SUB): p.mkdir(parents=True,exist_ok=True)
FONT='/opt/cosmosluminosity/content/themes/clean/assets/fonts'

reels={
'01_old_life_still_works':{
 'clips':[('20261019_121805.mp4',18,3,656),('20261019_121805.mp4',24,3,656),('20261019_121805.mp4',48,3,656),('20261026_013647.mp4',83,3,656)],
 'duration':12,
 'events':[(0,3.0,'Your old life still works.','main'),(3.0,8.4,'It just no longer holds all of\nwho you are becoming.','main'),(8.4,11.4,'This is not failure.\nThis is becoming.','gold')]
},
'02_you_are_not_lost':{
 'clips':[('20261024_163840.mp4',8,3,656),('20261024_163840.mp4',21,4,656),('20261017_165151.mp4',64,3,900),('20261017_165151.mp4',72,3,800)],
 'duration':13,
 'events':[(0,2.7,'You are not lost.','gold'),(2.7,9.5,'You are between an identity\nthat no longer fits…','main'),(9.5,12.5,'…and a life that\nhas not taken shape yet.','main')]
},
'03_choose_a_season':{
 'clips':[('20261024_144707.mp4',7,3,656),('20261024_144707.mp4',14,3,656),('20261026_020000.mp4',22,3,656),('20261026_020000.mp4',33,3,656)],
 'duration':12,
 'events':[(0,4.2,"You don't need to choose\na smaller self.",'main'),(4.2,8.7,'Choose what becomes real\nin this season.','main'),(8.7,11.6,'Choose a season.\nNot a smaller identity.','gold')]
},
'04_visibility_before_confidence':{
 'clips':[('20261026_014149.mp4',100,4,656),('20261026_014149.mp4',120,4,656),('20261024_144707.mp4',14,3,656),('20261026_013647.mp4',133,4,656)],
 'duration':15,
 'events':[(0,3.8,'You may be waiting\nto feel ready.','main'),(3.8,8.2,"Confidence doesn't\ncome first.",'main'),(8.2,11.0,'Visibility does.','gold'),(11.0,14.5,"Be seen before\nit's perfect.",'main')]
},
'05_intuition_without_fantasy':{
 'clips':[('20261024_144951.mp4',14,3,656),('20261024_144951.mp4',21,4,656),('20261026_020000.mp4',99,4,656),('20261026_020000.mp4',110,4,656)],
 'duration':15,
 'events':[(0,5.2,'The moment you stop\nlying to yourself…','main'),(5.2,8.6,'…your intuition\ngets louder.','gold'),(8.6,12.0,'Then test what you hear\nin material life.','main'),(12.0,14.6,'Honesty. Action. Feedback.','gold')]
}}

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

def write_ass(name,cfg):
 # text safe zone: centered around upper-middle, clear of Instagram UI
 hdr='''[Script Info]\nScriptType: v4.00+\nPlayResX: 1080\nPlayResY: 1920\nWrapStyle: 2\nScaledBorderAndShadow: yes\n\n[V4+ Styles]\nFormat: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding\nStyle: main,Manrope SemiBold,64,&H00F8F3EC,&H000000FF,&HB0000000,&H78090510,-1,0,0,0,100,100,0,0,3,8,0,8,90,90,360,1\nStyle: gold,Cormorant Garamond SemiBold,78,&H0045DAF1,&H000000FF,&HB0000000,&H78090510,-1,-1,0,0,100,100,0,0,3,8,0,8,80,80,360,1\nStyle: brand,Manrope SemiBold,25,&H00D8B876,&H000000FF,&H80000000,&H00000000,-1,0,0,0,100,100,4,0,1,2,0,2,70,70,315,1\n\n[Events]\nFormat: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\n'''
 lines=[]
 for start,end,text,style in cfg['events']:
  text=text.replace('\n',r'\N')
  lines.append(f'Dialogue: 0,{ass_time(start)},{ass_time(end)},{style},,0,0,0,,{{\\fad(180,180)}}{text}')
 lines.append(f'Dialogue: 0,{ass_time(0)},{ass_time(cfg["duration"])},brand,,0,0,0,,COSMOS LUMINOSITY')
 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,x) in enumerate(cfg['clips']):
  p=TMP/f'{name}_{i}.mp4'; parts.append(p)
  vf=(f'crop=607:1080:{x}:0,scale=1080:1920:flags=lanczos,'
      f'eq=contrast=1.04:saturation=0.92:brightness=-0.015,'
      f'unsharp=5:5:0.35:5:5:0.0,fps=30,format=yuv420p')
  cmd=['ffmpeg','-y','-hide_banner','-loglevel','error','-ss',str(start),'-t',str(dur),'-i',str(SRC/fn),'-an','-vf',vf,'-c:v','libx264','-preset','veryfast','-crf','19','-movflags','+faststart',str(p)]
  subprocess.run(cmd,check=True)
 concat=TMP/f'{name}.txt'; concat.write_text('\n'.join("file '"+str(p)+"'" for p in parts)+'\n')
 base=TMP/f'{name}_base.mp4'
 subprocess.run(['ffmpeg','-y','-hide_banner','-loglevel','error','-f','concat','-safe','0','-i',str(concat),'-c','copy',str(base)],check=True)
 ass=write_ass(name,cfg); final=OUT/f'{name}.mp4'
 vf=f"subtitles='{ass}':fontsdir='{FONT}'"
 subprocess.run(['ffmpeg','-y','-hide_banner','-loglevel','error','-i',str(base),'-vf',vf,'-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)
