/*
 * Os modelos prontos do editor de banners (estilo vitrine de marketplace:
 * cor forte, preço grande, selo de oferta, produto em destaque). Cada modelo
 * monta um DOCUMENTO de peças soltas: é só o ponto de partida, a pessoa mexe
 * em tudo depois.
 *
 * Servem a qualquer tamanho. Deitado (carrossel, faixa): uma coluna de texto
 * e a foto do outro lado. Em pé e quadrado (story, post): tudo empilhado no
 * centro. A coluna é EMPILHADA: se a soma das alturas passa do espaço, tudo
 * diminui na mesma proporção (nada fica por cima de nada).
 */
import { luminancia, misturar, paginasDoDocumento, documentoDasPaginas, textoSobre, type DocumentoDoBanner, type Peca } from "./documento";
import { AMARELO, VERDE, QUASE_PRETO, texto, forma, imagem, documento, fundoDoBanner, empilhar, linhaDoLogo, corDeFundo, type Linha, type PedidoDoModelo } from "./modelos-base";
import { MODELOS_PRO } from "./modelos-pro";
import { MODELOS_DA_COLECAO } from "./modelos-colecao";
import { MODELOS_DOS_RAMOS } from "./modelos-ramos";
import { MODELOS_DE_CANECA } from "./modelos-canecas";
import { MODELOS_DE_CARROSSEL } from "./modelos-carrosseis";
import { MODELOS_DE_BANNER } from "./modelos-banners";
import { MODELOS_ANIMADOS } from "./modelos-animados";
import { MODELOS_EM_RITMO } from "./modelos-em-ritmo";
import { MODELOS_DE_ESTUDIO } from "./modelos-de-estudio";
import { MODELOS_DE_GALA } from "./modelos-de-gala";
import { MODELOS_DE_CALENDARIO } from "./modelos-calendarios";

export type { PedidoDoModelo } from "./modelos-base";

/* Os ramos da galeria (os modelos dos ramos de out/2026); sem ramo = serve a qualquer loja. */
export type RamoDoModelo = "sublimacao" | "grafica" | "personalizados";
export const RAMOS_DOS_MODELOS: Record<RamoDoModelo, string> = { sublimacao: "Sublimação", grafica: "Gráfica", personalizados: "Personalizados" };

/*
 * Cada modelo é feito para um uso (como no Canva): banner da loja (faixa
 * larga), post (quadrado e 4:5; carrossel = várias páginas de post, `paginas`
 * diz quantas), story/reels ou caneca. A galeria e o painel do editor mostram
 * SÓ os modelos do uso do tamanho escolhido; num tamanho sem modelos
 * (YouTube, anúncio, A4...) fica só o "Em branco". Adaptar para outro tamanho
 * é coisa do "Redimensionar", dentro do editor.
 */
export type UsoDoModelo = "faixa" | "post" | "story" | "caneca" | "a4-deitada";
export type ModeloDoEditor = { chave: string; nome: string; descricao: string; montar: (p: PedidoDoModelo) => DocumentoDoBanner; ramo?: RamoDoModelo; feitoPara?: UsoDoModelo | "carrossel"; paginas?: number; /* Já vem com a animação montada (vira vídeo). */ animado?: boolean };

/** O uso de um tamanho (largura ÷ altura); `impressao` = arte com resolução de impressão (têm modelos a caneca e a folha A4 deitada, a do calendário). */
export function usoDoTamanho(largura: number, altura: number, impressao = false): UsoDoModelo | null {
  const r = largura / Math.max(1, altura);
  if (impressao) return r >= 1.95 && r <= 2.35 ? "caneca" : Math.abs(r - 297 / 210) < 0.01 ? "a4-deitada" : null;
  if (r >= 2.4) return "faixa";
  if (r >= 0.74 && r <= 1.05) return "post";
  if (r <= 0.6) return "story";
  return null;
}

