import { cookies } from "next/headers";
import { NextResponse } from "next/server";
import { createAdminClient } from "@/lib/supabase-admin";
import { digitsOnly, validateBrazilianDocument } from "@/lib/document-utils";
import { normalizeWhatsappForLink } from "@/lib/phone";
import { parseMercadoPagoSettings, resolveMercadoPagoPublicConfig } from "@/lib/mercado-pago";
import { lerConfiguracaoDoAsaas } from "@/lib/asaas";
import { confirmarPedidoSemValor } from "@/lib/catalog-payment-processing";
import { conferirEstoqueAntesDeCobrar } from "@/lib/estoque-antes-de-cobrar";
import { carregarPagamento, meiosDoLocal } from "@/lib/provedor-de-pagamento";
import { isPickupShippingOption, type ShippingSelection } from "@/lib/catalog-shipping";
import { isClientAddressComplete, normalizeClientAddressInput } from "@/lib/client-portal-addresses";
import { faltaParaOPedidoMinimo, resolverVisao } from "@/lib/loja/regras-da-loja";
import { navegadorDaEquipe } from "@/lib/loja/visao.server";
import {
  avisarLojaDoPedido,
  calculateItemTotal,
  calculateItemsSubtotal,
  conferirPrecosNoServidor,
  mensagemDoPedidoNoWhatsapp,
  normalizarItens,
  resolveValidatedShippingSelection,
  unidadesDosItens,
  type ItemDoPedido,
} from "@/lib/pedido-da-loja.server";
import {
  calcularCuponsDoPedido,
  codigoDoPedido,
  codigosDoCorpo,
  codigosPorVaga,
  cuponsNoPedido,
  mensagemDosErros,
  ligarUsosAoPedido,
  reservarUsosDosCupons,
  soltarReservasDosCupons,
  soltarUsoDoPedidoEmAberto,
} from "@/lib/cupom-da-loja.server";

/* O item do checkout e o mesmo item do pedido da loja (lib/pedido-da-loja.server.ts). */
type CheckoutItemInput = ItemDoPedido;

type CheckoutProfileInput = {
  name?: string | null;
  company_name?: string | null;
  document?: string | null;
  email?: string | null;
  phone?: string | null;
  whatsapp?: string | null;
  address_zip?: string | null;
  address_street?: string | null;
  address_number?: string | null;
  address_complement?: string | null;
  address_neighborhood?: string | null;
  address_city?: string | null;
  address_state?: string | null;
  notes?: string | null;
};

type NormalizedCheckoutProfile = ReturnType<typeof normalizeProfileInput>;
type CheckoutShippingSelectionInput = ShippingSelection | null | undefined;
type CheckoutAddressSelectionInput = {
  selectedAddressId?: string | null;
  saveAddressToBook?: boolean | null;
  setAsDefaultAddress?: boolean | null;
} | null | undefined;

type DeliveryAddressSnapshot = {
  source: "saved_address" | "checkout_form";
  selected_address_id: string | null;
  label: string | null;
  recipient_name: string | null;
  phone: string | null;
  zip: string | null;
  street: string | null;
  number: string | null;
  complement: string | null;
  neighborhood: string | null;
  city: string | null;
  state: string | null;
  reference: string | null;
  summary: string | null;
};

type SessionClientAddress = {
  id: string;
  label?: string | null;
  recipient_name?: string | null;
  phone?: string | null;
  zip?: string | null;
  street?: string | null;
  number?: string | null;
  complement?: string | null;
  neighborhood?: string | null;
  city?: string | null;
  state?: string | null;
  reference?: string | null;
  is_default?: boolean | null;
};

type SessionPayload = {
  client?: {
    id: string;
    name?: string | null;
    portal_status?: string | null;
    document?: string | null;
    email?: string | null;
    phone?: string | null;
    whatsapp?: string | null;
    company_name?: string | null;
    address_zip?: string | null;
    address_street?: string | null;
    address_number?: string | null;
    address_complement?: string | null;
    address_neighborhood?: string | null;
    address_city?: string | null;
    address_state?: string | null;
    notes?: string | null;
    addresses?: SessionClientAddress[] | null;
  } | null;
};

function normalizeText(value: unknown) {
  return String(value || "").trim();
}

function normalizeProfileInput(input: CheckoutProfileInput | null | undefined) {
  return {
    name: normalizeText(input?.name),
    company_name: normalizeText(input?.company_name),
    document: digitsOnly(input?.document || "").slice(0, 14),
    email: normalizeText(input?.email),
    phone: normalizeText(input?.phone),
    whatsapp: normalizeText(input?.whatsapp),
    address_zip: normalizeText(input?.address_zip),
    address_street: normalizeText(input?.address_street),
    address_number: normalizeText(input?.address_number),
    address_complement: normalizeText(input?.address_complement),
    address_neighborhood: normalizeText(input?.address_neighborhood),
    address_city: normalizeText(input?.address_city),
    address_state: normalizeText(input?.address_state).toUpperCase(),
    notes: normalizeText(input?.notes),
  };
}

