#!/usr/bin/env python3
"""
render_v3.py - Video 2 Meta App Review: whatsapp_business_messaging
MUDANCAS DA V3 (pedido Renato, 2026-09-03):
  1. L4 REMOVIDA definitivamente. L5 estendida para cobrir o gap:
     L5 entra em 90.5s (logo que L3 sai), sai em 121.0s - sem buraco.
  2. TODAS as legendas movidas pro TOPO do frame (abaixo da URL bar):
     Single line Y = 115 (box topo = 95, abaixo da URL bar, acima do conteudo critico)
     Double line L3: linha1 Y=115, linha2 Y=199 (com FS_MONEY=59)
  3. Backup da v1 feito antes de sobrescrever.

MAPEAMENTO DE LEGENDAS (5 no total, sem L4):
  L1: 17.0 - 30.0s   Tela Turmas
  L2: 57.0 - 68.0s   Seletor de template aberto
  L3: 90.5 - 103.0s  Clique em Disparar (money legend 2 linhas, FS*1.3x)
  L5: 90.5 - 121.0s  Mensagem entregue no WhatsApp Web
                      (ESTICADA: antes era 103.0-121.0, agora cobre gap da L4)
  L6: 147.0 - 155.16s KPIs de entrega/leitura

POSICAO TOPO (calibrada frame a frame, confirmada visualmente):
  - URL bar do Chrome termina em ~Y=90 no frame 1920x1080
  - Box de legenda comeca em Y=95 (text Y=115, boxborderw=20)
  - Box de legenda single termina em Y=95+46+40=181
  - Botao Disparar (L3): Y~458 - completamente seguro
  - Balao See you there! (L5): Y~655 - completamente seguro
  - KPIs tabela (L6): conteudo em Y>120 ja livre do box

INPUT:  1900x1072, 30fps, H264+AAC, 155.16s, 160MB
OUTPUT: 1920x1080, 30fps, H264, sem audio, ~155s
"""

import subprocess
import os
import sys
import json
import shutil

INPUT = '/opt/mia/workspace/clientes/self/meta_app_review_video2/screencast_bruto.mp4'
WORK_DIR = '/opt/mia/workspace/clientes/self/meta_app_review_video2/renders'
OUTPUT = '/opt/mia/workspace/clientes/self/meta_app_review_video2/self-whatsapp_business_messaging.mp4'
OUTPUT_V1_BACKUP = '/opt/mia/workspace/clientes/self/meta_app_review_video2/self-whatsapp_business_messaging.v1.mp4'
PREVIEWS_DIR = '/opt/mia/workspace/clientes/self/meta_app_review_video2/previews_v2'
FONT = '/home/mia/.fonts/px3lab/Inter-Bold.ttf'

os.makedirs(WORK_DIR, exist_ok=True)
os.makedirs(PREVIEWS_DIR, exist_ok=True)

def run(cmd, desc):
    print(f"\n=== {desc} ===", flush=True)
    result = subprocess.run(cmd, capture_output=True, text=True)
    if result.returncode != 0:
        print(f"STDOUT: {result.stdout[-500:]}", flush=True)
        print(f"STDERR: {result.stderr[-2000:]}", flush=True)
        sys.exit(1)
    if result.stderr:
        lines = [l for l in result.stderr.split('\n') if l.strip()]
        if lines:
            print(f"  -> {lines[-1]}", flush=True)
    print(f"OK - {desc}", flush=True)
    return result

def ffprobe_duration(path):
    r = subprocess.run(
        ['ffprobe', '-v', 'quiet', '-show_format', '-of', 'json', path],
        capture_output=True, text=True
    )
    try:
        return float(json.loads(r.stdout)['format']['duration'])
    except:
        return 0

# ============================================================
# BACKUP DA V1 (antes de sobrescrever)
# ============================================================
if os.path.exists(OUTPUT):
    print(f"\n=== Backup v1 -> {OUTPUT_V1_BACKUP} ===", flush=True)
    shutil.move(OUTPUT, OUTPUT_V1_BACKUP)
    print(f"OK - Backup feito: {OUTPUT_V1_BACKUP}", flush=True)
else:
    print(f"AVISO: arquivo de saida nao existe, sem backup necessario.", flush=True)

