#!/usr/bin/env python3
import json, subprocess, time
from pathlib import Path
PROJECT=Path('/data/video-pipeline/Channel-Loi-Co-Nhan/project/11062026-001-Biet-Du-Thi-Khong-Nhuc')
LOGO=Path('/data/video-pipeline/Channel-Loi-Co-Nhan/data/logo/logoloiconhan.png')
BGM=Path('/data/video-pipeline/Channel-Loi-Co-Nhan/data/bgm/paulyudin-sentimental-story-182512.mp3')
LOG=PROJECT/'logs/fix_sub_audio_render.log'
SUB_FONT_SIZE=9
SUB_MARGIN_V=35

def log(s):
    line=time.strftime('%F %T ')+s
    print(line, flush=True)
    LOG.parent.mkdir(parents=True, exist_ok=True)
    with LOG.open('a', encoding='utf-8') as f: f.write(line+'\n')

def run(cmd):
    log('RUN '+' '.join(map(str, cmd)))
    subprocess.check_call(list(map(str, cmd)))

def dur(p):
    return float(subprocess.check_output(['ffprobe','-v','error','-show_entries','format=duration','-of','default=nw=1:nk=1',str(p)], text=True).strip())

def ts(sec):
    ms=int(round(sec*1000)); h=ms//3600000; ms%=3600000; m=ms//60000; ms%=60000; s=ms//1000; ms%=1000
    return f'{h:02}:{m:02}:{s:02},{ms:03}'

def safe_text_one_line(text):
    return ' '.join(text.replace('\n',' ').split())

def main():
    LOG.write_text('', encoding='utf-8')
    timeline=json.loads((PROJECT/'audio/master_narration_timeline.json').read_text(encoding='utf-8'))['items']
    data=json.loads((PROJECT/'script/scenes.json').read_text(encoding='utf-8'))
    by_id={s['scene_id']:s for s in data['scenes']}
    sub=PROJECT/'subtitles/master_subtitles_one_line_bottom.srt'
    sub.parent.mkdir(parents=True, exist_ok=True)
    blocks=[]
    for i,it in enumerate(timeline,1):
        text=safe_text_one_line(by_id[it['scene_id']]['narration'])
        blocks.append(f"{i}\n{ts(it['start'])} --> {ts(it['speech_end'])}\n{text}\n")
    sub.write_text('\n'.join(blocks), encoding='utf-8')
    seglist=PROJECT/'render_onepass/segments.txt'
    master=PROJECT/'audio/master_narration.wav'
    mainv=PROJECT/'output/main_story.mp4'
    # Re-render main with one-line bottom subtitles. PlayRes makes ASS font sizing stable for 1080x1920.
    fc=(
        f"[0:v]scale=1080:1920:force_original_aspect_ratio=increase,"
        f"crop=1080:1920,subtitles='{sub}':force_style='FontName=DejaVu Sans,FontSize={SUB_FONT_SIZE},Outline=1,Alignment=2,MarginV={SUB_MARGIN_V},WrapStyle=2'[base];"
        f"movie='{LOGO}',scale=160:-1,format=rgba,colorchannelmixer=aa=0.55[wm];"
        f"[base][wm]overlay=W-w-35:35[v]"
    )
    run(['ffmpeg','-y','-v','error','-f','concat','-safe','0','-i',seglist,'-i',master,'-filter_complex',fc,'-map','[v]','-map','1:a','-r','30','-c:v','libx264','-pix_fmt','yuv420p','-c:a','aac','-b:a','192k','-ar','44100','-ac','2','-shortest',mainv])
    # Rebuild final with re-encode (not stream copy) to avoid broken AAC from concat copy.
    intro=PROJECT/'output/intro/intro.mp4'
    pause=PROJECT/'output/intro/intro_pause_4s.mp4'
    listp=PROJECT/'output/final/final_concat.txt'
    listp.parent.mkdir(parents=True, exist_ok=True)
    listp.write_text(f"file '{intro}'\nfile '{pause}'\nfile '{mainv}'\n", encoding='utf-8')
    no_bgm=PROJECT/'output/final/final_no_bgm.mp4'
    final=PROJECT/'output/final/final_video.mp4'
    run(['ffmpeg','-y','-v','error','-f','concat','-safe','0','-i',listp,'-vf','scale=1080:1920,format=yuv420p','-af','aresample=44100:async=1:first_pts=0','-r','30','-c:v','libx264','-pix_fmt','yuv420p','-c:a','aac','-b:a','192k','-ar','44100','-ac','2',no_bgm])
    run(['ffmpeg','-y','-v','error','-i',no_bgm,'-stream_loop','-1','-i',BGM,'-filter_complex','[0:a]aresample=44100:async=1:first_pts=0,volume=1.0[a0];[1:a]aresample=44100,volume=0.14[bgm];[a0][bgm]amix=inputs=2:duration=first:dropout_transition=2,alimiter=limit=0.95[a]','-map','0:v','-map','[a]','-c:v','copy','-c:a','aac','-b:a','192k','-ar','44100','-ac','2','-shortest',final])
    # Decode check catches audio corruption, not only container metadata.
    run(['ffmpeg','-v','error','-i',final,'-f','null','-'])
    info=json.loads((PROJECT/'output/info.json').read_text(encoding='utf-8'))
    info.update({'final_video':str(final),'duration_sec':dur(final),'subtitle_mode':'one_line_bottom','subtitle_font_size':SUB_FONT_SIZE,'subtitle_margin_v':SUB_MARGIN_V,'audio_fix':'reencoded_concat_and_final_aac_44100_stereo'})
    (PROJECT/'output/info.json').write_text(json.dumps(info, ensure_ascii=False, indent=2), encoding='utf-8')
    log('COMPLETE '+str(final))
if __name__=='__main__': main()