function normalizeAddressSelection(input: CheckoutAddressSelectionInput) {
  return {
    selectedAddressId: normalizeText(input?.selectedAddressId),
    saveAddressToBook: Boolean(input?.saveAddressToBook),
    setAsDefaultAddress: Boolean(input?.setAsDefaultAddress),
  };
}

function buildDeliveryAddressSnapshot(params: {
  profileInput: NormalizedCheckoutProfile;
  addressSelection: ReturnType<typeof normalizeAddressSelection>;
  selectedAddress?: SessionClientAddress | null;
}) {
  const { profileInput, addressSelection, selectedAddress } = params;
  const normalizedSelected = selectedAddress ? normalizeClientAddressInput(selectedAddress) : null;
  const recipientName =
    normalizeText(normalizedSelected?.recipient_name) ||
    normalizeText(profileInput.company_name) ||
    normalizeText(profileInput.name) ||
    null;
  const contactPhone =
    normalizeText(normalizedSelected?.phone) ||
    normalizeText(profileInput.phone) ||
    normalizeText(profileInput.whatsapp) ||
    null;
  const reference =
    normalizeText(normalizedSelected?.reference) ||
    normalizeText(profileInput.notes) ||
    null;
  const addressFields = {
    zip: normalizeText(normalizedSelected?.zip) || profileInput.address_zip || null,
    street: normalizeText(normalizedSelected?.street) || profileInput.address_street || null,
    number: normalizeText(normalizedSelected?.number) || profileInput.address_number || null,
    complement: normalizeText(normalizedSelected?.complement) || profileInput.address_complement || null,
    neighborhood: normalizeText(normalizedSelected?.neighborhood) || profileInput.address_neighborhood || null,
    city: normalizeText(normalizedSelected?.city) || profileInput.address_city || null,
    state: normalizeText(normalizedSelected?.state) || profileInput.address_state || null,
  };

  return {
    source: selectedAddress?.id ? "saved_address" : "checkout_form",
    selected_address_id: addressSelection.selectedAddressId || null,
    label: normalizeText(normalizedSelected?.label) || null,
    recipient_name: recipientName,
    phone: contactPhone,
    zip: addressFields.zip,
    street: addressFields.street,
    number: addressFields.number,
    complement: addressFields.complement,
    neighborhood: addressFields.neighborhood,
    city: addressFields.city,
    state: addressFields.state,
    reference: reference,
    summary: [
      [addressFields.street, addressFields.number].filter(Boolean).join(", "),
      addressFields.complement || "",
      addressFields.neighborhood || "",
      [addressFields.city, addressFields.state].filter(Boolean).join(" / "),
      addressFields.zip ? `CEP ${addressFields.zip}` : "",
    ]
      .filter(Boolean)
      .join(" • ") || null,
  } satisfies DeliveryAddressSnapshot;
}

async function resolveEffectiveCheckoutProfile(params: {
  admin: ReturnType<typeof createAdminClient>;
  profileId: string;
  sessionPayload: SessionPayload;
  profileInput: NormalizedCheckoutProfile;
  addressSelection: ReturnType<typeof normalizeAddressSelection>;
}) {
  const { admin, profileId, sessionPayload, profileInput, addressSelection } = params;
  const selectedAddressId = addressSelection.selectedAddressId;
  if (!selectedAddressId) {
    return {
      profileInput,
      deliveryAddress: buildDeliveryAddressSnapshot({
        profileInput,
        addressSelection,
      }),
    };
  }

  const availableAddresses = Array.isArray(sessionPayload.client?.addresses) ? sessionPayload.client?.addresses : [];
  const selectedFromSession = availableAddresses.find((address) => String(address.id || "") === selectedAddressId);

  let selectedAddress = selectedFromSession || null;
  if (!selectedAddress) {
    const { data } = await admin
      .from("client_addresses")
      .select("id,label,recipient_name,phone,zip,street,number,complement,neighborhood,city,state,reference,is_default")
      .eq("id", selectedAddressId)
      .eq("client_id", sessionPayload.client?.id || "")
      .eq("user_id", profileId)
      .is("deleted_at", null)
      .maybeSingle();
    selectedAddress = (data as typeof selectedFromSession) || null;
  }

  if (!selectedAddress?.id) {
    throw new Error("O endereço selecionado para entrega não foi encontrado.");
  }

  const normalizedSelected = normalizeClientAddressInput({
    label: selectedAddress.label,
    recipient_name: selectedAddress.recipient_name,
    phone: selectedAddress.phone,
    zip: selectedAddress.zip,
    street: selectedAddress.street,
    number: selectedAddress.number,
    complement: selectedAddress.complement,
    neighborhood: selectedAddress.neighborhood,
    city: selectedAddress.city,
    state: selectedAddress.state,
    reference: selectedAddress.reference,
    is_default: selectedAddress.is_default,
  });

  if (!isClientAddressComplete(normalizedSelected)) {
    throw new Error("O endereço selecionado está incompleto.");
  }

  const nextProfileInput = {
    ...profileInput,
    address_zip: normalizedSelected.zip || "",
    address_street: normalizedSelected.street || "",
    address_number: normalizedSelected.number || "",
    address_complement: normalizedSelected.complement || "",
    address_neighborhood: normalizedSelected.neighborhood || "",
    address_city: normalizedSelected.city || "",
    address_state: normalizedSelected.state || "",
    notes: profileInput.notes || normalizedSelected.reference || "",
  };

  return {
    profileInput: nextProfileInput,
    deliveryAddress: buildDeliveryAddressSnapshot({
      profileInput: nextProfileInput,
      addressSelection,
      selectedAddress,
    }),
  };
}

