import { trackerStatus, stepProgressDirection, financialsType, stepIds } from '@root/constants';

const updateEPDSteps = (state, payload) => {
  const { steppers, initProgressSteps } = state;
  const stepperList = [...steppers];
  const scoringinputIndex = stepperList.findIndex(item => item.stepId === stepIds.SCORING_INPUTS);
  if (payload?.financialType === financialsType.WithoutFinancials) {
    if (scoringinputIndex > -1) {
      stepperList.splice(scoringinputIndex, 1);
    }
  } else if (payload?.financialType === financialsType.WithFinancials || ![undefined, '2'].includes(payload?.compType)) {
    if (scoringinputIndex < 0) {
      stepperList.splice(2, 0, initProgressSteps[2]);
    }
  }
  return stepperList;
};

export const updateProgressTrackerState = (state, selectedStep) => {
  const steppers = updateEPDSteps(state, selectedStep);
  return steppers?.map(items => {
    const { stepId, nestedSteps } = items;
    if (stepId === selectedStep.stepId) {
      if (nestedSteps?.length) {
        const updatedNestedSteps = nestedSteps.map(nestedItems => (nestedItems.stepId === selectedStep.nestedStepId) ? {
          ...nestedItems,
          showStep: selectedStep.showStep,
          isDisabled: selectedStep.isDisabled,
          isTileDisplay: (typeof selectedStep?.isTileDisplay === 'boolean')
            ? selectedStep.isTileDisplay : nestedItems.isTileDisplay,
          status: selectedStep?.status
            ? selectedStep.status
            : (selectedStep.showStep ? trackerStatus.SELECTED : trackerStatus.NOT_SELECTED)
        } : nestedItems);
        const isSelectedItemsEnabled = updatedNestedSteps.filter(
          ({ status }) => status === trackerStatus.SELECTED).length;
        const isActiveNestedItems = updatedNestedSteps.filter(
          ({ status }) => status === trackerStatus.ACTIVE).length;
        const isCompletedNestedSteps = updatedNestedSteps.filter(
          ({ status }) => status === trackerStatus.COMPLETED).length;
        const parentItemStatus = isActiveNestedItems
          ? trackerStatus.ACTIVE : (isSelectedItemsEnabled ? trackerStatus.SELECTED :
            (isCompletedNestedSteps ? trackerStatus.COMPLETED : trackerStatus.NOT_SELECTED));
        return {
          ...items,
          nestedSteps: updatedNestedSteps,
          status: parentItemStatus
        };
      }
      return {
        ...items,
        showStep: selectedStep.showStep,
        status: selectedStep.showStep ? trackerStatus.SELECTED : trackerStatus.NOT_SELECTED
      };
    }
    return items;
  });
};

export const getVisibleSteps = stepperData => {
  const activeSteps = stepperData
    .reduce((acc, items) => [...acc, items], [])
    .filter(({ showStep }) => showStep);
  return activeSteps;
};

export const getActiveStep = steps => {
  let activeStep = {};
  steps.forEach(step => {
    if (step?.nestedSteps?.length > 0) {
      activeStep = step.nestedSteps.find(st => st.status === trackerStatus.ACTIVE) || activeStep;
    } else if (step.status === trackerStatus.ACTIVE) {
      activeStep = step;
    }
  });
  return activeStep;
};

const updateNestedStepObject = (step, status, position = stepProgressDirection.CURRENT) => {
  let subSteps = step.nestedSteps;
  if (step.isSubSection) {
    const idx = step.nestedSteps?.findIndex(it =>
      (it.status === trackerStatus.COMPLETED || it.status === trackerStatus.SELECTED));

    subSteps = step.nestedSteps?.length ? step.nestedSteps.map((nestedStep, i) => {
      if (position === stepProgressDirection.BACKWARD) {
        return {
          ...nestedStep,
          status: (nestedStep.status !== trackerStatus.NOT_SELECTED) ? trackerStatus.SELECTED : nestedStep.status
        };
      } else if (position === stepProgressDirection.FORWARD) {
        return {
          ...nestedStep,
          status: (nestedStep.status !== trackerStatus.NOT_SELECTED) ? trackerStatus.COMPLETED : nestedStep.status
        };
      }
      if (idx === i) {
        return { ...nestedStep, status };
      }
      return {
        ...nestedStep,
        status: (nestedStep.status !== trackerStatus.NOT_SELECTED) ? trackerStatus.SELECTED : nestedStep.status
      };
    }) : [];
  }
  return subSteps;
};


