import { NextResponse } from "next/server";
import sharp from "sharp";
import { ChromeAusente } from "@/lib/catalogo-pdf/servidor/imprimir";
import { contatosNovos } from "@/lib/assistentes/contatos";
import { BannerDemorou, GeradorOcupado, imprimirImagem } from "@/lib/assistentes/ferramentas/gerador-de-banner";
import { arquivoFinal } from "@/lib/assistentes/ferramentas/gerador-de-banner-imagem";
import { documentoLimpo, textosDoDocumento } from "@/lib/banner-editor/documento";
import { ImagemRecusada, baixarDoDeposito, htmlComAsImagens, quemPodeCriarArtes } from "@/lib/banner-editor/servidor";

export const runtime = "nodejs";
export const dynamic = "force-dynamic";
export const maxDuration = 90;

/**
 * O editor de artes (peças soltas que a pessoa arrasta, gira e pinta).
 *
 * GET: o que o editor precisa da loja para começar (cor, logo e a proporção
 * dele, nome) e as fotos dos produtos (o editor também abre fora do editor da
 * loja, na tela Artes, sem a lista de produtos à mão).
 * POST: o documento pronto vira a imagem do banner da loja. O documento é
 * conferido peça por peça (lib/banner-editor/documento.ts), as imagens só
 * podem vir do depósito da Ktalogu e entram embutidas, o texto passa pela
 * mesma peneira de contato do gerador antigo, e a imagem final vai para o
 * depósito `products` da loja, com a sessão de quem pediu. O download (PNG,
 * JPG, PDF) é outra rota: /api/artes/exportar.
 *
 * Mesma permissão do gerador: criar banners (catalog.banners.write) ou cuidar
 * do marketing (marketing.manage).
 */

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

export async function GET() {
  const acesso = await quemPodeCriarArtes();
  if (acesso.falha) return erro(acesso.falha.texto, acesso.falha.status);
  const [{ data: perfil }, { data: listaDeProdutos }] = await Promise.all([
    acesso.supabase.from("profiles").select("primary_color,catalog_logo_url,logo_url,catalog_name,store_name").eq("id", acesso.dono).maybeSingle(),
    acesso.supabase
      .from("products")
      .select("id,name,price,image_url")
      .eq("user_id", acesso.dono)
      .eq("active", true)
      .not("image_url", "is", null)
      .order("created_at", { ascending: false })
      .limit(300),
  ]);
  const loja = (perfil ?? {}) as Record<string, string | null>;
  const logo = String(loja.catalog_logo_url || loja.logo_url || "") || null;
  let proporcaoDoLogo: number | null = null;
  if (logo) {
    const bytes = await baixarDoDeposito(logo);
    if (bytes) {
      const meta = await sharp(bytes, { limitInputPixels: 60_000_000 }).trim({ threshold: 12 }).toBuffer({ resolveWithObject: true }).catch(() => null);
      if (meta?.info.width && meta.info.height) proporcaoDoLogo = Math.round((meta.info.width / meta.info.height) * 100) / 100;
    }
  }
  return NextResponse.json(
    {
      cor: loja.primary_color || "#6D28D9",
      logo,
      proporcaoDoLogo,
      nome: loja.catalog_name || loja.store_name || null,
      dono: acesso.dono,
      produtos: (listaDeProdutos || []).map((p) => ({ id: String(p.id), name: String(p.name || ""), price: Number(p.price) || 0, image_url: p.image_url ? String(p.image_url) : null })),
    },
    { headers: { "Cache-Control": "no-store" } },
  );
}

export async function POST(req: Request) {
  const acesso = await quemPodeCriarArtes();
  if (acesso.falha) return erro(acesso.falha.texto, acesso.falha.status);
  const corpo = (await req.json().catch(() => null)) as Record<string, unknown> | null;
  if (!corpo) return erro("Pedido inválido.", 400);

  const largura = Math.round(Number(corpo.largura));
  const altura = Math.round(Number(corpo.altura));
  if (!Number.isFinite(largura) || !Number.isFinite(altura) || largura < 320 || altura < 120 || largura > 2400 || altura > 2400) {
    return erro("Tamanho do banner inválido.", 400);
  }
  const documento = documentoLimpo(corpo.documento, largura, altura);
  if (!documento.pecas.some((p) => !p.oculta)) return erro("O banner está vazio. Ponha pelo menos um texto ou uma imagem.", 400);

  if (contatosNovos(null, textosDoDocumento(documento).join("\n")).length) {
    return erro("O banner da loja não leva link, telefone, e-mail ou chave Pix. Tire esse dado do texto (para outras artes, use Baixar).", 400);
  }

  let html: string;
  try {
    html = await htmlComAsImagens(documento);
  } catch (falha) {
    if (falha instanceof ImagemRecusada) return erro(falha.message, 400);
    throw falha;
  }
  let png: Buffer;
  try {
    png = await imprimirImagem(html, largura, altura);
  } catch (falha) {
    if (falha instanceof ChromeAusente) return erro("O gerador de banners não está disponível agora. Você ainda pode enviar uma imagem pronta.", 503);
    if (falha instanceof BannerDemorou) return erro("O banner demorou demais para ficar pronto. Tente de novo em instantes.", 504);
    if (falha instanceof GeradorOcupado) return erro("O gerador está ocupado com outros banners. Tente de novo em um minuto.", 429);
    console.error("[editor] banner do editor", falha instanceof Error ? falha.message : falha);
    return erro("Não deu para gerar o banner agora. Tente de novo em instantes.", 500);
  }

  const final = await arquivoFinal(png, false);
  const caminho = `catalog/sections/pagina-inicial/editor/${Math.random().toString(16).slice(2, 10)}_${Date.now()}.${final.extensao}`;
  const { error: erroDoEnvio } = await acesso.supabase.storage.from("products").upload(caminho, final.conteudo, { contentType: final.tipo, upsert: false });
  if (erroDoEnvio) {
    console.error("[editor] guardar banner do editor", erroDoEnvio.message);
    return erro("O banner ficou pronto, mas não deu para guardar. Tente de novo.", 500);
  }
  const url = acesso.supabase.storage.from("products").getPublicUrl(caminho).data.publicUrl;
  return NextResponse.json({ url, largura, altura }, { headers: { "Cache-Control": "no-store" } });
}
