import { conteudoDaPeca, estiloDaCaixa, fontesDoDocumento, garantirFontes, type DocumentoDoBanner, type Peca } from "@/lib/banner-editor/documento";
import { encolherTexto } from "./texto-que-cabe";

/*
 * O texto que cabe, fora do palco: a página é desenhada escondida (o mesmo
 * HTML do palco), cada texto que passa da caixa encolhe na medida certa e a
 * conta repete até caber (três voltas, como o encaixe do palco). Serve às
 * cópias em outros tamanhos, que vão direto para "Suas artes" sem abrir.
 */
export async function encaixarForaDoPalco(pagina: DocumentoDoBanner): Promise<DocumentoDoBanner> {
  if (typeof document === "undefined") return pagina;
  garantirFontes(fontesDoDocumento([pagina]));
  const caixa = document.createElement("div");
  caixa.setAttribute("aria-hidden", "true");
  caixa.style.cssText = `position:fixed;left:-30000px;top:0;width:${pagina.largura}px;height:${pagina.altura}px;overflow:hidden;visibility:hidden;pointer-events:none;contain:strict`;
  document.body.appendChild(caixa);
  let atual = pagina;
  try {
    for (let volta = 0; volta < 3; volta += 1) {
      caixa.innerHTML = atual.pecas.map((p) => `<div data-peca="${p.id}" style="${estiloDaCaixa(p)}">${conteudoDaPeca(p)}</div>`).join("");
      await document.fonts.ready;
      await new Promise((r) => requestAnimationFrame(() => requestAnimationFrame(r)));
      let mudou = false;
      const pecas = atual.pecas.map((p): Peca => {
        /* Decoração (letra gigante apagada, só contorno, em curva) passa da caixa de propósito. */
        if (p.tipo !== "texto" || p.oculta || p.opacidade < 0.35 || p.pintura.tipo === "nenhuma" || p.curva) return p;
        const campo = caixa.querySelector<HTMLElement>(`[data-peca="${CSS.escape(p.id)}"] [data-texto]`)?.parentElement;
        if (!campo) return p;
        const excesso = Math.max(campo.scrollHeight / Math.max(1, campo.clientHeight), campo.scrollWidth / Math.max(1, campo.clientWidth));
        if (excesso <= 1.08) return p;
        mudou = true;
        return { ...p, ...encolherTexto(p, Math.max(0.3, 0.97 / excesso)) };
      });
      atual = { ...atual, pecas };
      if (!mudou) break;
    }
  } finally {
    caixa.remove();
  }
  return atual;
}
