import React, { useRef, useEffect, useMemo, useState, useCallback } from 'react';
import { makeStyles, useTheme, Tabs, Tab, CardContent, Card, LinearProgress, Badge, Tooltip, Grow } from '@material-ui/core';
import { Box } from '../../../UI/Box';
import { Typography } from '../../../UI/dataDisplay/typography/Typography';
import { CircularProgress } from '../../../UI/loading/CircularProgress';
import { Form } from '../Form';
import { useTranslation } from 'react-i18next';
import { FluentButton } from '../../../UI/inputs/buttons/FluentButton';
import { CreditCardForm } from './CreditCardForm';
import { BankAccountForm } from './BankAccountForm';
import { CreditCardIcon } from './CreditCardIcon';
import { BankIcon } from './BankIcon';
import { CashForm } from './CashForm';
import { CashIcon } from './CashIcon';
import { DisabledOverlay } from './DisableOverlay';
import { CheckIcon } from './CheckIcon';
import { LayoutUnit } from '../../../layout/LayoutUnit';
import { TabPanel } from './TabPanel';
import { useAxiosGet } from '../../useAxiosGet';
import { ConfigService } from '../../../configService';
import { stringToProps } from '../../stringUtils';
import { apiMutate } from '../../useAxiosMutate';
import { useUser } from '../../auth/useUser';
import { PaymentVendorFactoryEnum } from '../../../enums/paymentVendorFactoryEnum';
import { PaymentMethodTypeEnum } from '../../../enums/paymentMethodTypeEnum';
import grey from '@material-ui/core/colors/grey';
const useStyles = makeStyles((theme) => ({
    tab: {
        color: grey[800],
        '&.Mui-selected': {
            color: theme.palette.secondary.main,
        },
        textTransform: 'none',
        minWidth: 115,
        width: 115,
    },
    cardFullWidth: {
        width: "100%",
        minWidth: "100%",
        padding: 0,
    },
    paddingZero: {
        padding: 0,
    },
    submitControl: {
        marginLeft: '50px',
    },
    buttonProgress: {
        color: theme.palette.secondary.main,
        position: 'absolute',
        top: '50%',
        left: '50%',
        marginTop: -12,
        marginLeft: -12,
    },
    dropDownPaymentsCard: {
        padding: '20px 12px 0px 12px',
    },
    assetTypeLabel: {
        top: theme.spacing(-0.7),
    },
    formControl: {
        width: '100%',
        marginTop: '-15px',
    },
}));
/** paymentMethodIcons @type {*} */
const paymentMethodIcons = {
    'Credit Card': CreditCardIcon,
    'Cash': CashIcon,
    'eCheck': BankIcon,
    'Debit Card': CheckIcon,
};
const DEFAULT_ACCOUNT_TYPES = [
    { name: 'Checking', value: 'checking' },
    { name: 'Savings', value: 'savings' },
];
const PAYMENT_METHODS = {
    CREDIT_CARD: 'credit card',
    CASH: 'cash',
    E_CHECK: 'echeck',
    DEBIT_CARD: 'debit card'
};
/**
 * getPaymentMethodIcon
 *
 * @param {string} paymentMethodName
 * @param {boolean} isSelected
 * @param {boolean} isEnabled
 * @param {*} theme
 * @return {*}
 */