/** O modelo aparece só no tamanho do uso dele ("Em branco" aparece em todos). */
export function modeloAparece(m: ModeloDoEditor, largura: number, altura: number, impressao = false) {
  if (m.chave === "branco") return true;
  const uso = usoDoTamanho(largura, altura, impressao);
  return uso !== null && (m.feitoPara === "carrossel" ? "post" : m.feitoPara) === uso;
}

/* ---------------------------------------------------------------- oferta */

function ofertaRelampago(p: PedidoDoModelo): DocumentoDoBanner {
  const { largura: W, altura: H } = p;
  const deitado = W / H >= 1.6;
  const fundo = corDeFundo(p.cor);
  const pecas: Peca[] = [];
  let logo: Linha[] = [];
  const u = deitado ? H : Math.min(W, H) * 0.62;

  const chamada = texto({ nome: "Chamada", texto: "OFERTA RELÂMPAGO", tamanho: u * 0.05, peso: 900, cor: fundo, espaco: 0.06, alinhamento: "centro", fundo: { forma: "pilula", cor: "#FFFFFF", cor2: null, raio: 0 } });
  const titulo = texto({ nome: "Título", texto: "ATÉ 50% OFF", tamanho: u * 0.27, fonte: "anton", peso: 400, sombra: "dura", linha: 1, alinhamento: deitado ? "esquerda" : "centro" });
  const apoio = texto({ nome: "Texto", texto: "Canecas, crachás e brindes com preço de fábrica", tamanho: u * 0.055, peso: 600, linha: 1.2, alinhamento: deitado ? "esquerda" : "centro" });
  const botao = texto({ nome: "Botão", texto: "COMPRE AGORA", tamanho: u * 0.055, peso: 900, cor: QUASE_PRETO, alinhamento: "centro", espaco: 0.04, fundo: { forma: "pilula", cor: AMARELO, cor2: null, raio: 0 } });
  const foto = p.foto ? imagem({ nome: "Foto", src: p.foto, rot: -4, borda: { cor: "#FFFFFF", largura: 1 }, ajuste: "conter" }) : null;
  const selo = texto({ nome: "Selo", texto: "-50%", tamanho: 10, fonte: "anton", peso: 400, cor: QUASE_PRETO, alinhamento: "centro", rot: -12, fundo: { forma: "explosao", cor: AMARELO, cor2: null, raio: 0 } });

  if (deitado) {
    const m = H * 0.1;
    const lado = H * 0.78;
    const coluna = W - m * 2 - (foto ? lado + W * 0.06 : 0);
    empilhar(
      [
        ...(logo = linhaDoLogo(p, H * 0.1, H * 0.05)),
        { peca: chamada, w: H * 0.95, h: H * 0.11, depois: H * 0.03, fixa: true },
        { peca: titulo, w: coluna, h: H * 0.3, depois: H * 0.01 },
        { peca: apoio, w: coluna * 0.9, h: H * 0.08, depois: H * 0.06 },
        { peca: botao, w: H * 0.78, h: H * 0.13, fixa: true },
      ],
      m,
      coluna,
      m,
      H - m,
      false,
    );
    if (foto) Object.assign(foto, { x: W - m - lado - W * 0.02, y: (H - lado) / 2, w: lado, h: lado });
  } else {
    const m = W * 0.07;
    const lado = Math.min(W * 0.66, H * 0.4);
    logo = linhaDoLogo(p, u * 0.11, u * 0.05);
    const linhas: Linha[] = [...logo];
    if (foto) linhas.push({ peca: foto, w: lado, h: lado, depois: u * 0.06, fixa: true });
    linhas.push(
      { peca: chamada, w: u * 0.95, h: u * 0.11, depois: u * 0.03, fixa: true },
      { peca: titulo, w: W - m * 2, h: u * 0.3, depois: u * 0.01 },
      { peca: apoio, w: W - m * 2, h: u * 0.08, depois: u * 0.06 },
      { peca: botao, w: u * 0.78, h: u * 0.13, fixa: true },
    );
    empilhar(linhas, m, W - m * 2, m, H - m, true);
  }
  if (foto) {
    foto.raio = foto.w * 0.06;
    foto.borda = { cor: "#FFFFFF", largura: Math.max(4, foto.w * 0.035) };
    pecas.push(foto);
  }
  pecas.push(...logo.map((l) => l.peca), chamada, titulo, apoio, botao);
  /* O selo morde o canto da foto (ou fica no alto à direita, sem foto). */
  const ladoDoSelo = (foto ? foto.w : u) * 0.42;
  Object.assign(selo, {
    w: ladoDoSelo,
    h: ladoDoSelo,
    tamanho: ladoDoSelo * 0.3,
    x: foto ? foto.x - ladoDoSelo * 0.35 : W - ladoDoSelo - u * 0.08,
    y: foto ? foto.y - ladoDoSelo * 0.3 : u * 0.08,
  });
  pecas.push(selo);
  return documento(W, H, fundoDoBanner({ cor: fundo, cor2: misturar(fundo, "#000000", 0.3), angulo: 120, textura: "raios", corDaTextura: "#FFFFFF" }), ordenarLogoPrimeiro(pecas));
}

