import React, { useEffect, useState } from 'react';
import { Alert, Button, Sidecar, useToast } from '@theorchard/suite-components';
import { useIdentity } from '@theorchard/suite-frontend';
import debounce from 'lodash-es/debounce';
import {
    useSendAdvancePayment,
    useUpdateWorksheetPaymentContractAdvance,
} from 'src/apollo/mutations/contract-advance';
import { useLazyWorksheetPaymentContractAdvances } from 'src/apollo/queries/payment-group-payment';
import { ADVANCE_PAYMENT_ACTIONS } from 'src/constants';
import { isResentPaymentAllowed } from 'src/utils/payment-overview';
import ContractAdmin from './contract-admin';
import FinanceAdmin from './finance-admin';
import type { WorksheetPaymentContractAdvanceQuery } from 'src/apollo/queries/payment-group-payment/__generated__/worksheet-payment-contract-advance';
import { usePayoneerOutageStatus } from '../shared/payoneer-service-outage-alert';
import { ABACUS_ACTION_STATUSES } from '@theorchard/accounting-apps-shared';

type WorksheetPaymentContractAdvance =
    WorksheetPaymentContractAdvanceQuery['worksheetPaymentContractAdvance'];

export interface AdvancePaymentApprovalSidecarProps {
    createdBy?: string;
    isFeatureAbacusCreateAndApprovePaymentsEnabled?: boolean;
    isFeatureAbacusPayoneerOutageCheckEnabled?: boolean;
    salesforceId?: string | null;
    worksheetPaymentContractAdvance:
        | WorksheetPaymentContractAdvance
        | undefined;
}

const AdvancePaymentApprovalSidecar: React.FC<
    AdvancePaymentApprovalSidecarProps
