import { useGetCompanyDatesMutation } from '@root/apis/financialStatementApi';
import {
    useGetPandGInputsMutation, useGetParentInfoMutation
} from '@root/apis/parentAndGovermentApi';
import { dataSourceConstants, platforms } from '@root/constants';
import { companyDataSettingSelector } from '@root/store/companyDataSettings/companyDataSettings.selector';
import { ciCompanySelectedData, isRetainValues,
    companyInformation } from '@root/store/companyInformation/companyInformation.selector';
import { fetchParent, fetchParentCompany, fetchPeriodDates,
    fetchparentAndGovernment,
    selectedParentDataInputs,
    fetchOnlyparent,
    updateParentAndGovernment } from '@root/store/parentAndGovernment/parentAndGovernment.reducer';
import { parentAndGovernment } from '@root/store/parentAndGovernment/parentAndGovernment.selector';
import { setEnableNext } from '@root/store/progressTracker/progressTracker.reducer';
import { NotificationTypeWrapper } from '@spglobal/ca-mfe-package-utils';
import { addNotificationWrapper, useToastNotification } from '@spglobal/ca-mfe-package-utils/dist/hooks';
import React, { useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { batch, useDispatch, useSelector } from 'react-redux';
import { decimalSettings } from '@root/store/userInformation/userInformation.reducer';
import { addDecimalBasedOnValue } from '@utils/common';
import _ from 'lodash';

const getPeriodDateOption = (type, resp) => ({
    ...resp,
    label: type === 'LTM' ? resp?.periodDate : resp?.fiscalYear,
    value: type === 'LTM' ? resp?.periodDate : resp?.fiscalYear
});

let prevSessionData = {};

const formatNumValue = (numValue, decimalValue) => addDecimalBasedOnValue(numValue, decimalValue) || '';

const parentAndGovermentApi = Component => function ParentGovernmentAPI (props) {
    const dispatch = useDispatch();
    const { t } = useTranslation();
    const { parentInfo,
        parentGovernment,
        parentCompany,
        selectedDataInputs,
        missingFocusFinInputs } = useSelector(parentAndGovernment);
    const { selectedValues } = useSelector(companyDataSettingSelector);
    const companySelectedData = useSelector(ciCompanySelectedData);
    const { companyData } = useSelector(companyInformation);
    const decimalValue = useSelector(decimalSettings);
    const [getCompanyDates] = useGetCompanyDatesMutation();
    const [getPandGInputs] = useGetPandGInputsMutation();
    const [getParentInfo] = useGetParentInfoMutation();
    const { addNotification } = useToastNotification();
    const { isPropCompany, isUnlinkCompany, isUnlinkPropCompany, companyId, csCompanyId } = companyData;
    const scoreDate = selectedValues?.scoreDate;
    const asOfDate = selectedValues?.asOfDate;
    const { periodType, dataSource, periodDate, currency } = selectedDataInputs;
    const parentPeriodType = periodType?.label || parentInfo.periodType || selectedValues?.periodType?.label;
    const parentCompanyId = parentCompany?.value || null;
    const isUnlinkDS = isUnlinkCompany || isUnlinkPropCompany;
    const lastPayload = parentGovernment?.current?.lastPayload;
    const dataInputProp = selectedValues?.dataSource?.value === '0' || isPropCompany;
    const [firstLoad, setFirstLoad] = useState(true);
    const [preventCall, setPreventCall] = useState(true);
    const retainValues = useSelector(isRetainValues);

    const retainUserInputs = (resp, secondLoad = false) => {
        const parentResp = resp?.data?.parent.length ? _.cloneDeep(resp.data.parent) : [];
        let governmentResp = resp?.data?.government ? _.cloneDeep(resp.data.government) : [];
        const nonFinPgMetricsResp = resp?.data?.nonFinPgMetrics ? _.cloneDeep(resp.data.nonFinPgMetrics) : [];
        const oldParentData = prevSessionData?.original?.data;
        const updatedParentData = prevSessionData?.current?.data;

        const getUserInput = (section, gI, mI, val, altValue) => {
            const oldValue = oldParentData[section] && oldParentData[section][gI]?.metrics[mI][val];
            const newValue = updatedParentData[section] && updatedParentData[section][gI]?.metrics[mI][val];
            return ![null, undefined].includes(newValue) && oldValue !== newValue ? newValue : altValue;
        };

        if(secondLoad) {
            updatedParentData?.parent.forEach(p => {
                const finIndex = parentResp.findIndex(i => i.groupItemCode === p.groupItemCode);
                finIndex === -1 && parentResp.push(_.cloneDeep(p));
            });
            governmentResp = _.cloneDeep(updatedParentData?.government);
        }

        try{
            parentResp?.forEach((group, groupIndex) => {
                group?.metrics?.forEach((m, mi)=>{
                    if(m.metricDropDown) {
                        m.strValue = getUserInput('parent', groupIndex, mi, 'strValue', m.strValue);
                    }
                    if(!m.metricDropDown) {
                        m.numValue = getUserInput('parent', groupIndex, mi, 'numValue',
                        formatNumValue(m.numValue, decimalValue));
                    }
                    if(m.analyticsName === 'SUPPORT_EXPECTATION'){
                        m.strValue = getUserInput('parent', groupIndex, mi, 'strValue', m.strValue);
                    }
                });
            });

            nonFinPgMetricsResp?.forEach((group, groupIndex) => {
                group?.metrics.forEach((m, mi) => {
                    m.numValue = getUserInput('nonFinPgMetrics', groupIndex, mi, 'numValue',
                        formatNumValue(m.numValue, decimalValue));
                });
            });

            governmentResp?.forEach((group, groupIndex) => {
                group?.metrics.forEach((m, mi) => {
                    m.numValue = getUserInput('government', groupIndex, mi, 'numValue',
                        formatNumValue(m.numValue, decimalValue));
                });
            });

        } catch (err) {
            console.log(err);
        }

        return {...resp,
            data: { parent: parentResp, government: governmentResp, nonFinPgMetrics: nonFinPgMetricsResp}
        };
    };
    const parentInfoApiCall = async () => {
        dispatch(setEnableNext(false));
        const payload = {
            scoreDate,
            'period': {
                'periodType': selectedValues?.periodType?.label,
                'quarter': selectedValues?.financialStatement?.fiscalQuarter,
                'year': selectedValues?.financialStatement?.fiscalYear
            },
            ...(!isUnlinkCompany && { companyId }),
            ...(dataInputProp && { datasource: platforms.CIQPROP }),
            ...(csCompanyId && { csCompanyId })
        };

        if(retainValues && Object.keys(parentCompany).length && parentCompany?.label !== null ){
            companyDatesCall();
                    } else {
            const resp = await getParentInfo(payload);
            if(resp?.data?.noData || resp?.data?.error){
                addNotificationWrapper(t('scoringui:errorNotificationMsg'), NotificationTypeWrapper.ERROR, addNotification);
            } else {
                const parentRespObj = {...resp.data, label: resp.data.parentCompanyName, value: resp.data.parentCompanyId};
                dispatch(fetchParentCompany(parentRespObj));
                companyDatesCall({...resp.data, propLoad: dataInputProp &&
                     resp.data.parentCompanyId && resp.data.parentCompanyName});
                            }
        }
    };

    const companyDatesCall = async (parentInfo = {}) => {
        dispatch(setEnableNext(false));

        const parentInfoDate = {
            periodDate: parentInfo?.periodDate,
            periodType: parentInfo?.periodType,
            periodQuarter: parentInfo?.periodQuarter,
            periodYear: parentInfo?.periodYear,
            currencyIso: parentInfo?.currencyIso,
            label: parentInfo?.periodType === 'LTM' ? parentInfo?.periodDate : parentInfo?.periodYear,
            value: parentInfo?.periodType === 'LTM' ? parentInfo?.periodDate : parentInfo?.periodYear
        };

        const isProp = parentInfo?.propLoad || dataSource?.value === '0';
        const companyId = parentCompanyId || parentInfo?.parentCompanyId;
        const payload = {
            periodType: parentPeriodType,
            asOfDate,
            companyId,
            withoutFin: false,
            ...(isProp ? { datasource: platforms.CIQPROP }
                : ((isUnlinkDS && !companyId) ? { datasource: platforms.CIQUNLINK }
                    : { datasource: platforms.CIQ }))
        };

        const resp = await getCompanyDates(payload);
        const selectedInputs = _.cloneDeep(selectedDataInputs);

        if(resp?.data?.error){
            addNotificationWrapper(t('scoringui:errorNotificationMsg'), NotificationTypeWrapper.ERROR, addNotification);
        } else {
            if(resp?.data?.dateValue){

                const datesList = [...resp.data.dateValue];
                const selectedFinStatement = (()=>{
                    if(!selectedDataInputs?.periodDate){
                        const findDate = resp?.data?.dateValue[0];
                        return findDate ? getPeriodDateOption(parentPeriodType, findDate) :
                            getPeriodDateOption(parentPeriodType, resp?.data?.dateValue[0]);
                    }
                    const checkPeriodExist = resp?.data?.dateValue.findIndex(d => (
                        d.periodDate === selectedDataInputs?.periodDate?.periodDate));
                    if(Object.keys(selectedDataInputs.periodDate).length &&
                        selectedDataInputs.periodDate.periodDate === parentCompany?.periodDate &&
                        selectedDataInputs.periodDate.periodType === parentCompany?.periodType &&
                        selectedDataInputs.periodDate.periodType === datesList[0]?.periodType &&
                        selectedDataInputs?.dataSource?.value === '0' &&
                        checkPeriodExist === -1){
                        datesList.unshift({
                            periodDate: selectedDataInputs?.periodDate?.periodDate,
                            currencyIso: selectedDataInputs?.periodDate?.currencyIso,
                            restatementType: selectedDataInputs?.periodDate?.restatementType,
                            fiscalYear: selectedDataInputs?.periodDate?.periodYear,
                            fiscalQuarter: selectedDataInputs?.periodDate?.periodQuarter,
                            periodType: selectedDataInputs?.periodDate?.periodType,
                            ...selectedDataInputs?.periodDate
                        });
                    }
                    return getPeriodDateOption(parentPeriodType, datesList[0]);
                })();
                const getPeriodDate = parentInfo?.periodDate ? parentInfoDate : selectedFinStatement;
                const removeCurrency = args => {
                    if(args?.currency){
                        // eslint-disable-next-line @typescript-eslint/no-unused-vars
                        const {currency, ...obj} = args;
                        return obj;
                    }
                    return args;
                };
                const isParent = datesList[0]?.currencyIso || Array.isArray(parentCompany) ?
                    removeCurrency({...selectedDataInputs}) : {...selectedDataInputs};
                if(Array.isArray(parentCompany) && selectedDataInputs?.dataSource?.value === '0'){
                    isParent.dataSource = {...dataSourceConstants[0]};
                }
                (()=>{
                    if(parentInfo?.parentCompanyId && parentInfo?.parentCompanyName && parentInfo?.propLoad){
                        isParent.dataSource = {...dataSourceConstants[1]};
                    }
                })();
                setPreventCall(false);
                dispatch(selectedParentDataInputs({...isParent, periodDate: getPeriodDate}));
                dispatch(fetchPeriodDates(datesList || [...getPeriodDate]));
                Array.isArray(parentCompany) && dispatch(fetchParentCompany({}));
            } else {
                const selectedInputs = {...selectedDataInputs};
                (()=>{
                    selectedInputs.periodDate = parentInfo?.periodDate ? parentInfoDate : {};
                    if(parentInfo?.parentCompanyId &&
                        parentInfo?.parentCompanyName &&
                        parentInfo?.propLoad
                        ){
                        selectedInputs.dataSource = {...dataSourceConstants[1]};
                    }
                })();
                setPreventCall(false);
                dispatch(selectedParentDataInputs({...selectedInputs}));
                dispatch(fetchPeriodDates(parentInfo?.periodDate ? [parentInfoDate] : []));
            }
            firstLoad && parentAndGovernAPiCall(parentInfo,
                Boolean(resp?.data?.dateValue?.length) && resp?.data?.dateValue[0] || []);
            setFirstLoad(false);
        }
    };

    const parentAndGovernAPiCall = async (parentInfo = {}, latestDate={}) => {
        dispatch(setEnableNext(false));
        Object.keys(parentGovernment?.original).length && dispatch(fetchParent());
        const savePayload = {
            asOfDate,
            'periodType': selectedValues?.periodType?.label,
            'quarter': selectedValues?.financialStatement?.fiscalQuarter,
            'year': selectedValues?.financialStatement?.fiscalYear,
            'country': companySelectedData?.country?.value,
            'industry': companySelectedData?.industry?.value,
            'currencyCode': selectedValues?.currency?.value,
            'dataSource': selectedValues?.dataSource?.value
        };
        const initialLoad = lastPayload?.asOfDate !== asOfDate || lastPayload?.periodType !== savePayload?.periodType ||
            lastPayload?.quarter !== savePayload?.quarter || lastPayload?.year !== savePayload?.year ||
            lastPayload?.country !== savePayload?.country || lastPayload?.industry !== savePayload?.industry ||
            lastPayload?.currencyCode !== savePayload?.currencyCode;
        const getParentLoad = () => ({
                'parentCompanyId': parentInfo?.parentCompanyId || parentCompany?.value || null,
                'parentCompanyName': parentInfo?.parentCompanyName || parentCompany?.label || null,
                'currencyCode': parentInfo?.currencyIso || currency?.value,
                'periodType': parentInfo?.periodType || periodDate?.periodType,
                'periodQuarter': parentInfo?.periodQuarter || periodDate?.fiscalQuarter,
                'periodYear': parentInfo?.periodYear || periodDate?.fiscalYear,
                'periodDate': parentInfo?.periodDate || periodDate?.periodDate
            });
        const parentreq= {...getParentLoad()};
        if(initialLoad){
            (()=>{
                if(!parentreq.currencyCode && parentInfo?.parentCompanyId) {
                    parentreq.currencyCode = latestDate?.currencyIso || selectedValues?.currency?.value;}
                if(!parentreq.periodType) {
                    parentreq.periodType = latestDate?.periodType || selectedValues?.periodType?.label;}
                if(!parentreq.periodQuarter) {
                    parentreq.periodQuarter = latestDate?.fiscalQuarter
                     || selectedValues?.financialStatement?.fiscalQuarter;}
                if(!parentreq.periodYear) {
                    parentreq.periodYear = latestDate?.fiscalYear || selectedValues?.financialStatement?.fiscalYear;}
                if(!parentreq.periodDate) {
                    parentreq.periodDate = latestDate?.periodDate || selectedValues?.financialStatement?.periodDate;}
            })();
        }
        const isProp = parentInfo?.propLoad || dataSource?.value === '0';
        const payload = {
            'settings': {
                'periodType': selectedValues?.periodType?.label,
                'countryIsoCode': companySelectedData?.country?.value,
                'industryCode': companySelectedData?.industry?.value,
                'periodQuarter': selectedValues?.financialStatement?.fiscalQuarter,
                'periodYear': selectedValues?.financialStatement?.fiscalYear,
                'currencyCode': selectedValues?.currency?.value,
                initialLoad,
                asOfDate,
                'focusMetrics': missingFocusFinInputs,
                'parentRequest': parentreq,
                'numberOfDecimalPlaces' : decimalValue
            },
            ...(isProp && { datasource: platforms.CIQPROP }),
            ...(!isUnlinkCompany && { companyId }),
            ...(csCompanyId && { csCompanyId })
        };

        try {
            const resp = await getPandGInputs(payload);
            if (!resp?.data || resp?.data?.error) {
                addNotificationWrapper(t('scoringui:errorNotificationMsg'), NotificationTypeWrapper.ERROR, addNotification);
            } else {
                if (retainValues && Object.keys(parentGovernment?.current).length) {
                    prevSessionData = parentGovernment;
                }
                if (Object.keys(parentGovernment?.original).length && !initialLoad) {
                    batch(() => {
                        dispatch(fetchOnlyparent({ ...resp?.data, lastPayload: savePayload }));
                        if (retainValues && parentGovernment?.current) {
                            dispatch(updateParentAndGovernment(
                                retainUserInputs({ ...resp?.data, lastPayload: savePayload }, true)
                            ));
                        }
                    });
                } else {
                    batch(() => {
                        dispatch(fetchparentAndGovernment({ ...resp?.data, lastPayload: savePayload }));
                        if (retainValues && Object.keys(parentGovernment?.current).length) {
                            dispatch(updateParentAndGovernment(
                                retainUserInputs({ ...resp?.data, lastPayload: savePayload })
                            ));
                        }
                    });
                }
            }
        } catch (err) {
            console.log(err);
        }

        dispatch(setEnableNext(true));
      };

      useEffect(()=>{
        if(!Object.keys(parentCompany).length ||
            lastPayload?.asOfDate !== asOfDate ||
            lastPayload?.periodType !== selectedValues?.periodType?.label ||
            lastPayload?.quarter !== selectedValues?.financialStatement?.fiscalQuarter ||
            lastPayload?.year !== selectedValues?.financialStatement?.fiscalYear ||
            lastPayload?.dataSource !== selectedValues?.dataSource?.value ){
               parentInfoApiCall();
        } else {
            setFirstLoad(false);
            setPreventCall(false);
        }
      }, []);

      useEffect(()=>{
        if(!firstLoad && (lastPayload?.periodType !== selectedValues?.periodType?.label ||
            lastPayload?.asOfDate !== asOfDate)){
            companyDatesCall();
        }
        if(!firstLoad) {
            companyDatesCall();
        }
      }, [parentCompany, periodType, dataSource]);

      useEffect(()=>{
        const payLoadChangesCheck = (lastPayload?.country !== companySelectedData?.country?.value ||
            lastPayload?.industry !== companySelectedData?.industry?.value ||
            lastPayload?.currencyCode !== selectedValues?.currency?.value);

        if((Object.keys(parentCompany).length && payLoadChangesCheck && preventCall)) {
            parentAndGovernAPiCall();
            setPreventCall(false);
        }
        !firstLoad && !preventCall && parentAndGovernAPiCall();
      }, [periodDate, currency]);

    return <Component {...props}/>;
};

export default parentAndGovermentApi;