const getPaymentMethodIcon = (paymentMethodName, isSelected, isEnabled, theme) => {
    // Determine the icon color based on the selection and enablement status
    const color = isEnabled ? (isSelected ? theme.palette.secondary.main : grey[800]) : grey[400];
    // Find the corresponding icon component from the mapping
    const IconComponent = paymentMethodIcons[paymentMethodName];
    // Return null if no matching icon is found (unknown payment method)
    if (!IconComponent)
        return null;
    return (React.createElement(Badge, { color: "secondary", badgeContent: !isEnabled ? "!" : null }, React.createElement(IconComponent, { color: color })));
};
/**
 * PaymentForm Component
 *
 * This component provides a user interface for selecting and handling different payment methods.
 * It allows users to switch between available payment methods using tabs and handles the form submission process.
 * Each payment method has its own form component that is displayed based on the selected tab.
 *
 * Props:
 *   @param {PaymentMethodProps} props - Object containing the following properties:
 *     @param {string} id - Unique identifier for the payment form.
 *     @param {number} [activeTab=0] - The index of the currently active tab. Defaults to 0.  [OPTIONAL]
 *     @param {any[]} [paymentAccounts] - Array of payment accounts associated with the user. [OPTIONAL]
 *     @param {PaymentDetails} paymentDetails - Object containing details about the customer's payment information.
 *     @param {any[]} [bankAccountTypes=DEFAULT_ACCOUNT_TYPES] - Array of available bank account types, with a default value.
 *     @param {boolean} loading - Boolean flag indicating if asynchronous operations like data fetching are in progress.
 *     @param {Function} onTabChange - Function to be called when the active tab changes.
 *     @param {Function} [onFormStatusChange] - Optional function to handle status changes during form interactions.
 *     @param {Function} [onSubmitCompleted] - Optional function to be called upon successful form submission.
 *     @param {Function} presetDataRequest - Function to prepare the data request for payment processing.
 *     @param {Function} [submit] - Optional function to be called on form submission.
 *     @param {any} [children] - Optional elements to be rendered inside the form.
 *     @param {"before" | "after" | "outside"} [childrenPosition="before"] - Position of the children elements relative to the form.
 *     @param {string} [actionLabel] - Optional label for the form action button.
 *     @param {any} [render] - Optional render function for custom rendering inside the component.
 *
 * Usage:
 * The component renders tabs to switch between different payment methods and handles form interactions
 * for submitting payments. It integrates with Material-UI components to render the form and uses React hooks
 * for managing state, such as the currently active tab and form interaction data.
 *
 * The component uses the `useMemo` hook to optimize rendering performance and to handle the memoization of
 * computed payment fields. It ensures that the form submission process is smooth, even for hosted payments.
 *
 * Each payment method form (e.g., CreditCardForm, eCheckForm, etc.) is conditionally rendered based on the
 * currently selected payment method, ensuring a consistent user experience.
 *
 * Example:
 * <PaymentForm
 *   id="paymentForm"
 *   activeTab={0}
 *   paymentAccounts={accounts}
 *   paymentDetails={paymentDetails}
 *   bankAccountTypes={accountTypes}
 *   loading={isLoading}
 *   onTabChange={handleTabChange}
 *   onFormStatusChange={handleStatusChange}
 *   presetDataRequest={createDataRequest}
 *   onSubmitCompleted={handleSubmitCompleted}
 *   actionLabel="Enter Card Details"
 *   submit={handleSubmit}
 * />
 *
 * Note:
 * This component should be used within a React environment that supports hooks and functional components.
 * It relies on Material-UI for UI components and theming.
 */
