import {
  createContext,
  type PropsWithChildren,
  useContext,
  useState,
} from 'react';
import { useFormContext, useWatch } from 'react-hook-form';

import {
  SessionStatus,
  SessionSteps,
} from 'src/pages/dashboard/Learning/Sessions/constants';
import {
  type NewSessionFormValues,
  type SessionStepsType,
} from 'src/pages/dashboard/Learning/Sessions/types';
import { useLokaliseTranslation } from 'src/utils/i18n';

import { useSessionStatus } from './useSessionStatus';

type StepAction = {
  show: boolean;
  disabled: boolean;
  buttonText: string;
  handle: () => void;
};

type NewStep = {
  id: SessionStepsType;
  title: string;
};

type NewCurrentStep = {
  value: number;
  id: SessionStepsType;
};

type NewStepperValue = {
  currentStep: NewCurrentStep;
  steps: NewStep[];
  back: StepAction;
  next: StepAction;
  setStep: (step: SessionStepsType) => void;
  isLastStep: boolean;
  isFirstStep: boolean;
};

const ACTION_DEFAULT = {
  show: false,
  disabled: false,
  handle: () => null,
  buttonText: '',
};

const NewStepperContext = createContext({
  currentStep: {
    id: SessionSteps.BASIC_INFORMATION,
    value: 0,
  },
  steps: [],
  back: ACTION_DEFAULT,
  next: ACTION_DEFAULT,
  setStep: () => null,
  isLastStep: false,
  isFirstStep: true,
} as NewStepperValue);

export const NewStepperProvider = ({ children }: PropsWithChildren) => {
  const { t } = useLokaliseTranslation('learning');
  const [currentValue, setCurrentValue] = useState(0);
  const { control } = useFormContext<NewSessionFormValues>();
  const { blockSessionEdition } = useSessionStatus();

  const status = useWatch({ control, name: 'basic_information.status' });

  const isEditingSession =
    status === SessionStatus.published && location.pathname.includes('/edit');

  const steps = Object.values(SessionSteps).map(step => ({
    id: step,
    title: t(`common.${step}`),
  }));

  const handleBack = () => setCurrentValue(Math.max(currentValue - 1, 0));
  const handleNext = () =>
    setCurrentValue(Math.min(currentValue + 1, steps.length - 1));

  const setStep = (step: SessionStepsType) => {
    setCurrentValue(steps.findIndex(s => s.id === step));
  };

  const lastStep = steps.length - 1;

  const isLastStep = currentValue === lastStep;
  const isFirstStep = currentValue === 0;

  const nextButtonText = () => {
    if (!isLastStep) return t('general:next');
    if (isEditingSession) return t('general:save_changes');

    return t('session.publish.title');
  };

  const disabledNextButton = () => {
    if (blockSessionEdition && isLastStep) return true;
    return false;
  };

  return (
    <NewStepperContext.Provider
      value={{
        currentStep: {
          value: currentValue,
          id: steps[currentValue].id,
        },
        steps,
        back: {
          handle: handleBack,
          show: currentValue > 0,
          buttonText: t('general:back'),
          disabled: false,
        },
        next: {
          handle: handleNext,
          show: currentValue <= lastStep,
          buttonText: nextButtonText(),
          disabled: disabledNextButton(),
        },
        setStep,
        isLastStep,
        isFirstStep,
      }}
    >
      {children}
    </NewStepperContext.Provider>
  );
};

export const useNewSessionStepper = () => useContext(NewStepperContext);
