import { NextResponse } from "next/server";
import { createAdminClient } from "@/lib/supabase-admin";
import { carregarLoja } from "@/lib/loja/dados-da-loja";
import { lerVisaoDaLoja } from "@/lib/loja/visao.server";
import { empresaNoEstoqueV2, estoqueDaEscolhaNoBanco } from "@/lib/estoque-v2-da-loja.server";
import { avisosDoCarrinho, combinacaoDaEscolha, estoqueDaEscolha } from "@/lib/estoque-v2-da-loja";
import { itensParaConferir } from "@/lib/estoque-antes-de-cobrar";
import { conferirItensNoBanco } from "@/lib/conferir-itens";

/*
  Estoque v2 na loja: a conta do banco para a escolha exata do cliente.

  - { slug, produto: { product_id, selected_options, quantity, width_m, height_m, completa } }
    → a página do produto: limita? quanto dá? cabe? e a frase ("Esgotado em G / Preta.").
  - { slug, itens: [...] } → o carrinho inteiro somado por célula (dois produtos
    que usam a mesma camiseta disputam o mesmo saldo): uma frase por item que falta.

  Fora do v2 responde { v2: false } e a loja segue com a regra de sempre
  (o saldo que já vem com o produto). Só a chave de serviço pergunta ao banco:
  o visitante não chama as funções do estoque (migration 211).
*/

export const dynamic = "force-dynamic";

const UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
const LIMITE_DE_ITENS = 60;

export async function POST(request: Request) {
  let corpo: Record<string, unknown> = {};
  try {
    corpo = (await request.json()) as Record<string, unknown>;
  } catch {
    return NextResponse.json({ error: "Pedido inválido." }, { status: 400 });
  }
  const slug = String(corpo.slug || "").trim().toLowerCase();
  if (!slug) return NextResponse.json({ error: "Loja inválida." }, { status: 400 });

  try {
    const dados = await carregarLoja(slug);
    if (!dados?.profile) return NextResponse.json({ error: "Loja não encontrada." }, { status: 404 });
    const { visao } = await lerVisaoDaLoja(slug, dados.profile);
    if (visao.exigeLoginNaLoja || visao.lojaFechada) return NextResponse.json({ error: "Entre na loja para continuar." }, { status: 401 });

    const admin = createAdminClient();
    const dono = String(dados.profile.id);
    if (!(await empresaNoEstoqueV2(admin, dono))) return NextResponse.json({ v2: false });

    /* O carrinho inteiro. */
    if (Array.isArray(corpo.itens)) {
      const brutos = (corpo.itens as Array<Record<string, unknown>>).slice(0, LIMITE_DE_ITENS);
      /* O índice que volta é o do carrinho (o banco numera só os que foram). */
      const indices: number[] = [];
      const itens = brutos.filter((item, indice) => {
        const ok = UUID.test(String(item?.product_id || "")) && Number(item?.quantity || 0) > 0;
        if (ok) indices.push(indice);
        return ok;
      });
      const lista = itensParaConferir(itens as never);
      if (!lista.length) return NextResponse.json({ v2: true, ok: true, avisos: {} });
      const resposta = await conferirItensNoBanco(admin, dono, lista as never);
      if (!resposta) return NextResponse.json({ v2: true, ok: true, avisos: {} });
      const avisos = avisosDoCarrinho(resposta.problemas, lista as never);
      const porIndiceDoCarrinho: Record<string, string> = {};
      for (const [indice, frase] of avisos) porIndiceDoCarrinho[String(indices[indice])] = frase;
      return NextResponse.json({ v2: true, ok: resposta.ok !== false, avisos: porIndiceDoCarrinho });
    }

    /* A escolha da página do produto. */
    const produto = (corpo.produto || {}) as Record<string, unknown>;
    const produtoId = String(produto.product_id || "");
    if (!UUID.test(produtoId)) return NextResponse.json({ error: "Produto inválido." }, { status: 400 });
    const { data: dele } = await admin
      .from("products")
      .select("id,product_attributes(name)")
      .eq("id", produtoId)
      .eq("user_id", dono)
      .maybeSingle();
    if (!dele) return NextResponse.json({ error: "Produto não encontrado." }, { status: 404 });
    const resposta = await estoqueDaEscolhaNoBanco(admin, {
      produtoId,
      selected: produto.selected_options,
      quantidade: Number(produto.quantity) || 1,
      largura: Number(produto.width_m) || null,
      altura: Number(produto.height_m) || null,
    });
    const atributos = ((dele as { product_attributes?: Array<{ name?: string | null }> }).product_attributes || []).map((a) =>
      String(a?.name || "")
    );
    const estoque = estoqueDaEscolha(resposta, {
      combinacao: combinacaoDaEscolha(produto.selected_options, atributos),
      escolhaCompleta: produto.completa === true,
    });
    if (!estoque) return NextResponse.json({ v2: true, limita: false, disponivel: null, cabe: true, motivo: null, aviso: null });
    return NextResponse.json(estoque);
  } catch {
    /* Falhou a pergunta: a loja não trava por isso (o servidor confere de
       novo ao fechar o pedido e antes de cobrar). */
    return NextResponse.json({ v2: true, limita: false, disponivel: null, cabe: true, motivo: null, aviso: null, falhou: true });
  }
}
