/* eslint-disable @typescript-eslint/indent */
import 'react-international-phone/style.css';

import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
import { FlagEmoji } from 'react-international-phone';
// import { useTheme } from '@arcblock/ux/lib/Theme';
import Toast from '@arcblock/ux/lib/Toast';
import type {
  TCheckoutSession,
  TCheckoutSessionExpanded,
  TCustomer,
  TLineItemExpanded,
  TPaymentIntent,
  TPaymentMethodExpanded,
} from '@blocklet/payment-types';
import { Box, Button, CircularProgress, Divider, Fade, Stack, Tooltip, Typography } from '@mui/material';
import { useMemoizedFn, useSetState } from 'ahooks';
import pWaitFor from 'p-wait-for';
import { useEffect, useMemo, useRef } from 'react';
import { Controller, useFormContext, useWatch } from 'react-hook-form';
import { joinURL } from 'ufo';
import { dispatch } from 'use-bus';
import isEmail from 'validator/es/lib/isEmail';
import { BN, fromTokenToUnit, fromUnitToToken } from '@ocap/util';
import DID from '@arcblock/ux/lib/DID';
import { PayFailedEvent } from '@arcblock/ux/lib/withTracker/action/pay';

import isEmpty from 'lodash/isEmpty';
import { HelpOutline, OpenInNew } from '@mui/icons-material';
import { ReactGA } from '@arcblock/ux/lib/withTracker';
import trim from 'lodash/trim';
import FormInput from '../../components/input';
import FormLabel from '../../components/label';
import { usePaymentContext } from '../../contexts/payment';
import { useSubscription } from '../../hooks/subscription';
import api from '../../libs/api';
import {
  flattenPaymentMethods,
  formatError,
  formatQuantityInventory,
  getPrefix,
  getQueryParams,
  getStatementDescriptor,
  getTokenBalanceLink,
  isCrossOrigin,
  getCheckoutAmount,
  formatNumber,
  formatUsdAmount,
  getUsdAmountFromBaseAmount,
  getUsdAmountFromTokenUnits,
  formatAmount,
} from '../../libs/util';
import type { CheckoutCallbacks, CheckoutContext } from '../../types';
import AddressForm from './address';
import CurrencySelector from './currency';
import PhoneInput from './phone';
import StripeCheckout from './stripe';
import { useMobile } from '../../hooks/mobile';
import { formatPhone, validatePhoneNumber } from '../../libs/phone-validator';
import LoadingButton from '../../components/loading-button';
import OverdueInvoicePayment from '../../components/over-due-invoice-payment';
import { saveCurrencyPreference } from '../../libs/currency';
import ConfirmDialog from '../../components/confirm';
import ServiceSuspendedDialog from '../../components/service-suspended-dialog';
import PriceChangeConfirm from '../../components/price-change-confirm';
import { getFieldValidation, validatePostalCode } from '../../libs/validator';

// Generate unique idempotency key for submit (Final Freeze Architecture)
const generateIdempotencyKey = (sessionId: string, currencyId: string): string => {
  return `${sessionId}-${currencyId}-${Date.now()}-${Math.random().toString(36).substring(2, 10)}`;
};

export const waitForCheckoutComplete = async (sessionId: string) => {
  let result: CheckoutContext;

  await pWaitFor(
    async () => {
      const { data } = await api.get(`/api/checkout-sessions/retrieve/${sessionId}`);
      if (
        data.paymentIntent &&
        data.paymentIntent.status === 'requires_action' &&
        data.paymentIntent.last_payment_error
      ) {
        throw new Error(data.paymentIntent.last_payment_error.message);
      }

      result = data;

      return (
        // eslint-disable-next-line @typescript-eslint/return-await
        data.checkoutSession?.status === 'complete' &&
        ['paid', 'no_payment_required'].includes(data.checkoutSession?.payment_status)
      );
    },
    { interval: 2000, timeout: 3 * 60 * 1000 }
  );

  // @ts-ignore
  return result;
};

export const hasDidWallet = (user: any) => {
  const connected = user?.connectedAccounts || user?.extraConfigs?.connectedAccounts || [];
  return connected.some((x: any) => x.provider === 'wallet');
};

type PageData = CheckoutContext &
  CheckoutCallbacks & {
    onQuoteUpdated?: (
      data: Pick<CheckoutContext, 'checkoutSession' | 'quotes' | 'rateUnavailable' | 'rateError'>
    ) => void;
    onPaymentIntentUpdate?: (intent: TPaymentIntent | null) => void;
    onlyShowBtn?: boolean;
    isDonation?: boolean;
  };

type UserInfo = {
  name?: string;
  fullName?: string;
  email?: string;
  phone?: string;
  address?: {
    country?: string;
    state?: string;
    province?: string;
    line1?: string;
    line2?: string;
    city?: string;
    postal_code?: string;
    postalCode?: string;
  };
  metadata?: {
    phone?: {
      country?: string;
      phoneNumber?: string;
    };
  };
};

type FastCheckoutInfo = {
  open: boolean;
  loading: boolean;
  sourceType: 'balance' | 'delegation' | 'credit';
  amount: string;
  payer?: string;
  availableCredit?: string;
  balance?: string;
};

const setUserFormValues = (
  userInfo: UserInfo,
  currentValues: any,
  setValue: Function,
  options: { preferExisting?: boolean; showPhone?: boolean; shouldValidate?: boolean } = {}
) => {
  const { preferExisting = true, shouldValidate = false } = options;
  const basicFields = {
    customer_name: userInfo.name || userInfo.fullName,
    customer_email: userInfo.email,
    customer_phone: formatPhone(userInfo.phone),
  };
  const addressFields: Record<string, any> = {
    'billing_address.state': userInfo.address?.state || userInfo.address?.province,
    'billing_address.line1': userInfo.address?.line1,
    'billing_address.line2': userInfo.address?.line2,
    'billing_address.city': userInfo.address?.city,
    'billing_address.postal_code': userInfo.address?.postal_code || userInfo.address?.postalCode,
    'billing_address.country': userInfo.address?.country || 'us',
  };

  if (options.showPhone) {
    addressFields['billing_address.country'] = userInfo.metadata?.phone?.country || userInfo.address?.country;
  }

  const allFields = { ...addressFields, ...basicFields };

  const updatedFields: Record<string, any> = {
    ...currentValues,
    billing_address: {
      ...currentValues.billing_address,
    },
  };

  Object.entries(allFields).forEach(([field, value]) => {
    if (!preferExisting || !currentValues[field.split('.')[0]]) {
      setValue(field, value, { shouldValidate });

      if (field.startsWith('billing_address.')) {
        const addressKey = field.replace('billing_address.', '');
        updatedFields.billing_address[addressKey] = value;
      } else {
        updatedFields[field] = value;
      }
    }
  });

  return updatedFields;
};

// ✅ No longer need to collect quotes from frontend - backend auto-finds them
// const collectQuotes = (lineItems: TLineItemExpanded[]) =>
//   lineItems
//     ?.filter((item) => (item.price as any)?.pricing_type === 'dynamic' && (item as any)?.quote_id)
//     .map((item) => ({
//       price_id: item.price_id,
//       quote_id: (item as any).quote_id,
//     })) || [];

