/*
 * Modelos "de estúdio" (out/2026), com tudo o que o editor de vídeo faz: voz
 * gerada e legenda automática no tempo da fala, números que sobem, 3D com
 * perspectiva (cartões que viram, peças inclinadas, palavras que tombam),
 * partículas (fogos, faíscas, brilhos, confete), borrão de movimento,
 * máscaras e transições em 3D. As fotos são molduras: Substituir troca.
 */
import { PARADO, PERSPECTIVA, type AnimacaoDaPeca } from "./animacao";
import { temposDoProjeto } from "./cena";
import { novoId, type DistorcaoDaPeca, type DocumentoDoBanner, type Peca, type PecaDeTextura } from "./documento";
import { anima, cena, comTrilha, elemento, escuro, fala, fotoNaMoldura, lima, marcado, papel } from "./modelos-em-ritmo";
import { comLegenda } from "./narracao";
import NARRACOES from "./narracoes-dos-modelos.json";
import { marca, f, t, sombraDe } from "./modelos-ramos";
import type { PedidoDoModelo } from "./modelos-base";
import { pontoNoEstado } from "./perspectiva";

const W = 1080;
const H = 1920;
const LIMA = "#C6F432";
const TINTA = "#0B0D09";

/* A peça inclinada em 3D, parada (os cantos com perspectiva, como o "Girar em 3D" do painel). */
function inclinada<T extends Peca>(p: T, rx: number, ry: number): T {
  const p3 = PERSPECTIVA * Math.max(p.w, p.h);
  const cantos = ([[0, 0], [p.w, 0], [p.w, p.h], [0, p.h]] as const).map(([x0, y0]) => {
    const [x, y] = pontoNoEstado({ ...PARADO, rx, ry }, [p.w / 2, p.h / 2], p3, x0, y0);
    return [Math.round((x / p.w) * 10000) / 10000, Math.round((y / p.h) * 10000) / 10000] as [number, number];
  }) as DistorcaoDaPeca["cantos"];
  return { ...p, distorcao: { cantos, giro3d: [rx, ry] } };
}
/* Partículas na tela inteira (ou numa faixa). */
function particulas(estilo: PecaDeTextura["estilo"], cor: string, quantidade: number, extra: Partial<PecaDeTextura> = {}): PecaDeTextura {
  return { id: novoId("tex"), tipo: "textura", nome: "Partículas", x: 0, y: 0, w: W, h: H, rot: 0, opacidade: 1, estilo, cor, quantidade, tamanho: 20, centroX: 50, centroY: 50, giro: 0, ...extra };
}
const contador = (de: number, inicio: number, duracao: number): Partial<AnimacaoDaPeca> => ({ contador: { de, inicio, duracao, curva: "freia" } });
/* Um número grande que sobe (Anton), com a legenda dele embaixo. */
function numero(nome: string, texto: string, legenda: string, y: number, tamanho: number, cor: string, corDaLegenda: string, inicio: number, de: number, duracao = 1.4) {
  return [
    ...anima(t(nome, { x: 40, y, w: 1000, h: Math.round(tamanho * 1.05) }, { texto, fonte: "anton", peso: 400, tamanho, linha: 1, cor, alinhamento: "centro" }), "carimbo", inicio, { duracao: 0.35, ...contador(de, inicio + 0.1, duracao) }),
    ...anima(t(`${nome} (legenda)`, { x: 90, y: y + Math.round(tamanho * 1.05) + 10, w: 900, h: 90 }, { texto: legenda, fonte: "montserrat", peso: 800, tamanho: 50, cor: corDaLegenda, alinhamento: "centro" }), "subir", inicio + 0.4),
  ];
}

/* ===================================================== Lançamento narrado */

type Narracao = { src: string; duracao: number; palavras: Array<{ texto: string; inicio: number; fim: number }> };
const narracao = (chave: string) => (NARRACOES as Record<string, Narracao>)[chave];

