#!/usr/bin/env python3
"""
Pipeline de corte de reels verticais 1080x1920 do Borrello.
Usa transcrição Whisper JSON + ffmpeg pra cortar, recortar vertical e queimar legendas.

Público: 60+ — fonte GRANDE (72px), ritmo tranquilo, legenda com bom contraste.
"""
import json
import os
import subprocess
import sys
import textwrap
from pathlib import Path

# ---------------------------------------------------------------------------
# CONFIG
# ---------------------------------------------------------------------------
VIDEO_SRC = "/opt/mia/workspace/clientes/borrello/live_feng_shui_raw/Feng Shui - Metafisica nos Imóveis.mp4"
TRANSCRIPT_JSON = "/opt/mia/workspace/clientes/borrello/live_feng_shui_raw/live_audio_90min.json"
OUT_DIR = "/opt/mia/workspace/clientes/borrello/live_feng_shui_cortes/"
WATERMARK = "@franciscoborrello"

# Dimensoes reel vertical Instagram/TikTok/Shorts
REEL_W = 1080
REEL_H = 1920

# Fonte para legendas — usar DejaVu pra garantir acentuacao em PT-BR
# Ou Noto Serif se disponivel (mais proxima do editorial Borrello)
def find_font():
    candidates = [
        "/usr/share/fonts/truetype/noto/NotoSerif-Bold.ttf",
        "/usr/share/fonts/truetype/dejavu/DejaVuSerif-Bold.ttf",
        "/usr/share/fonts/truetype/liberation/LiberationSerif-Bold.ttf",
        "/usr/share/fonts/truetype/freefont/FreeSerifBold.ttf",
        "/usr/share/fonts/truetype/ubuntu/Ubuntu-B.ttf",
        "/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf",
    ]
    for c in candidates:
        if os.path.exists(c):
            return c
    # fallback: encontrar qualquer bold disponivel
    result = subprocess.run(
        ["fc-list", ":style=Bold", "--format=%{file}\n"],
        capture_output=True, text=True
    )
    fonts = [l.strip() for l in result.stdout.splitlines() if ".ttf" in l or ".TTF" in l]
    return fonts[0] if fonts else "/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf"

FONT_PATH = find_font()
print(f"Fonte selecionada: {FONT_PATH}")

# ---------------------------------------------------------------------------
# Segmentos de corte — definidos manualmente com base na transcricao
# (preenchido pelo script analyze_transcript.py ou manualmente)
# Formato: (start_s, end_s, slug, gancho_3s)
# ---------------------------------------------------------------------------
CUTS = []  # preenchido abaixo apos analise

# ---------------------------------------------------------------------------
# HELPERS
# ---------------------------------------------------------------------------

def ts_to_sec(ts: str) -> float:
    """'HH:MM:SS' ou 'MM:SS' para segundos float."""
    parts = ts.split(":")
    if len(parts) == 3:
        return int(parts[0]) * 3600 + int(parts[1]) * 60 + float(parts[2])
    elif len(parts) == 2:
        return int(parts[0]) * 60 + float(parts[1])
    return float(parts[0])