/* O logo é a primeira peça da lista (fica por baixo e é fácil de achar nas camadas). */
function ordenarLogoPrimeiro(pecas: Peca[]) {
  return [...pecas.filter((x) => x.tipo === "imagem" && x.papel === "logo"), ...pecas.filter((x) => !(x.tipo === "imagem" && x.papel === "logo"))];
}

/* ----------------------------------------------------------------- preço */

function precoEmDestaque(p: PedidoDoModelo): DocumentoDoBanner {
  const { largura: W, altura: H } = p;
  const deitado = W / H >= 1.6;
  const fundo = corDeFundo(p.cor);
  const pecas: Peca[] = [];
  let logo: Linha[] = [];
  const u = deitado ? H : Math.min(W, H) * 0.62;

  const titulo = texto({ nome: "Título", texto: "Caneca personalizada", tamanho: u * 0.13, peso: 900, linha: 1, alinhamento: deitado ? "esquerda" : "centro" });
  const antigo = texto({ nome: "Preço antigo", texto: "De R$ 49,90", tamanho: u * 0.06, peso: 600, riscado: true, opacidade: 0.85, alinhamento: deitado ? "esquerda" : "centro" });
  const preco = texto({ nome: "Preço", texto: "R$ 29,90", tamanho: u * 0.19, fonte: "anton", peso: 400, cor: QUASE_PRETO, alinhamento: "centro", fundo: { forma: "etiqueta", cor: AMARELO, cor2: null, raio: 0 } });
  const faixa = texto({ nome: "Faixa", texto: "FRETE GRÁTIS", tamanho: u * 0.055, peso: 900, alinhamento: "centro", espaco: 0.05, fundo: { forma: "faixa", cor: VERDE, cor2: null, raio: 0 } });
  const foto = p.foto ? imagem({ nome: "Foto", src: p.foto, circulo: true, sombra: false, ajuste: "cobrir" }) : null;

  if (deitado) {
    const m = H * 0.1;
    const lado = H * 0.84;
    const x = W * 0.05 + lado + W * 0.05;
    empilhar(
      [
        ...(logo = linhaDoLogo(p, H * 0.1, H * 0.05)),
        { peca: titulo, w: W - x - m, h: H * 0.17, depois: H * 0.02 },
        { peca: antigo, w: W - x - m, h: H * 0.08, depois: H * 0.02 },
        { peca: preco, w: H * 1.15, h: H * 0.28, depois: H * 0.05, fixa: true },
        { peca: faixa, w: H * 0.8, h: H * 0.12, fixa: true },
      ],
      x,
      W - x - m,
      m,
      H - m,
      false,
    );
    if (foto) Object.assign(foto, { x: W * 0.05, y: (H - lado) / 2, w: lado, h: lado });
  } else {
    const m = W * 0.07;
    const lado = Math.min(W * 0.66, H * 0.4);
    logo = linhaDoLogo(p, u * 0.1, u * 0.05);
    const linhas: Linha[] = [...logo];
    if (foto) linhas.push({ peca: foto, w: lado, h: lado, depois: u * 0.07, fixa: true });
    linhas.push(
      { peca: titulo, w: W - m * 2, h: u * 0.17, depois: u * 0.02 },
      { peca: antigo, w: W - m * 2, h: u * 0.08, depois: u * 0.02 },
      { peca: preco, w: u * 1.15, h: u * 0.28, depois: u * 0.05, fixa: true },
      { peca: faixa, w: u * 0.8, h: u * 0.12, fixa: true },
    );
    empilhar(linhas, m, W - m * 2, m, H - m, true);
  }
  if (foto) {
    /* O círculo branco atrás da foto, um pouco maior. */
    const borda = foto.w * 0.06;
    pecas.push(forma({ nome: "Círculo", forma: "circulo", x: foto.x - borda, y: foto.y - borda, w: foto.w + borda * 2, h: foto.h + borda * 2, cor: "#FFFFFF", sombra: true }));
    pecas.push(foto);
  }
  pecas.push(...logo.map((l) => l.peca), titulo, antigo, preco, faixa);
  return documento(W, H, fundoDoBanner({ cor: fundo, cor2: misturar(fundo, "#FFFFFF", 0.18), angulo: 200, textura: "pontos", corDaTextura: "#FFFFFF" }), pecas);
}

