import { NextResponse } from "next/server";
import sharp from "sharp";
import { BannerDemorou, GeradorOcupado, fotografarCamadas } from "@/lib/assistentes/ferramentas/gerador-de-banner";
import { ChromeAusente } from "@/lib/catalogo-pdf/servidor/imprimir";
import { pecaNoValor } from "./contador";
import type { DocumentoDoBanner } from "./documento";
import { camadasDoVideo, tamanhoDoVideo } from "./video-camadas";
import { ImagemRecusada, htmlComAsImagens } from "./servidor";

/**
 * As camadas do vídeo animado de uma página: o fundo e cada peça (ou grupo,
 * com o que está dentro dela) fotografados sozinhos no Chrome do servidor (o
 * mesmo desenho do download), em PNG transparente; o fundo em JPG. O
 * navegador anima e grava o MP4 (lib/banner-editor/video.ts). Comum à rota do
 * editor (/api/artes/video/camadas) e à do link público da arte.
 */

function erro(texto: string, status: number) {
  return NextResponse.json({ error: texto }, { status, headers: { "Cache-Control": "no-store" } });
}

export async function respostaDasCamadas(pagina: DocumentoDoBanner | undefined, pedido: { limite?: unknown; contador?: { id?: unknown; valores?: unknown } }) {
  const corpo = pedido;
  if (!pagina?.pecas.length) return erro("A arte está vazia.", 400);
  const video = tamanhoDoVideo(pagina.largura, pagina.altura, Number(corpo.limite) || undefined);
  const escala = video.largura / pagina.largura;
  /*
   * O número que sobe: o texto fotografado em cada valor da contagem (cada
   * valor vira uma cópia da peça numa página só, uma camada por cópia).
   */
  if (corpo.contador) {
    const peca = pagina.pecas.find((p) => p.id === String(corpo.contador?.id ?? ""));
    const valores = Array.isArray(corpo.contador.valores) ? corpo.contador.valores.slice(0, 40).map(Number).filter(Number.isFinite) : [];
    if (!peca || peca.tipo !== "texto" || !valores.length) return erro("Esse texto não tem número para contar.", 400);
    const copias: DocumentoDoBanner = { ...pagina, pecas: valores.map((v, i) => ({ ...pecaNoValor(peca, v), id: `${peca.id}-v${i}`, animacao: undefined, grupo: undefined, dentroDe: undefined })) };
    try {
      const html = await htmlComAsImagens(copias, { escala });
      const fotos = await fotografarCamadas(html, pagina.largura, pagina.altura, escala, copias.pecas.map((p) => ({ ids: [p.id], fundo: false })));
      const variantes = await Promise.all(fotos.map(async (foto, i) => ({ valor: valores[i], imagem: `data:image/png;base64,${(await sharp(foto).resize(video.largura, video.altura, { fit: "fill" }).png({ compressionLevel: 8 }).toBuffer()).toString("base64")}` })));
      return NextResponse.json({ variantes }, { headers: { "Cache-Control": "no-store" } });
    } catch (falha) {
      if (falha instanceof GeradorOcupado) return erro("O servidor está ocupado com outros arquivos. Tente de novo em um minuto.", 503);
      console.error("[artes] contador do vídeo", falha instanceof Error ? falha.message : falha);
      return erro("Não deu para preparar o número que sobe.", 500);
    }
  }
  const camadas = camadasDoVideo(pagina);
  try {
    const html = await htmlComAsImagens(pagina, { escala });
    const fotos = await fotografarCamadas(html, pagina.largura, pagina.altura, escala, camadas.map((c) => ({ ids: c.ids, fundo: c.fundo })));
    const prontas = await Promise.all(
      fotos.map(async (foto, i) => {
        const imagem = sharp(foto).resize(video.largura, video.altura, { fit: "fill" });
        const dados = camadas[i].fundo ? await imagem.jpeg({ quality: 90 }).toBuffer() : await imagem.png({ compressionLevel: 8 }).toBuffer();
        return { ...camadas[i], imagem: `data:image/${camadas[i].fundo ? "jpeg" : "png"};base64,${dados.toString("base64")}` };
      }),
    );
    return NextResponse.json({ largura: video.largura, altura: video.altura, escala, camadas: prontas }, { headers: { "Cache-Control": "no-store" } });
  } catch (falha) {
    if (falha instanceof GeradorOcupado) return erro("O servidor está ocupado com outros arquivos. Tente de novo em um minuto.", 503);
    if (falha instanceof BannerDemorou) return erro("O vídeo demorou demais para preparar. Tente de novo.", 504);
    if (falha instanceof ImagemRecusada) return erro(falha.message, 400);
    if (falha instanceof ChromeAusente) return erro("O gerador de vídeo não está disponível neste servidor agora.", 503);
    console.error("[artes] camadas do vídeo", falha instanceof Error ? falha.message : falha);
    return erro("Não deu para preparar o vídeo.", 500);
  }
}

