import React, { useContext, useEffect, useState } from 'react';
import { Field, Select } from '@theorchard/suite-components';
import { useParams } from 'react-router-dom';
import { AbacusContractType } from 'src/apollo/definitions/globalTypes';
import { useContractTermsByContractId } from 'src/apollo/queries/contract-term';
import { PopupModal } from 'src/components/shared/popup-modal';
import {
    ADD_CONTRACT_TERM_CONDITION,
    DELETE_ALL_TERM_CONDITIONS,
    EMPTY_TERM_CONDITIONS,
    SET_ERRORS,
} from 'src/constants';
import { ContractTermContext } from 'src/contexts/contract-term-context';
import useContractSearch from 'src/hooks/contract-search';
import { formatConditions } from 'src/utils/contract-terms';
import { copyContractTermConditionsFormValidations } from 'src/utils/form-validations/contract-term-form-validation';
import type {
    AbacusDistroContractTermCondition,
    AbacusNrContractTermCondition,
} from 'src/types/abacus-contract-term';

export interface CopyTermConditionsFormPopupPropType {
    contractType: AbacusContractType;
    isCopyConditionsModalOpen: boolean;
    setIsCopyConditionsModalOpen: any;
}

export const CopyTermConditionsFormPopup: React.FC<
    CopyTermConditionsFormPopupPropType