async function saveCheckoutAddressToBook(params: {
  admin: ReturnType<typeof createAdminClient>;
  profileId: string;
  clientId: string;
  profileInput: NormalizedCheckoutProfile;
  addressSelection: ReturnType<typeof normalizeAddressSelection>;
}) {
  const { admin, profileId, clientId, profileInput, addressSelection } = params;
  if (!addressSelection.saveAddressToBook || !isClientAddressComplete(profileInput)) {
    return;
  }

  const normalized = normalizeClientAddressInput({
    label: addressSelection.setAsDefaultAddress ? "Principal" : "Entrega",
    recipient_name: profileInput.company_name || profileInput.name,
    phone: profileInput.phone || profileInput.whatsapp,
    zip: profileInput.address_zip,
    street: profileInput.address_street,
    number: profileInput.address_number,
    complement: profileInput.address_complement,
    neighborhood: profileInput.address_neighborhood,
    city: profileInput.address_city,
    state: profileInput.address_state,
    reference: profileInput.notes,
    is_default: addressSelection.setAsDefaultAddress,
  });

  const { data: existingAddress } = await admin
    .from("client_addresses")
    .select("id,is_default")
    .eq("client_id", clientId)
    .eq("user_id", profileId)
    .eq("zip", normalized.zip || "")
    .eq("street", normalized.street || "")
    .eq("number", normalized.number || "")
    .eq("neighborhood", normalized.neighborhood || "")
    .eq("city", normalized.city || "")
    .eq("state", normalized.state || "")
    .is("deleted_at", null)
    .maybeSingle();

  if (addressSelection.setAsDefaultAddress) {
    await admin
      .from("client_addresses")
      .update({ is_default: false, updated_at: new Date().toISOString() })
      .eq("client_id", clientId)
      .eq("user_id", profileId)
      .is("deleted_at", null);
  }

  if (existingAddress?.id) {
    await admin
      .from("client_addresses")
      .update({
        label: normalized.label || "Entrega",
        recipient_name: normalized.recipient_name || null,
        phone: normalized.phone || null,
        zip: normalized.zip || null,
        street: normalized.street || null,
        number: normalized.number || null,
        complement: normalized.complement || null,
        neighborhood: normalized.neighborhood || null,
        city: normalized.city || null,
        state: normalized.state || null,
        reference: normalized.reference || null,
        is_default: addressSelection.setAsDefaultAddress || existingAddress.is_default,
        updated_at: new Date().toISOString(),
      })
      .eq("id", existingAddress.id)
      .eq("client_id", clientId)
      .eq("user_id", profileId)
      .is("deleted_at", null);
  } else {
    await admin.from("client_addresses").insert({
      user_id: profileId,
      client_id: clientId,
      label: normalized.label || "Entrega",
      recipient_name: normalized.recipient_name || null,
      phone: normalized.phone || null,
      zip: normalized.zip || null,
      street: normalized.street || null,
      number: normalized.number || null,
      complement: normalized.complement || null,
      neighborhood: normalized.neighborhood || null,
      city: normalized.city || null,
      state: normalized.state || null,
      reference: normalized.reference || null,
      is_default: Boolean(addressSelection.setAsDefaultAddress),
    });
  }

  if (addressSelection.setAsDefaultAddress) {
    await admin
      .from("clients")
      .update({
        address_zip: normalized.zip || null,
        address_street: normalized.street || null,
        address_number: normalized.number || null,
        address_complement: normalized.complement || null,
        address_neighborhood: normalized.neighborhood || null,
        address_city: normalized.city || null,
        address_state: normalized.state || null,
        updated_at: new Date().toISOString(),
      })
      .eq("id", clientId)
      .eq("user_id", profileId);
  }
}

/*
  O que a finalização exige. A tela (CatalogCheckoutClient) pede exatamente o
  mesmo: antes ela aceitava um contato qualquer e o servidor cobrava telefone E
  WhatsApp, e o cliente passava pelo formulário para tomar erro no fim. Um
  número basta para a loja falar com ele; o e-mail só é obrigatório quando a
  loja cobra online, porque o Mercado Pago e o Asaas não cobram sem ele.
*/
function getMissingCheckoutFields(
  profile: ReturnType<typeof normalizeProfileInput>,
  opcoes: { exigeEmail: boolean }
) {
  const missing: string[] = [];
  if (!profile.name) missing.push("Nome");
  if (!profile.document) missing.push("CPF/CNPJ");
  if (!profile.phone && !profile.whatsapp) missing.push("WhatsApp ou telefone");
  if (opcoes.exigeEmail && !profile.email) missing.push("E-mail");
  if (!profile.address_zip) missing.push("CEP");
  if (!profile.address_street) missing.push("Rua");
  if (!profile.address_number) missing.push("Numero");
  if (!profile.address_neighborhood) missing.push("Bairro");
  if (!profile.address_city) missing.push("Cidade");
  if (!profile.address_state) missing.push("UF");
  return missing;
}