export const PaymentForm = ({ id, activeTab = 0, externalId, paymentAccounts, paymentDetails, bankAccountTypes = DEFAULT_ACCOUNT_TYPES, loading, presetDataRequest, onTabChange, onFormStatusChange, onSubmitCompleted, submit, children, childrenPosition = "before", actionLabel, render }) => {
    const classes = useStyles();
    const theme = useTheme();
    const user = useUser();
    const { t } = useTranslation();
    const [value, setValue] = useState(activeTab);
    const formRef = useRef(null);
    const [paymentFormStatus, setPaymentFormStatus] = useState(null);
    const [paymentMethodsArray, setPaymentMethodsArray] = useState();
    const [selectedHostedPayment, setSelectedHostedPayment] = useState(null);
    const [selectedPaymentType, setSelectedPaymentType] = useState(PaymentMethodTypeEnum.CreditCard);
    const [loadingProcessPayment, setLoadingProcessPayment] = useState(false);
    const [selectedPaymentAccount, setSelectedPaymentAccount] = useState(null);
    // #region [API Calls]
    /**
     * API call to get the payment accounts (Credit cards, Bank accounts) associated with the account
     */
    const [{ data: paymentMethods, loading: loadingPaymentMethods }] = useAxiosGet(ConfigService.pgV1ApiUrl, `PaymentMethod`, {}, false);
    /**
     *  API call to get the payment method information and determine if the payment method is enabled or not
     *
     * @param {*} paymentMethodID : Credit card: 4001, Bank account: 4002, eCheck: 4004
     * @return {*}
     */
    const getPaymentMethodInfo = useCallback(async (paymentMethodID) => {
        if (!paymentMethodID || !(user === null || user === void 0 ? void 0 : user.currentTenantId)) {
            return;
        }
        try {
            const result = await apiMutate(ConfigService.pgV1ApiUrl, `AppPaymentVendor/PaymentMethod/${paymentMethodID}`, {
                method: 'GET',
            }, {});
            return result;
        }
        catch (error) {
            throw new Error(`Error getting payment method info: ${error === null || error === void 0 ? void 0 : error.message}`);
        }
    }, [user]);
    /**
     * API call to fetchPaymentMethod
     *
     * @param {string} currentTenantID
     * @param {string} paymentMethodId
     * @return {*}
     */
    const fetchPaymentMethod = useCallback(async (currentTenantID, paymentMethodId) => {
        if (!currentTenantID || !paymentMethodId) {
            return null;
        }
        return apiMutate(ConfigService.pgV1ApiUrl, `AppPaymentVendor/PaymentMethod/${paymentMethodId}`, {
            method: 'GET',
        }, {});
    }, []);
    /**
     * fetchPaymentMethodDetails
     *
     * @param {*} tenantID
     * @param {*} methodId
     * @return {*}
     */
    const fetchPaymentMethodDetails = useCallback(async (tenantID, methodId) => {
        const result = await fetchPaymentMethod(tenantID, methodId);
        const paymentMethod = result === null || result === void 0 ? void 0 : result.data;
        if (!paymentMethod) {
            throw new Error(`${t('Payment method configuration not found')}: ${methodId}`);
        }
        return paymentMethod;
    }, [fetchPaymentMethod]);
    /**
     * executePaymentPG
     *
     * @param {string} paymentType
     * @param {any} requestBody
     * @return {*}
     */
    const executePaymentPG = useCallback(async (paymentType, requestBody) => {
        if (!paymentType || !requestBody) {
            return null;
        }
        return apiMutate(ConfigService.pgV1ApiUrl, `ProcessPayment/${paymentType}`, {
            method: 'POST',
            data: requestBody,
        }, {});
    }, []);
    /**
     * executeHostedPaymentPG
     *
     * @param {string} paymentType
     * @param {any} requestBody
     * @return {*}
     */
    const executeHostedPaymentPG = useCallback(async (paymentType, requestBody) => {
        if (!paymentType || !requestBody) {
            return null;
        }
        const path = (requestBody === null || requestBody === void 0 ? void 0 : requestBody.paymentTokenId) ?
            `ProcessPayment/${paymentType}Profile` :
            `ProcessHostedPaymentPagePayment/${paymentType}`;
        return apiMutate(ConfigService.pgV1ApiUrl, path, {
            method: 'POST',
            data: requestBody,
        }, {});
    }, []);
    // #endregion
    // #region [Methods]
    const paymentMethodLabels = useMemo(() => ({
        "creditcard": t("Credit Card"),
        "debitcard": t("Debit Card"),
        "echeck": t("eCheck"),
        "check": t("Check"),
        "cash": t("Cash")
    }), [t]);
    /**
     * handleChange
     *
     * @param {React.ChangeEvent<{}>} event
     * @param {number} newValue
     */
    const handleChange = (event, newValue) => {
        var _a;
        event.preventDefault();
        setValue(newValue);
        const selectedPaymentMethod = paymentMethodsArray === null || paymentMethodsArray === void 0 ? void 0 : paymentMethodsArray[newValue];
        // Set selected payment method and hosted payment type
        setSelectedHostedPayment((_a = selectedPaymentMethod === null || selectedPaymentMethod === void 0 ? void 0 : selectedPaymentMethod.paymentVendorConnection) === null || _a === void 0 ? void 0 : _a.paymentVendorFactoryID);
        setSelectedPaymentType(selectedPaymentMethod === null || selectedPaymentMethod === void 0 ? void 0 : selectedPaymentMethod.paymentMethodID);
        onTabChange(event, selectedPaymentMethod);
    };
    const handleStatusChange = (paymentFormStatus) => {
        setPaymentFormStatus(paymentFormStatus);
        onFormStatusChange === null || onFormStatusChange === void 0 ? void 0 : onFormStatusChange(paymentFormStatus);
    };
    /**
     * useCallback()
     * renderPaymentMethodForm
     *
     * @param {any} method
     * @return {*}
     */
    const renderPaymentMethodForm = useCallback((method) => {
        var _a, _b, _c, _d;
        const isDisabled = !method.enabled;
        const overlayMessage = t("This Payment method is currently unavailable");
        return (React.createElement("div", { style: { position: 'relative' } }, isDisabled && React.createElement(DisabledOverlay, { message: overlayMessage }), React.createElement("div", { style: { opacity: isDisabled ? 0.5 : 1 } }, ((_a = method === null || method === void 0 ? void 0 : method.name) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === PAYMENT_METHODS.CREDIT_CARD && React.createElement(CreditCardForm, Object.assign({ onStatusChange: handleStatusChange, paymentDetails: paymentDetails, externalId: externalId, setSelectedPaymentAccount: setSelectedPaymentAccount, actionLabel: actionLabel }, method)), ((_b = method === null || method === void 0 ? void 0 : method.name) === null || _b === void 0 ? void 0 : _b.toLowerCase()) === PAYMENT_METHODS.CASH && React.createElement(CashForm, Object.assign({ onStatusChange: handleStatusChange, paymentDetails: paymentDetails }, method)), ((_c = method === null || method === void 0 ? void 0 : method.name) === null || _c === void 0 ? void 0 : _c.toLowerCase()) === PAYMENT_METHODS.E_CHECK && React.createElement(BankAccountForm, Object.assign({ bankAccountTypes: bankAccountTypes, onStatusChange: handleStatusChange, paymentDetails: paymentDetails, externalId: externalId, setSelectedPaymentAccount: setSelectedPaymentAccount, actionLabel: actionLabel }, method)), ((_d = method === null || method === void 0 ? void 0 : method.name) === null || _d === void 0 ? void 0 : _d.toLowerCase()) === PAYMENT_METHODS.DEBIT_CARD && React.createElement(CreditCardForm, Object.assign({ onStatusChange: handleStatusChange, paymentDetails: paymentDetails }, method)), " ")));
    }, [paymentDetails, bankAccountTypes]);
    /**
     * isLiveMode
     *
     * @return {*}
     */
    const isSandBoxMode = useMemo(() => {
        var _a, _b;
        const isLiveMode = ((_b = (_a = paymentMethodsArray === null || paymentMethodsArray === void 0 ? void 0 : paymentMethodsArray[value]) === null || _a === void 0 ? void 0 : _a.paymentVendorConnection) === null || _b === void 0 ? void 0 : _b.isLiveMode);
        if (isLiveMode === undefined) {
            return false;
        }
        return !isLiveMode;
    }, [paymentMethodsArray, value]);
    /**
     * getPaymentMethodLabel
     *
     * @param {*} method
     * @return {*}
     */
    const getPaymentMethodLabel = (method) => {
        var _a;
        const normalizedMethodName = ((_a = method === null || method === void 0 ? void 0 : method.name) === null || _a === void 0 ? void 0 : _a.toLowerCase().replace(/\s+/g, '')) || '';
        const methodLabel = (paymentMethodLabels === null || paymentMethodLabels === void 0 ? void 0 : paymentMethodLabels[normalizedMethodName]) || method.name;
        return methodLabel;
    };
    /**
     * setPaymentMethodsEnabled
     * take every paymentMethod (eCheck, credit card, etc) and verify if the payment methods are enabled or not
     * @return {*}
     */
    const setPaymentMethodsEnabled = useCallback(async () => {
        var _a;
        // Filter out any falsy paymentMethod values first
        const validPaymentMethods = paymentMethods === null || paymentMethods === void 0 ? void 0 : paymentMethods.filter(Boolean);
        // Use Promise.allSettled to handle both fulfilled and rejected promises
        const results = await Promise.allSettled(validPaymentMethods === null || validPaymentMethods === void 0 ? void 0 : validPaymentMethods.map(async (paymentMethod) => {
            var _a;
            try {
                const paymentMethodEnable = await getPaymentMethodInfo(paymentMethod.paymentMethodID);
                const paymentVendorConnection = ((_a = paymentMethodEnable === null || paymentMethodEnable === void 0 ? void 0 : paymentMethodEnable.data) === null || _a === void 0 ? void 0 : _a.paymentVendorConnection) || null;
                const providerType = paymentVendorConnection === null || paymentVendorConnection === void 0 ? void 0 : paymentVendorConnection.paymentVendorFactoryID;
                const hostedPaymentPageSetup = (paymentVendorConnection === null || paymentVendorConnection === void 0 ? void 0 : paymentVendorConnection.hostedPaymentPageSetup.find((x) => x.useHostedPaymentPage)) || null;
                const isHostedPaymentPage = (hostedPaymentPageSetup === null || hostedPaymentPageSetup === void 0 ? void 0 : hostedPaymentPageSetup.useHostedPaymentPage) || false;
                let providerProps = {};
                let hasReadPropertiesError = false;
                let readPropertiesMessageError = null;
                if (isHostedPaymentPage) {
                    const { error, attributes } = stringToProps(hostedPaymentPageSetup === null || hostedPaymentPageSetup === void 0 ? void 0 : hostedPaymentPageSetup.hostedPaymentPageConfig);
                    providerProps = Object.assign({ customCss: hostedPaymentPageSetup === null || hostedPaymentPageSetup === void 0 ? void 0 : hostedPaymentPageSetup.customCSS, attributes }, ((attributes === null || attributes === void 0 ? void 0 : attributes.baseUrl)
                        ? { baseUrl: attributes === null || attributes === void 0 ? void 0 : attributes.baseUrl }
                        : null));
                    hasReadPropertiesError = error ? true : false;
                    readPropertiesMessageError = error;
                }
                // Initialize returnObject with common properties
                let returnObject = {
                    paymentMethodID: paymentMethod.paymentMethodID,
                    name: paymentMethod.name,
                    enabled: (paymentMethodEnable === null || paymentMethodEnable === void 0 ? void 0 : paymentMethodEnable.status) === 200,
                    data: (paymentMethodEnable === null || paymentMethodEnable === void 0 ? void 0 : paymentMethodEnable.status) === 200
                        ? paymentMethodEnable.data
                        : null,
                    paymentVendorConnection,
                    isHostedPaymentPage,
                    providerType,
                    providerProps,
                    hasReadPropertiesError,
                    readPropertiesMessageError,
                };
                return returnObject;
            }
            catch (error) {
                console.error(`Error fetching payment method info for ${paymentMethod === null || paymentMethod === void 0 ? void 0 : paymentMethod.paymentMethodID}:`, error);
                return null;
            }
        }));
        // Filter out null results in case of errors
        const filteredResults = results
            .filter(result => result.status === 'fulfilled' && result.value !== null)
            .map((result) => result.value) || null;
        setPaymentMethodsArray(filteredResults);
        setSelectedHostedPayment(((_a = filteredResults === null || filteredResults === void 0 ? void 0 : filteredResults.find((x) => x.enabled)) === null || _a === void 0 ? void 0 : _a.providerType) || null);
    }, [paymentMethods]);
    /**
     * createHostedPaymentRequest
     *
     * @param {*} baseRequest
     * @param {*} paymentMethod
     * @return {*}
     */
    const createHostedPaymentRequest = useCallback((baseRequest, paymentMethod, paymentMethodId, selectedPaymentAccount) => {
        var _a, _b, _c, _d, _e, _f, _g, _h, _j;
        const vendorFactoryID = (_a = paymentMethod.paymentVendorConnection) === null || _a === void 0 ? void 0 : _a.paymentVendorFactoryID;
        let vendorRequest = {};
        switch (vendorFactoryID) {
            case PaymentVendorFactoryEnum.Fiserv:
                vendorRequest = Object.assign({ HostedPageToken: ((_b = paymentFormStatus === null || paymentFormStatus === void 0 ? void 0 : paymentFormStatus.payload) === null || _b === void 0 ? void 0 : _b.token) ||
                        ((_c = paymentFormStatus === null || paymentFormStatus === void 0 ? void 0 : paymentFormStatus.payload) === null || _c === void 0 ? void 0 : _c.message) }, (((_d = paymentFormStatus === null || paymentFormStatus === void 0 ? void 0 : paymentFormStatus.payload) === null || _d === void 0 ? void 0 : _d.expiry) && {
                    Expiry: (_e = paymentFormStatus === null || paymentFormStatus === void 0 ? void 0 : paymentFormStatus.payload) === null || _e === void 0 ? void 0 : _e.expiry,
                }));
                break;
            case PaymentVendorFactoryEnum.ICheck:
                if (!(paymentFormStatus === null || paymentFormStatus === void 0 ? void 0 : paymentFormStatus.isValid)) {
                    throw new Error(`${t('Payment error. Please check the form and try again')} ${paymentFormStatus === null || paymentFormStatus === void 0 ? void 0 : paymentFormStatus.errorMessage}`);
                }
                const responseObjet = JSON.parse(paymentFormStatus === null || paymentFormStatus === void 0 ? void 0 : paymentFormStatus.payload);
                vendorRequest = {
                    ResponseData: responseObjet === null || responseObjet === void 0 ? void 0 : responseObjet.transactionResponse,
                };
                break;
            case PaymentVendorFactoryEnum.Paymentus:
                const paymentTokenId = selectedPaymentAccount ? selectedPaymentAccount === null || selectedPaymentAccount === void 0 ? void 0 : selectedPaymentAccount.paymentTokenID : null;
                /* Paymentus uses a PaymentTokenId like an a Payment Account */
                vendorRequest = Object.assign(Object.assign({ NameOnAccount: (_f = paymentFormStatus === null || paymentFormStatus === void 0 ? void 0 : paymentFormStatus.payload) === null || _f === void 0 ? void 0 : _f.CardHolderName, HostedPageToken: (_g = paymentFormStatus === null || paymentFormStatus === void 0 ? void 0 : paymentFormStatus.payload) === null || _g === void 0 ? void 0 : _g.Token }, (((_h = paymentFormStatus === null || paymentFormStatus === void 0 ? void 0 : paymentFormStatus.payload) === null || _h === void 0 ? void 0 : _h.ExpiryDate) && {
                    Expiry: (_j = paymentFormStatus === null || paymentFormStatus === void 0 ? void 0 : paymentFormStatus.payload) === null || _j === void 0 ? void 0 : _j.ExpiryDate,
                })), (paymentTokenId && { PaymentTokenId: paymentTokenId }));
                break;
            default:
                break;
        }
        const request = Object.assign(Object.assign(Object.assign({}, baseRequest), { PaymentVendorFactoryID: vendorFactoryID }), vendorRequest);
        return request;
    }, [paymentFormStatus]);
    /**
     * createNonHostedPaymentRequest
     *
     * @param {*} baseRequest
     * @param {*} formData
     * @return {*}
     */
    const createNonHostedPaymentRequest = useCallback((baseRequest, formData) => {
        let dataRequest = Object.assign({}, baseRequest);
        if (selectedPaymentType === PaymentMethodTypeEnum.CreditCard) {
            Object.assign(dataRequest, setCreditCardAttr(formData));
        }
        else if (selectedPaymentType === PaymentMethodTypeEnum.eCheck) {
            Object.assign(dataRequest, setECheckAttr(formData));
        }
        return dataRequest;
    }, [selectedPaymentType]);
    /**
     * createDataRequest
     *
     * @param {*} formData
     * @param {*} paymentMethod
     * @param {*} isHostedPayment
     * @return {*}
     */
    const createDataRequest = useCallback((formData, paymentMethod, isHostedPayment, paymentMethodId, selectedPaymentAccount) => {
        const baseRequest = presetDataRequest(formData, paymentMethod, isHostedPayment);
        return isHostedPayment
            ? createHostedPaymentRequest(baseRequest, paymentMethod, paymentMethodId, selectedPaymentAccount)
            : createNonHostedPaymentRequest(baseRequest, formData);
    }, [paymentFormStatus, user, presetDataRequest, paymentDetails, selectedPaymentType]);
    /**
     * executePayment
     * Executes the payment process based on the payment method and request data.
     *
     * @param {*} paymentMethodId The ID of the payment method.
     * @param {*} dataRequest The request data for the payment.
     * @param {boolean} isHostedPayment Indicates if the payment is a hosted payment.
     * @return {*} The result of the payment execution.
     */
    const executePayment = useCallback(async (paymentMethodId, dataRequest, isHostedPayment) => {
        if (!paymentMethodId || !dataRequest) {
            throw new Error(t('Invalid payment data'));
        }
        if (typeof isHostedPayment !== 'boolean') {
            throw new Error(t('Invalid hosted payment flag'));
        }
        const paymentMethodName = PaymentMethodTypeEnum === null || PaymentMethodTypeEnum === void 0 ? void 0 : PaymentMethodTypeEnum[paymentMethodId];
        if (!paymentMethodName) {
            throw new Error(t('Unknown payment method') +
                `: ${paymentMethodId}`);
        }
        const response = isHostedPayment
            ? await executeHostedPaymentPG(paymentMethodName, dataRequest)
            : await executePaymentPG(paymentMethodName, dataRequest);
        return (response === null || response === void 0 ? void 0 : response.data) || null;
    }, [executePaymentPG, executeHostedPaymentPG]);
    /**
     * setCreditCardAttr
     *
     * @param {*} formData
     * @param {string} currentTenantID
     * @param {IPaymentMethod} paymentMethod
     * @return {*}
     */
    const setCreditCardAttr = (formData) => {
        var _a, _b;
        const expireMonth = (_a = formData.expiryDate.split('/')) === null || _a === void 0 ? void 0 : _a[0];
        const expireYear = (_b = formData.expiryDate.split('/')) === null || _b === void 0 ? void 0 : _b[1];
        const expirationDate = `20${expireYear}-${expireMonth}-01`;
        return {
            CardNumber: formData.cardNumber.replace(/\s/g, ''),
            ExpirationDate: expirationDate,
            SecurityCode: formData.cvv,
        };
    };
    /**
     * setECheckAttr
     * @param {*} formData
     */
    const setECheckAttr = (formData) => ({
        routingNumber: formData.routingNumber.replace(/\s/g, ''),
        accountNumber: formData.accountNumber.replace(/\s/g, ''),
    });
    // #endregion
    // #region [Submit]
    /**
     * submitPaymentForm
     * Processes the payment form submission.
     * @param {*} formData The form data.
     */
    const submitPaymentForm = useCallback(async (formData) => {
        var _a, _b, _c;
        if (!formData)
            return;
        setLoadingProcessPayment(true);
        const currentTenantID = user === null || user === void 0 ? void 0 : user.currentTenantId;
        const paymentMethodId = selectedPaymentType;
        if (!currentTenantID || !paymentMethodId) {
            onSubmitCompleted === null || onSubmitCompleted === void 0 ? void 0 : onSubmitCompleted(null, { error: true });
        }
        try {
            const paymentMethod = await fetchPaymentMethodDetails(currentTenantID, paymentMethodId);
            const isHostedPayment = ((_c = (_b = (_a = paymentMethod.paymentVendorConnection) === null || _a === void 0 ? void 0 : _a.hostedPaymentPageSetup) === null || _b === void 0 ? void 0 : _b[0]) === null || _c === void 0 ? void 0 : _c.useHostedPaymentPage) || false;
            const dataRequest = createDataRequest(formData, paymentMethod, isHostedPayment, paymentMethodId, selectedPaymentAccount);
            const paymentResult = await executePayment(paymentMethodId, dataRequest, isHostedPayment);
            onSubmitCompleted === null || onSubmitCompleted === void 0 ? void 0 : onSubmitCompleted(formData, paymentResult);
        }
        catch (error) {
            throw new Error("Error processing payment: " + (error === null || error === void 0 ? void 0 : error.message));
        }
        finally {
            setLoadingProcessPayment(false);
        }
    }, [paymentFormStatus, createDataRequest, selectedPaymentType, user, selectedPaymentAccount]);
    /**
     * Handles the form submission for iCheck payments.
     *
     * This function checks if the selected payment method is `ECheck` (electronic check)
     * from the `PaymentVendorFactoryEnum`. If it is, and the form reference (`formRef`) exists
     * and is currently mounted in the component, it programmatically triggers the form submission.
     *
     */
    const handleICheckPaymentFormStatus = useCallback(() => {
        var _a;
        if ((paymentFormStatus === null || paymentFormStatus === void 0 ? void 0 : paymentFormStatus.selectedHostedPayment) === PaymentVendorFactoryEnum.ICheck ||
            (paymentFormStatus === null || paymentFormStatus === void 0 ? void 0 : paymentFormStatus.selectedHostedPayment) === PaymentVendorFactoryEnum.Paymentus && (formRef === null || formRef === void 0 ? void 0 : formRef.current)) {
            (_a = formRef.current) === null || _a === void 0 ? void 0 : _a.submit();
        }
    }, [paymentFormStatus]);
    // #endregion
    // #region [Effects]
    useEffect(() => {
        setPaymentMethodsEnabled();
    }, [paymentMethods]);
    useEffect(() => {
        onFormStatusChange === null || onFormStatusChange === void 0 ? void 0 : onFormStatusChange(paymentFormStatus);
        handleICheckPaymentFormStatus();
    }, [paymentFormStatus]);
    // #endregion
    return (React.createElement(React.Fragment, null, loadingProcessPayment && (React.createElement(Box, { sx: {
            position: 'fixed',
            top: 0,
            left: 0,
            width: '100%',
            height: '100%',
            backgroundColor: 'rgba(255, 255, 255, 0.8)',
            zIndex: 9999,
            display: 'flex',
            alignItems: 'center',
            justifyContent: 'center',
        } }, React.createElement(CircularProgress, { size: "3rem", color: "primary" }))), React.createElement(Form, { id: id, onSubmit: submitPaymentForm, autocomplete: "off", render: (params) => {
            formRef.current = params === null || params === void 0 ? void 0 : params.form;
            return (React.createElement(React.Fragment, null, React.createElement(Box, { display: "flex", flexDirection: "column", style: { gap: '10px', flex: 1 } }, childrenPosition === "before" && children, React.createElement(Box, { display: "flex", flexDirection: "column", padding: "0" }, React.createElement(Tabs, { value: value, onChange: handleChange, "aria-label": t("(payment method tabs") }, paymentMethodsArray === null || paymentMethodsArray === void 0 ? void 0 : paymentMethodsArray.map((method, index) => (
            // @ts-ignore
            React.createElement(Tooltip, { key: method.paymentMethodID, title: !method.enabled ? t("This Payment method is currently unavailable") : "" }, React.createElement(Tab, { key: method.paymentMethodID, 
                //@ts-ignore
                icon: getPaymentMethodIcon(method.name, value === index, method.enabled, theme), label: getPaymentMethodLabel(method), "aria-label": getPaymentMethodLabel(method), className: classes.tab }))))), React.createElement(Card, { className: classes.cardFullWidth }, React.createElement(CardContent, { className: classes.paddingZero }, (loading || loadingPaymentMethods) && React.createElement(LinearProgress, null), React.createElement(Grow, Object.assign({ in: isSandBoxMode, style: { transformOrigin: '0 0 0', display: isSandBoxMode ? 'flex' : 'none' } }, (true ? { timeout: 800 } : {})), React.createElement(Box, { display: "flex", flexDirection: "row", justifyContent: "space-between", alignItems: "center", style: {
                    gap: '8px',
                    boxSizing: 'border-box',
                    background: '#FFF2CD',
                    borderWidth: '1px 0px',
                    borderStyle: 'solid',
                    borderColor: 'rgba(0, 0, 0, 0.12)',
                    padding: '10px',
                } }, React.createElement(Typography, { variant: "subtitle2", style: { width: '100%', textAlign: 'center' } }, t('You are currently in test mode using a Sandbox account')))), React.createElement(LayoutUnit, { unit: "xxs" }), paymentMethodsArray === null || paymentMethodsArray === void 0 ? void 0 : paymentMethodsArray.map((method, index) => (
            // @ts-ignore
            React.createElement(TabPanel, { value: value, index: index, key: method.paymentMethodID }, renderPaymentMethodForm(method)))), submit &&
                React.createElement(FluentButton, { variant: "contained", color: "secondary", disabled: false, type: "submit", className: classes.submitControl }, loading && React.createElement(CircularProgress, { size: 24, className: classes.buttonProgress }), React.createElement(Typography, null, t('Save')))))), childrenPosition === "after" && children, typeof render === 'function' ? render(params) : render), childrenPosition === "outside" && children));
        } })));
};
//# sourceMappingURL=PaymentForm.js.map