/* ------------------------------------------------------------ lançamento */

function lancamento(p: PedidoDoModelo): DocumentoDoBanner {
  const { largura: W, altura: H } = p;
  const deitado = W / H >= 1.6;
  const escuro = "#120A24";
  const cor = luminancia(p.cor) < 0.04 ? "#7C3AED" : p.cor;
  const pecas: Peca[] = [];
  let logo: Linha[] = [];
  const u = deitado ? H : Math.min(W, H) * 0.62;

  const chamada = texto({ nome: "Chamada", texto: "NOVIDADE", tamanho: u * 0.048, peso: 900, cor: textoSobre(cor), espaco: 0.14, alinhamento: "centro", fundo: { forma: "pilula", cor, cor2: null, raio: 0 } });
  const titulo = texto({ nome: "Título", texto: "Chegou a nova linha de crachás", tamanho: u * 0.15, peso: 900, linha: 1, espaco: -0.02, alinhamento: deitado ? "esquerda" : "centro" });
  const apoio = texto({ nome: "Texto", texto: "PVC resistente, impressão nítida e entrega rápida", tamanho: u * 0.05, peso: 500, opacidade: 0.85, alinhamento: deitado ? "esquerda" : "centro" });
  const botao = texto({ nome: "Botão", texto: "Conhecer agora", tamanho: u * 0.052, peso: 800, cor: escuro, alinhamento: "centro", fundo: { forma: "pilula", cor: "#FFFFFF", cor2: null, raio: 0 } });
  const foto = p.foto ? imagem({ nome: "Foto", src: p.foto, circulo: true, ajuste: "cobrir", borda: { cor: "#FFFFFF", largura: 1 } }) : null;

  if (deitado) {
    const m = H * 0.11;
    const lado = H * 0.86;
    const coluna = W - m * 2 - (foto ? lado + W * 0.08 : 0);
    empilhar(
      [
        ...(logo = linhaDoLogo(p, H * 0.1, H * 0.05)),
        { peca: chamada, w: H * 0.5, h: H * 0.1, depois: H * 0.04, fixa: true },
        { peca: titulo, w: coluna, h: H * 0.34, depois: H * 0.03 },
        { peca: apoio, w: coluna, h: H * 0.08, depois: H * 0.06 },
        { peca: botao, w: H * 0.74, h: H * 0.13, fixa: true },
      ],
      m,
      coluna,
      m,
      H - m,
      false,
    );
    if (foto) Object.assign(foto, { x: W - m - lado, y: (H - lado) / 2, w: lado, h: lado });
  } else {
    const m = W * 0.08;
    const lado = Math.min(W * 0.62, H * 0.38);
    logo = linhaDoLogo(p, u * 0.1, u * 0.05);
    const linhas: Linha[] = [...logo];
    if (foto) linhas.push({ peca: foto, w: lado, h: lado, depois: u * 0.08, fixa: true });
    linhas.push(
      { peca: chamada, w: u * 0.5, h: u * 0.1, depois: u * 0.04, fixa: true },
      { peca: titulo, w: W - m * 2, h: u * 0.34, depois: u * 0.03 },
      { peca: apoio, w: W - m * 2, h: u * 0.08, depois: u * 0.06 },
      { peca: botao, w: u * 0.74, h: u * 0.13, fixa: true },
    );
    empilhar(linhas, m, W - m * 2, m, H - m, true);
  }
  if (foto) {
    const luz = foto.w * 0.1;
    pecas.push(forma({ nome: "Luz", forma: "circulo", x: foto.x - luz, y: foto.y - luz, w: foto.w + luz * 2, h: foto.h + luz * 2, cor, opacidade: 0.9 }));
    foto.borda = { cor: "#FFFFFF", largura: Math.max(4, foto.w * 0.025) };
    pecas.push(foto);
  }
  pecas.push(...logo.map((l) => l.peca), chamada, titulo, apoio, botao);
  return documento(W, H, fundoDoBanner({ cor: escuro, cor2: misturar(escuro, cor, 0.35), angulo: 135, textura: "grao", corDaTextura: "#FFFFFF" }), pecas);
}

