import { NextResponse } from "next/server";
import { createAdminClient, createClient } from "@/lib/supabase-server";
import { canCompany, getCompanyContext, type CompanyContext } from "@/lib/company-context";
import { updateProductCost } from "@/lib/production/update-product-cost";
import { linhaDaComposicaoParaGravar } from "@/lib/estoque/gravar-composicao";

async function getAuth() {
  const supabase = await createClient();
  const {
    data: { user },
  } = await supabase.auth.getUser();
  return { supabase, user };
}

/* A linha só entra em produto desta empresa: o id do produto vem da tela. */
async function produtoDaEmpresa(adminSupabase: ReturnType<typeof createAdminClient>, ctx: CompanyContext, productId: unknown) {
  if (typeof productId !== "string" || !productId) return false;
  const ids = Array.from(new Set([ctx.companyId, ctx.ownerId, ...(ctx.tenantIds ?? [])].filter(Boolean))) as string[];
  const { data } = await adminSupabase.from("products").select("id").eq("id", productId).in("user_id", ids).maybeSingle();
  return Boolean(data);
}

/* Estoque v2 ligado? Só então as colunas novas da linha (quando sai, opção,
   quantidade por variação, célula) são gravadas. Fora dele, nada muda. */
async function empresaNoV2(adminSupabase: ReturnType<typeof createAdminClient>, ctx: CompanyContext) {
  const { data } = await adminSupabase.rpc("estoque_v2_ligado", { p_empresa: ctx.ownerId ?? ctx.companyId });
  return data === true;
}

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

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

  const body = (await req.json().catch(() => null)) as Record<string, unknown> | null;
  if (!body) return NextResponse.json({ error: "Nada para gravar." }, { status: 400 });
  const adminSupabase = createAdminClient();
  if (!(await produtoDaEmpresa(adminSupabase, ctx, body.product_id))) {
    return NextResponse.json({ error: "Produto não encontrado." }, { status: 404 });
  }

  /* As colunas de sempre (as que a tela manda) e, no estoque novo, as de baixa. */
  const v2 = await empresaNoV2(adminSupabase, ctx);
  const { data, error } = await adminSupabase
    .from("product_materials")
    .insert({
      product_id: body.product_id,
      material_id: body.material_id,
      consumption_qty: body.consumption_qty,
      waste_pct: body.waste_pct,
      cost_total: body.cost_total,
      ...(body.pieces_per_unit !== undefined ? { pieces_per_unit: body.pieces_per_unit } : {}),
      ...(body.consumption_base !== undefined ? { consumption_base: body.consumption_base } : {}),
      ...linhaDaComposicaoParaGravar(body, v2),
      user_id: ctx.companyId, // Ensure correct tenant ID
    })
    .select()
    .single();

  if (error) return NextResponse.json({ error: error.message }, { status: 400 });

  // Update product cost asynchronously
  if (data?.product_id) {
    updateProductCost(data.product_id).catch(err => console.error("Error updating product cost:", err));
  }

  return NextResponse.json(data);
}

/* Estoque v2: muda só o "quando sai" da linha (condição, quantidade por
   variação, célula). Quantidade e perda continuam pelo caminho de sempre. */
export async function PATCH(req: Request) {
  const { supabase, user } = await getAuth();
  if (!user) return NextResponse.json({ error: "Não autenticado." }, { status: 401 });

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

  const body = (await req.json().catch(() => null)) as Record<string, unknown> | null;
  const id = typeof body?.id === "string" ? body.id : "";
  if (!id) return NextResponse.json({ error: "Linha não encontrada." }, { status: 400 });

  const adminSupabase = createAdminClient();
  if (!(await empresaNoV2(adminSupabase, ctx))) {
    return NextResponse.json({ error: "O estoque novo ainda não está ligado nesta empresa." }, { status: 409 });
  }
  const { data: existente } = await adminSupabase.from("product_materials").select("id,product_id").eq("id", id).maybeSingle();
  if (!existente || !(await produtoDaEmpresa(adminSupabase, ctx, (existente as { product_id: string }).product_id))) {
    return NextResponse.json({ error: "Linha não encontrada." }, { status: 404 });
  }

  const { data, error } = await adminSupabase
    .from("product_materials")
    .update(linhaDaComposicaoParaGravar(body, true))
    .eq("id", id)
    .select("*, materials!material_id(name, unit, cost_per_unit, track_stock, is_service, grade, papel)")
    .single();
  if (error) return NextResponse.json({ error: error.message }, { status: 400 });

  updateProductCost((existente as { product_id: string }).product_id).catch((err) => console.error("Error updating product cost:", err));
  return NextResponse.json(data);
}

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

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

  const { searchParams } = new URL(req.url);
  const id = searchParams.get("id");

  if (!id) return NextResponse.json({ error: "ID required" }, { status: 400 });

  const adminSupabase = createAdminClient();

  // Get product_id before deleting
  const { data: existing, error: fetchError } = await adminSupabase
    .from("product_materials")
    .select("product_id")
    .eq("id", id)
    .single();

  if (fetchError || !existing) return NextResponse.json({ error: "Material não encontrado." }, { status: 404 });
  if (!(await produtoDaEmpresa(adminSupabase, ctx, existing.product_id))) {
    return NextResponse.json({ error: "Material não encontrado." }, { status: 404 });
  }

  const { error } = await adminSupabase
    .from("product_materials")
    .delete()
    .eq("id", id);

  if (error) return NextResponse.json({ error: error.message }, { status: 400 });

  // Update product cost asynchronously
  if (existing?.product_id) {
    updateProductCost(existing.product_id).catch(err => console.error("Error updating product cost:", err));
  }

  return NextResponse.json({ ok: true });
}