function lancamentoNarrado(p: PedidoDoModelo): DocumentoDoBanner {
  const voz = narracao("pro-lancamento-narrado");
  /* As cenas seguem as frases da fala (a legenda fica embaixo, a cena usa a parte de cima). */
  const c1 = cena(
    escuro([
      particulas("brilhos", "#FDE68A", 40),
      ...fala("Chegou", "CHEGOU", 170, 110, "#FFFFFF", 0.15, 0.4),
      ...anima(t("Novidade", { x: 40, y: 290, w: 1000, h: 230 }, { texto: "NOVIDADE", fonte: "anton", peso: 400, tamanho: 220, cor: LIMA, alinhamento: "centro" }), "tombar", 0.5, { duracao: 0.7 }),
      ...anima(fotoNaMoldura("Foto do produto", "caneca-roxo", { x: 250, y: 560, w: 580, h: 580 }, { circulo: true, sombra: sombraDe("#000000", 40, 80, 0.5) }), "virar", 0.8, { duracao: 0.9, enfase: "balancar3d", ritmo: 3.2 }),
    ]),
    2.4,
    "aproximar",
    null,
  );
  const c2 = cena(
    lima([
      ...anima(inclinada(fotoNaMoldura("Foto 2", "caneca-branca-recorte", { x: 600, y: 520, w: 420, h: 560, rot: 0 }, { ajuste: "conter", sombra: sombraDe("#000000", 30, 60, 0.3) }), 8, -22), "chicote", 0.2, { direcao: "esquerda", duracao: 0.5, enfase: "flutuar", ritmo: 2.6 }),
      ...fala("Já passou", "JÁ PASSOU DE", 210, 100, TINTA, 0.3, 0.6),
      ...anima(t("Mil", { x: 40, y: 340, w: 600, h: 260 }, { texto: "+1.000", fonte: "anton", peso: 400, tamanho: 240, linha: 1, cor: TINTA, alinhamento: "centro" }), "carimbo", 0.9, { duracao: 0.35, ...contador(0, 1.0, 1.9) }),
      ...marcado("Vendas", "VENDAS", 620, 130, 2.6),
      particulas("faiscas", "#FFFFFF", 50, { centroX: 30, centroY: 70, opacidade: 0.9 }),
    ]),
    3.5,
    "parado",
    { tipo: "virar", duracao: 0.6 },
  );
  const c3 = cena(
    papel([
      ...fala("De", "DE", 200, 90, TINTA, 0.15, 0.3),
      ...anima(t("Preço antigo", { x: 40, y: 300, w: 1000, h: 190 }, { texto: "R$ 99,90", fonte: "anton", peso: 400, tamanho: 170, linha: 1, cor: "#8A8D84", alinhamento: "centro" }), "subir", 0.25),
      ...anima(f("Risco", "retangulo", { x: 190, y: 385, w: 700, h: 24, rot: -5 }, "#E5262E", { raio: 12 }), "revelar", 1.6, { direcao: "direita", duracao: 0.3 }),
      ...anima(t("Preço novo", { x: 40, y: 560, w: 1000, h: 300 }, { texto: "R$ 49,90", fonte: "anton", peso: 400, tamanho: 270, linha: 1, cor: TINTA, alinhamento: "centro" }), "carimbo", 1.7, { duracao: 0.3, ...contador(99.9, 1.75, 0.9), enfase: "pulsar", ritmo: 1.2 }),
      ...anima(t("Selo", { x: 680, y: 500, w: 360, h: 130, rot: 10 }, { texto: "-50%", fonte: "anton", peso: 400, tamanho: 84, cor: TINTA, alinhamento: "centro", fundo: { forma: "pilula", cor: LIMA } }), "elastico", 2.4, { duracao: 0.5, enfase: "tremer", ritmo: 1 }),
    ]),
    3.5,
    "parado",
    { tipo: "persianas", duracao: 0.6 },
  );
  const c4 = cena(
    escuro([
      particulas("fogos", "#FBBF24", 140, { h: 1100 }),
      ...anima(t("Corre", { x: 40, y: 230, w: 1000, h: 300 }, { texto: "CORRE!", fonte: "anton", peso: 400, tamanho: 280, cor: LIMA, alinhamento: "centro" }), "elastico", 0.35, { duracao: 0.6, enfase: "tremer", ritmo: 0.9 }),
      ...elemento("v-botao-comprar", { x: 200, y: 610, w: 680, h: 375 }, 0.6),
      ...anima(marca(p, 330, 1040, 90, "#FFFFFF", "centro"), "surgir", 1.2),
    ]),
    3.0,
    "parado",
    { tipo: "circulo", duracao: 0.5 },
  );
  const paginas = comLegenda([c1, c2, c3, c4], voz?.palavras ?? [], 0, 0, "palavras");
  const { inicios } = temposDoProjeto(paginas);
  return comTrilha(paginas, "fma-loyalty-freak-music-high-technologic-beat-explosion", [["impacto", inicios[1] + 0.9, 0.35], ["carimbo", inicios[2] + 1.7, 0.45], ["pop", inicios[3] + 0.35, 0.5]], voz ? { src: voz.src, duracao: voz.duracao, nome: "Narração (Clara)" } : undefined);
}

/* ====================================================== Resultados do mês */

