import { cookies } from "next/headers";
import { NextResponse } from "next/server";
import { createAdminClient } from "@/lib/supabase-admin";
import { normalizeWhatsappForLink } from "@/lib/phone";
import { digitsOnly } from "@/lib/document-utils";
import { lerClienteLogado, navegadorDaEquipe } from "@/lib/loja/visao.server";
import { faltaParaOPedidoMinimo, resolverVisao } from "@/lib/loja/regras-da-loja";
import { origemDaRequisicao, tentativaPermitida } from "@/lib/limite-de-tentativas";
import type { ShippingSelection } from "@/lib/catalog-shipping";
import {
  avisarLojaDoPedido,
  calculateItemsSubtotal,
  conferirPrecosNoServidor,
  gravarPedidoDaLoja,
  mensagemDoPedidoNoWhatsapp,
  normalizarItens,
  normalizeText,
  resolveValidatedShippingSelection,
  unidadesDosItens,
} from "@/lib/pedido-da-loja.server";
import { isPickupShippingOption } from "@/lib/catalog-shipping";
import {
  calcularCuponsDoPedido,
  codigoDoPedido,
  codigosDoCorpo,
  codigosPorVaga,
  mensagemDosErros,
  cuponsNoPedido,
  ligarUsosAoPedido,
  reservarUsosDosCupons,
  soltarReservasDosCupons,
  SEM_CUPONS,
} from "@/lib/cupom-da-loja.server";

/*
  O pedido feito pela loja sem passar pelo checkout com pagamento.

  Dois modos:
  - "whatsapp": o pedido do tema Padrao e do Vendor sem pagamento online, que
    antes nascia direto do navegador (funcao do banco liberada para o
    visitante, gravando os precos que o navegador mandava). Agora e o
    servidor que precifica, confere cupom, limites, estoque e frete, grava e
    abre o WhatsApp.
  - "orcamento": o pedido de orcamento (regra da loja). O cliente nao ve
    precos; o pedido e gravado com os precos do cadastro para o lojista, e a
    mensagem do WhatsApp sai sem valor nenhum.

  Em qualquer modo a loja e avisada (sino e celular).
*/

export const dynamic = "force-dynamic";

type Corpo = {
  slug?: string;
  modo?: "whatsapp" | "orcamento";
  items?: unknown;
  couponCode?: string | null;
  /** Até um cupom de desconto e um de frete grátis (o carrinho de agora). */
  couponCodes?: string[] | null;
  shippingSelection?: ShippingSelection | null;
  customer?: { name?: string; phone?: string; whatsapp?: string; email?: string; notes?: string } | null;
  clearAfterOpen?: boolean;
};

const COLUNAS_DA_LOJA =
  "id,slug,catalog_name,store_name,whatsapp,company_whatsapp,catalog_price_mode,catalog_price_hidden_text,catalog_price_login_text," +
  "catalog_price_notice,catalog_purchase_mode,catalog_cta_label,catalog_checkout_label,catalog_quote_open_whatsapp,catalog_access_mode," +
  "catalog_signup_mode,catalog_require_login_to_order,catalog_min_order_total,catalog_min_order_items,catalog_status,catalog_status_message,whatsapp_templates";