> = ({
    createdBy,
    isFeatureAbacusCreateAndApprovePaymentsEnabled,
    isFeatureAbacusPayoneerOutageCheckEnabled,
    salesforceId,
    worksheetPaymentContractAdvance,
}) => {
    const identity = useIdentity();
    const toast = useToast();
    const {
        updateWorksheetPaymentAdvance,
        loading: updateWorksheetPaymentAdvanceLoading,
    } = useUpdateWorksheetPaymentContractAdvance();
    const [formData, setFormData] = useState({
        salesforceId: salesforceId,
        salesforceIdConfirmed: false,
        fundsConfirmed: false,
    });
    const [error, setError] = useState();

    const [open, setOpen] = useState(false);
    const closeModal = () => {
        setOpen(false);
    };

    const isCreatedByTheSameUser = identity.id === createdBy;

    const worksheetPaymentContractAdvanceId =
        worksheetPaymentContractAdvance?.worksheetPaymentContractAdvanceId;

    const contractAdvancesRequestParams = {
        salesforceId: salesforceId,
        limit: 2,
        offset: 0,
    };

    const { sendPayment, loading: sendPaymentLoading } =
        useSendAdvancePayment();

    const { getWorksheetPaymentContractAdvances, data: contractAdvances } =
        useLazyWorksheetPaymentContractAdvances(contractAdvancesRequestParams);
    const salesforceIdUpdated =
        contractAdvances?.worksheetPaymentContractAdvances?.items[0]?.actionStates.find(
            state =>
                state.actionName ===
                    ADVANCE_PAYMENT_ACTIONS.SALESFORCE_ID_LINKED &&
                state.actionStatus === ABACUS_ACTION_STATUSES.COMPLETE
        );

    const actionStates = worksheetPaymentContractAdvance?.actionStates;
    const salesforceIdLinked = actionStates?.find(
        state =>
            state.actionName === ADVANCE_PAYMENT_ACTIONS.SALESFORCE_ID_LINKED &&
            state.actionStatus === ABACUS_ACTION_STATUSES.COMPLETE
    );
    const salesforceIdConfirmed = actionStates?.find(
        state =>
            state.actionName ===
                ADVANCE_PAYMENT_ACTIONS.SALESFORCE_ID_CONFIRMED &&
            state.actionStatus === ABACUS_ACTION_STATUSES.COMPLETE
    );

    const fundsConfirmed = actionStates?.find(
        state =>
            state.actionName === ADVANCE_PAYMENT_ACTIONS.FUNDS_CONFIRMED &&
            state.actionStatus === ABACUS_ACTION_STATUSES.COMPLETE
    );

    const lastModified = salesforceIdUpdated?.lastModified.slice(0, 10);
    const lastModifiedByIdentityName =
        salesforceIdUpdated?.lastModifiedByIdentity?.name;

    const debouncedUpdateWorksheet = React.useMemo(
        () =>
            debounce(variables => {
                updateWorksheetPaymentAdvance({ variables })
                    .then(async response => {
                        const salesforceId =
                            response.data?.updateWorksheetPaymentContractAdvance
                                .salesforceId;
                        salesforceId &&
                            (await getWorksheetPaymentContractAdvances({
                                variables: {
                                    ...contractAdvancesRequestParams,
                                    salesforceId: salesforceId,
                                },
                            }));
                    })
                    .catch(err => {
                        setError(err[0].message || JSON.stringify(err));
                    });
            }, 1500),
        [getWorksheetPaymentContractAdvances, updateWorksheetPaymentAdvance]
    );
    //Stop the invocation of the debounced function
    //after unmounting
    useEffect(() => {
        return () => {
            debouncedUpdateWorksheet.cancel();
        };
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, []);

    const changeHandler = (e: {
        target: { name: string; value: string | boolean };
    }) => {
        const {
            target: { name, value },
        } = e;
        setFormData({ ...formData, [name]: value });
        if (name === 'salesforceId' && worksheetPaymentContractAdvanceId) {
            const variables = {
                salesforceId: value.toString() || null,
                worksheetPaymentContractAdvanceId:
                    worksheetPaymentContractAdvanceId,
            };
            debouncedUpdateWorksheet(variables);
        }
    };

    const {
        alert,
        isPayoneerOutage,
        isLoading: isPayoneerServiceStatusLoading,
    } = usePayoneerOutageStatus({
        skip:
            !salesforceIdConfirmed ||
            !fundsConfirmed ||
            !isFeatureAbacusPayoneerOutageCheckEnabled,
    });

    const sendPaymentsAbacusEvent =
        worksheetPaymentContractAdvance?.abacusEvents?.find(
            event => event.eventName === ADVANCE_PAYMENT_ACTIONS.SEND_PAYMENTS
        );

    const resentPaymentIsAllowed =
        worksheetPaymentContractAdvance &&
        isResentPaymentAllowed(worksheetPaymentContractAdvance);

    const confirmDisabled = () => {
        if (resentPaymentIsAllowed) {
            return false;
        }
        return (
            (isCreatedByTheSameUser && !salesforceIdLinked) ||
            !fundsConfirmed ||
            sendPaymentLoading ||
            Boolean(sendPaymentsAbacusEvent)
        );
    };

    const onConfirmSendPaymentHandler = () => {
        if (worksheetPaymentContractAdvanceId) {
            const variables = {
                worksheetPaymentContractAdvanceId:
                    worksheetPaymentContractAdvanceId,
            };
            sendPayment({ variables })
                .then(() => {
                    toast('Payment has been successfully sent.');
                    closeModal();
                })
                .catch(err => {
                    setError(err[0].message || JSON.stringify(err));
                });
        }
    };

    return (
        <>
            <Button
                variant="primary"
                testId="actionButton"
                onClick={() => setOpen(true)}
            >
                Payment Approval
            </Button>

            <Sidecar
                confirmDisabled={
                    ((isPayoneerOutage || isPayoneerServiceStatusLoading) &&
                        isFeatureAbacusPayoneerOutageCheckEnabled) ||
                    confirmDisabled() ||
                    !isFeatureAbacusCreateAndApprovePaymentsEnabled
                }
                confirmTitle={
                    isCreatedByTheSameUser ? 'Finish' : 'Send to Payoneer'
                }
                isOpen={open}
                onConfirm={() => {
                    isCreatedByTheSameUser && salesforceIdLinked
                        ? closeModal()
                        : onConfirmSendPaymentHandler();
                }}
                onRequestClose={closeModal}
                testId="AdvancePaymentApprovalSidecar"
                title="Payment Approval"
            >
                <div>
                    <ContractAdmin
                        changeHandler={changeHandler}
                        disabled={Boolean(salesforceIdConfirmed)}
                        salesforceId={formData.salesforceId}
                        updateWorksheetPaymentAdvanceLoading={
                            updateWorksheetPaymentAdvanceLoading
                        }
                        worksheetContractAdvancesTotalCount={
                            contractAdvances?.worksheetPaymentContractAdvances
                                .totalCount
                        }
                        lastModified={lastModified}
                        lastModifiedByIdentityName={lastModifiedByIdentityName}
                        isFeatureAbacusCreateAndApprovePaymentsEnabled={
                            isFeatureAbacusCreateAndApprovePaymentsEnabled
                        }
                    />
                    <FinanceAdmin
                        salesforceIdConfirmed={salesforceIdConfirmed}
                        fundsConfirmed={fundsConfirmed}
                        isDisabled={
                            isCreatedByTheSameUser || !salesforceIdLinked
                        }
                        worksheetPaymentContractAdvanceId={
                            worksheetPaymentContractAdvanceId
                        }
                        isFeatureAbacusCreateAndApprovePaymentsEnabled={
                            isFeatureAbacusCreateAndApprovePaymentsEnabled
                        }
                    />
                    {salesforceIdConfirmed && fundsConfirmed && alert}
                    {error && <Alert text={error} variant="error" />}
                </div>
            </Sidecar>
        </>
    );
};

export default AdvancePaymentApprovalSidecar;