async function replaceCatalogOrderItems(
  admin: ReturnType<typeof createAdminClient>,
  catalogOrderId: string,
  items: Array<{
    product_id: string;
    name: string;
    quantity: number;
    unit_type: string;
    width_m: number;
    height_m: number;
    length_m: number;
    variation_description: string;
    selected_options: Record<string, unknown> | null;
    price: number;
    price_on_request: boolean;
    valor_minimo_aplicado?: number | null;
    valor_sem_minimo?: number | null;
  }>
) {
  const { error: deleteError } = await admin.from("catalog_order_items").delete().eq("catalog_order_id", catalogOrderId);
  if (deleteError) {
    throw new Error("Não foi possível atualizar os itens do pedido.");
  }

  const payload = items.map((item) => ({
    catalog_order_id: catalogOrderId,
    product_id: item.product_id || null,
    title: item.name,
    description: item.variation_description || "",
    quantity: Number(item.quantity || 0),
    unit_type: item.unit_type || "unit",
    width_m: item.width_m || 0,
    height_m: item.height_m || 0,
    length_m: item.length_m || 0,
    unit_price: Number(item.price || 0),
    total_price: Number(calculateItemTotal(item)),
    variation_description: item.variation_description || "",
    selected_options: item.selected_options || null,
    raw_item: {
      product_id: item.product_id || null,
      name: item.name,
      quantity: Number(item.quantity || 0),
      unit_type: item.unit_type || "unit",
      width_m: item.width_m || 0,
      height_m: item.height_m || 0,
      length_m: item.length_m || 0,
      unit_price: Number(item.price || 0),
      total_price: Number(calculateItemTotal(item)),
      variation_description: item.variation_description || "",
      selected_options: item.selected_options || null,
      raw_price_on_request: Boolean(item.price_on_request),
      valor_minimo_aplicado: item.valor_minimo_aplicado ?? null,
      valor_sem_minimo: item.valor_minimo_aplicado != null ? item.valor_sem_minimo ?? null : null,
    },
  }));

  const { error: insertError } = await admin.from("catalog_order_items").insert(payload);
  if (insertError) {
    throw new Error("Não foi possível salvar os itens atualizados do pedido.");
  }
}

async function cancelPendingCatalogPayments(
  admin: ReturnType<typeof createAdminClient>,
  catalogOrderId: string
) {
  const now = new Date().toISOString();
  const { error } = await admin
    .from("catalog_order_payments")
    .update({
      status: "cancelled",
      provider_status: "replaced_in_checkout",
      provider_status_detail: "checkout_updated_before_new_attempt",
      cancelled_at: now,
      updated_at: now,
    })
    .eq("catalog_order_id", catalogOrderId)
    .eq("status", "pending");

  if (error) {
    throw new Error("Não foi possível invalidar as tentativas de pagamento anteriores.");
  }
}