function resultadosDoMes(p: PedidoDoModelo): DocumentoDoBanner {
  const cartao = (y: number, inclinacao: number, inicio: number, texto: string, legenda: string, de: number, cor: string) => {
    const fundo = inclinada(f("Cartão", "retangulo", { x: 110, y, w: 860, h: 330 }, "#FFFFFF", { raio: 44, sombra: sombraDe("#000000", 26, 60, 0.18) as never }), 6, inclinacao);
    return [
      ...anima(fundo, "virar", inicio, { duracao: 0.8 }),
      ...anima(t("Número", { x: 150, y: y + 40, w: 780, h: 180 }, { texto, fonte: "anton", peso: 400, tamanho: 160, linha: 1, cor, alinhamento: "centro" }), "surgir", inicio + 0.45, { duracao: 0.3, ...contador(de, inicio + 0.5, 1.5) }),
      ...anima(t("Legenda", { x: 150, y: y + 225, w: 780, h: 70 }, { texto: legenda, fonte: "montserrat", peso: 800, tamanho: 44, cor: "#55584F", alinhamento: "centro" }), "subir", inicio + 0.7),
    ];
  };
  const c1 = cena(
    escuro([
      particulas("brilhos", "#C6F432", 45),
      ...anima(t("Resultados", { x: 40, y: 640, w: 1000, h: 230 }, { texto: "RESULTADOS", fonte: "anton", peso: 400, tamanho: 200, cor: "#FFFFFF", alinhamento: "centro" }), "virar", 0.2, { porPalavra: true, duracao: 0.9 }),
      ...marcado("Mês", "DE OUTUBRO", 900, 150, 1.0),
      ...anima(marca(p, 330, 1500, 90, "#FFFFFF", "centro"), "surgir", 1.4),
    ]),
    2.6,
    "aproximar",
    null,
  );
  const c2 = cena(
    papel([
      ...fala("Vendemos", "EM UM MÊS", 150, 110, TINTA, 0.1, 0.5),
      ...cartao(330, -14, 0.3, "R$ 25.300", "em vendas", 0, "#16A34A"),
      ...cartao(720, 14, 0.8, "1.240", "pedidos entregues", 0, "#7C3AED"),
      ...cartao(1110, -14, 1.3, "4,9", "de nota dos clientes", 0, "#F59E0B"),
    ]),
    4.2,
    "parado",
    { tipo: "virar", duracao: 0.6 },
  );
  const c3 = cena(
    lima([
      ...fala("Crescemos", "CRESCEMOS", 300, 150, TINTA, 0.2, 0.5),
      ...numero("Crescimento", "+38%", "em relação a setembro", 480, 300, TINTA, "#365314", 0.6, 0, 1.6),
      ...elemento("v-progresso", { x: 140, y: 1000, w: 800, h: 196 }, 0.9),
      particulas("faiscas", "#FFFFFF", 60, { centroX: 50, centroY: 60, opacidade: 0.8 }),
    ]),
    3.4,
    "parado",
    { tipo: "chicote", duracao: 0.45 },
  );
  const c4 = cena(
    escuro([
      particulas("fogos", "#FBBF24", 150, { h: 1200 }),
      ...anima(t("Obrigado", { x: 40, y: 640, w: 1000, h: 260 }, { texto: "OBRIGADO!", fonte: "anton", peso: 400, tamanho: 230, cor: LIMA, alinhamento: "centro" }), "tombar", 0.3, { porPalavra: true, duracao: 0.7, enfase: "pulsar", ritmo: 1.6 }),
      ...anima(t("Clientes", { x: 90, y: 920, w: 900, h: 120 }, { texto: "a todos que compraram com a gente", fonte: "caveat", peso: 700, tamanho: 84, cor: "#FFFFFF", alinhamento: "centro" }), "desfocar", 1.0, { duracao: 0.5 }),
      ...anima(marca(p, 330, 1150, 100, "#FFFFFF", "centro"), "surgir", 1.4),
    ]),
    3.2,
    "parado",
    { tipo: "preto", duracao: 0.5 },
  );
  const paginas = [c1, c2, c3, c4];
  const { inicios } = temposDoProjeto(paginas);
  return comTrilha(paginas, "fma-loyalty-freak-music-everyone-is-so-alive", [["pop", inicios[1] + 0.3, 0.4], ["pop", inicios[1] + 0.8, 0.4], ["pop", inicios[1] + 1.3, 0.4], ["impacto", inicios[3] + 0.3, 0.5]]);
}

/* ================================================== Oferta relâmpago 3D */

