"use client";

import { useId, type ReactNode } from "react";
import { QRCodeSVG } from "qrcode.react";

import { ModalPortal } from "@/app/_components/core/modal-portal";
import type { PaymentLaunchFlow } from "@/app/_hooks/use-payment-launch-flow";

import { LazyStripePaymentDialog } from "./lazy-stripe-payment-dialog";
import { stripePaymentDialogStyles as styles } from "./stripe-payment-dialog.styles";

type PaymentLaunchDialogFlow = Pick<
  PaymentLaunchFlow,
  | "handleEzpayCancel"
  | "handleEzpayConfirm"
  | "handleQrisClose"
  | "handleStripeClose"
  | "handleStripeConfirmed"
  | "isConfirmingEzpay"
  | "qrisErrorMessage"
  | "qrisPayment"
  | "qrisStatus"
  | "shouldShowEzpayConfirmDialog"
  | "shouldShowQrisDialog"
  | "shouldShowStripeDialog"
  | "stripeClientSecret"
>;

export interface PaymentLaunchDialogsProps {
  currentOrderId: string | null;
  externalCheckoutAnalyticsKey: string;
  ezpayDescription: ReactNode;
  launch: PaymentLaunchDialogFlow;
  stripeReturnPath?: string;
}

export function PaymentLaunchDialogs({
  currentOrderId,
  externalCheckoutAnalyticsKey,
  ezpayDescription,
  launch,
  stripeReturnPath,
}: PaymentLaunchDialogsProps) {
  return (
    <>
      {launch.shouldShowEzpayConfirmDialog ? (
        <EzpayRedirectConfirmDialog
          orderId={currentOrderId ?? ""}
          description={ezpayDescription}
          externalCheckoutAnalyticsKey={externalCheckoutAnalyticsKey}
          isConfirming={launch.isConfirmingEzpay}
          onCancel={launch.handleEzpayCancel}
          onConfirm={launch.handleEzpayConfirm}
        />
      ) : null}
      {launch.shouldShowQrisDialog && launch.qrisPayment ? (
        <QrisPaymentDialog
          payment={launch.qrisPayment}
          status={launch.qrisStatus}
          errorMessage={launch.qrisErrorMessage}
          onClose={launch.handleQrisClose}
        />
      ) : null}
      {launch.shouldShowStripeDialog && launch.stripeClientSecret ? (
        <LazyStripePaymentDialog
          clientSecret={launch.stripeClientSecret}
          returnPath={stripeReturnPath}
          onClose={launch.handleStripeClose}
          onConfirmed={launch.handleStripeConfirmed}
        />
      ) : null}
    </>
  );
}

interface QrisPaymentDialogProps {
  errorMessage: string | null;
  onClose: () => void;
  payment: NonNullable<PaymentLaunchFlow["qrisPayment"]>;
  status: PaymentLaunchFlow["qrisStatus"];
}

function formatQrisAmount(amountCents: number, currency: string): string {
  const normalizedCurrency = currency.trim().toUpperCase() || "IDR";
  try {
    return new Intl.NumberFormat("id-ID", {
      style: "currency",
      currency: normalizedCurrency,
      maximumFractionDigits: normalizedCurrency === "IDR" ? 0 : 2,
    }).format(amountCents / 100);
  } catch {
    return `${normalizedCurrency} ${(amountCents / 100).toFixed(2)}`;
  }
}

function qrisStatusMessage(
  status: PaymentLaunchFlow["qrisStatus"],
  errorMessage: string | null,
): string {
  if (status === "failed") return errorMessage || "Payment failed. Please try again.";
  if (status === "expired") return errorMessage || "This QRIS order has expired.";
  return "Waiting for payment";
}

function QrisPaymentDialog({
  errorMessage,
  onClose,
  payment,
  status,
}: QrisPaymentDialogProps) {
  const titleId = useId();
  const statusMessage = qrisStatusMessage(status, errorMessage);

  return (
    <ModalPortal
      open
      persistent
      onClose={onClose}
      scrimClassName={styles.overlay}
      panelClassName={styles.dialog}
      scrimOpacity={0.5}
      ariaLabelledBy={titleId}
    >
      <div className={`${styles.header} text-center`}>
        <h2 id={titleId} className={styles.title}>
          Scan to pay with QRIS
        </h2>
        <p className={styles.content}>
          Open a QRIS-compatible banking or wallet app and scan this code.
        </p>
      </div>
      <div className="mb-4 flex min-h-64 items-center justify-center rounded-2xl bg-white p-4">
        {payment.qrData ? (
          <QRCodeSVG
            value={payment.qrData}
            title="QRIS payment QR code"
            size={256}
            level="M"
            marginSize={2}
            className="h-auto w-full max-w-64"
          />
        ) : (
          <p className={styles.error} role="alert">
            QRIS data is unavailable. Please close this dialog and try again.
          </p>
        )}
      </div>
      <div className="mb-4 flex flex-col gap-2 text-center">
        <p className={styles.content}>Order No. {payment.orderId}</p>
        <p className="m-0 text-xl font-bold text-text-foreground">
          {formatQrisAmount(payment.amountCents, payment.currency)}
        </p>
        <p
          className={status === "failed" || status === "expired" ? styles.error : styles.content}
          role="status"
        >
          {statusMessage}
        </p>
      </div>
      <div className={styles.actions}>
        <button
          type="button"
          className={`${styles.button} ${styles.secondary}`}
          onClick={onClose}
        >
          Close
        </button>
      </div>
    </ModalPortal>
  );
}

interface EzpayRedirectConfirmDialogProps {
  description: ReactNode;
  externalCheckoutAnalyticsKey: string;
  isConfirming: boolean;
  onCancel: () => void;
  onConfirm: () => void;
  orderId: string;
}

function EzpayRedirectConfirmDialog({
  description,
  externalCheckoutAnalyticsKey,
  isConfirming,
  onCancel,
  onConfirm,
  orderId,
}: EzpayRedirectConfirmDialogProps) {
  const titleId = useId();

  return (
    <ModalPortal
      open
      persistent
      onClose={onCancel}
      scrimClassName={styles.overlay}
      panelClassName={styles.dialog}
      scrimOpacity={0.5}
      role="alertdialog"
      ariaLabelledBy={titleId}
    >
      <div className={styles.header}>
        <h2 id={titleId} className={styles.title}>
          Continue to payment?
        </h2>
        <p className={styles.content}>{description}</p>
        <p className={styles.content}>Order No. {orderId}</p>
      </div>
      <div className={styles.actions}>
        <button
          type="button"
          className={`${styles.button} ${styles.secondary}`}
          disabled={isConfirming}
          onClick={onCancel}
        >
          Cancel
        </button>
        <button
          type="button"
          data-analytics-key={externalCheckoutAnalyticsKey}
          data-analytics-label="Continue to external checkout"
          className={`${styles.button} ${styles.primary}`}
          disabled={isConfirming}
          onClick={onConfirm}
        >
          {isConfirming ? "Opening..." : "Continue"}
        </button>
      </div>
    </ModalPortal>
  );
}
