import React, {
  ReactNode,
  memo,
  useCallback,
  useEffect,
  useMemo,
  useRef,
} from 'react';
import {useTranslation} from 'react-i18next';
import {FormProvider, useForm} from 'react-hook-form';
import {ZodTypeAny} from 'zod';
import {useNavigation} from '@react-navigation/native';
import {zodResolver} from '@hookform/resolvers/zod';
import {Stepper, useStepper} from '@components';
import {FormStep, SubmitData} from '@components/DynamicForm/interfaces';
import {
  createZodSchemaFromQuestion,
  groupFormValues,
} from '@components/DynamicForm/utils';
import {differenceInSeconds} from '@shared/utils';

interface Props {
  StepHeaderComponent?: ReactNode;
  StepBodyComponent?: (data: FormStep) => ReactNode;
  onSubmitPress?: () => void;
  disabled?: boolean;
  submitText: string;
  FormHeader?: ReactNode;
  routes: {key: string; data: FormStep | FormStep[]}[];
  buttonIsLoading?: boolean;
  onSubmit?: (data: SubmitData) => void;
}

function FormWrapperStepper({
  disabled,
  submitText,
  routes,
  buttonIsLoading,
  onSubmit,
}: Props) {
  const {t} = useTranslation();
  const navigation = useNavigation();
  const {
    goToStep,
    currentIndex,
    setData,
    data: stepperData,
  } = useStepper<{key: string; data: FormStep | FormStep[]}[]>();
  const startTime = useRef(new Date());

  const currentStep = stepperData[currentIndex]?.data as FormStep;
  const schema = useMemo(
    () =>
      currentStep
        ? createZodSchemaFromQuestion(currentStep as FormStep)
        : undefined,
    [currentStep],
  );

  const methods = useForm({
    resolver: zodResolver(schema as ZodTypeAny),
    mode: 'onChange',
  });

  useEffect(() => {
    setData(routes);
  }, [routes, setData]);

  const isLastStep = useMemo(
    () => currentIndex === routes.length - 1,
    [currentIndex, routes.length],
  );

  const {trigger, getValues} = methods;

  const onSubmitPress = useCallback(
    (data: {[key: string]: string}) => {
      const formValues = groupFormValues(data);
      const now = new Date();
      onSubmit?.({
        formValues,
        fillingTime: differenceInSeconds(now, startTime.current),
      });
    },
    [onSubmit],
  );

  const onNextPress = useCallback(async () => {
    const isValid = await trigger();

    const formData = getValues();
    if (isValid) {
      isLastStep ? onSubmitPress(formData) : goToStep(currentIndex + 1);
    }
  }, [trigger, getValues, isLastStep, onSubmitPress, goToStep, currentIndex]);

  useEffect(() => {
    navigation.setOptions({
      headerShown: false,
    });
  }, [navigation]);

  return stepperData ? (
    <FormProvider {...methods} key={currentIndex}>
      <Stepper.Content>
        <Stepper.Header />
        <Stepper.ProgressBar />
        <Stepper.ScreenStack />
        <Stepper.Footer
          nextLabel={isLastStep ? submitText : t('general.next')}
          goNext={onNextPress}
          disabled={isLastStep && disabled}
          isLoading={buttonIsLoading}
          label={`${currentIndex + 1}/${routes.length}`}
        />
      </Stepper.Content>
    </FormProvider>
  ) : null;
}

export default memo(FormWrapperStepper);