const updateStatusProperty = (steppers, initProgressStep, currentIndex) => {
  const updatedStepObject = steppers.map((step, index) => {
    let { status, nestedSteps, validationStatus } = step;
    if (index === currentIndex) {
      nestedSteps = updateNestedStepObject(step, trackerStatus.ACTIVE);
      status = trackerStatus.ACTIVE;
      initProgressStep?.validationStatus && (validationStatus = initProgressStep?.validationStatus);
    } else if (index < currentIndex) {
      nestedSteps = updateNestedStepObject(step, trackerStatus.COMPLETED, stepProgressDirection.FORWARD);
      status = (status === trackerStatus.NOT_SELECTED) ? trackerStatus.NOT_SELECTED : trackerStatus.COMPLETED;
    } else {
      nestedSteps = updateNestedStepObject(step, trackerStatus.SELECTED, stepProgressDirection.BACKWARD);
      status = (status === trackerStatus.NOT_SELECTED) ? trackerStatus.NOT_SELECTED : trackerStatus.SELECTED;
    }
    return { ...step, status, nestedSteps, validationStatus };
  });
  return updatedStepObject;
};


export const updateActiveState = (state, payload) => {
  const { steppers, initProgressSteps } = state;
  let currentIndex = steppers.findIndex(step => step.stepId === payload.stepId);
  let initialStepInfo = initProgressSteps?.find(p => p.stepId === payload.stepId);

  if (payload.parentStepId) {
    const parentCurrentIndex = steppers.findIndex(step => step.stepId === payload.parentStepId);
    const parentPrevActiveIndex = steppers.findIndex(step => step.status === trackerStatus.ACTIVE);
    const parentPrevActive = steppers.find(step => step.status === trackerStatus.ACTIVE);
    const nestedItem = steppers[parentCurrentIndex].nestedSteps;
    if(parentCurrentIndex !== parentPrevActiveIndex){
      // const prevNestedItem = steppers[parentPrevActiveIndex].nestedSteps;
      if(parentCurrentIndex > parentPrevActiveIndex){
        steppers[parentPrevActiveIndex].nestedSteps =
         updateNestedStepObject(parentPrevActive, trackerStatus.COMPLETED, stepProgressDirection.FORWARD);
        // steppers[parentPrevActiveIndex].status = trackerStatus.COMPLETED;
      } else {
        steppers[parentPrevActiveIndex].nestedSteps =
         updateNestedStepObject(parentPrevActive, trackerStatus.SELECTED, stepProgressDirection.BACKWARD);
        // steppers[parentPrevActiveIndex].status = trackerStatus.SELECTED;
      }
    }
    initialStepInfo = initProgressSteps?.find(p => p.stepId === payload.parentStepId)?.
    nestedSteps?.find(ns => ns.stepId === payload.stepId);
    currentIndex = nestedItem.findIndex(step => step.stepId === payload.stepId);
    const updatedStatusProp = updateStatusProperty(nestedItem, initialStepInfo, currentIndex);
    steppers[parentCurrentIndex].nestedSteps = updatedStatusProp;
    steppers[parentPrevActiveIndex].status = (parentCurrentIndex > parentPrevActiveIndex)
      ? trackerStatus.COMPLETED : trackerStatus.SELECTED;
    steppers[parentCurrentIndex].status = trackerStatus.ACTIVE;
    return steppers;
  }
  return updateStatusProperty(steppers, initialStepInfo, currentIndex);
};


export const updateFormData = (formData, payload) => {
  const { componentKey, fields } = payload;
  if (!formData.length) {
    return [{ [componentKey]: fields }];
  }
  const updatedState = formData.map(data => {
    const [key] = Object.keys(data);
    return key === componentKey ? { [key]: fields } : { [key]: data[key] };
  });

  const result = updatedState.find(data => componentKey in data);
  if (!result) {
    updatedState.push({ [componentKey]: fields });
  }
  return updatedState;
};

export const getNextSelectedStep = (state, payload) => {
  const { steppers } = state;
  const currentStep = payload?.nestedStepId;
  const parentStep = payload?.stepId;
  const getParentIndex = steppers.findIndex(parent => parent.stepId === parentStep);
  const getNestedIndex = steppers[getParentIndex]?.nestedSteps?.findIndex(ns => ns.stepId === currentStep);
  const stepsFrom = steppers.slice(getParentIndex);
  let nextStep = null;
  let nextStepParent = null;
  stepsFrom.forEach( step => {
    if(nextStep === null){
      if(step.nestedSteps && step.nestedSteps.length){
        step.nestedSteps.forEach((ns, i) => {
          if(i > getNestedIndex && ns.showStep && ns.stepId !== currentStep && !nextStep){
            nextStep = ns.stepId;
            nextStepParent = step.stepId;
          }
        });
      } else {
        step.showStep && (nextStep = step.stepId);
      }
    }
  });

  return {nextStep, nextStepParent};
};
