import React, {useEffect, useLayoutEffect, useMemo, useRef, useState} from 'react';
import { FormGroup, Icon, InputField, LoadingBar, IconNames, Tooltip } from '@spglobal/ca-mfe-package-utils';
import { batch, useDispatch, useSelector } from 'react-redux';
import { useTranslation } from 'react-i18next';
import styles from './GovernmentSupport.scss';
import BackwardForwardButton from '../BackwardForwardButton';
import classNames from 'classnames';
import { parentAndGovernment } from '@root/store/parentAndGovernment/parentAndGovernment.selector';
import { scoringInputsResp } from '@root/store/scoringInputs/scoringInputs.selector';
import { upadateScoringInput } from '@root/store/scoringInputs/scoringInputs.reducer';
import _ from 'lodash';
import { companyDataSettingSelector } from '@root/store/companyDataSettings/companyDataSettings.selector';
import { getValueFormat, checkIsNotValidInput, addDecimalBasedOnValue, trimValueToLength,
   setDecimalLength } from '@root/utils/common';
import {
  updateParentAndGovernment,
  clearAllValidationsForGovtSupport
} from '@root/store/parentAndGovernment/parentAndGovernment.reducer';
import parentAndGovermentApi from '../ParentAdjustments/ParentGovernmentAPI';
import { positiveMetrics, stepIds, getRegexPatterns } from '@root/constants';
import WithValidation from '@root/hoc/WithValidation';
import { LoaderPosition } from '@spglobal/react-components';
import AdjustmentHeader from './../Common/AdjustmentHeader';
import FinancialStatements from '../ScoringInputs/FinancialStatements';
import useGenerateScore from '@root/hooks/useGenerateScore';
import { skipCurrentStep } from '@root/store/progressTracker/progressTracker.reducer';
import InputPopover from '../ScoringInputs/InputPopover';
import { setEditPreferences } from '@root/store/scoringSelection/scoringSelection.reducer';
import VersionFooter from '../Common/VersionFooter';
import { decimalSettings } from '@root/store/userInformation/userInformation.reducer';