async function upsertCatalogOrder(params: {
  admin: ReturnType<typeof createAdminClient>;
  slug: string;
  existingOrderId: string;
  profileId: string;
  sessionClientId: string;
  profileInput: NormalizedCheckoutProfile;
  subtotal: number;
  discount: number;
  shipping: number;
  /** O frete cheio, antes do cupom de frete gratis (igual a shipping sem ele). */
  shippingOriginal: number;
  /** Os cupons, como vão no cart_payload (coupon = o de desconto, coupons = os dois). */
  cupom: ReturnType<typeof cuponsNoPedido>;
  total: number;
  couponCode: string;
  items: Array<{
    product_id: string;
    name: string;
    quantity: number;
    unit_type: string;
    width_m: number;
    height_m: number;
    length_m: number;
    variation_description: string;
    selected_options: Record<string, unknown> | null;
    price: number;
    price_on_request: boolean;
    valor_minimo_aplicado?: number | null;
    valor_sem_minimo?: number | null;
  }>;
  whatsappUrl: string;
  hasOnRequestItems: boolean;
  clientEmail: string;
  provedorDePagamento: string | null;
  shippingSelection: ShippingSelection | null;
  addressSelection: ReturnType<typeof normalizeAddressSelection>;
  deliveryAddress: DeliveryAddressSnapshot;
}) {
  const {
    admin,
    slug,
    existingOrderId,
    profileId,
    sessionClientId,
    profileInput,
    subtotal,
    discount,
    shipping,
    shippingOriginal,
    cupom,
    total,
    couponCode,
    items,
    whatsappUrl,
    hasOnRequestItems,
    clientEmail,
    provedorDePagamento,
    shippingSelection,
    addressSelection,
    deliveryAddress,
  } = params;

  const orderPayload = {
    currency: "BRL",
    subtotal,
    discount,
    total,
    coupon_code: couponCode || null,
    customer_name: profileInput.name,
    customer_document: profileInput.document,
    customer_phone: profileInput.phone,
    customer_whatsapp: profileInput.whatsapp,
    notes: profileInput.notes || "",
    whatsapp_url: whatsappUrl,
    items: items.map((item) => ({
      product_id: item.product_id || null,
      name: item.name,
      description: item.variation_description || "",
      quantity: Number(item.quantity || 0),
      unit_type: item.unit_type || "unit",
      width_m: item.width_m || 0,
      height_m: item.height_m || 0,
      length_m: item.length_m || 0,
      unit_price: Number(item.price || 0),
      total_price: Number(calculateItemTotal(item)),
      variation_description: item.variation_description || "",
      selected_options: item.selected_options || null,
      raw_price_on_request: Boolean(item.price_on_request),
      valor_minimo_aplicado: item.valor_minimo_aplicado ?? null,
      valor_sem_minimo: item.valor_minimo_aplicado != null ? item.valor_sem_minimo ?? null : null,
    })),
    cart_payload: {
      source: "identified_checkout",
      has_on_request: hasOnRequestItems,
      client_email: clientEmail,
      client_document: profileInput.document,
      shipping: shippingSelection
        ? {
            destination_zip: shippingSelection.destination_zip,
            amount: shipping,
            option: shippingSelection.option,
            ...(shippingOriginal - shipping > 0.004
              ? { original_amount: shippingOriginal, coupon_discount: Number((shippingOriginal - shipping).toFixed(2)) }
              : {}),
          }
        : null,
      ...cupom,
      address_summary: [
        profileInput.address_street,
        profileInput.address_number,
        profileInput.address_neighborhood,
        profileInput.address_city,
        profileInput.address_state,
      ]
        .filter(Boolean)
        .join(", "),
      delivery_address: deliveryAddress,
      client_profile: {
        name: profileInput.name,
        company_name: profileInput.company_name || null,
        document: profileInput.document,
        email: clientEmail,
        phone: profileInput.phone,
        whatsapp: profileInput.whatsapp,
        address_zip: profileInput.address_zip,
        address_street: profileInput.address_street,
        address_number: profileInput.address_number,
        address_complement: profileInput.address_complement,
        address_neighborhood: profileInput.address_neighborhood,
        address_city: profileInput.address_city,
        address_state: profileInput.address_state,
        notes: profileInput.notes || null,
      },
      address_selection: {
        selected_address_id: addressSelection.selectedAddressId || null,
        save_to_book: addressSelection.saveAddressToBook,
        set_as_default: addressSelection.setAsDefaultAddress,
      },
    },
  };

  if (existingOrderId) {
    const { data: existingOrder, error: existingOrderError } = await admin
      .from("catalog_orders")
      .select("id,user_id,number,status,payment_status,approved_order_id")
      .eq("id", existingOrderId)
      .eq("user_id", profileId)
      .maybeSingle();

    const canReuseExistingOrder =
      !existingOrderError &&
      existingOrder?.id &&
      existingOrder.status === "pending" &&
      !existingOrder.approved_order_id &&
      existingOrder.payment_status !== "approved";

    if (canReuseExistingOrder) {
      const now = new Date().toISOString();
      const { error: updateOrderError } = await admin
        .from("catalog_orders")
        .update({
          client_id: sessionClientId,
          customer_name: profileInput.name,
          customer_phone: profileInput.phone,
          customer_whatsapp: profileInput.whatsapp,
          notes: profileInput.notes || null,
          currency: "BRL",
          subtotal,
          discount,
          total,
          coupon_code: couponCode || null,
          cart_payload: orderPayload.cart_payload,
          whatsapp_url: whatsappUrl,
          payment_provider: provedorDePagamento,
          payment_required: Boolean(provedorDePagamento),
          payment_status: "unpaid",
          payment_method: null,
          payment_reference: null,
          paid_at: null,
          updated_at: now,
        })
        .eq("id", existingOrder.id);

      if (updateOrderError) {
        throw new Error("Não foi possível atualizar o pedido em aberto.");
      }

      await replaceCatalogOrderItems(admin, existingOrder.id, items);
      await cancelPendingCatalogPayments(admin, existingOrder.id);

      return {
        id: existingOrder.id,
        number: existingOrder.number || null,
      };
    }
  }

  const orderResult = await admin.rpc("create_public_catalog_order", {
    p_slug: slug,
    p_payload: orderPayload,
  });

  if (orderResult.error || !orderResult.data?.id) {
    throw new Error("Não foi possível registrar o pedido.");
  }

  await admin
    .from("catalog_orders")
    .update({
      client_id: sessionClientId,
      customer_name: profileInput.name,
      customer_phone: profileInput.phone,
      customer_whatsapp: profileInput.whatsapp,
      notes: profileInput.notes || null,
      payment_provider: provedorDePagamento,
      payment_required: Boolean(provedorDePagamento),
      payment_status: "unpaid",
      updated_at: new Date().toISOString(),
    })
    .eq("id", orderResult.data.id);

  return {
    id: orderResult.data.id as string,
    number: (orderResult.data.number as number | null | undefined) ?? null,
  };
}