# ============================================================
# PASSO 1: Escalar video inteiro para 1920x1080
# ============================================================
nozoom_out = f'{WORK_DIR}/nozoom_base_v3.mp4'

run([
    'ffmpeg', '-y',
    '-i', INPUT,
    '-vf', 'scale=1920:1080:force_original_aspect_ratio=decrease,pad=1920:1080:(ow-iw)/2:(oh-ih)/2:color=black',
    '-r', '30',
    '-c:v', 'libx264', '-crf', '17', '-preset', 'fast',
    '-an',
    nozoom_out
], 'Passo 1: Escala video completo 1920x1080 sem zoom')

d = ffprobe_duration(nozoom_out)
print(f"Base sem zoom: {d:.2f}s (esperado ~155.16s)")

# ============================================================
# PASSO 2: Queimar legendas - POSICAO TOPO
#
# Calibracao (confirmada visualmente):
#   URL bar Chrome termina em ~Y=90 na 1080p escalada
#   Single line: Y=115 (box topo=95, box base=181)
#   Double line L3 (FS=59): Y1=115 (box_base=194), Y2=199 (gap=5px, box_base=278)
#
# MUDANCAS DA V3:
#   - L4 REMOVIDA (decisao Renato)
#   - L5 esticada: 90.5 -> 121.0 (cobre gap onde era L4 + slot original)
#   - TODAS as legendas no topo (Y=115 single, Y=115/199 double)
# ============================================================

FS = 46         # font size single line
TC = 'white'
BC = '0x000000@0.87'
BP = 20         # box padding

# L3 MONEY LEGEND - zoom 1.3x no texto
FS_MONEY = int(FS * 1.3)  # 59px

# Posicoes TOPO (Y do texto, nao do box)
YT_SINGLE = 115   # single line - box topo=95, abaixo da URL bar
YT_M1     = 115   # money double linha 1 - mesmo que single
YT_M2     = 199   # money double linha 2 - gap de 5px apos box da linha 1 (base=194)

def dt(text, t0, t1, y, fs=None):
    """Gera filtro drawtext."""
    if fs is None:
        fs = FS
    esc = text.replace("'", "\\'").replace(':', '\\:').replace('%', '\\%')
    return (
        f"drawtext=fontfile='{FONT}'"
        f":text='{esc}'"
        f":fontcolor={TC}:fontsize={fs}"
        f":box=1:boxcolor={BC}:boxborderw={BP}"
        f":x=(w-text_w)/2:y={y}"
        f":enable='between(t,{t0},{t1})'"
    )

filters = ','.join([
    # L1 - single - Tela Turmas (17-30s)
    dt('Our clients import and manage their graduating students in the platform.', 17.0, 30.0, YT_SINGLE),

    # L2 - single - Template aprovado (57-68s)
    dt('Marketing and utility messages are sent only through approved templates.', 57.0, 68.0, YT_SINGLE),

    # L3 - double + zoom 1.3x - MONEY LEGEND whatsapp_business_messaging (90.5-103.0s)
    dt('Our app uses whatsapp_business_messaging', 90.5, 103.0, YT_M1, FS_MONEY),
    dt('to send messages through the Cloud API.', 90.5, 103.0, YT_M2, FS_MONEY),

    # L4 REMOVIDA - decisao do Renato (2026-09-03)
    # L5 ESTICADA: 90.5-121.0 (cobre o gap de 90.5-103.0 que era L4 + slot original 103-121)
    # L3 e L5 se SOBREPOEM em 90.5-103.0 intencionalmente? NAO.
    # CORRECAO: L5 entra em 103.0 (logo que L3 sai) e fica ate 121.0.
    # O GAP 90.5-103.0 era da L4. L3 ja ocupa esse slot com a money legend.
    # L5 cobre 103.0-121.0 (slot original). Sem gap, sem sobreposicao.
    # RECALCULO: brief diz "L5 entra logo que L3 sai" = 103.0
    dt('The message is delivered to the recipient.', 103.0, 121.0, YT_SINGLE),

    # L6 - single - KPIs entrega/leitura (147-155.16s)
    dt('Delivery and read receipts arrive by webhook and update the dashboard.', 147.0, 155.16, YT_SINGLE),
])

