import React, { useCallback, useState, useEffect, useMemo, useRef } from 'react';
import { useDispatch } from 'react-redux';
import { useAppSelector } from '@akinon/next/redux/hooks';
import { Icon } from '@akinon/next/components';
import { getPosError } from '@akinon/next/utils';
import { useMasterpassAccount } from '../hooks/useMasterpassAccount';
import { useMasterpassPayment } from '../hooks/useMasterpassPayment';
import { useMasterpassScript } from '../hooks/useMasterpassScript';
import { useSetMasterpassRestBinNumberMutation } from '../redux/api';
import {
  setLastCheckedBin,
  clearNewCardFormData,
  setError,
  clearAllErrors,
  setLocale,
  setCurrency
} from '../redux/reducer';
import {
  getPaymentPending,
  clearPaymentPending
} from '../utils/payment-utils';
import type { CreditCardFormData } from '../utils/validation-schemas';
import type {
  MasterpassRestOptionCustomRender,
  MasterpassRestOptionTexts
} from '../types/custom-render.types';
import type { MasterpassEnvironment } from '../utils/constants';
import LinkModal from '../components/link-modal';
import OTPModal from '../components/otp-modal';
import CardList from '../components/card-list';
import ConfirmationModal from '../components/confirmation-modal';
import InstallmentList from '../components/installment-list';
import CreditCardForm from '../components/credit-card-form';
import PaymentMethodSelector from '../components/payment-method-selector';
import InformationModal from '../components/information-modal';
import RewardSelectionModal from '../components/reward-selection-modal';
import type { RewardItem } from '../types/payment.types';
import mpBlackLogo from '../assets/img/masterpass-black-logo.png';

interface MasterpassRestOptionProps {
  locale?: string;
  currency?: string;
  sdkUrl?: string;
  environment?: MasterpassEnvironment;
  texts?: MasterpassRestOptionTexts;
  customRender?: MasterpassRestOptionCustomRender;
  enableRewards?: boolean;
}

