"""
Karaoke v2 - design limpo tipo Submagic/Opus Clip.

ABORDAGEM:
- Janela deslizante de UMA LINHA por vez (max 4-5 palavras visivel)
- Cada palavra ativa mostra a linha atual com highlight laranja nessa palavra
- ZERO sobreposicao de cues (cada cue termina antes do proximo comecar)
- Fonte grande, sem quebra de linha (maxima 5 palavras por linha)

LAYOUT:
- Alinhamento: bottom-center (an2)
- PlayResX=1080, PlayResY=1920
- MarginV=360 (posiciona ~75% da altura = 1920 - 360 - altura_texto)
- FontSize=52 (Liberation Sans Bold)
- Cor base: branco, highlight: laranja #F97316
- Outline 3.5px preto + shadow para contraste

FORMATO CUES:
- Uma cue = uma palavra ativa
- Texto: [palavra_antes] [PALAVRA_ATIVA_laranja] [palavra_depois]
  (mostra contexto de +/- 2 palavras ao redor da ativa)
- Timing: do inicio da palavra ativa ate o inicio da proxima (ou end+80ms)
"""

import json
import re
from pathlib import Path

# ---- config ---------------------------------------------------------------
SEG_START = 677.47
SEG_END   = 745.42

CONTEXT_BEFORE = 2   # palavras antes da ativa para mostrar
CONTEXT_AFTER  = 2   # palavras depois da ativa para mostrar

COLOR_BASE      = "&H00FFFFFF"
COLOR_HIGHLIGHT = "&H0016A3F9"   # laranja #F97316 em BGR do ASS
COLOR_SHADOW    = "&H80000000"

FONT_NAME = "Liberation Sans"
FONT_SIZE = 54
MARGIN_V  = 380     # pixels da borda inferior

TR_PATH = Path(
    "/opt/mia/workspace/videos/borrello_lives/edit/transcripts/"
    "ENERGIAS DO SOBSOLO - CASAS QUE MATAM _ Francisco Borrello.json"
)
OUT_ASS = Path("/opt/mia/workspace/videos/borrello_lives/edit/karaoke_v2.ass")

# ---- helpers --------------------------------------------------------------

def ass_time(t: float) -> str:
    t = max(0.0, t)
    h = int(t // 3600)
    m = int((t % 3600) // 60)
    s = int(t % 60)
    cs = int((t - int(t)) * 100)
    return f"{h}:{m:02d}:{s:02d}.{cs:02d}"


def escape_ass(text: str) -> str:
    return text.replace("{", "\\{").replace("}", "\\}")


def make_window_line(words: list[dict], active_idx: int, ctx_before: int, ctx_after: int) -> str:
    """Monta a linha de texto com janela de contexto ao redor da palavra ativa."""
    start = max(0, active_idx - ctx_before)
    end = min(len(words), active_idx + ctx_after + 1)
    window = words[start:end]
    active_in_window = active_idx - start

    parts = []
    for i, w in enumerate(window):
        text = escape_ass(w["text"])
        if i == active_in_window:
            parts.append(f"{{\\c{COLOR_HIGHLIGHT}\\b1}}{text}{{\\b0\\c{COLOR_BASE}}}")
        else:
            parts.append(text)
    return " ".join(parts)


def load_words(tr_path: Path, seg_start: float, seg_end: float) -> list[dict]:
    data = json.loads(tr_path.read_text())
    words = [
        w for w in data["words"]
        if w["type"] == "word"
        and w.get("start") is not None
        and w["start"] >= seg_start - 0.15
        and w["end"] <= seg_end + 0.3
    ]
    return words


# ---- header ASS -----------------------------------------------------------

ASS_HEADER = """\
[Script Info]
Title: Borrello Karaoke v2
ScriptType: v4.00+
WrapStyle: 2
ScaledBorderAndShadow: yes
PlayResX: 1080
PlayResY: 1920

[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: Default,{font},{size},{cb},%s,&H00000000,{cs},-1,0,0,0,100,100,0.5,0,1,3.5,1.5,2,40,40,{mv},1

[Events]
Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
""" % COLOR_BASE  # placeholders preenchidos abaixo

ASS_HEADER = (
    "[Script Info]\n"
    "Title: Borrello Karaoke v2\n"
    "ScriptType: v4.00+\n"
    "WrapStyle: 2\n"
    "ScaledBorderAndShadow: yes\n"
    "PlayResX: 1080\n"
    "PlayResY: 1920\n"
    "\n"
    "[V4+ Styles]\n"
    "Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, "
    "Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, "
    "Shadow, Alignment, MarginL, MarginR, MarginV, Encoding\n"
    f"Style: Default,{FONT_NAME},{FONT_SIZE},{COLOR_BASE},{COLOR_BASE},"
    f"&H00000000,{COLOR_SHADOW},-1,0,0,0,100,100,0.5,0,1,3.5,1.5,2,40,40,{MARGIN_V},1\n"
    "\n"
    "[Events]\n"
    "Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\n"
)


# ---- main -----------------------------------------------------------------

def main():
    print(f"Carregando transcrição...")
    words = load_words(TR_PATH, SEG_START, SEG_END)
    print(f"  {len(words)} palavras no trecho")

    lines = [ASS_HEADER]
    n_cues = 0

    for i, word in enumerate(words):
        cue_start = max(0.0, word["start"] - SEG_START)

        # fim da cue: inicio da proxima palavra (ou end da atual + 80ms)
        if i + 1 < len(words):
            cue_end = max(0.0, words[i + 1]["start"] - SEG_START)
        else:
            cue_end = max(0.0, word["end"] - SEG_START + 0.08)

        # garantir duracao minima de 50ms e sem overlap
        if cue_end <= cue_start:
            cue_end = cue_start + 0.05

        text = make_window_line(words, i, CONTEXT_BEFORE, CONTEXT_AFTER)
        line = (
            f"Dialogue: 0,{ass_time(cue_start)},{ass_time(cue_end)},"
            f"Default,,0,0,0,,{text}"
        )
        lines.append(line)
        n_cues += 1

    content = "\n".join(lines)
    OUT_ASS.write_text(content, encoding="utf-8")
    print(f"ASS salvo: {OUT_ASS}")
    print(f"  {n_cues} cues (1 por palavra, sem sobreposicao)")

    # mostrar amostra
    cues = [l for l in content.split("\n") if l.startswith("Dialogue:")]
    print("\nAmostra (primeiras 4 cues):")
    for c in cues[:4]:
        print(f"  {c[:120]}")


if __name__ == "__main__":
    main()