const GovernmentSupport = props => {
    useGenerateScore();
    const { t } = useTranslation();
    const dispatch = useDispatch();
    const { parentGovernment, isLoading } = useSelector(parentAndGovernment);
    const { scoringInputs } = useSelector(scoringInputsResp);
    const { selectedValues } = useSelector(companyDataSettingSelector);
    const decimalValue = useSelector(decimalSettings);
    const loader = useMemo(()=> isLoading, [isLoading]);
    const [govInputData, setGovInputData] = useState([]);
    const [focusFinInput, setFocusFinInput] = useState(null);
    const exp = getRegexPatterns();
    const governmentNonFinLabelValue = {
      'GROSS_DOMESTIC_PRODUCT': t('scoringui:PCA:millions'),
      'POPULATION': t('scoringui:PCA:thousands')
    };

    const governmentData = parentGovernment?.current?.data?.government || [];
    const governmentSections = (() => {
      const sectionsObj = {};
      governmentData?.forEach((g, i) => (sectionsObj[g.groupItemCode] = i));
      return sectionsObj;
    })();
    const orginalScoringData = scoringInputs?.originalResp?.data;
    const currScoringData = scoringInputs?.currentResp?.data;

    useEffect(()=>{
      dispatch(clearAllValidationsForGovtSupport());
    }, []);

    const getFinancialParent = name => {
      const financialData = _.cloneDeep(orginalScoringData?.financial);
      let groupDetails = {};
      financialData.forEach((group, index) => {
        group?.metrics?.forEach((m, i) => {
          if(m.analyticsName === name){
            groupDetails = {
              parentIndex: index,
              metricIndex: i,
              group,
              metric: m
            };
          }
        });
      });
      return groupDetails;
    };

    const getOriginalFinValue = name => getFinancialParent(name)?.metric?.numValue || null;
    const getCurrentFinVal = name => {
      const { parentIndex, metricIndex } = getFinancialParent(name);
      return currScoringData?.financial[parentIndex]?.metrics[metricIndex]?.numValue || null;
    };

    const focusFinancialChange = (name, val) => {
      const scoringResp = _.cloneDeep(scoringInputs?.currentResp);
      const { parentIndex, metricIndex } = getFinancialParent(name);
      scoringResp.data.financial[parentIndex].metrics[metricIndex].numValue =
       ['', null].includes(val.trim()) ? null : Number(val);
      !isNaN(val) && dispatch(upadateScoringInput(scoringResp));
      setFocusFinInput(val);
    };

    const handleInputsChange = (groupIndex, metricIndex, val) => {
      const focusNonFinData = _.cloneDeep(governmentData);
      const trimvalue = typeof val === 'string' ? val.trim() : val;
      const isNotValidValue = ['', null].includes(trimvalue);
      const onlyPositiveReg = new RegExp(exp.positiveNumeric);
      const fieldName = focusNonFinData[groupIndex].metrics[metricIndex].analyticsName;
      const checkForPositives = positiveMetrics.includes(fieldName) && !isNotValidValue ? onlyPositiveReg.test(val) : true;

      const updatedData = _.cloneDeep(parentGovernment?.current);
      if(!isNaN(val) && checkForPositives){
        focusNonFinData[groupIndex].metrics[metricIndex].numValue = isNotValidValue ? null : Number(val);
        focusNonFinData[groupIndex].metrics[metricIndex].isNotValidInput = false;
      } else if (isNaN(val)){
        focusNonFinData[groupIndex].metrics[metricIndex].isNotValidInput = true;
      }
      if(focusNonFinData[groupIndex].groupItemCode === 'FOCUS_NONFINANCIALS'){
        focusNonFinData[groupIndex].metrics[metricIndex].isNotValidInput = checkIsNotValidInput(
          focusNonFinData[groupIndex].metrics[metricIndex].analyticsName, val
        );
      }
      updatedData.data.government = focusNonFinData;
      dispatch(updateParentAndGovernment(updatedData));
      if(govInputData?.length){
        const updateGovState = _.cloneDeep(govInputData);
        updateGovState[groupIndex].metrics[metricIndex].numValue = val;
        setGovInputData(updateGovState);
      } else {
        const setData = _.cloneDeep(focusNonFinData);
        setData[groupIndex].metrics[metricIndex].numValue = val;
        setGovInputData(setData);
      }
    };

    const getOriginalValue = (groupIndex, metricIndex) => {
      const originalGovermentData = parentGovernment?.original?.data?.government || [];
      return originalGovermentData[groupIndex].metrics[metricIndex].numValue;
    };

    const getCustomRegEx = (inputProps, isGovOwnerShip, isTotalRevenueOrGDP) => {
      if (isGovOwnerShip) {
        return exp.percentageNumeric;
      }
      if (positiveMetrics.includes(inputProps.name)) {
        return isTotalRevenueOrGDP ? exp.validateNumeric : exp.positiveNumeric;
      }
      return exp.validateNumeric;
    };

    const getFeedbackText = inputProps => {
      if (positiveMetrics.includes(inputProps.name)) {
        return (
          <div className={styles['negative-value-error']}>
            {t('scoringui:scoringInputs:enterValueGreaterZero')}
          </div>
        );
      }
      return '';
    };

  const [inputState, setInputState] = useState({
    inputValues: {}
  });

  const cursorPositionRef = useRef(null);
  const decimalLenRef = useRef({});
  useLayoutEffect(() => {
    if (cursorPositionRef.current) {
      const { cursorPosition, element } = cursorPositionRef.current;
      try {
        element.setSelectionRange(cursorPosition, cursorPosition);
        // eslint-disable-next-line no-empty
      } catch (err) { }
      cursorPositionRef.current = null;
    }
  }, [inputState.inputValues]);

  const getInputValue = (inputProps, isTotalRevenueOrGDP, decimalValue) => {
    if (isTotalRevenueOrGDP) {
      return addDecimalBasedOnValue(inputProps.value, decimalValue) || '';
  }
  return inputProps.value;
};

  const initializeDecimalLength = (key, inputProps, isTotalRevenueOrGDP) => {
    if (!(key in decimalLenRef.current)) {
      const decimalPart = String(inputProps.value).split('.')[1] || '';
      decimalLenRef.current[key] = isTotalRevenueOrGDP ? setDecimalLength(decimalPart, inputProps.value, decimalValue) : 2;
    }
  };

  const handleInputChange = (event, decimalValue, inputProps, givenInput, title) => {
    const value = trimValueToLength(event.target.value) ?? event.target.value;
    if (value !== event.target.value) { return; }
    const name = event.target.name;
    const key = `${name}`;
    const inputElement = event.target;
    const cursorPosition = inputElement.selectionStart;

    // Save cursor position
    cursorPositionRef.current = {
      cursorPosition,
      element: inputElement
    };

    const regex = new RegExp(exp.validateNumeric);
    const isValid = regex.test(value);
    if (!isValid) {
      inputOnChangeIcon(inputProps, givenInput, title, true);
      return;
    }

    const formatted = addDecimalBasedOnValue(value, decimalValue);
    const decimalPart = String(formatted).split('.')[1] || '';
    decimalLenRef.current[key] = setDecimalLength(decimalPart, formatted, decimalValue);


    setInputState(prevState => ({
      ...prevState,
      inputValues: { ...prevState.inputValues, [key]: value }
    }));
  };

  const inputSuffixIcon = (inputProps, givenInput, title) => (
    <span className={classNames('spg-d-inline-block spg-ml-2xs invalid-icon')}>
      <Tooltip
        width="160"
        placement="top"
        triggerElement={
          <span className="spg-ml-xs">
            <Icon color="red" icon={IconNames.CAUTION} />
          </span>
        }
      >
        <div>
          {!givenInput
            ? _.unescape(t('scoringui:scoringInputs:requiredFieldText', { fieldName: title }))
            : positiveMetrics.includes(inputProps.name) && !isNaN(givenInput)
              ? t('scoringui:scoringInputs:enterValueGreaterZero')
              : t('scoringui:scoringInputs:enterValidValueText')}
        </div>
      </Tooltip>
    </span>
  );

  const inputOnChangeIcon = (inputProps, givenInput, title, isNotValid) => (
    <span
      className={classNames('spg-d-inline-block spg-ml-2xs invalid-icon')}
      style={{ visibility: isNotValid ? 'visible' : 'hidden' }}
    >
      <Tooltip
        width="160"
        placement="top"
        triggerElement={
          <span className="spg-ml-xs">
            <Icon color="red" icon={IconNames.CAUTION} />
          </span>
        }
      >
        <div>
          {!givenInput
            ? _.unescape(t('scoringui:scoringInputs:requiredFieldText', { fieldName: title }))
            : positiveMetrics.includes(inputProps.name) && !isNaN(givenInput)
              ? t('scoringui:scoringInputs:enterValueGreaterZero')
              : t('scoringui:scoringInputs:enterValidValueText')}
        </div>
      </Tooltip>
    </span>
  );

  const inputWithLabel = (inputLabelprops: { title: any; mnemonic: any; inputProps: any;
     middleValue: any; isProp?: any }) => {
    const { title = '', mnemonic, middleValue = null, inputProps = {}, isProp = false } = inputLabelprops;
    const isGovOwnerShip = inputProps.name === 'GOVERNMENT_OWNERSHIP';
    const isTotalRevenueOrGDP = ['TOTAL_REVENUE', 'GROSS_DOMESTIC_PRODUCT'].includes(inputProps.name);
    const customRegEx = getCustomRegEx(inputProps, isGovOwnerShip, isTotalRevenueOrGDP);
    inputProps.feedbackText = getFeedbackText(inputProps);
    inputProps.value = getInputValue(inputProps, isTotalRevenueOrGDP, decimalValue);
    const key = `${inputProps.name}`;
    initializeDecimalLength(key, inputProps, isTotalRevenueOrGDP);

    if (!['', null].includes(inputProps.value)) {
      inputProps.value = Number(inputProps.value);
    }

    let givenInput = '';
    govInputData.forEach(({ metrics }) => {
      metrics.forEach(m => {
        if (m.analyticsName === inputProps.name) {
          givenInput = m.numValue;
        }
      });
    });

    inputProps.name === 'TOTAL_REVENUE' && !givenInput && (givenInput = focusFinInput);


    return (
      <div className={styles['input-wrapper']}>
        <FormGroup
          className="spg-d-flex spg-justify-between spg-align-baseline spg-px-md spg-pb-sm spg-mb-0"
          label={
            <div>
              <span className="spg-text spg-text-bold">{title}</span>
              <span className={classNames('spg-text spg-ml-xs', inputProps?.isRequired ? styles.red : styles.blue)}>
                {inputProps?.isRequired ? '*' : '(Optional)'}
              </span>
              <InputPopover description={title} mnemonic={mnemonic} analyticsName={inputProps.name} />
            </div>
          }
          inlineLabelClasses={styles['label-conatiner']}
          inlineContentClasses={classNames(styles['input-container'], 'input-field')}
          isInline={true}
        >
          <div className="spg-d-flex spg-justify-between spg-align-center">
            <div
              className={classNames(
                'spg-text spg-text-italic',
                isProp && styles['prop-green'],
                middleValue !== parseFloat(inputProps.value) && styles['opacity-3']
              )}
            >
              {!isNaN(middleValue) ? getValueFormat(middleValue, decimalLenRef.current[`${inputProps.name}`]) : middleValue}
              {isGovOwnerShip && middleValue && '%'}
            </div>
            <div className={classNames('spg-text', styles['input-field'])}>
              <InputField
                {...inputProps}
                value={inputState.inputValues[inputProps.name] ?? inputProps.value}
                showTitle={true}
                valueSuffix={['GOVERNMENT_OWNERSHIP'].includes(inputProps.name) ? '%' : null}
                feedbackText=""
                requiredFeedbackText=""
                customTextRegEx={customRegEx}
                elementProps={{ componentSize: 'small' }}
                triggerValidation={props.triggerValidation}
                validationcallback={props.validationHandler}
                {...(isTotalRevenueOrGDP && {
                  onChange: e => {
                      handleInputChange(e, decimalValue, inputProps, givenInput, title);
                  }
                })}
                suffix={inputSuffixIcon(inputProps, givenInput, title)}
                endParanthesis={true}
                {...(decimalLenRef.current[`${inputProps.name}`] !== undefined && {
                  decimalLength: decimalLenRef.current[`${inputProps.name}`],
                  fixedDecimals: true
                })}
              />
            </div>
          </div>
        </FormGroup>
      </div>
    );
  };

    const skipStep = () => {
      batch(() => {
        dispatch(skipCurrentStep({
          stepId: stepIds.ADJUSTMENTS,
          nestedStepId: stepIds.GOVERNMENT_SUPPORT
        }));
        dispatch(setEditPreferences({remove: stepIds.GOVERNMENT_SUPPORT}));
      });
    };

    return(
      <div className={classNames(styles['government-adjustment-conatiner'], 'spg-position-relative')}>
        <FinancialStatements />
        {loader ? <LoadingBar position={LoaderPosition.ABSOLUTE} /> : <div>
          <AdjustmentHeader
            wrapperClasses={classNames(styles.pageheading, 'spg-mb-md')}
            adjHeader={t('scoringui:GovernmentSupport:GovernmentSupport_title')}
            onSkip={skipStep}
          />
          <div className={styles.GSouter}>
            <div className={styles.col}>

              <div className='FCNFI'>
                <div className = {
                  classNames('spg-py-xs spg-heading spg-heading--xxsmall spg-text-center', styles['heading-box'])}>
                  <div>{t('scoringui:GovernmentSupport:focuscmpnonfininput_title')}</div>
                </div>

                <div className='spg-pb-md'>
                  {
                    governmentData[governmentSections.FOCUS_NONFINANCIALS]?.metrics.map((m, i) => inputWithLabel({
                      title: m.description,
                      mnemonic: m.mnemonic,
                      inputProps: {
                        name: m.analyticsName,
                        value: m.numValue,
                        isRequired: m.requiredType,
                        onBlur: val => handleInputsChange(governmentSections.FOCUS_NONFINANCIALS, i, val)
                      },
                      middleValue: getOriginalValue(governmentSections.FOCUS_NONFINANCIALS, i)
                    }))
                  }
                </div>

              </div>
              <div className='FCFI'>
                <div className = {
                  classNames('spg-py-xs spg-heading spg-heading--xxsmall spg-text-center', styles['heading-box'])}>
                  <div>{t('scoringui:GovernmentSupport:focuscmpfininput_title')} (
                    {t('scoringui:PCA:millions')}, {selectedValues?.currency?.value}
                    )
                  </div>
                </div>

                <div className='spg-pb-md'>
                  {
                    governmentData[governmentSections.FOCUS_FINANCIALS]?.metrics.map(m => inputWithLabel({
                      title: m.description,
                      mnemonic: m.mnemonic,
                      isProp: selectedValues?.dataSource?.value === '0',
                      inputProps: {
                        name: m.analyticsName,
                        value: getCurrentFinVal(m.analyticsName),
                        isRequired: m.requiredType,
                        onBlur: val => focusFinancialChange(m.analyticsName, val)
                      },
                      middleValue: getOriginalFinValue(m.analyticsName)
                    }))
                  }
                </div>

              </div>

            </div>
            <div className={styles.col}>
              <div className='GNFI'>
                <div className = {
                  classNames('spg-py-xs spg-heading spg-heading--xxsmall spg-text-center', styles['heading-box'])}>
                    <div>{t('scoringui:GovernmentSupport:govnonfininput_title')}</div>
                </div>

                <div className='spg-pb-md'>
                  {
                    governmentData[governmentSections.GOVT_NONFINANCIALS]?.metrics.map((m, i) => inputWithLabel({
                        title: `${m.description} (${governmentNonFinLabelValue[m.analyticsName]})`,
                        mnemonic: m.mnemonic,
                        inputProps: {
                          name: m.analyticsName,
                          value: m.numValue,
                          isRequired: m.requiredType,
                          onBlur: val => handleInputsChange(governmentSections.GOVT_NONFINANCIALS, i, val)
                        },
                        middleValue: getOriginalValue(governmentSections.GOVT_NONFINANCIALS, i)
                      })
                    )
                  }
                </div>
              </div>
              </div>

          </div>
        </div>}
        <div>
          <BackwardForwardButton />
        </div>
        <VersionFooter/>
      </div>
    );


};

export default WithValidation(parentAndGovermentApi(GovernmentSupport));