export async function POST(request: Request) {
  try {
    const origem = origemDaRequisicao(request);
    if (!tentativaPermitida(`pedido:${origem}`, 30, 10 * 60)) {
      return NextResponse.json({ error: "Muitos pedidos seguidos. Aguarde alguns minutos." }, { status: 429 });
    }

    const body = ((await request.json().catch(() => null)) || {}) as Corpo;
    const slug = normalizeText(body.slug).toLowerCase();
    const modo = body.modo === "orcamento" ? "orcamento" : "whatsapp";
    const items = normalizarItens(body.items);
    if (!slug) return NextResponse.json({ error: "Loja inválida." }, { status: 400 });
    if (!items.length) return NextResponse.json({ error: "Seu carrinho está vazio." }, { status: 400 });

    const admin = createAdminClient();
    const { data: perfil } = await admin.from("profiles").select(COLUNAS_DA_LOJA).eq("slug", slug).maybeSingle();
    const loja = perfil as (Record<string, unknown> & { id: string }) | null;
    if (!loja?.id) return NextResponse.json({ error: "Loja não encontrada." }, { status: 404 });

    const token = (await cookies()).get("ks_client_portal")?.value || "";
    const [cliente, equipe] = await Promise.all([lerClienteLogado(slug, token), navegadorDaEquipe(loja.id)]);
    const visao = resolverVisao(loja, cliente ? { id: cliente.id, name: cliente.name, status: cliente.status } : null, equipe);

    if (visao.lojaFechada || visao.lojaPausada) {
      return NextResponse.json({ error: visao.motivoDoBloqueio || "A loja não está recebendo pedidos agora." }, { status: 403 });
    }
    if (visao.aguardandoAprovacao) {
      return NextResponse.json({ error: "Seu cadastro ainda está em análise pela loja." }, { status: 403 });
    }
    if (visao.cadastroRecusado) {
      return NextResponse.json({ error: "Seu cadastro não foi aprovado pela loja." }, { status: 403 });
    }
    if (visao.exigeLoginNaLoja || visao.precisaEntrar || (visao.exigeLoginParaFechar && !cliente)) {
      return NextResponse.json({ error: "Entre na sua conta para fechar o pedido." }, { status: 401 });
    }
    if (visao.modoDeCompra === "showcase") {
      return NextResponse.json({ error: "Esta loja não recebe pedidos pela internet." }, { status: 403 });
    }
    const kind: "order" | "quote_request" = modo === "orcamento" || visao.modoDeCompra === "quote" ? "quote_request" : "order";
    /* So entra o que a loja oferece a esse visitante: pedido pelo carrinho
       numa loja de carrinho, lista de orcamento numa loja de orcamento. */
    if ((kind === "order" && visao.modoDeCompra !== "cart") || (modo === "orcamento" && visao.modoDeCompra !== "quote")) {
      return NextResponse.json({ error: "Esta loja fecha pedidos de outro jeito. Recarregue a página." }, { status: 400 });
    }

    /* Quem pede. Com sessao, e o cadastro; sem, o que a pessoa digitou. No
       pedido de orcamento o nome e um contato sao obrigatorios: a loja precisa
       responder para alguem. */
    const digitado = body.customer || {};
    const customer = cliente
      ? {
          name: normalizeText(cliente.name) || normalizeText(digitado.name),
          phone: normalizeText(cliente.phone) || normalizeText(digitado.phone),
          whatsapp: normalizeText(cliente.whatsapp) || normalizeText(cliente.phone) || normalizeText(digitado.whatsapp),
          email: normalizeText(cliente.email) || normalizeText(digitado.email),
          document: digitsOnly(cliente.document || "").slice(0, 14),
          company_name: normalizeText(cliente.company_name),
          notes: normalizeText(digitado.notes).slice(0, 1000),
        }
      : {
          name: normalizeText(digitado.name).slice(0, 120),
          phone: normalizeText(digitado.phone).slice(0, 30),
          whatsapp: normalizeText(digitado.whatsapp).slice(0, 30) || normalizeText(digitado.phone).slice(0, 30),
          email: normalizeText(digitado.email).slice(0, 160),
          document: "",
          company_name: "",
          notes: normalizeText(digitado.notes).slice(0, 1000),
        };
    if (kind === "quote_request") {
      if (!customer.name) return NextResponse.json({ error: "Diga o seu nome para a loja responder." }, { status: 400 });
      if (!customer.whatsapp && !customer.email) {
        return NextResponse.json({ error: "Informe um WhatsApp ou e-mail para a loja responder." }, { status: 400 });
      }
    }

    /* O preco e a verdade do banco; o que o navegador mandou so serve de pista. */
    await conferirPrecosNoServidor(admin, loja.id, items);

    const unidades = unidadesDosItens(items);
    const subtotal = Number(calculateItemsSubtotal(items).toFixed(2));
    const falta = faltaParaOPedidoMinimo(visao.regras, { total: subtotal, unidades, mostrarPreco: visao.mostrarPreco });
    if (falta) return NextResponse.json({ error: falta }, { status: 400 });

    const shippingSelection =
      kind === "order"
        ? await resolveValidatedShippingSelection({ admin, slug, items, selection: body.shippingSelection })
        : null;
    const shippingTotal = shippingSelection ? Number(Number(shippingSelection.option.price || 0).toFixed(2)) : 0;

    /* Os cupons sao conferidos aqui, com o frete ja validado: ate um de
       desconto e um de frete gratis, digitados ou automaticos. O desconto
       nunca vem do navegador. */
    const cupons =
      kind === "order" && visao.mostrarPreco
        ? await calcularCuponsDoPedido(admin, {
            storeId: loja.id,
            codigos: codigosDoCorpo(body),
            items,
            cliente: cliente ? { id: cliente.id } : null,
            frete: shippingSelection
              ? { valor: shippingTotal, cep: shippingSelection.destination_zip, retirada: isPickupShippingOption(shippingSelection.option) }
              : null,
          })
        : SEM_CUPONS;
    /* Codigo mandado que nao vale e recusado com a razao (o carrinho so manda
       os codigos aplicados; os automaticos o servidor acha sozinho). */
    if (cupons.erros.length) throw new Error(mensagemDosErros(cupons));
    const couponCode = codigoDoPedido(cupons);
    const codigos = codigosPorVaga(cupons);
    const discount = cupons.desconto;
    const shippingDiscount = Math.min(cupons.descontoNoFrete, shippingTotal);
    const shippingCharged = Number(Math.max(shippingTotal - shippingDiscount, 0).toFixed(2));
    const total = Number(Math.max(subtotal - discount + shippingCharged, 0).toFixed(2));

    const storeName = normalizeText(loja.catalog_name || loja.store_name) || "Loja";
    const whatsappDigits = normalizeWhatsappForLink(String(loja.company_whatsapp || loja.whatsapp || ""));
    const abreWhatsapp = kind === "order" ? true : visao.regras.abrirWhatsappNoOrcamento;
    if (kind === "order" && !whatsappDigits) {
      return NextResponse.json({ error: "A loja ainda não configurou o WhatsApp." }, { status: 400 });
    }

    const hasOnRequest = items.some((item) => item.price_on_request);
    const mensagem = (numero: number | null) =>
      mensagemDoPedidoNoWhatsapp({
        storeName,
        kind,
        numero,
        items,
        mostrarPrecos: visao.mostrarPreco,
        cliente: customer.name || customer.whatsapp || customer.email ? customer : null,
        subtotal,
        discount,
        shippingTotal,
        total,
        couponCode: codigos.desconto,
        shippingDiscount,
        shippingCouponCode: codigos.frete,
        shippingSelection,
        modelos: visao.regras.mensagensDoWhatsapp,
      });
    const urlDoWhatsapp = (numero: number | null) =>
      whatsappDigits && abreWhatsapp ? `https://wa.me/${whatsappDigits}?text=${encodeURIComponent(mensagem(numero))}` : "";

    /* A trava do limite: o uso e reservado antes de gravar o pedido. */
    const usosDosCupons = await reservarUsosDosCupons(admin, cupons, { clienteId: cliente?.id || null });
    const pedido = await gravarPedidoDaLoja(admin, {
      slug,
      storeId: loja.id,
      kind,
      items,
      subtotal,
      discount,
      shipping: shippingCharged,
      total,
      couponCode,
      customer: {
        name: customer.name,
        phone: customer.phone,
        whatsapp: customer.whatsapp,
        email: customer.email,
        document: customer.document,
        notes: customer.notes,
      },
      clientId: cliente?.id || null,
      whatsappUrl: urlDoWhatsapp(null),
      cartPayload: {
        source: kind === "quote_request" ? "quote_request" : cliente ? "identified_whatsapp" : "whatsapp",
        has_on_request: hasOnRequest,
        prices_hidden_from_customer: !visao.mostrarPreco,
        clear_after_open: Boolean(body.clearAfterOpen),
        client_email: customer.email || null,
        client_document: customer.document || null,
        shipping: shippingSelection
          ? {
              destination_zip: shippingSelection.destination_zip,
              amount: shippingCharged,
              option: shippingSelection.option,
              ...(shippingDiscount > 0 ? { original_amount: shippingTotal, coupon_discount: shippingDiscount } : {}),
            }
          : null,
        ...cuponsNoPedido(cupons),
      },
      paymentProvider: null,
    }).catch(async (erro) => {
      await soltarReservasDosCupons(admin, usosDosCupons);
      throw erro;
    });
    await ligarUsosAoPedido(admin, usosDosCupons, pedido.id);

    /* A URL definitiva leva o numero do pedido, para a loja achar na hora. */
    const whatsappUrl = urlDoWhatsapp(pedido.number);
    if (whatsappUrl) {
      await admin.from("catalog_orders").update({ whatsapp_url: whatsappUrl }).eq("id", pedido.id);
    }

    await avisarLojaDoPedido(admin, {
      storeId: loja.id,
      orderId: pedido.id,
      kind,
      numero: pedido.number,
      cliente: customer.name || null,
      total: kind === "quote_request" ? null : total,
      itens: unidades,
    }).catch(() => undefined);

    return NextResponse.json({
      ok: true,
      kind,
      order_id: pedido.id,
      order_number: pedido.number,
      whatsapp_url: whatsappUrl || null,
    });
  } catch (error) {
    const message = error instanceof Error ? error.message : "Não foi possível registrar o pedido.";
    return NextResponse.json({ error: message }, { status: 400 });
  }
}