// FIXME: https://stripe.com/docs/elements/address-element
// TODO: https://country-regions.github.io/react-country-region-selector/
// https://www.npmjs.com/package/postal-codes-js
// https://www.npmjs.com/package/val-zip
// https://npm.runkit.com/zips
export default function PaymentForm({
  checkoutSession,
  paymentMethods,
  paymentIntent,
  paymentLink,
  customer,
  onPaid,
  onError,
  onQuoteUpdated = undefined,
  onPaymentIntentUpdate = undefined,
  // mode,
  action,
  onlyShowBtn = false,
  isDonation = false,
  rateUnavailable = false,
}: PageData) {
  // const theme = useTheme();
  const { t, locale } = useLocaleContext();
  const { isMobile } = useMobile();
  const { session, connect, payable, setPaymentState } = usePaymentContext();
  const subscription = useSubscription('events');
  const formErrorPosition = 'bottom';
  const {
    control,
    getValues,
    setValue,
    handleSubmit,
    formState: { errors },
    trigger,
  } = useFormContext();
  const errorRef = useRef<HTMLDivElement | null>(null);
  const processingRef = useRef(false);
  // Stable idempotency key: reuse same Quote on retry (intent: "retry with same Quote")
  const idempotencyKeyRef = useRef('');
  const sessionFingerprintRef = useRef('');
  const quantityInventoryStatus = useMemo(() => {
    let status = true;
    for (const item of checkoutSession.line_items) {
      if (formatQuantityInventory(item.price, item.quantity)) {
        status = false;
        break;
      }
    }
    return status;
  }, [checkoutSession]);
  const [state, setState] = useSetState<{
    submitting: boolean;
    paying: boolean;
    paid: boolean;
    paymentIntent?: TPaymentIntent;
    stripeContext?: {
      client_secret: string;
      intent_type: string;
      status: string;
    };
    customer?: TCustomer;
    customerLimited?: boolean;
    serviceSuspended?: boolean;
    stripePaying: boolean;
    fastCheckoutInfo: FastCheckoutInfo | null;
    creditInsufficientInfo: {
      open: boolean;
    } | null;
    showEditForm: boolean;
    // Final Freeze: Price change confirmation state
    priceChangeConfirm: {
      open: boolean;
      previewRate?: string;
      submitRate?: string;
      changePercent: number;
      formData?: any;
    } | null;
  }>({
    submitting: false,
    paying: false,
    paid: false,
    paymentIntent,
    stripeContext: undefined,
    customer,
    customerLimited: false,
    serviceSuspended: false,
    stripePaying: false,
    fastCheckoutInfo: null,
    creditInsufficientInfo: null,
    showEditForm: false,
    priceChangeConfirm: null,
  });

  const currencies = flattenPaymentMethods(paymentMethods);
  const searchParams = getQueryParams(window.location.href);

  const onCheckoutComplete = useMemoizedFn(async ({ response }: { response: TCheckoutSession }) => {
    if (response.id === checkoutSession.id && state.paid === false) {
      await handleConnected();
    }
  });

  useEffect(() => {
    if (subscription) {
      subscription.on('checkout.session.completed', onCheckoutComplete);
    }
  }, [subscription]); // eslint-disable-line react-hooks/exhaustive-deps

  // Sync payment states to PaymentContext
  useEffect(() => {
    setPaymentState({
      paying: state.submitting || state.paying,
      stripePaying: state.stripePaying,
    });
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [state.submitting, state.paying, state.stripePaying]);

  const mergeUserInfo = (
    customerInfo: UserInfo | (TCustomer & { fullName?: string }),
    userInfo?: UserInfo
  ): UserInfo => {
    return {
      ...(userInfo || {}),
      name: customerInfo?.name || customerInfo?.fullName || userInfo?.name || userInfo?.fullName,
      fullName: customerInfo?.name || customerInfo?.fullName || userInfo?.name || userInfo?.fullName,
      email: customerInfo?.email || userInfo?.email,
      phone: customerInfo?.phone || userInfo?.phone,
      address: {
        ...(userInfo?.address || {}),
        ...(customerInfo?.address || {}),
        country: customerInfo?.address?.country || userInfo?.address?.country,
        state: customerInfo?.address?.state || userInfo?.address?.province,
        line1: customerInfo?.address?.line1 || userInfo?.address?.line1,
        line2: customerInfo?.address?.line2 || userInfo?.address?.line2,
        city: customerInfo?.address?.city || userInfo?.address?.city,
        postal_code: customerInfo?.address?.postal_code || userInfo?.address?.postalCode,
      },
      metadata: {
        ...(userInfo?.metadata || {}),
        phone: {
          country: customerInfo?.address?.country || userInfo?.metadata?.phone?.country,
          phoneNumber: customerInfo?.phone || userInfo?.metadata?.phone?.phoneNumber,
        },
      },
    };
  };

  useEffect(() => {
    const initUserInfo = async () => {
      if (session?.user) {
        const values = getValues();
        let userInfo = session.user;
        try {
          const { data: customerInfo } = await api.get('/api/customers/me?skipSummary=1&fallback=1');
          userInfo = mergeUserInfo(customerInfo, userInfo);
        } catch (err) {
          // @ts-ignore
          userInfo = mergeUserInfo(customer || {}, userInfo);
          console.error(err);
        }
        const formValues = setUserFormValues(userInfo, values, setValue, {
          preferExisting: false,
          showPhone: checkoutSession.phone_number_collection?.enabled,
        });

        const isValid = validateUserInfo(formValues);
        setState({ showEditForm: !isValid });
      } else {
        setUserFormValues(
          {
            name: '',
            email: '',
            phone: '',
            address: {
              state: '',
              line1: '',
              line2: '',
              city: '',
              postal_code: '',
            },
          },
          {},
          setValue,
          { preferExisting: false, showPhone: checkoutSession.phone_number_collection?.enabled }
        );
      }
    };
    if (state.submitting) {
      return;
    }
    initUserInfo();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [session?.user, checkoutSession.phone_number_collection?.enabled]);

  const paymentMethod = useWatch({ control, name: 'payment_method' });
  const paymentCurrencyId = useWatch({ control, name: 'payment_currency' });
  // const domSize = useSize(document.body);

  // const isColumnLayout = useCreation(() => {
  //   if (domSize) {
  //     if (domSize?.width <= theme.breakpoints.values.md) {
  //       return true;
  //     }
  //   }
  //   return false;
  // }, [domSize, theme]);

  const afterUserLoggedIn = useMemoizedFn(() => {
    handleSubmit(onFormSubmit, onFormError)();
  });

  const payee = getStatementDescriptor(checkoutSession.line_items);
  let buttonText = '';
  if (paymentLink?.donation_settings) {
    if (action) {
      buttonText = action;
    } else {
      buttonText = t('payment.checkout.donate');
    }
  } else {
    buttonText = t(`payment.checkout.${checkoutSession.mode}`);
  }
  buttonText = session?.user || isDonation ? buttonText : t('payment.checkout.connect', { action: buttonText });

  const method = paymentMethods.find((x) => x.id === paymentMethod) as TPaymentMethodExpanded;
  const paymentCurrency = currencies.find((x) => x.id === paymentCurrencyId);
  const showStake = method.type === 'arcblock' && !checkoutSession.subscription_data?.no_stake;
  const hasDynamicPricing = useMemo(
    () =>
      (checkoutSession.line_items || []).some((item: any) => {
        const price = item.upsell_price || item.price;
        return price && (price as any)?.pricing_type === 'dynamic';
      }),
    [checkoutSession.line_items]
  );
  const rateUnavailableForDynamic = hasDynamicPricing && rateUnavailable;
  const canPay = payable && !rateUnavailableForDynamic;

  const isDonationMode = checkoutSession?.submit_type === 'donate' && isDonation;
  const [priceUpdateInfo, setPriceUpdateInfo] = useSetState<{
    open: boolean;
    total: string;
    usd: string | null;
    hasQuotes: boolean;
    baseCurrency: string;
    oldTotal: string;
    reason: 'rateChanged' | 'recalculated';
  }>({
    open: false,
    total: '',
    usd: null,
    hasQuotes: false,
    baseCurrency: 'USD',
    oldTotal: '',
    reason: 'recalculated',
  });
  // lockExpiredInfo state removed - now auto-refreshes instead

  const normalizeExchangeRate = useMemoizedFn((rate?: string | null): string | null => {
    if (!rate) {
      return null;
    }
    const value = Number(rate);
    if (!Number.isFinite(value)) {
      return null;
    }
    return value.toFixed(8);
  });

  const getExchangeRateFromSession = useMemoizedFn((sessionData?: TCheckoutSession | null): string | null => {
    if (!sessionData?.line_items?.length) {
      return null;
    }
    for (const item of sessionData.line_items as TLineItemExpanded[]) {
      const rate = (item as any)?.exchange_rate;
      if (rate) {
        return rate;
      }
    }
    return null;
  });

  const quoteAutoRetryRef = useRef(false);
  const lastRetryKeyRef = useRef<string>('');
  const buildRetryKey = useMemoizedFn((sessionData?: TCheckoutSession | null) => {
    if (!sessionData?.line_items?.length) {
      return '';
    }
    return (sessionData.line_items as TLineItemExpanded[])
      .map((item) => {
        const priceId = item.price_id || item.price?.id || '';
        const quoteId = (item as any)?.quote_id || '';
        const quotedAmount = (item as any)?.quoted_amount || '';
        const exchangeRate = (item as any)?.exchange_rate || '';
        return `${priceId}:${quoteId}:${quotedAmount}:${exchangeRate}`;
      })
      .join('|');
  });

  const buildPriceUpdateSummary = useMemoizedFn((sessionData: TCheckoutSession) => {
    if (!paymentCurrency) {
      return { total: '', usd: null, hasQuotes: false, baseCurrency: 'USD', totalUnit: null as BN | null };
    }
    const lineItems = (sessionData.line_items || []) as TLineItemExpanded[];
    let baseCurrency = 'USD';
    for (const item of lineItems) {
      const price = item.upsell_price || item.price;
      const base = (price as any)?.base_currency;
      if (base) {
        baseCurrency = base;
        break;
      }
    }
    const hasQuotes = lineItems.some((item) => (item as any)?.quoted_amount && (item as any)?.exchange_rate);
    if (!hasQuotes) {
      return { total: '', usd: null, hasQuotes: false, baseCurrency, totalUnit: null as BN | null };
    }
    let trialInDays = Number(sessionData?.subscription_data?.trial_period_days || 0);
    const trialCurrencyIds = (sessionData?.subscription_data?.trial_currency || '')
      .split(',')
      .map(trim)
      .filter(Boolean);
    if (trialCurrencyIds.length > 0 && paymentCurrencyId && trialCurrencyIds.includes(paymentCurrencyId) === false) {
      trialInDays = 0;
    }
    const { total } = getCheckoutAmount(lineItems, paymentCurrency, trialInDays > 0);
    const discountAmount = new BN(sessionData.total_details?.amount_discount || '0');
    const totalUnit = new BN(total).sub(discountAmount);
    const normalizedTotalUnit = totalUnit.isNeg() ? new BN(0) : totalUnit;
    const totalDisplay = `${formatNumber(
      fromUnitToToken(normalizedTotalUnit.toString(), paymentCurrency.decimal),
      6
    )} ${paymentCurrency.symbol}`;

    const itemUsdReferences = lineItems.map((item) => {
      const price = item.upsell_price || item.price;
      const baseAmount = (price as any)?.base_amount;
      const hasBaseAmount = baseAmount !== undefined && baseAmount !== null;
      if (hasBaseAmount) {
        return getUsdAmountFromBaseAmount(baseAmount, item.quantity || 0);
      }
      const exchangeRate = (item as any)?.exchange_rate;
      const quotedAmount = (item as any)?.quoted_amount;
      if (!exchangeRate || !quotedAmount) {
        return null;
      }
      return getUsdAmountFromTokenUnits(new BN(quotedAmount), paymentCurrency.decimal, exchangeRate);
    });
    const usdValues = itemUsdReferences.filter((value): value is string => Boolean(value));
    if (!usdValues.length) {
      return { total: totalDisplay, usd: null, hasQuotes, baseCurrency, totalUnit: normalizedTotalUnit };
    }
    const sumUnit = usdValues.reduce((acc, value) => acc.add(new BN(fromTokenToUnit(value, 8))), new BN(0));
    const totalUsdReference = fromUnitToToken(sumUnit.toString(), 8);
    return {
      total: totalDisplay,
      usd: formatUsdAmount(totalUsdReference, locale),
      hasQuotes,
      baseCurrency,
      totalUnit: normalizedTotalUnit,
    };
  });

  const compareTotals = useMemoizedFn((prevSession: TCheckoutSession, nextSession: TCheckoutSession) => {
    const prev = buildPriceUpdateSummary(prevSession);
    const next = buildPriceUpdateSummary(nextSession);
    if (!prev.totalUnit || !next.totalUnit) {
      return { changed: false, prev, next };
    }
    const diff = next.totalUnit.sub(prev.totalUnit).abs();
    const epsilon = new BN(1);
    return { changed: diff.gt(epsilon), prev, next };
  });

  const applyQuoteUpdate = useMemoizedFn(
    (
      payload: { checkoutSession: TCheckoutSession; quotes?: any; rateUnavailable?: boolean; rateError?: string },
      options: { forceConfirm?: boolean; reason?: 'rateChanged' | 'recalculated' } = {}
    ) => {
      if (!payload?.checkoutSession) {
        return;
      }
      onQuoteUpdated?.({
        checkoutSession: payload.checkoutSession as TCheckoutSessionExpanded,
        quotes: payload.quotes,
        rateUnavailable: payload.rateUnavailable,
        rateError: payload.rateError,
      });
      const { changed, prev, next } = compareTotals(checkoutSession, payload.checkoutSession);
      const previousRate = normalizeExchangeRate(getExchangeRateFromSession(checkoutSession));
      const nextRate = normalizeExchangeRate(getExchangeRateFromSession(payload.checkoutSession));
      const rateChanged = !!(previousRate && nextRate && previousRate !== nextRate);
      const shouldShowModal = (options.forceConfirm || changed) && next.hasQuotes;
      if (shouldShowModal) {
        setPriceUpdateInfo({
          open: true,
          total: next.total,
          usd: next.usd,
          hasQuotes: next.hasQuotes,
          baseCurrency: next.baseCurrency,
          oldTotal: prev.total,
          reason: options.reason || (rateChanged ? 'rateChanged' : 'recalculated'),
        });
        return;
      }
      setPriceUpdateInfo({ open: false });
      const retryKey = buildRetryKey(payload.checkoutSession);
      if (retryKey && retryKey !== lastRetryKeyRef.current) {
        lastRetryKeyRef.current = retryKey;
        quoteAutoRetryRef.current = true;
      }
    }
  );

  const validateUserInfo = (values: any) => {
    if (!values) {
      return false;
    }

    const fieldValidation = checkoutSession.metadata?.page_info?.field_validation;

    const customerName = values.customer_name;
    if (!customerName || customerName.trim() === '') {
      return false;
    }

    const customerEmail = values.customer_email;
    if (!customerEmail || !isEmail(customerEmail)) {
      return false;
    }

    const nameValidation = getFieldValidation('customer_name', fieldValidation, locale);
    if (nameValidation.pattern) {
      const pattern = nameValidation.pattern.value;
      if (!pattern.test(customerName)) {
        return false;
      }
    }

    const emailValidation = getFieldValidation('customer_email', fieldValidation, locale);
    if (emailValidation.pattern) {
      const pattern = emailValidation.pattern.value;
      if (!pattern.test(customerEmail)) {
        return false;
      }
    }

    const billingAddress = values.billing_address || {};
    const { postal_code: postalCode, country, state: stateValue, line1, city } = billingAddress;
    if (!postalCode || !validatePostalCode(postalCode, country)) {
      return false;
    }

    const postalCodeValidation = getFieldValidation('billing_address.postal_code', fieldValidation, locale);
    if (postalCodeValidation.pattern) {
      const pattern = postalCodeValidation.pattern.value;
      if (!pattern.test(postalCode)) {
        return false;
      }
    }

    if (!stateValue) {
      return false;
    }
    const stateValidation = getFieldValidation('billing_address.state', fieldValidation, locale);
    if (stateValidation.pattern) {
      const pattern = stateValidation.pattern.value;
      if (!pattern.test(stateValue)) {
        return false;
      }
    }

    if (checkoutSession.phone_number_collection?.enabled) {
      const customerPhone = values.customer_phone;
      if (!customerPhone || customerPhone.trim() === '') {
        return false;
      }
      const phoneValidation = getFieldValidation('customer_phone', fieldValidation, locale);
      if (phoneValidation.pattern) {
        const pattern = phoneValidation.pattern.value;
        if (!pattern.test(customerPhone)) {
          return false;
        }
      }
    }

    const addressMode = checkoutSession.billing_address_collection;
    if (addressMode === 'required') {
      if (!country || !stateValue || !line1 || !city || !postalCode) {
        return false;
      }

      const line1Validation = getFieldValidation('billing_address.line1', fieldValidation, locale);
      if (line1Validation.pattern) {
        const pattern = line1Validation.pattern.value;
        if (!pattern.test(line1)) {
          return false;
        }
      }

      const cityValidation = getFieldValidation('billing_address.city', fieldValidation, locale);
      if (cityValidation.pattern) {
        const pattern = cityValidation.pattern.value;
        if (!pattern.test(city)) {
          return false;
        }
      }
    }

    return true;
  };

  const customerName = useWatch({ control, name: 'customer_name' });
  const customerEmail = useWatch({ control, name: 'customer_email' });
  const customerPhone = useWatch({ control, name: 'customer_phone' });
  const billingAddress = useWatch({ control, name: 'billing_address' });

  const showForm = session?.user ? state.showEditForm : false;

  useEffect(() => {
    if (!quoteAutoRetryRef.current) {
      return;
    }
    if (state.submitting || state.paying) {
      return;
    }
    quoteAutoRetryRef.current = false;
    onAction();
  }, [state.submitting, state.paying]); // eslint-disable-line react-hooks/exhaustive-deps

  const handleConnected = async () => {
    if (processingRef.current) {
      return;
    }
    processingRef.current = true;
    setState({ paying: true });
    try {
      const result = await waitForCheckoutComplete(checkoutSession.id);
      if (state.paid === false) {
        setState({ paid: true, paying: false });
        onPaid(result);
      }
    } catch (err) {
      const errorMessage = formatError(err);
      const payFailedEvent: PayFailedEvent = {
        action: 'payFailed',
        // @ts-ignore 后续升级的话就会报错了，移除这个 lint 即可
        mode: checkoutSession.mode,
        errorMessage,
        success: false,
      };
      ReactGA.event(payFailedEvent.action, payFailedEvent);

      Toast.error(errorMessage);
    } finally {
      setState({ paying: false });
      processingRef.current = false;
    }
  };

  useEffect(() => {
    if (errorRef.current && !isEmpty(errors) && isMobile) {
      errorRef.current.scrollIntoView({ behavior: 'smooth' });
    }
  }, [errors, isMobile]);

  const onUserLoggedIn = async () => {
    const { data: profile } = await api.get('/api/customers/me?fallback=1&skipSummary=1');
    if (profile) {
      const values = getValues();
      const userInfo = mergeUserInfo(profile, session?.user);
      const formValues = setUserFormValues(userInfo, values, setValue, {
        preferExisting: false,
        showPhone: checkoutSession.phone_number_collection?.enabled,
        shouldValidate: true,
      });

      const isValid = validateUserInfo(formValues);
      setState({ showEditForm: !isValid });
      await trigger();
    }
  };

  const handleFastCheckoutConfirm = async () => {
    if (!state.fastCheckoutInfo) return;

    setState({
      fastCheckoutInfo: {
        ...state.fastCheckoutInfo,
        loading: true,
      },
    });

    try {
      // ✅ No longer need to send quotes - backend auto-finds them
      const result = await api.post(`/api/checkout-sessions/${checkoutSession.id}/fast-checkout-confirm`, {});
      if (result.data.paymentIntent) {
        onPaymentIntentUpdate?.(result.data.paymentIntent);
      }
      if (result.data.fastPaid) {
        setState({
          fastCheckoutInfo: null,
          paying: true,
        });
        await handleConnected();
      } else {
        Toast.error(t('payment.checkout.fastPay.failed'));
        setState({
          fastCheckoutInfo: null,
          paying: true,
        });
        openConnect();
      }
    } catch (err: unknown) {
      console.error(err);
      const errorCode = (err as any)?.response?.data?.code;
      // Auto-refresh for quote-related errors (including lock expired)
      if (
        [
          'QUOTE_LOCK_EXPIRED',
          'QUOTE_AMOUNT_MISMATCH',
          'QUOTE_EXPIRED_OR_USED',
          'QUOTE_NOT_FOUND',
          'QUOTE_REQUIRED',
        ].includes(errorCode)
      ) {
        try {
          const { data: refreshed } = await api.get(`/api/checkout-sessions/retrieve/${checkoutSession.id}`, {
            params: { forceRefresh: '1' },
          });
          if (refreshed?.checkoutSession) {
            applyQuoteUpdate(refreshed, { reason: 'rateChanged' });
            Toast.info(t('payment.checkout.quote.updated.pleaseRetry') || 'Price updated, please resubmit');
          }
        } catch (refreshError) {
          console.error(refreshError);
          Toast.error(formatError(refreshError));
        } finally {
          setState({ fastCheckoutInfo: null });
        }
        return;
      }
      if (errorCode === 'QUOTE_UPDATED') {
        const payload = (err as any)?.response?.data;
        if (payload?.checkoutSession) {
          applyQuoteUpdate(payload);
        }
        setState({ fastCheckoutInfo: null });
        return;
      }
      if (errorCode === 'RATE_UNAVAILABLE') {
        const payload = (err as any)?.response?.data;
        if (payload?.checkoutSession) {
          onQuoteUpdated?.({
            checkoutSession: payload.checkoutSession as TCheckoutSessionExpanded,
            quotes: payload.quotes,
            rateUnavailable: payload.rateUnavailable,
            rateError: payload.rateError,
          });
        }
        setState({ fastCheckoutInfo: null });
        return;
      }
      Toast.error(formatError(err));
      setState({
        fastCheckoutInfo: null,
      });
    }
  };

  const handleFastCheckoutCancel = () => {
    setState({ fastCheckoutInfo: null });
  };

  const handleCreditInsufficientClose = () => {
    setState({ creditInsufficientInfo: null });
  };

  const handlePriceUpdateConfirm = () => {
    setPriceUpdateInfo({ open: false });
    quoteAutoRetryRef.current = true;
  };

  const handlePriceUpdateCancel = () => {
    setPriceUpdateInfo({ open: false });
  };

  // Final Freeze: Handle price change confirmation (PRICE_CHANGED error)
  const handlePriceChangeConfirm = () => {
    const formData = state.priceChangeConfirm?.formData;
    setState({ priceChangeConfirm: null });
    if (formData) {
      // Retry submit with price_confirmed flag
      onFormSubmit(formData);
    }
  };

  const handlePriceChangeCancel = () => {
    setState({ priceChangeConfirm: null });
  };

  const openConnect = () => {
    try {
      if (!['arcblock', 'ethereum', 'base'].includes(method.type)) {
        return;
      }
      setState({ paying: true });
      connect.open({
        locale,
        containerEl: undefined as unknown as Element,
        action: checkoutSession.mode,
        prefix: joinURL(getPrefix(), '/api/did'),
        saveConnect: false,
        useSocket: isCrossOrigin() === false,
        extraParams: { checkoutSessionId: checkoutSession.id, sessionUserDid: session?.user?.did },
        onSuccess: async () => {
          connect.close();
          await handleConnected();
        },
        onClose: () => {
          connect.close();
          setState({ submitting: false, paying: false });
        },
        onError: (err: any) => {
          console.error(err);
          setState({ submitting: false, paying: false });
          onError(err);
        },
        messages: {
          title: t('payment.checkout.connectModal.title', { action: buttonText }),
          scan: t('payment.checkout.connectModal.scan'),
          confirm: t('payment.checkout.connectModal.confirm'),
          cancel: t('payment.checkout.connectModal.cancel'),
        },
      } as any);
    } catch (err) {
      Toast.error(formatError(err));
    }
  };

  const onFormSubmit = async (data: any) => {
    if (state.submitting) {
      return;
    }

    const userInfo = session.user;

    if (!userInfo.sourceAppPid) {
      const hasVendorConfig = checkoutSession.line_items?.some(
        (item: TLineItemExpanded) => !!item?.price?.product?.vendor_config?.length
      );
      if (hasVendorConfig) {
        Toast.error(t('payment.checkout.vendor.accountRequired'));
        return;
      }
    }

    // ✅ No longer need to collect or validate quotes - backend auto-finds them
    // const quotes = collectQuotes(checkoutSession.line_items as TLineItemExpanded[]);
    // if (
    //   (checkoutSession.line_items || []).some((item: any) => item.price?.pricing_type === 'dynamic') &&
    //   quotes.length === 0
    // ) {
    //   Toast.error(t('payment.checkout.quote.expired'));
    //   return;
    // }

    setState({ submitting: true });
    try {
      let result;
      // Final Freeze: Add idempotency_key and preview_rate for dynamic pricing
      const previewRate =
        checkoutSession.line_items?.find((item: TLineItemExpanded) => (item as any)?.exchange_rate)?.exchange_rate ||
        undefined;

      // Stable idempotency key: only regenerate when payment context changes
      // Same context retry → reuse Quote (intent: "Failed Payments don't invalidate Quote")
      const items = (checkoutSession.line_items || []) as TLineItemExpanded[];
      const itemsSig = items
        .map((i: TLineItemExpanded) => `${(i as any).upsell_price_id || i.price_id}:${i.quantity}`)
        .join('|');
      const fingerprint = `${checkoutSession.id}-${paymentCurrency?.id}-${itemsSig}`;
      if (fingerprint !== sessionFingerprintRef.current || !idempotencyKeyRef.current) {
        sessionFingerprintRef.current = fingerprint;
        idempotencyKeyRef.current = generateIdempotencyKey(checkoutSession.id, paymentCurrency?.id || '');
      }

      const payload = {
        ...data,
        // Final Freeze: Include these for new quote creation at submit
        idempotency_key: idempotencyKeyRef.current,
        preview_rate: (previewRate as unknown as string) || undefined,
        price_confirmed: state.priceChangeConfirm?.formData ? true : undefined,
      };

      if (isDonationMode) {
        result = await api.put(`/api/checkout-sessions/${checkoutSession.id}/donate-submit`, payload);
      } else {
        result = await api.put(`/api/checkout-sessions/${checkoutSession.id}/submit`, payload);
      }
      setState({
        paymentIntent: result.data.paymentIntent,
        stripeContext: result.data.stripeContext,
        customer: result.data.customer,
        submitting: false,
        customerLimited: false,
      });
      if (result.data.paymentIntent) {
        onPaymentIntentUpdate?.(result.data.paymentIntent);
      }

      if (['arcblock', 'ethereum', 'base'].includes(method.type)) {
        // 如果不需要支付（如免费试用），直接确认
        if (result.data.noPaymentRequired) {
          try {
            const confirmResult = await api.post(
              `/api/checkout-sessions/${checkoutSession.id}/fast-checkout-confirm`,
              {}
            );
            if (confirmResult.data.paymentIntent) {
              onPaymentIntentUpdate?.(confirmResult.data.paymentIntent);
            }
            if (confirmResult.data.fastPaid || confirmResult.data.checkoutSession?.status === 'complete') {
              setState({ paying: true });
              await handleConnected();
            } else {
              openConnect();
            }
          } catch (confirmErr) {
            console.error('noPaymentRequired confirm failed', confirmErr);
            openConnect();
          }
          return;
        }

        // 优先判断 credit 支付
        if (paymentCurrency?.type === 'credit') {
          if (result.data.creditSufficient === true) {
            // 如果是 credit 支付且有足够额度，显示 credit 确认弹窗
            setState({
              fastCheckoutInfo: {
                open: true,
                loading: false,
                sourceType: 'credit',
                amount: result.data.fastPayInfo?.amount || '0',
                payer: result.data.fastPayInfo?.payer,
                availableCredit: result.data.fastPayInfo?.amount || '0',
                balance: result.data.fastPayInfo?.token?.balance || '0',
              },
            });
          } else {
            // 如果是 credit 支付但额度不足，显示额度不足弹窗
            setState({
              creditInsufficientInfo: {
                open: true,
              },
            });
          }
        } else if (
          (result.data.balance?.sufficient || result.data.delegation?.sufficient) &&
          !isDonationMode &&
          result.data.fastPayInfo
        ) {
          setState({
            fastCheckoutInfo: {
              open: true,
              loading: false,
              sourceType: result.data.fastPayInfo.type,
              amount: result.data.fastPayInfo.amount,
              payer: result.data.fastPayInfo.payer,
            },
          });
        } else {
          openConnect();
        }
      }
      if (['stripe'].includes(method.type)) {
        if (result.data.stripeContext?.status === 'succeeded') {
          setState({ paying: true });
        } else {
          setTimeout(() => {
            setState({ stripePaying: true });
          }, 200);
        }
      }
    } catch (err: any) {
      console.error(err);
      let shouldToast = true;

      const errorCode = err.response?.data?.code;
      if (errorCode) {
        if (
          ![
            'QUOTE_UPDATED',
            'RATE_UNAVAILABLE',
            'QUOTE_LOCK_EXPIRED',
            'QUOTE_AMOUNT_MISMATCH',
            'QUOTE_EXPIRED_OR_USED',
            'QUOTE_NOT_FOUND',
            'QUOTE_REQUIRED',
            'QUOTE_MAX_PAYABLE_EXCEEDED',
          ].includes(errorCode)
        ) {
          dispatch(`error.${errorCode}`);
        }

        // Auto-refresh for all quote-related errors (no modal dialog)
        if (
          [
            'QUOTE_LOCK_EXPIRED',
            'QUOTE_AMOUNT_MISMATCH',
            'QUOTE_EXPIRED_OR_USED',
            'QUOTE_NOT_FOUND',
            'QUOTE_REQUIRED',
            'QUOTE_MAX_PAYABLE_EXCEEDED',
            'quote_validation_failed',
          ].includes(errorCode)
        ) {
          shouldToast = false;
          try {
            const { data: refreshed } = await api.get(`/api/checkout-sessions/retrieve/${checkoutSession.id}`, {
              params: { forceRefresh: '1' },
            });
            if (refreshed?.checkoutSession) {
              applyQuoteUpdate(refreshed, { reason: 'rateChanged' });
              Toast.info(t('payment.checkout.quote.updated.pleaseRetry') || 'Price updated, please resubmit');
            }
          } catch (refreshError) {
            console.error(refreshError);
            Toast.error(formatError(refreshError));
          }
        }

        if (errorCode === 'QUOTE_UPDATED') {
          shouldToast = false;
          const payload = err.response?.data;
          if (payload?.checkoutSession) {
            applyQuoteUpdate(payload);
          }
        }

        if (errorCode === 'RATE_UNAVAILABLE') {
          shouldToast = false;
          const payload = err.response?.data;
          if (payload?.checkoutSession) {
            onQuoteUpdated?.({
              checkoutSession: payload.checkoutSession,
              quotes: payload.quotes,
              rateUnavailable: payload.rateUnavailable,
              rateError: payload.rateError,
            });
          }
        }

        // Final Freeze: Handle new error codes
        if (errorCode === 'PRICE_UNAVAILABLE') {
          shouldToast = false;
          Toast.error(
            t('payment.checkout.priceChange.unavailable', {
              fallback: 'Unable to fetch exchange rate. Please try again later.',
            })
          );
        }

        if (errorCode === 'PRICE_UNSTABLE') {
          shouldToast = false;
          Toast.error(
            t('payment.checkout.priceChange.unstable', {
              fallback: 'Price is volatile. Please try again later.',
            })
          );
        }

        if (errorCode === 'PRICE_CHANGED') {
          shouldToast = false;
          const errorData = err.response?.data;
          // Show price change confirmation dialog
          setState({
            priceChangeConfirm: {
              open: true,
              changePercent: errorData?.change_percent || 0,
              formData: data, // Save form data for retry
            },
          });
        }

        if (errorCode === 'UNIFIED_APP_REQUIRED') {
          shouldToast = false;
          Toast.error(t('payment.checkout.vendor.accountRequired'));
        }

        if (errorCode === 'CUSTOMER_LIMITED') {
          shouldToast = false;
          setState({ customerLimited: true });
        }

        if (errorCode === 'STOP_ACCEPTING_ORDERS') {
          shouldToast = false;
          setState({ serviceSuspended: true });
        }
      }
      if (shouldToast) {
        Toast.error(formatError(err));
      }
    } finally {
      setState({ submitting: false });
    }
  };

  const onFormError = (err: unknown) => {
    if (err) {
      console.error(err);
    }
    setState({ submitting: false });
  };

  const onAction = () => {
    if (state.submitting || state.paying || !canPay) {
      return;
    }
    if (errorRef.current && !isEmpty(errors) && isMobile) {
      errorRef.current.scrollIntoView({ behavior: 'smooth' });
    }
    if (session?.user) {
      handleSubmit(onFormSubmit, onFormError)();
    } else {
      if (isDonationMode) {
        handleSubmit(onFormSubmit, onFormError)();
        return;
      }
      session?.login(() => {
        setState({ submitting: true });
        onUserLoggedIn()
          .then(afterUserLoggedIn)
          .catch((err) => {
            console.error(err);
            setState({ submitting: false });
          });
      });
    }
  };

  // Lock expired handlers removed - now auto-refreshes instead

  const onStripeConfirm = async () => {
    setState({ stripePaying: false, paying: true });
    await handleConnected();
  };

  const onStripeCancel = async () => {
    try {
      await api.post(`/api/checkout-sessions/${checkoutSession.id}/abort-stripe`);
    } catch (err) {
      console.error(err);
      Toast.error(formatError(err));
    } finally {
      setState({ stripePaying: false });
    }
  };

  useEffect(() => {
    const handleKeyDown = (e: KeyboardEvent) => {
      if (
        e.key === 'Enter' &&
        !state.submitting &&
        !state.paying &&
        !state.stripePaying &&
        quantityInventoryStatus &&
        canPay
      ) {
        onAction();
      }
    };

    window.addEventListener('keydown', handleKeyDown);
    return () => {
      window.removeEventListener('keydown', handleKeyDown);
    };
  }, [state.submitting, state.paying, state.stripePaying, quantityInventoryStatus, canPay]); // eslint-disable-line react-hooks/exhaustive-deps

  const balanceLink = getTokenBalanceLink(method, state.fastCheckoutInfo?.payer || '');

  const FastCheckoutConfirmDialog = state.fastCheckoutInfo && (
    <ConfirmDialog
      onConfirm={handleFastCheckoutConfirm}
      onCancel={handleFastCheckoutCancel}
      title={
        state.fastCheckoutInfo.sourceType === 'credit'
          ? t('payment.checkout.fastPay.credit.title')
          : t('payment.checkout.fastPay.title')
      }
      message={
        state.fastCheckoutInfo.sourceType === 'credit' ? (
          <Typography>
            {t('payment.checkout.fastPay.credit.meteringSubscriptionMessage', {
              available: `${formatAmount(state.fastCheckoutInfo?.balance || '0', paymentCurrency?.decimal || 18)} ${paymentCurrency?.symbol}`,
            })}
          </Typography>
        ) : (
          <Stack>
            <Typography>{t('payment.checkout.fastPay.autoPaymentReason')}</Typography>
            <Divider sx={{ mt: 1.5, mb: 1.5 }} />
            <Stack spacing={1}>
              <Stack
                sx={{
                  flexDirection: 'row',
                  alignItems: 'center',
                  justifyContent: 'space-between',
                }}>
                <Typography
                  sx={{
                    color: 'text.primary',
                    whiteSpace: 'nowrap',
                  }}>
                  {t('payment.checkout.fastPay.payer')}
                </Typography>
                <Box sx={{ display: 'flex', alignItems: 'center', gap: 0.5 }}>
                  <DID did={state.fastCheckoutInfo.payer || ''} compact responsive={false} />
                  {balanceLink && (
                    <Tooltip title={t('payment.checkout.fastPay.balanceLink')} placement="top">
                      <OpenInNew
                        sx={{
                          color: 'text.lighter',
                          fontSize: '0.85rem',
                          cursor: 'pointer',
                          '&:hover': { color: 'text.primary' },
                        }}
                        onClick={() => {
                          window.open(balanceLink, '_blank');
                        }}
                      />
                    </Tooltip>
                  )}
                </Box>
              </Stack>
              <Stack
                sx={{
                  flexDirection: 'row',
                  alignItems: 'center',
                  justifyContent: 'space-between',
                }}>
                <Typography
                  sx={{
                    color: 'text.primary',
                  }}>
                  {t('payment.checkout.fastPay.amount')}
                </Typography>
                <Typography>
                  {formatAmount(state.fastCheckoutInfo.amount, paymentCurrency?.decimal || 18)}{' '}
                  {paymentCurrency?.symbol}
                </Typography>
              </Stack>
            </Stack>
          </Stack>
        )
      }
      loading={state.fastCheckoutInfo.loading}
      color="primary"
    />
  );

  const CreditInsufficientDialog = state.creditInsufficientInfo && (
    <ConfirmDialog
      onConfirm={handleCreditInsufficientClose}
      onCancel={handleCreditInsufficientClose}
      title={t('payment.checkout.fastPay.credit.insufficientTitle')}
      message={<Typography>{t('payment.checkout.fastPay.credit.insufficientMessage')}</Typography>}
      confirm={t('common.confirm')}
    />
  );

  const PriceUpdatedDialog = priceUpdateInfo.open && (
    <ConfirmDialog
      onConfirm={handlePriceUpdateConfirm}
      onCancel={handlePriceUpdateCancel}
      title={t('payment.checkout.quote.priceUpdatedTitle')}
      message={
        <Stack spacing={1}>
          <Typography>
            {t(
              priceUpdateInfo.reason === 'rateChanged'
                ? 'payment.checkout.quote.priceUpdatedDescriptionRate'
                : 'payment.checkout.quote.priceUpdatedDescriptionRecalc'
            )}
          </Typography>
          {priceUpdateInfo.hasQuotes && (
            <Stack spacing={0.25}>
              <Typography sx={{ color: 'text.secondary', fontSize: '0.7875rem' }}>
                {t('payment.checkout.quote.priceUpdatedNewTotalLabel')}
              </Typography>
              <Typography sx={{ fontWeight: 600 }}>{priceUpdateInfo.total}</Typography>
              {priceUpdateInfo.usd && (
                <Typography sx={{ color: 'text.secondary' }}>
                  ≈ {priceUpdateInfo.usd} {priceUpdateInfo.baseCurrency}
                </Typography>
              )}
              {priceUpdateInfo.oldTotal && (
                <Typography sx={{ color: 'text.secondary', fontSize: '0.75rem' }}>
                  {t('payment.checkout.quote.priceUpdatedOldTotal', { total: priceUpdateInfo.oldTotal })}
                </Typography>
              )}
            </Stack>
          )}
        </Stack>
      }
      confirm={t('payment.checkout.quote.priceUpdatedConfirm')}
      cancel={t('common.cancel')}
      color="primary"
    />
  );
  // LockExpiredDialog removed - now auto-refreshes instead

  const getRedirectUrl = () => {
    if (searchParams.redirect) {
      return decodeURIComponent(searchParams.redirect);
    }
    if (checkoutSession.success_url) {
      return checkoutSession.success_url;
    }
    if (paymentLink?.after_completion?.redirect?.url) {
      return paymentLink.after_completion.redirect.url;
    }
    return undefined;
  };

  if (onlyShowBtn) {
    return (
      <>
        <Box className="cko-payment-submit-btn">
          <Button
            variant="contained"
            color="primary"
            size="large"
            className="cko-submit-button"
            onClick={() => {
              if (state.submitting || state.paying || !canPay) {
                return;
              }
              onAction();
            }}
            fullWidth
            disabled={state.stripePaying || !quantityInventoryStatus || !canPay}>
            {(state.submitting || state.paying) && (
              <CircularProgress size={16} sx={{ mr: 0.5, color: 'primary.contrastText' }} />
            )}
            {state.submitting || state.paying ? t('payment.checkout.processing') : buttonText}
          </Button>
        </Box>
        {state.customerLimited && (
          <OverdueInvoicePayment
            customerId={customer?.id || session?.user?.did}
            onPaid={() => {
              setState({ customerLimited: false });
              onAction();
            }}
            alertMessage={t('payment.customer.pastDue.alert.customMessage')}
            detailLinkOptions={{
              enabled: true,
              onClick: () => {
                setState({ customerLimited: false });
                window.open(
                  joinURL(
                    getPrefix(),
                    `/customer/invoice/past-due?referer=${encodeURIComponent(window.location.href)}`
                  ),
                  '_self'
                );
              },
            }}
            dialogProps={{
              open: state.customerLimited,
              onClose: () => setState({ customerLimited: false }),
              title: t('payment.customer.pastDue.alert.title'),
            }}
          />
        )}
        {state.serviceSuspended && (
          <ServiceSuspendedDialog open onClose={() => setState({ serviceSuspended: false })} />
        )}
        {FastCheckoutConfirmDialog}
        {CreditInsufficientDialog}
        {PriceUpdatedDialog}
        {/* Final Freeze: Price change confirmation dialog */}
        {state.priceChangeConfirm?.open && (
          <PriceChangeConfirm
            open
            changePercent={state.priceChangeConfirm.changePercent}
            onConfirm={handlePriceChangeConfirm}
            onCancel={handlePriceChangeCancel}
            loading={state.submitting}
          />
        )}
      </>
    );
  }
  return (
    <>
      <Fade in>
        <Stack className="cko-payment-contact">
          <Typography
            title={t('payment.checkout.paymentDetails')}
            sx={{
              color: 'text.primary',
              fontSize: {
                xs: '18px',
                md: '24px',
              },
              fontWeight: '700',
              lineHeight: '32px',
              mb: 2.5,
            }}>
            {t('payment.checkout.paymentDetails')}
          </Typography>
          <Fade in>
            <Stack
              direction="column"
              className="cko-payment-methods"
              sx={{
                alignItems: 'flex-start',
              }}>
              <Stack direction="row" sx={{ width: '100%' }}>
                <Controller
                  name="payment_currency"
                  control={control}
                  render={({ field }) => (
                    <CurrencySelector
                      value={field.value}
                      currencies={currencies}
                      onChange={async (id: string, methodId: string) => {
                        const oldCurrencyId = field.value;
                        field.onChange(id);
                        setValue('payment_method', methodId);
                        saveCurrencyPreference(id, session?.user?.did);

                        // Call API to switch currency and clear quote-related fields if currency changed
                        // This is essential because quotes are currency-specific (e.g., TBA quote with 18 decimals
                        // cannot be used for USD with 2 decimals)
                        if (oldCurrencyId && oldCurrencyId !== id) {
                          try {
                            const { data } = await api.put(
                              `/api/checkout-sessions/${checkoutSession.id}/switch-currency`,
                              {
                                currency_id: id,
                                payment_method_id: methodId,
                              }
                            );
                            if (data.currency_changed && onQuoteUpdated) {
                              onQuoteUpdated({ checkoutSession: data, quotes: data.quotes });
                            }
                          } catch (err) {
                            console.error('Failed to switch currency:', err);
                          }
                        }
                      }}
                    />
                  )}
                />
              </Stack>
              {state.stripePaying && state.stripeContext && (
                <StripeCheckout
                  clientSecret={state.stripeContext.client_secret}
                  intentType={state.stripeContext.intent_type}
                  publicKey={method.settings.stripe?.publishable_key as string}
                  customer={state.customer as TCustomer}
                  mode={checkoutSession.mode}
                  onConfirm={onStripeConfirm}
                  onCancel={onStripeCancel}
                  returnUrl={getRedirectUrl()}
                />
              )}
            </Stack>
          </Fade>
          {!showForm && session?.user && (
            <Stack
              spacing={1.25}
              sx={{
                mt: 2,
                p: 2,
                pt: 1,
                backgroundColor: 'background.paper',
                borderRadius: 1,
                border: '1px solid',
                borderColor: 'divider',
              }}>
              <Stack direction="row" justifyContent="space-between" alignItems="center" sx={{ mb: 0.25 }}>
                <Typography variant="subtitle2" sx={{ color: 'text.primary', fontSize: '0.875rem' }}>
                  {t('payment.checkout.customerInfo')}
                </Typography>
                <Button
                  size="small"
                  variant="text"
                  onClick={() => setState({ showEditForm: true })}
                  sx={{ minWidth: 0 }}>
                  {t('common.edit')}
                </Button>
              </Stack>
              <Stack spacing={0.5}>
                <Typography variant="body2" sx={{ color: 'text.primary', fontWeight: 600, fontSize: '0.9375rem' }}>
                  {customerName}
                </Typography>
                <Typography variant="body2" sx={{ color: 'text.secondary', fontSize: '0.8125rem' }}>
                  {customerEmail}
                </Typography>
                {checkoutSession.phone_number_collection?.enabled && customerPhone && (
                  <Typography variant="body2" sx={{ color: 'text.secondary', fontSize: '0.8125rem' }}>
                    {customerPhone}
                  </Typography>
                )}
                {billingAddress && (
                  <Stack direction="row" alignItems="center" spacing={0.75}>
                    {billingAddress.country && (
                      <FlagEmoji iso2={billingAddress.country.toLowerCase()} style={{ width: 18, height: 14 }} />
                    )}
                    <Typography variant="body2" sx={{ color: 'text.secondary', fontSize: '0.8125rem' }}>
                      {checkoutSession.billing_address_collection === 'required'
                        ? [billingAddress.line1, billingAddress.city, billingAddress.state].filter(Boolean).join(', ')
                        : billingAddress.state || ''}
                      {billingAddress.postal_code &&
                        ` [ ${t('payment.checkout.billing.postal_code')}: ${billingAddress.postal_code} ]`}
                    </Typography>
                  </Stack>
                )}
              </Stack>
            </Stack>
          )}
          {showForm && (
            <Stack
              direction="column"
              className="cko-payment-form"
              id="cko-payment-form"
              spacing={0}
              ref={!isEmpty(errors) ? (errorRef as any) : undefined}
              sx={{ flex: 1, overflow: 'auto', py: 1 }}>
              <FormLabel className="base-label">{t('payment.checkout.customer.name')}</FormLabel>
              <FormInput
                name="customer_name"
                variant="outlined"
                errorPosition={formErrorPosition}
                rules={{
                  required: t('payment.checkout.required'),
                  ...getFieldValidation('customer_name', checkoutSession.metadata?.page_info?.field_validation, locale),
                }}
              />
              <FormLabel className="base-label">{t('payment.checkout.customer.email')}</FormLabel>
              <FormInput
                name="customer_email"
                variant="outlined"
                errorPosition={formErrorPosition}
                rules={{
                  required: t('payment.checkout.required'),
                  validate: (x) => (isEmail(x) ? true : t('payment.checkout.invalid')),
                  ...getFieldValidation(
                    'customer_email',
                    checkoutSession.metadata?.page_info?.field_validation,
                    locale
                  ),
                }}
              />
              {checkoutSession.phone_number_collection?.enabled && (
                <>
                  <FormLabel className="base-label">{t('payment.checkout.customer.phone')}</FormLabel>
                  <PhoneInput
                    name="customer_phone"
                    variant="outlined"
                    errorPosition={formErrorPosition}
                    placeholder="Phone number"
                    rules={{
                      required: t('payment.checkout.required'),
                      validate: async (x: string) => {
                        const isValid = await validatePhoneNumber(x);
                        return isValid ? true : t('payment.checkout.invalid');
                      },
                      ...getFieldValidation(
                        'customer_phone',
                        checkoutSession.metadata?.page_info?.field_validation,
                        locale
                      ),
                    }}
                  />
                </>
              )}
              <AddressForm
                mode={checkoutSession.billing_address_collection as string}
                sx={{ marginTop: '0 !important' }}
                fieldValidation={checkoutSession.metadata?.page_info?.field_validation}
                errorPosition={formErrorPosition}
              />
            </Stack>
          )}
        </Stack>
      </Fade>
      <Divider sx={{ mt: 2.5, mb: 2.5 }} />
      <Fade in>
        <Stack className="cko-payment-submit">
          <Box className="cko-payment-submit-btn">
            <LoadingButton
              variant="contained"
              color="primary"
              size="large"
              className="cko-submit-button"
              onClick={() => {
                onAction();
              }}
              fullWidth
              loading={state.submitting || state.paying}
              disabled={state.stripePaying || !quantityInventoryStatus || !canPay}>
              {state.submitting || state.paying ? t('payment.checkout.processing') : buttonText}
            </LoadingButton>
          </Box>
          {['subscription', 'setup'].includes(checkoutSession.mode) && (
            <Typography sx={{ mt: 2.5, color: 'text.lighter', fontSize: '0.7875rem', lineHeight: '0.9625rem' }}>
              {showStake
                ? t('payment.checkout.confirm.withStake', { payee })
                : t('payment.checkout.confirm.withoutStake', { payee })}
            </Typography>
          )}
          {checkoutSession.metadata?.page_info?.form_purpose_description && (
            <Box sx={{ mt: 1, display: 'flex', alignItems: 'center', gap: 0.5 }}>
              <HelpOutline sx={{ color: 'text.lighter', fontSize: '0.75rem' }} />
              <Typography variant="body2" sx={{ fontSize: '0.75rem', color: 'text.lighter' }}>
                {locale === 'zh'
                  ? checkoutSession.metadata.page_info.form_purpose_description.zh
                  : checkoutSession.metadata.page_info.form_purpose_description.en}
              </Typography>
            </Box>
          )}
        </Stack>
      </Fade>
      {state.customerLimited && (
        <OverdueInvoicePayment
          customerId={customer?.id || session?.user?.did}
          onPaid={() => {
            setState({ customerLimited: false });
            onAction();
          }}
          alertMessage={t('payment.customer.pastDue.alert.customMessage')}
          detailLinkOptions={{
            enabled: true,
            onClick: () => {
              setState({ customerLimited: false });
              window.open(
                joinURL(getPrefix(), `/customer/invoice/past-due?referer=${encodeURIComponent(window.location.href)}`),
                '_self'
              );
            },
          }}
          dialogProps={{
            open: state.customerLimited,
            onClose: () => setState({ customerLimited: false }),
            title: t('payment.customer.pastDue.alert.title'),
          }}
        />
      )}
      {state.serviceSuspended && <ServiceSuspendedDialog open onClose={() => setState({ serviceSuspended: false })} />}
      {FastCheckoutConfirmDialog}
      {CreditInsufficientDialog}
      {PriceUpdatedDialog}
      {/* Final Freeze: Price change confirmation dialog */}
      {state.priceChangeConfirm?.open && (
        <PriceChangeConfirm
          open
          changePercent={state.priceChangeConfirm.changePercent}
          onConfirm={handlePriceChangeConfirm}
          onCancel={handlePriceChangeCancel}
          loading={state.submitting}
        />
      )}
      {/* LockExpiredDialog removed - now auto-refreshes instead */}
    </>
  );
}