const defaultTexts: MasterpassRestOptionTexts = {
  title: 'Masterpass Payment',
  newCardTitle: 'New Card Payment',
  selectCardTitle: 'Select a Card',
  installmentOptionsTitle: 'Installment Options',
  enterCardDetailsTitle: 'Enter Card Details',
  loadingMessage: 'Initializing payment system...',
  scriptLoadingMessage: 'Loading payment provider...',
  selectCardMessage: 'Select a card to see installment options',
  enterCardMessage: 'Enter your card number to see installment options',
  enterCardSubMessage:
    'Installment options will appear automatically as you type',
  enterDigitsMessage: 'Enter at least 6 digits to see installment options',
  noInstallmentMessage: 'No installment options available for this card',
  loadingInstallmentMessage: 'Loading installment options...',
  removeCardMessage:
    'Are you sure you want to remove <{cardAlias}> card from Masterpass infrastructure?',
  removeCardConfirmText: 'Yes',
  removeCardCancelText: 'No',
  removeCardLoadingText: 'Removing...',
  dismissButtonText: 'Dismiss',
  paymentErrorTitle: 'Payment Error',
  paymentErrorDefaultMessage: 'An error occurred during payment processing.',
  paymentMethodTitle: 'Payment Method',
  paymentMethodDescription: "Choose how you'd like to pay",
  savedCardsText: 'Saved Cards',
  savedCardsDescription: 'Use one of your saved cards ({count} available)',
  newCardText: 'New Card',
  newCardDescription: 'Enter a new card for payment',
  noPaymentMethodsText: 'No payment methods available',
  failedToSaveCardText: 'Failed to save card',
  paymentFailedText: 'Payment failed',
  otpHandlerNotAvailableText: 'OTP handler not available',
  failedToSelectCardText: 'Failed to select card',
  failedToSelectInstallmentText: 'Failed to select installment',
  cardNumberRequiredText: 'Card number is required',
  cardNumberInvalidText: 'Please enter a valid card number',
  expiryDateRequiredText: 'Expiry date is required',
  expiryDateInvalidText: 'Please enter a valid expiry date (MM/YY)',
  expiryDateExpiredText: 'Card has expired',
  cvvRequiredText: 'CVV is required',
  cvvInvalidText: 'CVV must be 3 or 4 digits',
  cardholderNameRequiredText: 'Cardholder name is required',
  cardholderNameTooShortText: 'Name must be at least 2 characters',
  cardholderNameTooLongText: 'Name must not exceed 50 characters',
  cardholderNameInvalidText: 'Name can only contain letters and spaces',
  cardAliasRequiredText: 'Card alias is required when saving card',
  cardAliasTooShortText: 'Card alias must be at least 2 characters',
  cardAliasTooLongText: 'Card alias must not exceed 20 characters',
  creditCardInfoTitle: 'Credit Card Information',
  checkingCardText: 'Checking card...',
  cardNumberLabel: 'Card Number',
  cardNumberPlaceholder: '1234 5678 9012 3456',
  cardholderNameLabel: 'Cardholder Name',
  cardholderNamePlaceholder: 'John Doe',
  expiryDateLabel: 'Expiry Date',
  expiryDatePlaceholder: 'MM/YY',
  cvcLabel: 'CVC/CVV',
  cvcPlaceholder3: '123',
  cvcPlaceholder4: '1234',
  saveCardLabel: 'Save this card for future payments',
  saveCardTermsPrefix: 'I have read the',
  saveCardTermsLink: 'Terms and Conditions',
  saveCardTermsSuffix: ', I want to save my card to Masterpass.',
  masterpassSecurityPrefix: 'Your card information is securely stored in',
  masterpassSecurityLink: 'Masterpass',
  masterpassSecuritySuffix: ", Mastercard's digital payment infrastructure.",
  cardAliasLabel: 'Card Nickname (optional)',
  cardAliasPlaceholder: 'My Visa Card',
  addCardButton: 'Add Card',
  cancelButton: 'Cancel',
  secureText: 'Secure',
  cvcHelpText: '{length}-digit security code on the {side} of your card',
  cvcFrontText: 'front',
  cvcBackText: 'back',
  defaultCardText: 'Default',
  expiresSoonText: 'Expires Soon',
  cvcCardLabel: 'CVC/CVV',
  secureCardText: 'Secure',
  cvcCardHelpText: '{length}-digit security code on the {side} of your card',
  confirmText: 'Confirm',
  cancelText: 'Cancel',
  loadingText: 'Loading...',
  installmentOptionsText: 'Installment Options',
  cardTypeLabel: 'Card Type:',
  singlePaymentText: 'Single Payment',
  installmentsText: '{count} Installments',
  noInterestText: 'No Interest',
  perMonthText: '/month',
  proceedToPaymentText: 'Proceed to Payment',
  processingPaymentText: 'Processing Payment...',
  cvcRequiredText: 'Please enter your CVC to proceed with payment',
  linkModalDescription:
    'Would you like to view the cards saved in your Masterpass account that was created with the phone number <PHONE_NUMBER>',
  linkAccountButton: 'Yes, I want it',
  linkModalCancelButton: 'No, I don\'t want it',
  whatIsMasterpassLink: 'What is Masterpass?',
  rtaVerificationTitle: 'Security Verification',
  rtaVerificationDescription: 'To continue with your transaction, please enter the verification code sent to your phone.',
  rtaVerificationPlaceholder: 'Verification Code',
  bankOtpVerificationTitle: 'Bank Authorization Required',
  bankOtpVerificationDescription: 'Please enter the one-time password sent by your bank to complete the verification.',
  bankOtpVerificationPlaceholder: 'Bank OTP Code',
  phoneVerificationTitle: 'Verify Your Phone Number',
  phoneVerificationDescription: 'Enter the verification code sent to your phone to confirm your Masterpass account.',
  phoneVerificationPlaceholder: 'SMS Verification Code',
  cvvVerificationTitle: 'Card Security Code Required',
  cvvVerificationDescription: 'Please enter the 3-digit security code (CVV) located on the back of your card to continue.',
  cvvVerificationPlaceholder: 'CVV',
  cvvVerificationHelperText: 'The CVV is the 3-digit number on the back of your card.',
  otpVerificationDescription: 'Please enter the verification code sent to your phone.',
  verifyButton: 'Verify',
  otpModalCancelButton: 'Cancel',
  otpModalErrorText: 'An unexpected error occurred. Please try again.',
  otpModalResendOtpButton: 'Resend OTP',
  sessionExpiredTitle: 'Session Expired',
  sessionExpiredMessage: 'Your session has expired due to inactivity. Please restart the process to continue.',
  sessionExpiredSecondaryMessage: 'For security reasons, sessions are only valid for a limited time.',
  sessionExpiredButton: 'Start Again',

  rewardModalTitle: 'Use Card Rewards',
  rewardModalDescription: 'Select the rewards you want to apply to this order.',
  rewardModalEmptyMessage: 'No rewards available for this card.',
  rewardModalConfirmText: 'Apply',
  rewardModalCancelText: 'Cancel',
  rewardModalLoadingText: 'Applying...',
  rewardOpenButtonText: 'Use Rewards',
  rewardSelectedSummaryText: '{count} reward(s) applied',
  rewardAvailableSummaryText: '{count} reward(s) available',
  rewardClearText: 'Clear',
  rewardCategorySpecialText: 'Special Rewards',
  rewardCategoryGeneralText: 'General Rewards',
  rewardFailedToLoadText: 'Failed to load rewards',
  rewardFailedToSelectText: 'Failed to apply rewards',
  rewardCappedNoticeText: '{amount} will be applied'
};

