import { NextResponse } from "next/server";
import { createAdminClient, createClient } from "@/lib/supabase-server";
import { canCompany, getCompanyContext } from "@/lib/company-context";

/**
 * Materializa itens da biblioteca no cadastro da empresa.
 *
 * É a metade invisível do "dessa precificação já nasce tudo": a tela manda os
 * slugs usados com o custo que a pessoa digitou, e daqui sai o registro em
 * `materials`/`machines`/`labor_roles` — criado se não existe, achado se já
 * existe (pelo `library_slug`), e com o custo atualizado quando divergir.
 *
 * Atualizar o custo não é efeito colateral, é o ponto: o cadastro do insumo é
 * a fonte, e se a pessoa corrigiu o preço da lona na precificação é porque a
 * lona custa isso agora — para todos os produtos que a usam.
 *
 * Nome, unidade e tipo vêm SEMPRE da biblioteca, nunca do cliente: o corpo da
 * requisição só tem direito a dizer qual slug e quanto custa. Máquina e cargo
 * criados aqui nascem com custo manual travado (`*_manual = true`), senão o
 * recálculo automático de hora de máquina zeraria o valor digitado.
 */

type ItemPedido = { slug?: unknown; custo?: unknown };

export async function POST(req: Request) {
  const supabase = await createClient();
  const {
    data: { user },
  } = await supabase.auth.getUser();
  if (!user) return NextResponse.json({ error: "Não autenticado." }, { status: 401 });

  const ctx = await getCompanyContext(supabase, user);
  if (!canCompany(ctx, user.id, "products.catalog.write")) {
    return NextResponse.json({ error: "Sem permissão." }, { status: 403 });
  }

  const body = (await req.json().catch(() => null)) as { itens?: ItemPedido[] } | null;
  const pedidos = (Array.isArray(body?.itens) ? body.itens : [])
    .map((i) => ({
      slug: typeof i.slug === "string" ? i.slug : "",
      custo: Number(i.custo),
    }))
    .filter((i) => i.slug && Number.isFinite(i.custo) && i.custo >= 0);

  if (pedidos.length === 0) {
    return NextResponse.json({ error: "Nenhum item válido." }, { status: 400 });
  }

  const admin = createAdminClient();
  const empresa = ctx.companyId;

  const { data: catalogo, error: erroCatalogo } = await admin
    .from("pricing_library_items")
    .select("slug,kind,name,unit,waste_pct_default,purchase_format,roll_width_m,roll_length_m,package_qty,sheet_width_m,sheet_height_m")
    .in("slug", pedidos.map((p) => p.slug));
  if (erroCatalogo) {
    return NextResponse.json({ error: erroCatalogo.message }, { status: 400 });
  }

  const porSlug = new Map((catalogo ?? []).map((c) => [c.slug, c]));
  const resolvidos: Record<string, { id: string; kind: string }> = {};

  for (const pedido of pedidos) {
    const item = porSlug.get(pedido.slug);
    /* Slug que a biblioteca não conhece é pedido inválido, não item novo. */
    if (!item) continue;

    if (item.kind === "material") {
      const { data: existente } = await admin
        .from("materials")
        .select("id,cost_per_unit,purchase_format")
        .eq("user_id", empresa)
        .eq("library_slug", item.slug)
        .limit(1)
        .maybeSingle();

      if (existente) {
        const mudancas: Record<string, unknown> = {};
        if (Number(existente.cost_per_unit) !== pedido.custo) {
          mudancas.cost_per_unit = pedido.custo;
        }
        /* Material criado antes de a biblioteca saber de formatos ficou no
           default 'unidade': completa com as especificações típicas. Quem já
           escolheu um formato de propósito não é tocado. */
        if ((existente.purchase_format ?? "unidade") === "unidade" &&
            (item.purchase_format ?? "unidade") !== "unidade") {
          mudancas.purchase_format = item.purchase_format;
          mudancas.roll_width_m = item.roll_width_m ?? null;
          mudancas.roll_length_m = item.roll_length_m ?? null;
          mudancas.package_qty = item.package_qty ?? null;
          mudancas.sheet_width_m = item.sheet_width_m ?? null;
          mudancas.sheet_height_m = item.sheet_height_m ?? null;
        }
        if (Object.keys(mudancas).length > 0) {
          await admin.from("materials").update(mudancas).eq("id", existente.id);
        }
        resolvidos[item.slug] = { id: existente.id, kind: item.kind };
        continue;
      }

      const { data: criado, error } = await admin
        .from("materials")
        .insert({
          user_id: empresa,
          name: item.name,
          unit: item.unit ?? "un",
          cost_per_unit: pedido.custo,
          waste_pct_default: item.waste_pct_default ?? 0,
          library_slug: item.slug,
          is_active: true,
          /* O insumo nasce sabendo como e comprado: a lona vem em bobina de
             1,60, o couche em pacote de 250 folhas. Tamanhos tipicos de
             mercado, editaveis no cadastro. */
          purchase_format: item.purchase_format ?? "unidade",
          roll_width_m: item.roll_width_m ?? null,
          roll_length_m: item.roll_length_m ?? null,
          package_qty: item.package_qty ?? null,
          sheet_width_m: item.sheet_width_m ?? null,
          sheet_height_m: item.sheet_height_m ?? null,
        })
        .select("id")
        .single();
      if (error) return NextResponse.json({ error: `${item.name}: ${error.message}` }, { status: 400 });
      resolvidos[item.slug] = { id: criado.id, kind: item.kind };
      continue;
    }

    if (item.kind === "maquina") {
      const { data: existente } = await admin
        .from("machines")
        .select("id,hourly_cost")
        .eq("user_id", empresa)
        .eq("library_slug", item.slug)
        .limit(1)
        .maybeSingle();

      if (existente) {
        if (Number(existente.hourly_cost) !== pedido.custo) {
          await admin
            .from("machines")
            .update({ hourly_cost: pedido.custo, hourly_cost_manual: true })
            .eq("id", existente.id);
        }
        resolvidos[item.slug] = { id: existente.id, kind: item.kind };
        continue;
      }

      const { data: criado, error } = await admin
        .from("machines")
        .insert({
          user_id: empresa,
          name: item.name,
          hourly_cost: pedido.custo,
          hourly_cost_manual: true,
          library_slug: item.slug,
          is_active: true,
        })
        .select("id")
        .single();
      if (error) return NextResponse.json({ error: `${item.name}: ${error.message}` }, { status: 400 });
      resolvidos[item.slug] = { id: criado.id, kind: item.kind };
      continue;
    }

    /* mao_de_obra */
    const { data: existente } = await admin
      .from("labor_roles")
      .select("id,hourly_rate")
      .eq("user_id", empresa)
      .eq("library_slug", item.slug)
      .limit(1)
      .maybeSingle();

    if (existente) {
      if (Number(existente.hourly_rate) !== pedido.custo) {
        await admin
          .from("labor_roles")
          .update({ hourly_rate: pedido.custo, hourly_rate_manual: true })
          .eq("id", existente.id);
      }
      resolvidos[item.slug] = { id: existente.id, kind: item.kind };
      continue;
    }

    const { data: criado, error } = await admin
      .from("labor_roles")
      .insert({
        user_id: empresa,
        role_name: item.name,
        hourly_rate: pedido.custo,
        hourly_rate_manual: true,
        library_slug: item.slug,
        is_active: true,
      })
      .select("id")
      .single();
    if (error) return NextResponse.json({ error: `${item.name}: ${error.message}` }, { status: 400 });
    resolvidos[item.slug] = { id: criado.id, kind: item.kind };
  }

  return NextResponse.json({ resolvidos });
}
