import { NextResponse } from "next/server";
import { abrirEstoque, exigirV2, produtoDaEmpresa, respostaDoErro, UUID } from "@/lib/estoque/servidor";
import { lerAtributos, lerItens } from "@/lib/estoque/leituras.server";
import type { ModoDoProduto } from "@/lib/estoque/tipos";

type Params = { params: Promise<{ id: string }> };

/*
 * O estoque de um produto do catálogo: de onde sai quando vende (pronto,
 * encomenda ou não controla), o item pronto ligado, a troca manual
 * variação → célula, os atributos e os itens prontos que dá para escolher.
 */
export async function GET(_req: Request, { params }: Params) {
  const r = await abrirEstoque(["products.read", "products.stock.read"]);
  if (!r.ok) return r.resposta;
  if (!r.e.v2) return NextResponse.json({ v2: false });
  const { id } = await params;
  const produto = await produtoDaEmpresa(r.e, id);
  if (!produto) return NextResponse.json({ error: "Produto não encontrado." }, { status: 404 });

  const [{ data: modo }, atributos, prontos, { count: linhas }] = await Promise.all([
    r.e.admin.rpc("estoque_v2_modo", { p_produto: produto.id }),
    lerAtributos(r.e, produto.id),
    lerItens(r.e, { papel: "pronto" }),
    r.e.admin.from("product_materials").select("id", { count: "exact", head: true }).eq("product_id", produto.id),
  ]);
  /* Receitas da opção: o motor as lê como linhas "só com esta opção" da
     composição (a tela de Composição mostra junto). */
  const { data: receitasBrutas } = await r.e.admin
    .from("product_option_recipes")
    .select("option_id,material_id,qty_per_piece,active,materials(name,unit)")
    .eq("product_id", produto.id)
    .eq("active", true);
  const receitas = ((receitasBrutas as unknown as Array<{ option_id: string; material_id: string; qty_per_piece: number; materials: { name: string; unit: string } | null }> | null) ?? []).map((x) => {
    const attr = atributos.find((a) => a.options.some((o) => o.id === x.option_id));
    return {
      option_id: x.option_id,
      atributo: attr?.name ?? null,
      opcao: attr?.options.find((o) => o.id === x.option_id)?.label ?? null,
      material_id: x.material_id,
      material: x.materials?.name ?? "Insumo",
      unidade: x.materials?.unit ?? "un",
      quantidade: Number(x.qty_per_piece) || 0,
    };
  });

  const item = produto.estoque_item_id ? prontos.find((p) => p.id === produto.estoque_item_id) ?? (await lerItens(r.e, { ids: [produto.estoque_item_id] }))[0] ?? null : null;

  return NextResponse.json({
    v2: true,
    produto: {
      id: produto.id,
      nome: produto.name,
      unidade_de_venda: produto.unit_type,
      modo_gravado: produto.estoque_modo,
      modo: (typeof modo === "string" ? modo : produto.estoque_modo || "nenhum") as ModoDoProduto,
      item_id: produto.estoque_item_id,
      mapa: Array.isArray(produto.estoque_mapa) ? produto.estoque_mapa : [],
    },
    item,
    atributos,
    linhas_da_composicao: linhas ?? 0,
    receitas,
    prontos: prontos.map((p) => ({ id: p.id, nome: p.nome, grade: p.grade, saldo: p.saldo, produto_id: p.produto_id, ativo: p.ativo })),
  });
}

/*
 * { acao: "configurar", modo, item_id?, mapa? } → estoque_configurar_produto
 * { acao: "criar_item", eixos? }               → estoque_criar_item_pronto
 */
export async function POST(req: Request, { params }: Params) {
  const r = await abrirEstoque("products.write");
  if (!r.ok) return r.resposta;
  const falta = exigirV2(r.e);
  if (falta) return falta;
  const { id } = await params;
  const produto = await produtoDaEmpresa(r.e, id);
  if (!produto) return NextResponse.json({ error: "Produto não encontrado." }, { status: 404 });
  const corpo = (await req.json().catch(() => null)) as Record<string, unknown> | null;

  if (corpo?.acao === "criar_item") {
    const eixos = Array.isArray(corpo.eixos)
      ? (corpo.eixos as unknown[]).map((x) => String(x ?? "").trim()).filter(Boolean).slice(0, 2)
      : null;
    const { data, error } = await r.e.supabase.rpc("estoque_criar_item_pronto", { p_produto: produto.id, p_eixos: eixos });
    if (error) return respostaDoErro(error);
    return NextResponse.json(data);
  }

  if (corpo?.acao === "configurar") {
    const modo = corpo.modo;
    if (modo !== "pronto" && modo !== "encomenda" && modo !== "nenhum") {
      return NextResponse.json({ error: "Escolha de onde sai: pronto, sob encomenda ou não controla." }, { status: 400 });
    }
    const item = typeof corpo.item_id === "string" && UUID.test(corpo.item_id) ? corpo.item_id : null;
    if (item) {
      const { data: meu } = await r.e.admin.from("materials").select("id").eq("id", item).in("user_id", r.e.ids).maybeSingle();
      if (!meu) return NextResponse.json({ error: "Item não encontrado." }, { status: 404 });
    }
    let mapa: unknown = null;
    if (Array.isArray(corpo.mapa)) {
      mapa = (corpo.mapa as Array<Record<string, unknown>>)
        .filter((l) => l && typeof l.combinacao === "object" && typeof l.celula_id === "string" && UUID.test(l.celula_id))
        .map((l) => {
          const q = Number(l.quantidade);
          return {
            combinacao: l.combinacao,
            celula_id: l.celula_id,
            ...(Number.isFinite(q) && q > 0 && q !== 1 ? { quantidade: q } : {}),
          };
        })
        .slice(0, 500);
    }
    const { data, error } = await r.e.supabase.rpc("estoque_configurar_produto", {
      p_produto: produto.id,
      p_modo: modo,
      p_item: item,
      p_mapa: mapa,
    });
    if (error) return respostaDoErro(error);
    return NextResponse.json(data);
  }

  return NextResponse.json({ error: "Ação desconhecida." }, { status: 400 });
}