const mergeTexts = (
  customTexts: MasterpassRestOptionTexts,
  defaultTexts: MasterpassRestOptionTexts
): MasterpassRestOptionTexts => {
  return {
    ...defaultTexts,
    ...customTexts
  };
};

const MasterpassRestOption: React.FC<MasterpassRestOptionProps> = ({
  locale = 'en',
  currency = 'usd',
  sdkUrl,
  environment,
  texts = defaultTexts,
  customRender,
  enableRewards = false
}) => {
  const mergedTexts = React.useMemo(
    () => mergeTexts(texts, defaultTexts),
    [texts]
  );

  const dispatch = useDispatch();
  const {
    paymentState,
    modalState,
    accountStatus,
    lastCheckedBin,
    isTokenLoading,
    locale: stateLocale,
    currency: stateCurrency,
    newCardFormData,
    error
  } = useAppSelector((state) => state.masterpassRest);

  const [paymentMethod, setPaymentMethod] = useState<
    'stored_card' | 'new_card'
  >('stored_card');
  const [cvc, setCvc] = useState<string>('');
  const [isProcessingPayment, setIsProcessingPayment] = useState(false);

  // Initialized during render (not in an effect) so consumers see the real
  // value before their own mount effects run.
  const [isPaymentPending, setIsPaymentPending] = useState<boolean>(() =>
    typeof window === 'undefined' ? false : Boolean(getPaymentPending())
  );

  const dismissPaymentPending = useCallback(() => {
    clearPaymentPending();
    setIsPaymentPending(false);
  }, []);

  const [setMasterpassRestBinNumber] = useSetMasterpassRestBinNumberMutation();

  const {
    isCheckoutLoading,
    isInstallmentLoading,
    isPrepareLoading,
    isFinalizeLoading,
    isRewardsQueryLoading,
    isRewardsSelectLoading,
    updatePaymentState,
    handleCardSelect,
    handleInstallmentSelect,
    processPayment,
    processDirectPayment,
    finalizePaymentAfterVerification,
    openRewardModal,
    closeRewardModal,
    confirmRewards,
    payableAmount
  } = useMasterpassPayment({ enableRewards });

  const {
    accountData,
    updateModalState,
    handleLinkConfirm,
    handleOTPSubmit,
    handleRemoveCard,
    confirmRemoveCard,
    handleAddCard,
    resetData
  } = useMasterpassAccount();

  const onScriptError = useCallback(
    (error: Error) => {
      dispatch(
        setError(
          'Failed to load payment provider script. Please try again later.'
        )
      );
    },
    [dispatch]
  );

  const { isScriptLoaded } = useMasterpassScript({
    locale: stateLocale || locale,
    sdkUrl,
    environment,
    onScriptError
  });

  useEffect(() => {
    if (locale !== stateLocale) {
      dispatch(setLocale(locale));
    }
    if (currency !== stateCurrency) {
      dispatch(setCurrency(currency));
    }
  }, [locale, currency, stateLocale, stateCurrency, dispatch]);

  useEffect(() => {
    const hasCards = accountData?.result?.cards && accountData.result.cards.length > 0;

    if (accountStatus?.isAccountNotLinked || accountStatus?.shouldShowDirectForm) {
      setPaymentMethod('new_card');
    } else if (hasCards) {
      setPaymentMethod('stored_card');
    } else {
      setPaymentMethod('new_card');
    }
  }, [accountStatus?.isAccountNotLinked, accountStatus?.shouldShowDirectForm, accountData?.result?.cards]);

  const handleBinChange = useCallback(
    async (bin: string) => {
      if (bin === lastCheckedBin) {
        return;
      }

      dispatch(setLastCheckedBin(bin));

      try {
        const apiPayload = {
          is_masterpass_stored_card: false,
          bin_number: bin
        };

        const result = await setMasterpassRestBinNumber(apiPayload).unwrap();

        if (result.context_list?.[0]?.page_context) {
          const pageContext = result.context_list[0].page_context;

          updatePaymentState({
            installments: pageContext.installments || [],
            cardType: pageContext.card_type
          });
        } else {
          updatePaymentState({
            installments: [],
            cardType: null
          });
        }
      } catch (error) {
        updatePaymentState({
          installments: [],
          cardType: null
        });
      }
    },
    [setMasterpassRestBinNumber, lastCheckedBin, dispatch, updatePaymentState]
  );

  useEffect(() => {
    const error = getPosError();

    if (error && Object.keys(error).length > 0) {
      dispatch(setError(error));

      // The completion request already ran and failed, so the order number it
      // was bound to is settled and the flow may restart from scratch.
      dismissPaymentPending();
    }

    return () => {
      resetData();
      dispatch(clearAllErrors());
    };
  }, [dispatch, resetData, dismissPaymentPending]);

  const getErrorInfo = (error: any) => {
    if (error && typeof error === 'object') {
      if (error.non_field_errors) {
        return {
          message: error.non_field_errors,
          type: mergedTexts.paymentErrorTitle
        };
      }

      if (error.three_d_secure) {
        return {
          message: error.three_d_secure,
          type: '3D Secure Error'
        };
      }

      const errorKeys = Object.keys(error);
      if (errorKeys.length > 0) {
        const firstKey = errorKeys[0];
        return {
          message: error[firstKey],
          type: firstKey
            .replace(/_/g, ' ')
            .replace(/\b\w/g, (l) => l.toUpperCase())
        };
      }
    }

    if (typeof error === 'string') {
      return {
        message: error,
        type: mergedTexts.paymentErrorTitle
      };
    }

    return null;
  };

  const handleSaveCard = useCallback(async (cardData: CreditCardFormData) => {
    try {
      dispatch(clearAllErrors());
      const addCardResult = await handleAddCard({
        cardNumber: cardData.cardNumber,
        cardholderName: cardData.cardholderName,
        expiryDate: cardData.expiryDate,
        cvv: cardData.cvv,
        cardAlias: cardData.cardAlias || ''
      });

      if (
        !addCardResult.success &&
        !addCardResult.requires3D &&
        !addCardResult.requiresOTP
      ) {
        dispatch(
          setError(addCardResult.message || mergedTexts.failedToSaveCardText)
        );
        return;
      }
    } catch (error) {
      dispatch(setError(error.message || mergedTexts.failedToSaveCardText));
    }
  }, [dispatch, handleAddCard, mergedTexts.failedToSaveCardText]);

  const handleProceedToPayment = useCallback(async () => {
    if (isProcessingPayment) return;

    setIsProcessingPayment(true);

    try {
      dispatch(clearAllErrors());

      const result = paymentMethod === 'new_card'
        ? await processDirectPayment()
        : await processPayment();

      if (result.requiresRedirect) {
        return;
      }

      if (result.requiresOTP && result.otpType) {
        updateModalState({
          showOTPModal: true,
          otpType: result.otpType,
          otpContext: 'payment'
        });
        return;
      }

      if (!result.success && result.message) {
        dispatch(setError(result.message));
      }
    } catch (error) {
      const errorMessage =
        error instanceof Error ? error.message : mergedTexts.paymentFailedText;
      dispatch(setError(errorMessage));
    } finally {
      setIsProcessingPayment(false);
    }
  }, [isProcessingPayment, dispatch, paymentMethod, processDirectPayment, processPayment, updateModalState, mergedTexts.paymentFailedText]);

  const handleOTPSubmitWithErrorHandling = useCallback(async (otp: string) => {
    if (!handleOTPSubmit)
      return {
        success: false,
        message: mergedTexts.otpHandlerNotAvailableText
      };

    const result = await handleOTPSubmit(otp, mergedTexts);

    // A payment-context OTP leaves the Masterpass transaction open; the backend
    // only learns about it once the completion request is sent.
    if (result?.success && result?.isPaymentContext) {
      const finalizeResult = await finalizePaymentAfterVerification(
        result.verificationData
      );

      if (!finalizeResult.success) {
        dispatch(
          setError(finalizeResult.message || mergedTexts.paymentFailedText)
        );
      }

      return finalizeResult;
    }

    return result;
  }, [
    handleOTPSubmit,
    finalizePaymentAfterVerification,
    dispatch,
    mergedTexts
  ]);

  const handleCardSelectWithErrorHandling = useCallback(async (card: any) => {
    try {
      dispatch(clearAllErrors());
      dismissPaymentPending();
      await handleCardSelect(card);
    } catch (error) {
      const errorMessage =
        error instanceof Error
          ? error.message
          : mergedTexts.failedToSelectCardText;
      dispatch(setError(errorMessage));
    }
  }, [dispatch, dismissPaymentPending, handleCardSelect, mergedTexts.failedToSelectCardText]);

  const handleInstallmentSelectWithErrorHandling = useCallback(async (installment: any) => {
    try {
      dispatch(clearAllErrors());
      dismissPaymentPending();
      await handleInstallmentSelect(installment);
    } catch (error) {
      const errorMessage =
        error instanceof Error
          ? error.message
          : mergedTexts.failedToSelectInstallmentText;
      dispatch(setError(errorMessage));
    }
  }, [dispatch, dismissPaymentPending, handleInstallmentSelect, mergedTexts.failedToSelectInstallmentText]);

  const handleConfirmRewards = useCallback(
    async (selected: RewardItem[]) => {
      const result = await confirmRewards(selected);
      if (!result.success) {
        dispatch(
          setError(result.message || mergedTexts.rewardFailedToSelectText)
        );
      }
    },
    [confirmRewards, dispatch, mergedTexts.rewardFailedToSelectText]
  );

  const handleCvcChange = useCallback((newCvc: string) => {
    setCvc(newCvc);
    updatePaymentState({ cvc: newCvc });
  }, [updatePaymentState]);

  const handlePaymentMethodChange = useCallback((method: 'stored_card' | 'new_card') => {
    dismissPaymentPending();
    setPaymentMethod(method);
    updatePaymentState({
      selectedCard: null,
      selectedInstallment: null,
      installments: [],
      cardType: null,
      cvc: ''
    });
    setCvc('');
    dispatch(setLastCheckedBin(''));
    dispatch(clearNewCardFormData());
  }, [dispatch, dismissPaymentPending, updatePaymentState]);

  const customRenderRef = useRef(customRender);
  customRenderRef.current = customRender;

  const memoizedComponents = useMemo(() => {
    const wrapRenderFunction = <P extends object>(
      renderFn?: (props: P) => React.ReactElement
    ): React.ComponentType<P> | undefined => {
      if (!renderFn) return undefined;
      return renderFn as React.ComponentType<P>;
    };

    return {
      PaymentMethodSelector: wrapRenderFunction(customRenderRef.current?.paymentMethodSelector) || PaymentMethodSelector,
      CardList: wrapRenderFunction(customRenderRef.current?.cardList) || CardList,
      CreditCardForm: wrapRenderFunction(customRenderRef.current?.creditCardForm) || CreditCardForm,
      InstallmentList: wrapRenderFunction(customRenderRef.current?.installmentList) || InstallmentList,
      LinkModal: wrapRenderFunction(customRenderRef.current?.linkModal) || LinkModal,
      OTPModal: wrapRenderFunction(customRenderRef.current?.otpModal) || OTPModal,
      ConfirmationModal: wrapRenderFunction(customRenderRef.current?.confirmationModal) || ConfirmationModal,
      RewardSelectionModal: wrapRenderFunction(customRenderRef.current?.rewardSelectionModal) || RewardSelectionModal
    };
  }, [
    customRender?.paymentMethodSelector,
    customRender?.cardList,
    customRender?.creditCardForm,
    customRender?.installmentList,
    customRender?.linkModal,
    customRender?.otpModal,
    customRender?.confirmationModal,
    customRender?.rewardSelectionModal
  ]);

  const hasStoredCards =
    accountData?.result?.cards && accountData.result.cards.length > 0;

  const shouldShowDirectForm =
    (accountStatus?.shouldShowDirectForm ?? false) ||
    !accountData ||
    !accountData.result?.cards ||
    accountData.result.cards.length === 0;

  const onCloseError = useCallback(() => dispatch(clearAllErrors()), [dispatch]);

  const fallbackOTPSubmit = useCallback(async () => ({ success: false }), []);

  const fullRenderProps = useMemo(() => ({
    paymentMethod,
    hasStoredCards,
    shouldShowDirectForm,
    cvc,
    error,
    isPaymentPending,
    dismissPaymentPending,

    accountData,
    accountStatus,
    modalState,
    paymentState,

    handlePaymentMethodChange,
    handleCardSelect: handleCardSelectWithErrorHandling,
    updateModalState,
    handleRemoveCard,
    confirmRemoveCard,
    handleCvcChange,
    handleSaveCard,
    handleBinChange,
    handleInstallmentSelect: handleInstallmentSelectWithErrorHandling,
    handleProceedToPayment,
    handleLinkConfirm,
    handleOTPSubmit: handleOTPSubmitWithErrorHandling || handleOTPSubmit || fallbackOTPSubmit,
    onCloseError,

    isCheckoutLoading,
    isInstallmentLoading,
    isPrepareLoading,
    isFinalizeLoading,
    isProcessingPayment,
    isRewardsQueryLoading,
    isRewardsSelectLoading,

    openRewardModal,
    closeRewardModal,
    handleConfirmRewards,
    payableAmount,

    texts: mergedTexts,

    components: memoizedComponents
  }), [
    paymentMethod,
    hasStoredCards,
    shouldShowDirectForm,
    cvc,
    error,
    isPaymentPending,
    dismissPaymentPending,
    accountData,
    accountStatus,
    modalState,
    paymentState,
    handlePaymentMethodChange,
    handleCardSelectWithErrorHandling,
    updateModalState,
    handleRemoveCard,
    confirmRemoveCard,
    handleCvcChange,
    handleSaveCard,
    handleBinChange,
    handleInstallmentSelectWithErrorHandling,
    handleProceedToPayment,
    handleLinkConfirm,
    handleOTPSubmit,
    fallbackOTPSubmit,
    onCloseError,
    isCheckoutLoading,
    isInstallmentLoading,
    isPrepareLoading,
    isFinalizeLoading,
    isProcessingPayment,
    isRewardsQueryLoading,
    isRewardsSelectLoading,
    openRewardModal,
    closeRewardModal,
    handleConfirmRewards,
    payableAmount,
    mergedTexts,
    memoizedComponents
  ]);

  if (isTokenLoading || !accountStatus || !modalState) {
    if (customRender?.loadingState) {
      return customRender.loadingState({ message: mergedTexts.loadingMessage });
    }
    return (
      <div className="flex items-center justify-center h-64">
        <div className="flex flex-col items-center gap-3">
          <div className="animate-spin rounded-full h-8 w-8 border-b-2 border-primary"></div>
          <p className="text-gray-500">{mergedTexts.loadingMessage}</p>
        </div>
      </div>
    );
  }

  if (!isScriptLoaded) {
    if (customRender?.loadingState) {
      return customRender.loadingState({
        message: mergedTexts.scriptLoadingMessage
      });
    }
    return (
      <div className="flex items-center justify-center h-64">
        <div className="flex flex-col items-center gap-3">
          <div className="animate-spin rounded-full h-8 w-8 border-b-2 border-primary"></div>
          <p className="text-gray-500">{mergedTexts.scriptLoadingMessage}</p>
        </div>
      </div>
    );
  }

  if (customRender?.fullRender) {
    return customRender.fullRender(fullRenderProps);
  }

  return (
    <div className="p-4">
      {hasStoredCards && !shouldShowDirectForm && (
        <div className="mb-6">
          {customRender?.paymentMethodSelector ? (
            customRender.paymentMethodSelector({
              cards: accountData.result.cards,
              selectedMethod: paymentMethod,
              onMethodChange: handlePaymentMethodChange,
              texts: mergedTexts
            })
          ) : (
            <PaymentMethodSelector
              cards={accountData.result.cards}
              selectedMethod={paymentMethod}
              onMethodChange={handlePaymentMethodChange}
              texts={mergedTexts}
            />
          )}
        </div>
      )}

      <div className="grid grid-cols-1 xl:grid-cols-2 gap-6 lg:gap-8">
        <div className="space-y-4">
          {paymentMethod === 'stored_card' &&
          hasStoredCards &&
          !shouldShowDirectForm ? (
            <>
              <h2 className="text-xl font-semibold mb-4">
                {mergedTexts.selectCardTitle}
              </h2>
              {customRender?.cardList ? (
                customRender.cardList({
                  cards: accountData.result.cards,
                  onCardSelect: handleCardSelectWithErrorHandling,
                  selectedCard: paymentState.selectedCard,
                  onRemove: handleRemoveCard || (() => {}),
                  removingCardId: modalState?.removingCardId,
                  cvc: cvc,
                  onCvcChange: handleCvcChange,
                  ...(enableRewards
                    ? {
                        availableRewards: paymentState.availableRewards,
                        selectedRewards: paymentState.selectedRewards,
                        isLoadingRewards:
                          paymentState.isLoadingRewards ||
                          isRewardsQueryLoading,
                        isConfirmingRewards: isRewardsSelectLoading,
                        onOpenRewardModal: openRewardModal,
                        onConfirmRewards: handleConfirmRewards,
                        rewardCurrency: stateCurrency || currency,
                        rewardPayableAmount: payableAmount
                      }
                    : {}),
                  texts: mergedTexts
                })
              ) : (
                <CardList
                  cards={accountData.result.cards}
                  onCardSelect={handleCardSelectWithErrorHandling}
                  selectedCard={paymentState.selectedCard}
                  onRemove={handleRemoveCard || (() => {})}
                  removingCardId={modalState?.removingCardId}
                  cvc={cvc}
                  onCvcChange={handleCvcChange}
                  {...(enableRewards
                    ? {
                        availableRewards: paymentState.availableRewards,
                        selectedRewards: paymentState.selectedRewards,
                        isLoadingRewards:
                          paymentState.isLoadingRewards ||
                          isRewardsQueryLoading,
                        isConfirmingRewards: isRewardsSelectLoading,
                        onOpenRewardModal: openRewardModal,
                        onConfirmRewards: handleConfirmRewards,
                        rewardCurrency: stateCurrency || currency,
                        rewardPayableAmount: payableAmount
                      }
                    : {})}
                  texts={mergedTexts}
                />
              )}
            </>
          ) : (
            <>
              <h2 className="text-xl font-semibold mb-4">
                {shouldShowDirectForm
                  ? mergedTexts.enterCardDetailsTitle
                  : mergedTexts.newCardTitle}
              </h2>
              {customRender?.creditCardForm ? (
                customRender.creditCardForm({
                  onSaveCard: handleSaveCard,
                  isLoading: isCheckoutLoading,
                  showSaveOption: !accountStatus?.isAccountNotLinked,
                  onBinChange: handleBinChange,
                  texts: mergedTexts
                })
              ) : (
                <CreditCardForm
                  onSaveCard={handleSaveCard}
                  isLoading={isCheckoutLoading}
                  showSaveOption={!accountStatus?.isAccountNotLinked}
                  onBinChange={handleBinChange}
                  texts={mergedTexts}
                />
              )}
            </>
          )}
        </div>

        <div className="space-y-4">
          <h2 className="text-xl font-semibold mb-4 xl:block hidden">
            {mergedTexts.installmentOptionsTitle}
          </h2>
          {paymentState?.installments?.length > 0 && paymentState?.cardType ? (
            customRender?.installmentList ? (
              customRender.installmentList({
                installments: paymentState.installments,
                cardType: paymentState.cardType,
                onInstallmentSelect: handleInstallmentSelectWithErrorHandling,
                selectedInstallment: paymentState.selectedInstallment,
                isLoading: isInstallmentLoading || isPrepareLoading,
                onProceedToPayment: handleProceedToPayment,
                paymentLoading:
                  isProcessingPayment ||
                  isPrepareLoading ||
                  isFinalizeLoading,
                texts: mergedTexts
              })
            ) : (
              <InstallmentList
                installments={paymentState.installments}
                cardType={paymentState.cardType}
                onInstallmentSelect={handleInstallmentSelectWithErrorHandling}
                selectedInstallment={paymentState.selectedInstallment}
                isLoading={isInstallmentLoading || isPrepareLoading}
                onProceedToPayment={handleProceedToPayment}
                paymentLoading={
                  isProcessingPayment ||
                  isPrepareLoading ||
                  isFinalizeLoading
                }
                texts={mergedTexts}
              />
            )
          ) : (
            <div className="flex items-center justify-center h-64 border-2 border-dashed border-gray-300">
              {isCheckoutLoading ? (
                <div className="flex flex-col items-center gap-3">
                  <div className="animate-spin rounded-full h-8 w-8 border-b-2 border-primary"></div>
                  <p className="text-gray-500">
                    {mergedTexts.loadingInstallmentMessage}
                  </p>
                </div>
              ) : customRender?.emptyState ? (
                customRender.emptyState({
                  paymentMethod,
                  cardNumberLength:
                    newCardFormData?.cardNumber?.replace(/\D/g, '').length || 0,
                  isCheckoutLoading
                })
              ) : (
                <div className="text-center">
                  <Icon
                    name="credit-card"
                    size={32}
                    className="mx-auto mb-3 text-gray-400"
                  />
                  {(() => {
                    if (paymentMethod === 'stored_card') {
                      return (
                        <p className="text-gray-500 text-sm">
                          {mergedTexts.selectCardMessage}
                        </p>
                      );
                    }

                    const cardNumberLength =
                      newCardFormData?.cardNumber?.replace(/\D/g, '').length ||
                      0;

                    if (cardNumberLength === 0) {
                      return (
                        <>
                          <p className="text-gray-500 text-sm">
                            {mergedTexts.enterCardMessage}
                          </p>
                          <p className="text-gray-400 text-xs mt-2">
                            {mergedTexts.enterCardSubMessage}
                          </p>
                        </>
                      );
                    } else if (cardNumberLength < 6) {
                      return (
                        <p className="text-gray-500 text-sm">
                          {mergedTexts.enterDigitsMessage}
                        </p>
                      );
                    } else {
                      return (
                        <p className="text-gray-500 text-sm">
                          {mergedTexts.noInstallmentMessage}
                        </p>
                      );
                    }
                  })()}
                </div>
              )}
            </div>
          )}
        </div>
      </div>

      {error &&
        (customRender?.errorDisplay ? (
          customRender.errorDisplay({
            error,
            onDismiss: () => dispatch(clearAllErrors()),
            getErrorInfo
          })
        ) : (
          <div className="mt-6 p-4 bg-[#fecaca] border-2 border-[#fca5a5]">
            <div>
              <h3 className="font-semibold mb-2 text-[#7f1d1d]">
                {getErrorInfo(error)?.type || mergedTexts.paymentErrorTitle}
              </h3>
              <p className="text-sm mb-3 text-[#991b1b]">
                {getErrorInfo(error)?.message ||
                  mergedTexts.paymentErrorDefaultMessage}
              </p>
              <button
                onClick={() => dispatch(clearAllErrors())}
                className="px-3 py-1 text-white text-sm transition-colors bg-[#dc2626] hover:bg-[#b91c1c]"
              >
                {mergedTexts.dismissButtonText}
              </button>
            </div>
          </div>
        ))}

      {customRender?.linkModal ? (
        customRender.linkModal({
          open: modalState?.showLinkModal ?? false,
          onClose: () => updateModalState({ showLinkModal: false }),
          onConfirm: handleLinkConfirm || (() => {}),
          texts: mergedTexts
        })
      ) : (
        <LinkModal
          open={modalState?.showLinkModal ?? false}
          onClose={() => updateModalState({ showLinkModal: false })}
          onConfirm={handleLinkConfirm || (() => {})}
          texts={mergedTexts}
        />
      )}

      {customRender?.otpModal ? (
        customRender.otpModal({
          open: modalState?.showOTPModal ?? false,
          onClose: () => updateModalState({ showOTPModal: false }),
          onSubmit: handleOTPSubmitWithErrorHandling,
          type: modalState?.otpType ?? 'OTP',
          responseCode: modalState?.verificationData?.result?.responseCode,
          description: modalState?.verificationData?.result?.description,
          texts: mergedTexts
        })
      ) : (
        <OTPModal
          open={modalState?.showOTPModal ?? false}
          onClose={() => updateModalState({ showOTPModal: false })}
          onSubmit={handleOTPSubmitWithErrorHandling}
          type={modalState?.otpType ?? 'OTP'}
          responseCode={modalState?.verificationData?.result?.responseCode}
          description={modalState?.verificationData?.result?.description}
          texts={mergedTexts}
        />
      )}

      {customRender?.confirmationModal ? (
        customRender.confirmationModal({
          open: !!modalState?.cardToDelete,
          onClose: () => updateModalState({ cardToDelete: null }),
          onConfirm: confirmRemoveCard || (() => {}),
          title: <img src={mpBlackLogo.src} alt="Masterpass" className="w-36 h-auto"/>,
          message: mergedTexts.removeCardMessage.replace(
            '{cardAlias}',
            modalState?.cardToDelete?.cardAlias || ''
          ),
          confirmText: mergedTexts.removeCardConfirmText,
          cancelText: mergedTexts.removeCardCancelText,
          isLoading: !!modalState?.removingCardId,
          loadingText: mergedTexts.removeCardLoadingText,
          texts: mergedTexts
        })
      ) : (
        <ConfirmationModal
          open={!!modalState?.cardToDelete}
          onClose={() => updateModalState({ cardToDelete: null })}
          onConfirm={confirmRemoveCard || (() => {})}
          title={<img src={mpBlackLogo.src} alt="Masterpass" className="w-36 h-auto"/>}
          message={mergedTexts.removeCardMessage.replace(
            '{cardAlias}',
            modalState?.cardToDelete?.cardAlias || ''
          )}
          confirmText={mergedTexts.removeCardConfirmText}
          cancelText={mergedTexts.removeCardCancelText}
          isLoading={!!modalState?.removingCardId}
          loadingText={mergedTexts.removeCardLoadingText}
          texts={mergedTexts}
        />
      )}

      <InformationModal
        open={modalState?.showInformationModal ?? false}
        onClose={() => updateModalState({ showInformationModal: false, informationModalData: null })}
        data={modalState?.informationModalData}
      />

      {enableRewards &&
        (customRender?.rewardSelectionModal ? (
          customRender.rewardSelectionModal({
            open: modalState?.showRewardModal ?? false,
            onClose: closeRewardModal,
            onConfirm: handleConfirmRewards,
            rewards: paymentState.availableRewards,
            selectedRewards: paymentState.selectedRewards,
            isLoading: isRewardsSelectLoading,
            currency: stateCurrency || currency,
            payableAmount,
            texts: mergedTexts
          })
        ) : (
          <RewardSelectionModal
            open={modalState?.showRewardModal ?? false}
            onClose={closeRewardModal}
            onConfirm={handleConfirmRewards}
            rewards={paymentState.availableRewards}
            selectedRewards={paymentState.selectedRewards}
            isLoading={isRewardsSelectLoading}
            currency={stateCurrency || currency}
            payableAmount={payableAmount}
            texts={mergedTexts}
          />
        ))}
    </div>
  );
};

export default MasterpassRestOption;