run([
    'ffmpeg', '-y',
    '-i', nozoom_out,
    '-vf', filters,
    '-c:v', 'libx264', '-crf', '18', '-preset', 'fast',
    '-profile:v', 'high', '-level', '4.1',
    '-an',
    '-movflags', '+faststart',
    OUTPUT
], 'Passo 2: Legendas queimadas no TOPO')

# ============================================================
# PASSO 3: Extrair 5 previews v2 (um por legenda)
# ============================================================
print("\n=== Gerando previews v2 ===", flush=True)

previews = [
    # (label, timestamp_meio_da_legenda, descricao)
    ('L1', 23.0,  'preview_v2_L1_turmas.jpg'),
    ('L2', 62.0,  'preview_v2_L2_template.jpg'),
    ('L3', 96.0,  'preview_v2_L3_money_disparar.jpg'),
    ('L5', 110.0, 'preview_v2_L5_waweb_balao.jpg'),
    ('L6', 150.0, 'preview_v2_L6_kpi_lidas.jpg'),
]

preview_paths = []
for label, t, fname in previews:
    out_path = f'{PREVIEWS_DIR}/{fname}'
    result = subprocess.run([
        'ffmpeg', '-y',
        '-ss', str(t),
        '-i', OUTPUT,
        '-frames:v', '1', '-update', '1',
        '-q:v', '3',
        out_path
    ], capture_output=True, text=True)
    if result.returncode != 0:
        print(f"  AVISO: falha ao extrair preview {label}: {result.stderr[-300:]}")
    else:
        size = os.path.getsize(out_path) // 1024
        print(f"  {label} -> {out_path} ({size}KB)")
        preview_paths.append(out_path)

# ============================================================
# VALIDACAO FINAL
# ============================================================
print("\n=== VALIDACAO FINAL ===", flush=True)
r = subprocess.run(
    ['ffprobe', '-v', 'quiet', '-show_streams', '-show_format', '-of', 'json', OUTPUT],
    capture_output=True, text=True
)
data = json.loads(r.stdout)
fmt = data['format']
streams = data['streams']

dur = float(fmt['duration'])
size_mb = int(fmt['size']) // 1024 // 1024

print(f"Arquivo: {OUTPUT}")
print(f"Duracao: {dur:.2f}s (esperado ~155.16s)")
print(f"Tamanho: {size_mb}MB (limite Meta <15MB)")
print(f"Streams: {len(streams)}")
for s in streams:
    if s['codec_type'] == 'video':
        print(f"  Video: {s['codec_name']} {s['width']}x{s['height']} {s.get('r_frame_rate','?')}fps")
    else:
        print(f"  Audio: {s['codec_name']} (ERRO - deve ser removido!)")

if len(streams) == 1 and streams[0]['codec_type'] == 'video':
    w = streams[0]['width']
    h = streams[0]['height']
    if w == 1920 and h == 1080:
        print("\nOK: 1920x1080, sem audio, H.264")
    else:
        print(f"\nAVISO: resolucao {w}x{h} (esperado 1920x1080)")
    if size_mb < 15:
        print(f"OK: tamanho {size_mb}MB < 15MB")
    else:
        print(f"AVISO: tamanho {size_mb}MB > 15MB - pode ser bloqueado no Telegram")
else:
    print("\nERRO: streams incorretos!")

print("\n=== RESUMO LEGENDAS V3 ===")
print("L1: 17.0 - 30.0s  | Tela Turmas | Y=115 (topo)")
print("L2: 57.0 - 68.0s  | Template aprovado | Y=115 (topo)")
print("L3: 90.5 - 103.0s | MONEY LEGEND Disparar | Y=115/199 (topo, double, FS=59)")
print("L4: REMOVIDA      | Decisao Renato 2026-09-03")
print("L5: 103.0 - 121.0s| WA Web balao entregue | Y=115 (topo, entrada em 103.0=saida L3)")
print("L6: 147.0 - 155.16s| KPIs entrega/leitura | Y=115 (topo)")
print(f"\n5 previews em: {PREVIEWS_DIR}")
print("Backup v1 em:", OUTPUT_V1_BACKUP)
print("\nRender v3 CONCLUIDO.")
