import { NextResponse } from "next/server";
import { abrirEstoque, exigirV2, produtoDaEmpresa, respostaDoErro, numeroOuNulo } from "@/lib/estoque/servidor";
import { lerCelulas, lerItens } from "@/lib/estoque/leituras.server";
import type { Celula, Disponibilidade } from "@/lib/estoque/tipos";

/*
 * A prévia ao vivo de um produto para uma escolha (combinação + opções):
 *  - venda: o que sai ao vender N (estoque_disponivel — a MESMA conta da loja,
 *    do PDV e do orçamento) e quanto dá para vender agora;
 *  - producao: o que sai da composição ao produzir N e em qual célula do item
 *    pronto entra (nada é gravado: a resolução da célula não cria célula).
 * Corpo: { produto_id, selected_options, quantidade, largura?, altura? }
 */
export async function POST(req: Request) {
  const r = await abrirEstoque(["products.read", "products.stock.read"]);
  if (!r.ok) return r.resposta;
  const falta = exigirV2(r.e);
  if (falta) return falta;
  const corpo = (await req.json().catch(() => null)) as Record<string, unknown> | null;
  const produto = await produtoDaEmpresa(r.e, String(corpo?.produto_id ?? ""));
  if (!produto) return NextResponse.json({ error: "Produto não encontrado." }, { status: 404 });

  const sel = corpo?.selected_options && typeof corpo.selected_options === "object" ? corpo.selected_options : { options: [] };
  const quantidade = Math.max(0.0001, numeroOuNulo(corpo?.quantidade) ?? 1);
  const largura = numeroOuNulo(corpo?.largura);
  const altura = numeroOuNulo(corpo?.altura);

  const { data: venda, error } = await r.e.supabase.rpc("estoque_disponivel", {
    p_produto: produto.id,
    p_selected_options: sel,
    p_quantidade: quantidade,
    p_largura: largura,
    p_altura: altura,
    p_maximo: true,
  });
  if (error) return respostaDoErro(error);

  /* Produção: as linhas da composição × quantidade, por célula. */
  const { data: linhas } = await r.e.admin.rpc("estoque_v2_linhas_da_composicao", {
    p_produto: produto.id,
    p_qtd: quantidade,
    p_w: largura,
    p_h: altura,
    p_sel: sel,
    p_plano: null,
    p_criar: false,
  });
  type Linha = { item_id: string; celula_id: string | null; quantidade: number; origem: string; linha_id: string };
  const lista = (linhas as Linha[] | null) ?? [];
  const celulas = await lerCelulas(r.e, lista.map((l) => l.celula_id).filter((x): x is string => Boolean(x)));
  const itensSemCelula = await lerItens(r.e, { ids: Array.from(new Set(lista.filter((l) => !l.celula_id).map((l) => l.item_id))) });
  const porChave = new Map<string, { celula: Celula | null; item_id: string; nome: string; quantidade: number; falta_escolher: string | null }>();
  for (const l of lista) {
    const chave = `${l.item_id}|${l.celula_id ?? ""}`;
    const atual = porChave.get(chave);
    if (atual) {
      atual.quantidade += Number(l.quantidade) || 0;
      continue;
    }
    const c = l.celula_id ? celulas.get(l.celula_id) ?? null : null;
    const semCelula = itensSemCelula.find((i) => i.id === l.item_id);
    porChave.set(chave, {
      celula: c,
      item_id: l.item_id,
      nome: c?.nome ?? semCelula?.nome ?? "Item",
      quantidade: Number(l.quantidade) || 0,
      falta_escolher: c ? null : semCelula ? semCelula.grade.map((e) => e.nome.toLowerCase()).join(" e ") || "a variação" : "a variação",
    });
  }
  const sai = Array.from(porChave.values()).sort((a, b) => a.nome.localeCompare(b.nome, "pt-BR"));

  let custo = 0;
  if (sai.length) {
    const { data: custos } = await r.e.admin.from("materials").select("id,cost_per_unit").in("id", sai.map((s) => s.item_id));
    const preco = new Map(((custos as Array<{ id: string; cost_per_unit: number | null }> | null) ?? []).map((m) => [m.id, Number(m.cost_per_unit) || 0]));
    custo = sai.reduce((s, x) => s + x.quantidade * (preco.get(x.item_id) ?? 0), 0);
  }

  let entra: Celula | null = null;
  let faltaEntrar: string | null = null;
  if (produto.estoque_item_id) {
    const { data: cel } = await r.e.admin.rpc("estoque_v2_resolver_celula", {
      p_item: produto.estoque_item_id,
      p_sel: sel,
      p_manual: Array.isArray(produto.estoque_mapa) ? produto.estoque_mapa : [],
      p_criar: false,
    });
    if (typeof cel === "string") entra = (await lerCelulas(r.e, [cel])).get(cel) ?? null;
    if (!entra) {
      const [item] = await lerItens(r.e, { ids: [produto.estoque_item_id] });
      faltaEntrar = item ? item.grade.map((e) => e.nome.toLowerCase()).join(" e ") || "a variação" : "a variação";
    }
  }

  return NextResponse.json({
    produto: { id: produto.id, nome: produto.name, modo: (venda as Disponibilidade)?.modo ?? produto.estoque_modo },
    venda,
    producao: {
      quantidade,
      tem_item_pronto: Boolean(produto.estoque_item_id),
      entra,
      falta_entrar: faltaEntrar,
      sai,
      custo_total: Math.round(custo * 100) / 100,
      custo_unitario: Math.round((custo / quantidade) * 10000) / 10000,
    },
  });
}
