import { NextResponse } from "next/server";
import { randomUUID } from "node:crypto";
import { createClient } from "@/lib/supabase-server";
import { canCompany, getCompanyContext } from "@/lib/company-context";
import {
  aplicarNosModelos,
  condicoesDoPadrao,
  lerModelos,
  NOME_DO_PADRAO_ANTIGO,
  type AcaoNosModelos,
} from "@/lib/modelos-de-condicoes";

export const runtime = "nodejs";

/* Os modelos de condições comerciais da empresa: a lista de onde todo
   orçamento novo parte. Ficam no perfil do dono, e só o dono mexe — o mesmo
   perfil que guarda as outras preferências do orçamento.
   A regra mora em lib/modelos-de-condicoes.ts; aqui é só ler, aplicar e
   gravar. A lista manda; `quote_default_payment_terms` é o espelho do modelo
   marcado como padrão, porque é dele que as telas antigas leem. */

function lerAcao(bruto: unknown): AcaoNosModelos | { erro: string } {
  const r = bruto && typeof bruto === "object" ? (bruto as Record<string, unknown>) : {};
  const id = typeof r.id === "string" ? r.id : "";
  const nome = typeof r.nome === "string" ? r.nome : "";

  switch (r.acao) {
    case "criar":
      return { acao: "criar", id: randomUUID(), nome, condicoes: r.payment_terms, padrao: r.padrao === true };
    case "renomear":
      return { acao: "renomear", id, nome };
    case "substituir":
      return { acao: "substituir", id, condicoes: r.payment_terms };
    case "excluir":
      return { acao: "excluir", id };
    case "padrao":
      /* Nulo de propósito: é assim que a empresa fica sem padrão. */
      return { acao: "padrao", id: r.id === null ? null : id };
    default:
      return { erro: "Ação desconhecida." };
  }
}

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, "quotes.write")) {
    return NextResponse.json({ error: "Sem permissão para mexer em orçamentos." }, { status: 403 });
  }
  const ownerId = ctx.ownerId || user.id;
  if (ownerId !== user.id) {
    return NextResponse.json({ error: "Só o dono da empresa mexe nos modelos de condições." }, { status: 403 });
  }

  const body = (await req.json().catch(() => null)) as Record<string, unknown> | null;

  const { data: perfil, error: erroDoPerfil } = await supabase
    .from("profiles")
    .select("quote_payment_terms_templates,quote_default_payment_terms")
    .eq("id", ownerId)
    .maybeSingle();
  if (erroDoPerfil) return NextResponse.json({ error: "Não deu para ler os modelos." }, { status: 400 });

  const linha = (perfil ?? {}) as { quote_payment_terms_templates?: unknown; quote_default_payment_terms?: unknown };
  const modelos = lerModelos(linha.quote_payment_terms_templates, linha.quote_default_payment_terms);

  /* Corpo antigo, de uma aba aberta antes desta tela existir: "este é o
     padrão da empresa". Vira substituir o modelo padrão, ou criar o primeiro. */
  const semAcao = body && !("acao" in body) && "payment_terms" in body;
  const padraoAtual = modelos.find((modelo) => modelo.padrao);
  const acao: AcaoNosModelos | { erro: string } = semAcao
    ? padraoAtual
      ? { acao: "substituir", id: padraoAtual.id, condicoes: body.payment_terms }
      : { acao: "criar", id: randomUUID(), nome: NOME_DO_PADRAO_ANTIGO, condicoes: body?.payment_terms, padrao: true }
    : lerAcao(body);

  if ("erro" in acao) return NextResponse.json({ error: acao.erro }, { status: 400 });

  const resultado = aplicarNosModelos(modelos, acao);
  if (!resultado.modelos) return NextResponse.json({ error: resultado.erro }, { status: 400 });

  const payment_terms = condicoesDoPadrao(resultado.modelos);
  const { error } = await supabase
    .from("profiles")
    .update({
      quote_payment_terms_templates: resultado.modelos,
      quote_default_payment_terms: payment_terms,
    })
    .eq("id", ownerId);
  if (error) return NextResponse.json({ error: error.message }, { status: 400 });

  return NextResponse.json({ ok: true, modelos: resultado.modelos, payment_terms });
}
