#!/usr/bin/env python3
"""Build ASS karaoke: one word at a time (TikTok style)."""
import json
from pathlib import Path

KARAOKE_DIR = Path('/opt/mia/workspace/clientes/px3lab/video_2_0/v2/karaoke')
SCENES = ['01_hook', '02_dor', '03_virada', '04_diferenciais', '05_autoridade', '06_cta']

# For cena 5, rewrite text: "foda" → "REFERÊNCIA" (visual override only)
# Word replacement map per scene
WORD_OVERRIDES = {
    '05_autoridade': {
        'foda': 'REFERÊNCIA',
        'foda.': 'REFERÊNCIA.',
    }
}

# Colors: white regular, lime highlight
LIME = r'&H0000FFAD'
WHITE = r'&H00FFFFFF'

ASS_HEADER = """[Script Info]
ScriptType: v4.00+
PlayResX: 1080
PlayResY: 1920
WrapStyle: 0
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: Karaoke, Inter Black, 96, {WHITE}, &H000000FF, &H00000000, &HB0000000, 1, 0, 0, 0, 100, 100, 0, 0, 3, 8, 0, 2, 60, 60, 380, 1

[Events]
Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
""".format(WHITE=WHITE)


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


def group_words(words, scene_name=None):
    """Group into chunks of 3-5 words that fit one line."""
    overrides = WORD_OVERRIDES.get(scene_name, {})
    chunks = []
    cur = []
    for i, w in enumerate(words):
        text = w['word'].strip()
        # Apply override if any
        lower = text.lower().rstrip('.,;!?')
        for k, v in overrides.items():
            if lower == k.rstrip('.,;!?'):
                # keep original punctuation
                punct = ''
                for ch in text[::-1]:
                    if ch in '.,;!?':
                        punct = ch + punct
                    else:
                        break
                text = v + punct
                break
        w = dict(w)
        w['word'] = text
        cur.append(w)
        clean = text.rstrip('.,;!?')
        is_punct_end = text and text[-1] in '.,;!?'
        gap = (words[i+1]['start'] - w['end']) if i+1 < len(words) else 999
        # Total chars in chunk
        chunk_len = sum(len(x['word']) for x in cur) + len(cur)
        if is_punct_end or gap > 0.30 or chunk_len > 26 or len(cur) >= 5:
            chunks.append(cur)
            cur = []
    if cur:
        chunks.append(cur)
    return chunks


def build_events(scene_name, offset=0.0, force_duration=None):
    data = json.loads((KARAOKE_DIR / f'{scene_name}.json').read_text())
    words = data.get('words', [])
    audio_dur = data.get('duration', 0.0)
    if force_duration is not None:
        audio_dur = force_duration
    events = []
    chunks = group_words(words, scene_name)

    for chunk in chunks:
        cstart = chunk[0]['start']
        cend = chunk[-1]['end']
        # Extend last chunk to end of scene
        is_last_chunk = (chunk is chunks[-1])
        chunk_end_display = audio_dur if is_last_chunk else cend + 0.05

        for i, w in enumerate(chunk):
            wstart = w['start']
            # Word display window: from wstart to next word's start (or chunk end)
            if i+1 < len(chunk):
                wend = chunk[i+1]['start']
            else:
                wend = chunk_end_display

            # Build line: previous words in chunk in white, current highlighted in lime, upcoming words dim white
            parts = []
            for j, ww in enumerate(chunk):
                text = ww['word'].strip().upper().replace('{','').replace('}','')
                if j == i:
                    # highlight: lime color
                    parts.append(r'{\c' + LIME.replace('&H00','&H') + r'}' + text + r'{\r}')
                else:
                    parts.append(text)
            line_text = ' '.join(parts)
            start_t = fmt_time(offset + wstart)
            end_t = fmt_time(offset + wend)
            events.append(f'Dialogue: 0,{start_t},{end_t},Karaoke,,0,0,0,,{line_text}')

    return events, audio_dur


def build_per_scene():
    for s in SCENES:
        events, dur = build_events(s, offset=0.0)
        ass = ASS_HEADER + '\n'.join(events) + '\n'
        (KARAOKE_DIR / f'{s}.ass').write_text(ass)
        print(f'{s}: {len(events)} events, dur {dur:.2f}s')


def build_master(scene_durations):
    """Build ONE master ASS for concatenated video."""
    all_events = []
    offset = 0.0
    for s, dur in zip(SCENES, scene_durations):
        events, _ = build_events(s, offset=offset, force_duration=dur)
        all_events.extend(events)
        offset += dur
    ass = ASS_HEADER + '\n'.join(all_events) + '\n'
    (KARAOKE_DIR / 'master.ass').write_text(ass)
    print(f'master ASS: {len(all_events)} events, total {offset:.2f}s')


if __name__ == '__main__':
    import sys
    if len(sys.argv) > 1 and sys.argv[1] == 'master':
        durs = [float(x) for x in sys.argv[2:]]
        build_master(durs)
    else:
        build_per_scene()