function ofertaRelampago3d(p: PedidoDoModelo): DocumentoDoBanner {
  const c1 = cena(
    escuro([
      particulas("faiscas", "#FDBA74", 90, { centroX: 50, centroY: 88 }),
      ...anima(t("Oferta", { x: 40, y: 560, w: 1000, h: 250 }, { texto: "OFERTA", fonte: "anton", peso: 400, tamanho: 240, cor: "#FFFFFF", alinhamento: "centro" }), "tombar", 0.15, { porPalavra: true, duracao: 0.6 }),
      ...marcado("Relâmpago", "RELÂMPAGO", 830, 170, 0.75),
      ...anima(f("Raio", "raio", { x: 790, y: 330, w: 210, h: 260, rot: 12 }, LIMA), "carimbo", 1.1, { duracao: 0.35, enfase: "tremer", ritmo: 0.8 }),
    ]),
    2.4,
    "aproximar",
    null,
  );
  const cartao = elemento("v-cartao-3d", { x: 190, y: 380, w: 700, h: 900 }, 0.2).map((x) => (x.tipo === "imagem" && x.moldura ? ({ ...x, src: fotoNaMoldura("", "presente-rosa", { x: 0, y: 0, w: 1, h: 1 }).src, moldura: false } as Peca) : x));
  const c2 = cena(
    lima([
      ...cartao,
      ...anima(t("Desconto", { x: 520, y: 200, w: 540, h: 260, rot: 8 }, { texto: "-70%", fonte: "anton", peso: 400, tamanho: 150, cor: TINTA, alinhamento: "centro", fundo: { forma: "explosao", cor: "#FFFFFF" } }), "elastico", 1.0, { duracao: 0.6, ...contador(0, 1.05, 1.1), enfase: "pulsar", ritmo: 1 }),
      particulas("brilhos", "#FFFFFF", 30),
    ]),
    3.2,
    "parado",
    { tipo: "persianas", duracao: 0.6 },
  );
  const c3 = cena(
    papel([
      ...fala("Só hoje", "SÓ HOJE", 220, 170, TINTA, 0.15, 0.4),
      /* A contagem em tinta escura (no papel claro). */
      ...elemento("v-contagem", { x: 340, y: 470, w: 400, h: 400 }, 0.4).map((x) => (x.tipo === "texto" ? ({ ...x, pintura: { tipo: "solida", cor: TINTA, cor2: TINTA, angulo: 0 } } as Peca) : x)),
      ...elemento("v-preco", { x: 140, y: 1000, w: 800, h: 420 }, 0.6),
    ]),
    3.0,
    "parado",
    { tipo: "virar", duracao: 0.6 },
  );
  const c4 = cena(
    escuro([
      particulas("confete", "#F43F5E", 110),
      ...anima(t("Garanta", { x: 40, y: 420, w: 1000, h: 220 }, { texto: "GARANTA O SEU", fonte: "anton", peso: 400, tamanho: 150, cor: "#FFFFFF", alinhamento: "centro" }), "chicote", 0.2, { porPalavra: true, duracao: 0.7 }),
      ...elemento("v-botao-comprar", { x: 200, y: 700, w: 680, h: 375 }, 0.7),
      ...anima(marca(p, 330, 1180, 100, "#FFFFFF", "centro"), "surgir", 1.2),
    ]),
    3.0,
    "parado",
    { tipo: "diagonal", duracao: 0.5 },
  );
  const paginas = [c1, c2, c3, c4];
  const { inicios } = temposDoProjeto(paginas);
  return comTrilha(paginas, "fma-holiznacc0-phonk-remix", [["impacto", inicios[0] + 1.1, 0.45], ["carimbo", inicios[1] + 1.0, 0.45], ["tambor", inicios[2] + 0.4, 0.4]]);
}

export const MODELOS_DE_ESTUDIO = [
  { chave: "animado-lancamento-narrado", nome: "Lançamento narrado", descricao: "Voz e legenda no tempo da fala, foto que vira em 3D, vendas e preço que contam", montar: lancamentoNarrado, feitoPara: "story" as const, paginas: 4, animado: true },
  { chave: "animado-resultados-do-mes", nome: "Resultados do mês", descricao: "Cartões em 3D que viram, números que sobem, barra enchendo e fogos", montar: resultadosDoMes, feitoPara: "story" as const, paginas: 4, animado: true },
  { chave: "animado-oferta-3d", nome: "Oferta relâmpago 3D", descricao: "Título que tomba palavra por palavra, faíscas, -70% subindo e contagem", montar: ofertaRelampago3d, feitoPara: "story" as const, paginas: 4, animado: true },
];
void novoId;
