"use client";

import { useEffect, useMemo, useState } from "react";
import { LoaderCircle } from "lucide-react";
import { CardPayment, Payment, initMercadoPago } from "@mercadopago/sdk-react";

type Payer = {
  name?: string | null;
  email?: string | null;
  document?: string | null;
};

function splitPersonName(value: string) {
  const parts = String(value || "")
    .trim()
    .split(/\s+/)
    .filter(Boolean);

  if (!parts.length) {
    return { firstName: "Cliente", lastName: "Ktalogu" };
  }

  if (parts.length === 1) {
    return { firstName: parts[0], lastName: "Cliente" };
  }

  return {
    firstName: parts[0],
    lastName: parts.slice(1).join(" "),
  };
}

function detectDocumentType(document: string) {
  const digits = String(document || "").replace(/\D/g, "");
  return digits.length === 14 ? "CNPJ" : "CPF";
}

export default function CatalogMercadoPagoPanel({
  publicKey,
  amount,
  payer,
  primaryColor,
  onSubmitPayment,
  title,
  description,
  showHeader = true,
  maxInstallments = 12,
  allowedPaymentTypes,
}: {
  publicKey: string;
  environment: "sandbox" | "production";
  amount: number;
  payer: Payer;
  primaryColor: string;
  onSubmitPayment: (payment: Record<string, unknown>, additionalData?: Record<string, unknown> | null) => Promise<void>;
  title?: string;
  description?: string;
  showHeader?: boolean;
  maxInstallments?: number;
  allowedPaymentTypes?: Array<"creditCard" | "bank_transfer" | "ticket">;
}) {
  const [ready, setReady] = useState(false);
  const [brickError, setBrickError] = useState<string | null>(null);
  const payerName = String(payer.name || "").trim();
  const payerDocument = String(payer.document || "").replace(/\D/g, "");

  useEffect(() => {
    if (!publicKey) return;
    initMercadoPago(publicKey);
  }, [publicKey]);

  const initialization = useMemo(() => {
    const { firstName, lastName } = splitPersonName(payerName);
    return {
      amount,
      payer: {
        firstName,
        lastName,
        email: payer.email || undefined,
        identification: payerDocument
          ? {
              type: detectDocumentType(payerDocument),
              number: payerDocument,
            }
          : undefined,
      },
    };
  }, [amount, payer.email, payerDocument, payerName]);

  /* A loja pediu so o cartao? Entao o formulario entra direto. */
  const somenteCartao =
    Array.isArray(allowedPaymentTypes) && allowedPaymentTypes.length === 1 && allowedPaymentTypes[0] === "creditCard";

  const cartaoCustomization = useMemo(
    () => ({
      paymentMethods: { maxInstallments },
      visual: {
        /* O titulo do formulario ja e dito pelo cartao escolhido na tela. */
        hideFormTitle: true,
        style: {
          theme: "flat",
          customVariables: {
            baseColor: primaryColor,
            textPrimaryColor: "#0f172a",
            textSecondaryColor: "#64748b",
            inputBackgroundColor: "#ffffff",
            formBackgroundColor: "#ffffff",
            borderRadiusSmall: "10px",
            borderRadiusMedium: "14px",
            borderRadiusLarge: "18px",
            formPadding: "20px",
            inputVerticalPadding: "14px",
            inputHorizontalPadding: "14px",
            fontSizeSmall: "13px",
            fontSizeMedium: "15px",
          },
        },
      },
    }),
    [maxInstallments, primaryColor]
  );

  const customization = useMemo(() => {
    const includedTypes =
      allowedPaymentTypes && allowedPaymentTypes.length > 0
        ? allowedPaymentTypes
        : ["creditCard", "bank_transfer", "ticket"];

    return {
      paymentMethods: {
        maxInstallments,
        ...(includedTypes.includes("creditCard") ? { creditCard: "all" as const } : {}),
        ...(includedTypes.includes("bank_transfer") ? { bankTransfer: "all" as const } : {}),
        ...(includedTypes.includes("ticket") ? { ticket: "all" as const } : {}),
      },
      visual: {
        hideRedirectionPanel: true,
        /* A escolha do meio de pagamento agora e nossa, na tela do checkout.
           Sem isso a caixa repetia o titulo "Meios de pagamento" e listava de
           novo a opcao que o cliente acabou de escolher. */
        hideFormTitle: true,
        /* O formulario de pagamento vem com a identidade visual do
           intermediario. Aqui ele recebe a cor, a tipografia e o arredondamento
           da propria loja, para o cliente continuar dentro da mesma marca do
           inicio ao fim da compra. */
        style: {
          theme: "flat",
          customVariables: {
            baseColor: primaryColor,
            textPrimaryColor: "#0f172a",
            textSecondaryColor: "#64748b",
            inputBackgroundColor: "#ffffff",
            formBackgroundColor: "#ffffff",
            borderRadiusSmall: "10px",
            borderRadiusMedium: "14px",
            borderRadiusLarge: "18px",
            /* Respiro dentro do formulario. Com `formPadding: 0` os meios de
               pagamento encostavam na borda do cartao e o bloco inteiro ficava
               apertado. */
            formPadding: "20px",
            inputVerticalPadding: "14px",
            inputHorizontalPadding: "14px",
            inputFocusedBoxShadow: "none",
            fontSizeSmall: "13px",
            fontSizeMedium: "15px",
            fontWeightSemiBold: "600",
          },
        },
      },
    };
  }, [allowedPaymentTypes, maxInstallments, primaryColor]);

  useEffect(() => {
    setReady(false);
    setBrickError(null);
  }, [amount, maxInstallments, payer.email, payerDocument, payerName, publicKey]);

  return (
    <div className="space-y-4">
      {showHeader ? (
        <div>
          <div>
            <div className="text-sm font-semibold text-slate-900">{title || "Pagamento"}</div>
            <div className="mt-1 text-xs text-slate-500">{description || ""}</div>
          </div>
        </div>
      ) : null}

      {brickError ? (
        <div className="rounded-2xl border border-rose-200 bg-rose-50 px-4 py-3 text-sm text-rose-700">{brickError}</div>
      ) : null}

      {!ready ? (
        <div className="flex items-center gap-2 rounded-2xl border border-slate-200 bg-slate-50 px-4 py-3 text-sm text-slate-600">
          <LoaderCircle className="h-4 w-4 animate-spin" />
          Carregando meios de pagamento...
        </div>
      ) : null}

      <div
        className="rounded-2xl border border-slate-200 bg-white p-1 sm:p-2"
        style={
          {
            ["--brand-color" as string]: primaryColor,
          } as React.CSSProperties
        }
      >
        {/* Quando a loja ja escolheu o meio na propria tela — hoje o cartao — a
            caixa mostra so o formulario. A caixa completa listaria de novo a
            forma de pagamento, e o cliente tinha que clicar duas vezes: uma no
            cartao da loja, outra na linha do provedor, para so entao ver os
            campos. */}
        {somenteCartao ? (
          <CardPayment
            initialization={{ amount, payer: { email: payer.email || undefined } }}
            customization={cartaoCustomization as never}
            locale="pt-BR"
            onReady={() => setReady(true)}
            onError={(error) => {
              const message =
                typeof error === "object" && error && "message" in error && typeof error.message === "string"
                  ? error.message
                  : "Nao foi possivel carregar o pagamento.";
              setBrickError(message);
            }}
            onSubmit={async (dadosDoCartao) => {
              setBrickError(null);
              await onSubmitPayment(
                {
                  paymentType: "credit_card",
                  selectedPaymentMethod: "credit_card",
                  formData: dadosDoCartao as unknown as Record<string, unknown>,
                },
                null
              );
            }}
          />
        ) : (
        <Payment
          initialization={initialization}
          customization={customization as never}
          locale="pt-BR"
          onReady={() => setReady(true)}
          onError={(error) => {
            const message =
              typeof error === "object" && error && "message" in error && typeof error.message === "string"
                ? error.message
                : "Nao foi possivel carregar o pagamento.";
            setBrickError(message);
          }}
          onSubmit={async (payment, additionalData) => {
            setBrickError(null);
            await onSubmitPayment(
              payment as unknown as Record<string, unknown>,
              (additionalData as unknown as Record<string, unknown> | null | undefined) || null
            );
          }}
        />
        )}
      </div>
    </div>
  );
}