> = ({
    contractType,
    isCopyConditionsModalOpen,
    setIsCopyConditionsModalOpen,
}) => {
    const { contractTermId: currentContractTermId } = useParams<{
        contractTermId: string;
    }>();
    const { state, dispatch } = useContext(ContractTermContext);

    const [contractTermsConditions, setContractTermsConditions] = useState<any>(
        {}
    );
    const [contractTermId, setContractTermId] = useState<string>('');
    const [contractTermsDropdownOptions, setContractTermsDropdownOptions] =
        useState<{ label: string; value: string }[]>([]);
    const [isCopyingConditions, setIsCopyingConditions] =
        useState<boolean>(false);

    const isDistroContract = contractType === AbacusContractType.DISTRIBUTION;
    const isNRContract =
        contractType === AbacusContractType.NEIGHBOURING_RIGHTS;
    const isSaveButtonDisabled =
        isCopyingConditions || (isDistroContract && !contractTermId);

    const saveButtonText = () => {
        if (isDistroContract) {
            return isCopyingConditions ? 'Copying' : 'Copy';
        } else {
            return 'Update';
        }
    };

    const {
        data: contractTerms,
        error: contractTermsError,
        getContractsTermsByContractId,
    } = useContractTermsByContractId();

    const {
        contractId,
        renderContractSearch,
        renderDefaultOption,
        clearSelect,
    } = useContractSearch({
        className: 'contractSearch',
        clearable: true,
        selectedOption: state?.contract?.contractId
            ? {
                  label: `(Current) ${state?.contract?.contractName} - ${state?.contract?.contractId}`,
                  value: state?.contract?.contractId,
              }
            : '',
        contractSearchResults: state?.contract?.contractId
            ? [
                  {
                      label: `(Current) ${state?.contract?.contractName} - ${state?.contract?.contractId}`,
                      value: state?.contract?.contractId,
                  },
              ]
            : [],
        placeholder: 'Search By Contract Name or ID',
        contractType,
    });

    useEffect(() => {
        isNRContract && renderDefaultOption();
    }, [state?.contract?.contractId]);

    useEffect(() => {
        if (contractTermsError?.message)
            dispatch({
                type: SET_ERRORS,
                error: [contractTermsError?.message],
            });
    }, [contractTermsError]);

    useEffect(() => {
        dispatch({ type: SET_ERRORS, error: [] });
        if (contractId) getContractsTermsByContractId(contractId);
    }, [contractId]);

    useEffect(() => {
        setContractTermId('');
        setContractTermsDropdownOptions([]);
        setContractTermsConditions({});

        if (contractId && contractTerms && contractTerms?.abacusContractTerms) {
            const options: { label: string; value: string }[] = [];
            let termConditions: any = {};
            contractTerms.abacusContractTerms.forEach(contractTerm => {
                if (currentContractTermId === contractTerm.contractTermId)
                    return;

                const label: string = contractTerm.contractTermName
                    ? `${contractTerm.contractTermName} - ${contractTerm.contractTermId}`
                    : `${contractTerm.contractTermId}`;

                options.push({
                    label: label || '',
                    value: contractTerm.contractTermId,
                });
                termConditions = {
                    ...termConditions,
                    [contractTerm.contractTermId]: contractTerm.conditions,
                };
            });
            setContractTermsDropdownOptions(options);
            setContractTermsConditions(termConditions);
        }
    }, [contractTerms, contractId]);

    const updateHandler = () => {
        const { countryCodes, storeIds, transactionTypeIds } = state;
        const validationErrors = copyContractTermConditionsFormValidations({
            contractId,
            contractTermId,
        });

        if (Object.keys(validationErrors).length > 0) {
            dispatch({ type: SET_ERRORS, error: validationErrors });
            return false;
        }

        setIsCopyingConditions(true);

        if (isDistroContract) {
            const copyTermConditions = contractTermsConditions[contractTermId];

            copyTermConditions.forEach(
                (condition: AbacusDistroContractTermCondition) => {
                    const conditionRow = {
                        contractTermConditionName:
                            condition.contractTermConditionName,
                        conditions: formatConditions(
                            condition?.conditions,
                            countryCodes,
                            storeIds,
                            transactionTypeIds
                        ),
                        priority: condition.priority + state.conditions.length,
                        termRate: condition.termRate,
                    };
                    dispatch({
                        type: ADD_CONTRACT_TERM_CONDITION,
                        condition: conditionRow,
                    });
                }
            );
        } else if (isNRContract) {
            dispatch({
                type: DELETE_ALL_TERM_CONDITIONS,
                deleteTermConditions: state.conditions,
            });

            dispatch({ type: EMPTY_TERM_CONDITIONS });

            const copyTermConditions = contractTermsConditions[contractTermId];

            copyTermConditions.forEach(
                (condition: AbacusNrContractTermCondition) => {
                    const conditionRow = {
                        contractTermConditionName:
                            condition.contractTermConditionName,
                        conditions: formatConditions(
                            condition?.conditions,
                            countryCodes,
                            storeIds,
                            transactionTypeIds
                        ),
                        priority: condition.priority,
                        commission: String(condition.commission),
                    };
                    dispatch({
                        type: ADD_CONTRACT_TERM_CONDITION,
                        condition: conditionRow,
                    });
                }
            );
        }

        setIsCopyingConditions(false);
        setIsCopyConditionsModalOpen(false);
        renderDefaultOption();
        setContractTermId('');
    };

    useEffect(() => {
        if (!isCopyConditionsModalOpen && isDistroContract) clearSelect();
    }, [isCopyConditionsModalOpen]);

    const headerLabel = (
        <h3
            className={`CopyTermCondition-popup-header ReactModal-popup-header ${contractType.toLocaleLowerCase()}`}
        >
            {isNRContract
                ? 'Copy Term Conditions From Another Term'
                : 'Copy Conditions From...'}
        </h3>
    );

    const modelContent = (
        <>
            {isDistroContract && (
                <Field
                    controlId="contractTermCopyConditionsText"
                    labelText=""
                    testId="contractTermCopyConditionsText"
                >
                    You can copy conditions from any other contract. They will
                    be added to the <br /> Terms currently open on this page.
                </Field>
            )}
            <Field
                controlId="contractTermCopyConditionsFromContract"
                labelText={isNRContract ? 'From Contract ...' : 'Contract'}
                testId="contractTermCopyConditionsFromContract"
                message={
                    state.errors['contract']
                        ? {
                              type: 'error' as const,
                              text: state.errors['contract'],
                          }
                        : undefined
                }
            >
                {renderContractSearch()}
            </Field>
            <Field
                controlId="contractTermCopyConditionsFromTerm"
                labelText={isNRContract ? 'From Term ...' : 'Term'}
                testId="contractTermCopyConditionsFromTerm"
                message={
                    state.errors['contract-term']
                        ? {
                              type: 'error' as const,
                              text: state.errors['contract-term'],
                          }
                        : undefined
                }
            >
                <Select
                    id="contractTermsDropdown"
                    options={contractTermsDropdownOptions}
                    placeholder="Select Term"
                    onChange={(e: any) =>
                        e && e.value
                            ? setContractTermId(e.value)
                            : setContractTermId('')
                    }
                    menuWidth="100%"
                    disabled={!contractId}
                    value={contractTermId}
                />
            </Field>
        </>
    );

    return (
        <PopupModal
            className="CopyTermCondition-popup"
            closeHandler={() => {
                setIsCopyConditionsModalOpen(false);
                isNRContract ? renderDefaultOption() : clearSelect();
                setContractTermId('');
            }}
            headerLabel={headerLabel}
            isOpen={isCopyConditionsModalOpen}
            isSaveButtonDisabled={isSaveButtonDisabled}
            isSaving={isCopyingConditions}
            modalContent={modelContent}
            saveButtonText={saveButtonText()}
            saveHandler={() => updateHandler()}
        />
    );
};