/* ---------------------------------------------------------------- branco */

function emBranco(p: PedidoDoModelo): DocumentoDoBanner {
  return documento(p.largura, p.altura, fundoDoBanner({ cor: corDeFundo(p.cor), textura: "nenhuma" }), []);
}

const MODELOS: ModeloDoEditor[] = [
  /* Banners da loja (faixa larga). */
  ...[
    { chave: "oferta", nome: "Oferta relâmpago", descricao: "Desconto grande, selo e botão", montar: ofertaRelampago },
    { chave: "preco", nome: "Preço em destaque", descricao: "Produto, preço de/por e frete", montar: precoEmDestaque },
    { chave: "lancamento", nome: "Lançamento", descricao: "Novidade com foto em evidência", montar: lancamento },
    ...MODELOS_PRO,
  ].map((m): ModeloDoEditor => ({ ...m, feitoPara: "faixa" })),
  ...MODELOS_DE_BANNER,
  /* Posts do Instagram (4:5). */
  ...MODELOS_DA_COLECAO.map((m): ModeloDoEditor => ({ ...m, feitoPara: "post" })),
  ...MODELOS_DOS_RAMOS,
  ...MODELOS_DE_CARROSSEL,
  ...MODELOS_DE_CANECA,
  ...MODELOS_ANIMADOS,
  ...MODELOS_EM_RITMO,
  ...MODELOS_DE_ESTUDIO,
  ...MODELOS_DE_GALA,
  ...MODELOS_DE_CALENDARIO,
  { chave: "branco", nome: "Em branco", descricao: "Só o fundo, você monta", montar: emBranco },
];

/* Toda arte montada por um modelo leva a origem: o "Redimensionar" remonta o modelo no tamanho novo (redimensionar.ts). */
export const MODELOS_DO_EDITOR: ModeloDoEditor[] = MODELOS.map((m) => ({
  ...m,
  montar: (p: PedidoDoModelo) => {
    const origem = { chave: m.chave, cor: p.cor, logo: p.logo, proporcaoDoLogo: p.proporcaoDoLogo ?? null, foto: p.foto };
    const folhas = paginasDoDocumento(m.montar(p));
    /* Carrossel: cada folha sabe qual é (o "Redimensionar" remonta a folha certa). */
    return documentoDasPaginas(folhas.map((folha, i) => ({ ...folha, modelo: i ? { ...origem, pagina: i } : origem })));
  },
}));
