import { ReactElement } from 'react';
import { Box, Stepper as MuiStepper, Step, StepIconProps, StepLabel, styled } from '@mui/material';
import { useWizardFormContext } from './Provider';
import { useFormState } from 'react-hook-form';
import _ from 'lodash';

interface WizardStepperProps {
  isHorizontal: boolean;
  setCurrentStep: (step: number) => void;
  stepFields: Array<Array<string>>;
}

const StyledStepper = styled(MuiStepper, {
  shouldForwardProp: (prop) => prop !== 'isHorizontal'
})<{ isHorizontal: boolean }>(({ theme, isHorizontal }) => ({
  paddingBottom: theme.spacing(2),
  display: 'flex',
  justifyContent: isHorizontal ? 'space-between' : 'flex-start',
  '.MuiStep-root': {
    flex: isHorizontal ? 1 : 'none',
    maxWidth: isHorizontal ? 'none' : '100%',
    display: 'flex',
    justifyContent: isHorizontal ? 'center' : 'flex-start'
  },
  '.MuiStepConnector-line.MuiStepConnector-lineVertical': {
    minHeight: 12
  },
  '.MuiStepConnector-vertical': {
    marginLeft: 14.5
  },
  '.MuiStepConnector-horizontal': {
    marginLeft: -10
  }
}));

const StyledStepIconRoot = styled(Box)<{
  ownerState: { completed?: boolean; active?: boolean; error?: boolean };
}>(({ theme, ownerState }) => ({
  backgroundColor: ownerState.error
    ? theme.palette.error.main
    : ownerState.completed || ownerState.active
    ? theme.palette.primary.main
    : theme.palette.mode === 'dark'
    ? theme.palette.grey[200]
    : theme.palette.grey[400],
  zIndex: 1,
  color: theme.palette.common.white,
  width: 30,
  height: 30,
  display: 'flex',
  borderRadius: '50%',
  justifyContent: 'center',
  alignItems: 'center'
}));

function StyledStepIcon({ completed, active, error, icon, className }: StepIconProps) {
  return (
    <StyledStepIconRoot ownerState={{ completed, active, error }} className={className}>
      {error ? '!' : icon}
    </StyledStepIconRoot>
  );
}

/**
 * Stepper component for rendering a step-by-step navigation UI.
 *
 * @param {Object} props - The properties object.
 * @param {boolean} props.isHorizontal - Determines the orientation of the stepper (horizontal or vertical).
 * @param {function} props.setCurrentStep - Function to set the current step index.
 * @param {Array} props.stepFields - Array of fields associated with each step.
 *
 * @returns {JSX.Element} The rendered Stepper component.
 */
function Stepper({ isHorizontal, setCurrentStep, stepFields }: WizardStepperProps) {
  const { currentStep, steps } = useWizardFormContext();
  const { errors } = useFormState();

  function handleClick(index: number) {
    if (index <= currentStep) {
      setCurrentStep(index);
    }
  }

  return (
    <StyledStepper
      activeStep={currentStep}
      orientation={isHorizontal ? 'horizontal' : 'vertical'}
      isHorizontal={isHorizontal}
      sx={{ p: 3, mt: 1 }}
    >
      {steps.map((step: ReactElement, index: number) => {
        const stepHasError = stepFields[index].some((field) => _.get(errors, field));
        const { label, icon } = step.props;

        return (
          <Step key={index}>
            <StepLabel
              StepIconComponent={StyledStepIcon}
              error={stepHasError}
              icon={icon}
              onClick={() => handleClick(index)}
              style={{ cursor: index <= currentStep ? 'pointer' : 'default' }}
            >
              {isHorizontal ? null : label}
            </StepLabel>
          </Step>
        );
      })}
    </StyledStepper>
  );
}

export { Stepper };