export async function POST(request: Request) {
  try {
    const cookieStore = await cookies();
    const token = cookieStore.get("ks_client_portal")?.value || "";
    if (!token) {
      return NextResponse.json({ error: "Faça login para finalizar o pedido." }, { status: 401 });
    }

    const body = (await request.json().catch(() => null)) as
      | {
          slug?: string;
          existingOrderId?: string;
          profile?: CheckoutProfileInput;
          items?: CheckoutItemInput[];
          subtotal?: number;
          discount?: number;
          shipping?: number;
          total?: number;
          couponCode?: string | null;
          couponCodes?: string[] | null;
          shippingSelection?: CheckoutShippingSelectionInput;
          addressSelection?: CheckoutAddressSelectionInput;
        }
      | null;

    const slug = normalizeText(body?.slug);
    const existingOrderId = normalizeText(body?.existingOrderId);
    const profileInput = normalizeProfileInput(body?.profile);
    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 sessionResult = await admin.rpc("client_portal_get_session", {
      p_slug: slug,
      p_session_token: token,
    });
    const sessionPayload = (sessionResult.data || null) as SessionPayload | null;
    if (sessionResult.error || !sessionPayload?.client?.id) {
      return NextResponse.json({ error: "Sessão inválida. Faça login novamente." }, { status: 401 });
    }

    const currentDocument = digitsOnly(sessionPayload.client.document || "").slice(0, 14);
    if (currentDocument && profileInput.document !== currentDocument) {
      return NextResponse.json(
        { error: "O CPF/CNPJ deste cadastro já está definido e não pode ser alterado por aqui." },
        { status: 400 }
      );
    }

    const { data: profile } = await admin
      .from("profiles")
      .select(
        "id,catalog_name,store_name,whatsapp,company_whatsapp,catalog_price_mode,catalog_purchase_mode,catalog_access_mode,catalog_require_login_to_order,catalog_min_order_total,catalog_min_order_items,catalog_status,catalog_status_message,whatsapp_templates"
      )
      .eq("slug", slug)
      .maybeSingle();

    if (!profile?.id) {
      return NextResponse.json({ error: "Loja não encontrada." }, { status: 404 });
    }

    /* As regras da loja valem aqui tambem: loja pausada nao fecha pedido,
       cadastro pendente nao compra, e o pedido de orcamento tem rota propria
       (/api/catalog/pedido). */
    const equipe = await navegadorDaEquipe(String(profile.id));
    const statusDoCliente =
      sessionPayload.client.portal_status === "pending" || sessionPayload.client.portal_status === "rejected"
        ? sessionPayload.client.portal_status
        : "approved";
    const visao = resolverVisao(
      profile as Record<string, unknown>,
      { id: sessionPayload.client.id, name: String(sessionPayload.client.name || ""), status: statusDoCliente },
      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.modoDeCompra !== "cart") {
      return NextResponse.json({ error: "Esta loja fecha pedidos de outro jeito. Volte ao carrinho." }, { status: 400 });
    }

    await conferirPrecosNoServidor(admin, String(profile.id), items);

    /*
      O que esta loja consegue cobrar, e quem cobra cada coisa.

      A mesma pergunta que a vitrine faz antes de mostrar o botão de pagar, e que
      o envio do pagamento refaz depois: uma regra só, para as três respostas não
      divergirem. Cada meio traz o seu provedor, porque o Pix pode ir para uma
      conta e o cartão para outra.
    */
    const meiosDeCobranca = await carregarPagamento(admin as never, profile.id)
      .then((estado) => meiosDoLocal(estado, "loja"))
      .catch(() => []);

    /* A chave pública do Mercado Pago só sai daqui quando ele realmente cobra
       algum meio nesta loja: é ela que monta o formulário de cartão no
       navegador, e não há por que entregá-la quando não há cartão. */
    const linhaDoMercadoPago = meiosDeCobranca.find((m) => m.provedor === "mercado_pago")?.integracao ?? null;
    const mercadoPagoConfig = linhaDoMercadoPago
      ? resolveMercadoPagoPublicConfig(linhaDoMercadoPago as never)
      : null;
    const hasOnRequestItems = items.some((item) => item.price_on_request);

    const whatsappDigits = normalizeWhatsappForLink(profile.company_whatsapp || profile.whatsapp || "");
    if (!whatsappDigits) {
      return NextResponse.json({ error: "A loja ainda não configurou o WhatsApp." }, { status: 400 });
    }

    const { data: conflictingClient, error: conflictingClientError } = await admin
      .from("clients")
      .select("id")
      .eq("user_id", profile.id)
      .eq("document", profileInput.document)
      .neq("id", sessionPayload.client.id)
      .eq("active", true)
      .or("is_deleted.is.null,is_deleted.eq.false")
      .maybeSingle();

    if (conflictingClientError) {
      return NextResponse.json({ error: "Não foi possível validar o CPF/CNPJ informado." }, { status: 500 });
    }

    if (conflictingClient?.id) {
      return NextResponse.json(
        { error: "Este CPF/CNPJ já está vinculado a outro cliente cadastrado nesta loja." },
        { status: 400 }
      );
    }

    const addressSelection = normalizeAddressSelection(body?.addressSelection);
    const resolvedCheckoutProfile = await resolveEffectiveCheckoutProfile({
      admin,
      profileId: profile.id,
      sessionPayload,
      profileInput,
      addressSelection,
    });
    const effectiveProfileInput = resolvedCheckoutProfile.profileInput;
    const deliveryAddress = resolvedCheckoutProfile.deliveryAddress;

    const missingFields = getMissingCheckoutFields(
      { ...effectiveProfileInput, email: effectiveProfileInput.email || normalizeText(sessionPayload.client.email) },
      { exigeEmail: meiosDeCobranca.length > 0 && !hasOnRequestItems }
    );
    if (missingFields.length > 0) {
      return NextResponse.json(
        { error: `Preencha os dados obrigatórios: ${missingFields.join(", ")}.` },
        { status: 400 }
      );
    }
    if (!validateBrazilianDocument(profileInput.document)) {
      return NextResponse.json({ error: "Informe um CPF ou CNPJ válido." }, { status: 400 });
    }

    const updateProfileResult = await admin.rpc("client_portal_update_profile", {
      p_slug: slug,
      p_session_token: token,
      p_name: profileInput.name || null,
      p_company_name: profileInput.company_name || null,
      p_document: profileInput.document || null,
      p_email: profileInput.email || null,
      p_phone: profileInput.phone || null,
      p_whatsapp: profileInput.whatsapp || null,
      p_address_zip: null,
      p_address_street: null,
      p_address_number: null,
      p_address_complement: null,
      p_address_neighborhood: null,
      p_address_city: null,
      p_address_state: null,
      p_notes: profileInput.notes || null,
    });

    if (updateProfileResult.error || !updateProfileResult.data?.ok) {
      return NextResponse.json({ error: "Não foi possível salvar os dados do cliente." }, { status: 400 });
    }

    await saveCheckoutAddressToBook({
      admin,
      profileId: profile.id,
      clientId: sessionPayload.client.id,
      profileInput: effectiveProfileInput,
      addressSelection,
    });

    const subtotal = Number(calculateItemsSubtotal(items).toFixed(2));
    const unidades = unidadesDosItens(items);
    const falta = faltaParaOPedidoMinimo(visao.regras, { total: subtotal, unidades, mostrarPreco: visao.mostrarPreco });
    if (falta) {
      return NextResponse.json({ error: falta }, { status: 400 });
    }
    const requestedShipping = Math.max(0, Number(body?.shipping || 0));
    const storeName = normalizeText(profile.catalog_name || profile.store_name || "Loja");
    const validatedShippingSelection = await resolveValidatedShippingSelection({
      admin,
      slug,
      items,
      selection: body?.shippingSelection,
    });
    const shippingTotal = validatedShippingSelection
      ? Number(validatedShippingSelection.option.price.toFixed(2))
      : 0;
    if (validatedShippingSelection && Math.abs(requestedShipping - shippingTotal) > 0.05) {
      return NextResponse.json({ error: "O valor do frete mudou. Recalcule antes de continuar." }, { status: 400 });
    }

    /* Os cupons sao conferidos no banco, 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 = await calcularCuponsDoPedido(admin, {
      storeId: String(profile.id),
      codigos: codigosDoCorpo(body),
      items,
      cliente: { id: sessionPayload.client.id },
      frete: validatedShippingSelection
        ? {
            valor: shippingTotal,
            cep: validatedShippingSelection.destination_zip,
            retirada: isPickupShippingOption(validatedShippingSelection.option),
          }
        : null,
      pedidoEmAberto: existingOrderId || null,
    });
    /* 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) {
      return NextResponse.json({ error: mensagemDosErros(cupons) }, { status: 400 });
    }
    const discount = cupons.desconto;
    const couponCode = codigoDoPedido(cupons);
    const codigos = codigosPorVaga(cupons);
    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 message = mensagemDoPedidoNoWhatsapp({
      storeName,
      kind: "order",
      numero: null,
      items,
      mostrarPrecos: true,
      cliente: {
        ...effectiveProfileInput,
        email: effectiveProfileInput.email || normalizeText(sessionPayload.client.email),
        address_summary: [
          effectiveProfileInput.address_street,
          effectiveProfileInput.address_number,
          effectiveProfileInput.address_complement,
          effectiveProfileInput.address_neighborhood,
          effectiveProfileInput.address_city,
          effectiveProfileInput.address_state,
          effectiveProfileInput.address_zip,
        ]
          .filter(Boolean)
          .join(", "),
      },
      subtotal,
      discount: Number.isFinite(discount) ? discount : 0,
      shippingTotal,
      total,
      couponCode: codigos.desconto,
      shippingDiscount,
      shippingCouponCode: codigos.frete,
      shippingSelection: validatedShippingSelection,
      modelos: visao.regras.mensagensDoWhatsapp,
    });

    const whatsappUrl = `https://wa.me/${whatsappDigits}?text=${encodeURIComponent(message)}`;

    /* Vai cobrar online: o carrinho inteiro tem que caber no estoque agora
       (a mesma conta da loja, do PDV e do orcamento). Pagamento sem pedido
       nunca: se nao cabe, o cliente volta ao carrinho antes de pagar. */
    if (meiosDeCobranca.length > 0 && !hasOnRequestItems) {
      const faltaEstoque = await conferirEstoqueAntesDeCobrar(
        admin as never,
        String(profile.id),
        items.map((item) => ({ ...item, title: item.name }))
      );
      if (faltaEstoque) {
        return NextResponse.json({ error: faltaEstoque, code: "estoque_insuficiente" }, { status: 409 });
      }
    }

    /* A trava do limite: o uso e reservado antes de gravar o pedido. O pedido
       em aberto que tenta de novo devolve o uso que segurava. */
    const usosDosCupons = await reservarUsosDosCupons(admin, cupons, {
      clienteId: sessionPayload.client.id,
      trocarPedido: existingOrderId || null,
    });
    if (!usosDosCupons.length && existingOrderId) await soltarUsoDoPedidoEmAberto(admin, existingOrderId);

    const orderResult = await upsertCatalogOrder({
      admin,
      slug,
      existingOrderId,
      profileId: profile.id,
      sessionClientId: sessionPayload.client.id,
      profileInput: {
        ...effectiveProfileInput,
        email: effectiveProfileInput.email || normalizeText(sessionPayload.client.email),
      },
      subtotal,
      discount: Number.isFinite(discount) ? Number(discount.toFixed(2)) : 0,
      shipping: shippingCharged,
      shippingOriginal: shippingTotal,
      cupom: cuponsNoPedido(cupons),
      total,
      couponCode,
      items,
      whatsappUrl,
      hasOnRequestItems,
      clientEmail: profileInput.email || normalizeText(sessionPayload.client.email),
      provedorDePagamento: hasOnRequestItems ? null : (meiosDeCobranca[0]?.provedor ?? null),
      shippingSelection: validatedShippingSelection,
      addressSelection,
      deliveryAddress,
    }).catch(async (erro) => {
      await soltarReservasDosCupons(admin, usosDosCupons);
      throw erro;
    });
    await ligarUsosAoPedido(admin, usosDosCupons, orderResult.id);

    /* A loja fica sabendo na hora, pague-se online ou pelo WhatsApp. So no
       pedido novo: a tentativa repetida de pagamento reaproveita o mesmo. */
    if (orderResult.id !== existingOrderId) {
      await avisarLojaDoPedido(admin, {
        storeId: String(profile.id),
        orderId: orderResult.id,
        kind: "order",
        numero: orderResult.number,
        cliente: profileInput.name || null,
        total,
        itens: unidades,
        aguardandoPagamento: meiosDeCobranca.length > 0 && !hasOnRequestItems && total > 0,
      }).catch(() => undefined);
    }

    const pagador = {
      name: profileInput.name,
      email: effectiveProfileInput.email || normalizeText(sessionPayload.client.email),
      document: profileInput.document,
    };

    /*
      Um fluxo só para pagamento online, com a lista de meios dentro.

      Antes havia um fluxo por provedor, e isso obrigava o checkout a saber o
      nome de cada um para decidir o que desenhar. Com três provedores um dia,
      seriam três ramos na tela. Agora a tela recebe o que pode oferecer e o
      nome de quem cobra cada coisa, e desenha a partir disso.
    */
    /*
      Pedido de valor zero (cupom de 100%).

      Não há o que cobrar: a tela de pagamento terminava em erro, porque o
      provedor recusa R$ 0. Agora ele é confirmado na hora, como um Pix
      aprovado. Se a loja aprova os pedidos pagos à mão ("criar pedido ao
      aprovar o pagamento" desligado), ele segue pelo WhatsApp, como os demais
      pedidos que a loja confere antes.
    */
    if (meiosDeCobranca.length > 0 && !hasOnRequestItems && total <= 0) {
      const quemCobraria = meiosDeCobranca[0];
      const criaSozinho =
        quemCobraria.provedor === "asaas"
          ? lerConfiguracaoDoAsaas(quemCobraria.integracao?.settings).auto_create_order_on_approved_payment
          : parseMercadoPagoSettings(quemCobraria.integracao?.settings).auto_create_order_on_approved_payment;
      if (criaSozinho) {
        await confirmarPedidoSemValor(admin as never, orderResult.id);
        return NextResponse.json({
          ok: true,
          flow: "confirmado",
          order_id: orderResult.id,
          order_number: orderResult.number,
        });
      }
      return NextResponse.json({
        ok: true,
        flow: "whatsapp",
        whatsapp_url: whatsappUrl,
        order_id: orderResult.id,
        order_number: orderResult.number,
      });
    }

    if (meiosDeCobranca.length > 0 && !hasOnRequestItems) {
      return NextResponse.json({
        ok: true,
        flow: "pagamento",
        order_id: orderResult.id,
        order_number: orderResult.number,
        payment: {
          amount: total,
          payer: pagador,
          meios: meiosDeCobranca.map((m) => ({ meio: m.meio, provedor: m.provedor })),
          /* Só quando o Mercado Pago cobra algum meio aqui. */
          mercado_pago: mercadoPagoConfig
            ? { environment: mercadoPagoConfig.environment, public_key: mercadoPagoConfig.publicKey }
            : null,
        },
      });
    }

    return NextResponse.json({
      ok: true,
      flow: "whatsapp",
      whatsapp_url: whatsappUrl,
      order_id: orderResult.id,
      order_number: orderResult.number,
    });
  } catch (error) {
    const message = error instanceof Error ? error.message : "Não foi possível finalizar o pedido.";
    return NextResponse.json({ error: message }, { status: 500 });
  }
}