def sec_to_ts(s: float) -> str:
    h = int(s // 3600)
    m = int((s % 3600) // 60)
    sec = s % 60
    return f"{h:02d}:{m:02d}:{sec:06.3f}"


def load_transcript(path: str):
    with open(path) as f:
        data = json.load(f)
    return data.get("segments", [])


def get_text_in_range(segments, start_s, end_s):
    """Retorna lista de (start, end, text) para o intervalo dado."""
    result = []
    for seg in segments:
        seg_s = float(seg["start"])
        seg_e = float(seg["end"])
        if seg_e <= start_s:
            continue
        if seg_s >= end_s:
            break
        # Clipar ao intervalo do corte
        adj_s = max(seg_s, start_s) - start_s
        adj_e = min(seg_e, end_s) - start_s
        text = seg["text"].strip()
        if text:
            result.append((adj_s, adj_e, text))
    return result


def build_ass_content(captions, video_duration, font_path, font_name="DejaVuSerif"):
    """Gera conteudo ASS com fonte grande para publico 60+."""
    # Cabecalho ASS
    header = f"""[Script Info]
ScriptType: v4.00+
PlayResX: {REEL_W}
PlayResY: {REEL_H}
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
; Fonte grande (72px), cor creme/dourado, outline escuro, posicao inferior
Style: Default,DejaVu Serif,72,&H00F5E6C8,&H000000FF,&H00000000,&H80000000,-1,0,0,0,100,100,0,0,1,4,2,2,60,60,140,1

[Events]
Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
"""
    events = []
    for (s, e, text) in captions:
        # Quebrar linhas longas — max 28 chars por linha pro reel vertical
        wrapped = textwrap.fill(text, width=28)
        wrapped_ass = wrapped.replace("\n", "\\N")
        # Escape de caracteres especiais ASS
        wrapped_ass = wrapped_ass.replace("{", "\\{").replace("}", "\\}")

        def to_ass_time(sec):
            h = int(sec // 3600)
            m = int((sec % 3600) // 60)
            s_rem = sec % 60
            cs = int((s_rem - int(s_rem)) * 100)
            return f"{h}:{m:02d}:{int(s_rem):02d}.{cs:02d}"

        events.append(
            f"Dialogue: 0,{to_ass_time(s)},{to_ass_time(e)},Default,,0,0,0,,{wrapped_ass}"
        )

    return header + "\n".join(events) + "\n"


def make_reel(idx, start_s, end_s, slug, gancho, segments):
    """Corta, recorta vertical e queima legendas num reel."""
    out_path = os.path.join(OUT_DIR, f"reel_{idx:02d}_{slug}.mp4")
    if os.path.exists(out_path):
        print(f"  [ja existe] {out_path}")
        return out_path

    duration = end_s - start_s
    print(f"\n[reel_{idx:02d}] {slug} | {sec_to_ts(start_s)} -> {sec_to_ts(end_s)} ({duration:.0f}s)")
    print(f"  Gancho: {gancho}")

    # Legendas para este corte
    captions = get_text_in_range(segments, start_s, end_s)

    # Arquivo ASS temporario
    ass_path = f"/tmp/reel_{idx:02d}_captions.ass"
    ass_content = build_ass_content(captions, duration, FONT_PATH)
    with open(ass_path, "w", encoding="utf-8") as f:
        f.write(ass_content)

    # Watermark texto (@franciscoborrello) — posicao superior direita
    watermark_filter = (
        f"drawtext=text='{WATERMARK}':"
        f"fontfile='{FONT_PATH}':"
        f"fontsize=42:"
        f"fontcolor=0xF5E6C8@0.85:"
        f"x=w-tw-40:"
        f"y=60:"
        f"shadowcolor=black@0.7:"
        f"shadowx=2:shadowy=2"
    )

    # Pipeline ffmpeg:
    # 1. Cortar segmento (-ss/-t)
    # 2. Recortar crop central 9:16 do 16:9 original (1280x720 -> crop 405x720, escalar 1080x1920)
    # 3. Queimar legendas ASS
    # 4. Watermark
    # Video source: 1280x720. Para 9:16 vertical: crop 405 de largura centrado
    crop_w = int(720 * 9 / 16)  # = 405
    crop_x = (1280 - crop_w) // 2  # = 437
    # Escalar 405x720 para 1080x1920

    vf = (
        f"crop={crop_w}:{720}:{crop_x}:0,"
        f"scale={REEL_W}:{REEL_H}:flags=lanczos,"
        f"ass='{ass_path}',"
        f"{watermark_filter}"
    )

    cmd = [
        "ffmpeg", "-y",
        "-ss", str(start_s),
        "-i", VIDEO_SRC,
        "-t", str(duration),
        "-vf", vf,
        "-c:v", "libx264",
        "-preset", "fast",
        "-crf", "22",
        "-c:a", "aac",
        "-b:a", "128k",
        "-movflags", "+faststart",
        "-pix_fmt", "yuv420p",
        out_path
    ]

    print(f"  Renderizando...")
    result = subprocess.run(cmd, capture_output=True, text=True, timeout=300)
    if result.returncode != 0:
        print(f"  ERRO ffmpeg:\n{result.stderr[-2000:]}")
        return None

    size_mb = os.path.getsize(out_path) / 1024 / 1024
    print(f"  OK -> {out_path} ({size_mb:.1f} MB)")
    return out_path


# ---------------------------------------------------------------------------
# DEFINICAO DOS CORTES (preenchida pelo analyze_transcript.py)
# ---------------------------------------------------------------------------

def load_cuts_from_analysis():
    """Carrega cortes definidos pelo analise de transcricao."""
    cuts_file = os.path.join(OUT_DIR, "cuts_analysis.json")
    if os.path.exists(cuts_file):
        with open(cuts_file) as f:
            return json.load(f)
    return []


# ---------------------------------------------------------------------------
# MAIN
# ---------------------------------------------------------------------------

if __name__ == "__main__":
    os.makedirs(OUT_DIR, exist_ok=True)

    print(f"Carregando transcricao: {TRANSCRIPT_JSON}")
    segments = load_transcript(TRANSCRIPT_JSON)
    print(f"  {len(segments)} segmentos carregados")

    cuts = load_cuts_from_analysis()
    if not cuts:
        print("ERRO: cuts_analysis.json nao encontrado. Rode analyze_transcript.py primeiro.")
        sys.exit(1)

    print(f"\nTotal de cortes: {len(cuts)}")
    rendered = []
    for i, cut in enumerate(cuts, 1):
        result = make_reel(
            idx=i,
            start_s=cut["start"],
            end_s=cut["end"],
            slug=cut["slug"],
            gancho=cut["gancho"],
            segments=segments
        )
        if result:
            rendered.append({
                "file": result,
                "slug": cut["slug"],
                "gancho": cut["gancho"],
                "start": cut["start"],
                "end": cut["end"],
            })

    print(f"\n=== REELS GERADOS: {len(rendered)}/{len(cuts)} ===")
    for r in rendered:
        dur = r["end"] - r["start"]
        fname = os.path.basename(r["file"])
        size_mb = os.path.getsize(r["file"]) / 1024 / 1024
        print(f"  {fname} | {dur:.0f}s | {size_mb:.1f}MB | gancho: {r['gancho'][:60]}")

    # Salvar resumo
    summary_path = os.path.join(OUT_DIR, "reels_summary.json")
    with open(summary_path, "w") as f:
        json.dump(rendered, f, indent=2, ensure_ascii=False)
    print(f"\nResumo salvo: {summary_path}")
