import { type Dispatch, type SetStateAction, useEffect, useState } from 'react';
import { type UseFormReturn } from 'react-hook-form';
import {
  type UseMutationOptions,
  type UseMutationResult,
  useMutation,
} from 'react-query';

import {
  type DynamicFormAnswer,
  type DynamicFormAnswerSection,
  type ErrorTextsDefinition,
} from '../types';

import useBuildDynamicForm, {
  buildFormSchemaAndValues,
} from './useBuildDynamicForm';

export type UseDynamicFormAnswerProps<
  T extends DynamicFormAnswer = DynamicFormAnswer,
> = {
  /** The function to get the dynamic form answer */
  getAnswerFn?: () => Promise<T>;
  /** The options for the get answer mutation */
  getAnswerMutationOptions?: Omit<
    UseMutationOptions<T, unknown, void>,
    'mutationFn'
  >;
  /** The error texts */
  errorTexts: ErrorTextsDefinition;
};

export type UseDynamicFormAnswerReturn<
  T extends DynamicFormAnswer = DynamicFormAnswer,
> = {
  /** Whether the form is loading */
  isLoading: boolean;
  /** The dynamic form answer */
  formAnswer: T | null;
  /** The mutation to get the dynamic form answer */
  getAnswerMutation: UseMutationResult<T, unknown, void>;
  /** The react-hook-form instance */
  form: UseFormReturn<Record<string, unknown>, unknown>;
  /** Function to handle the submit form section */
  submitSection: (params?: { onError?: (error: unknown) => void }) => void;
  /** Function to change the step */
  changeStep: ({ isBackStep }: { isBackStep?: boolean }) => void;
  /** The title of the form */
  formTitle: string;
  /** Whether the form is frozen */
  isFrozen: boolean;
  /** Whether the form is on the first section */
  isOnFirstSection: boolean;
  /** Whether the form is on the last section */
  isOnLastSection: boolean;
  /** Function to get the form response */
  setFormTitle: Dispatch<SetStateAction<string>>;
  /** Function to get the form response */
  setIsFrozen: Dispatch<SetStateAction<boolean>>;
  /** The current section */
  currentSection?: DynamicFormAnswerSection | undefined | null;
};

const useDynamicFormAnswer = <T extends DynamicFormAnswer = DynamicFormAnswer>({
  getAnswerFn,
  getAnswerMutationOptions,
  errorTexts,
}: UseDynamicFormAnswerProps<T>): UseDynamicFormAnswerReturn<T> => {
  const [currentSectionIndex, setCurrentSectionIndex] = useState(0);
  const [formAnswer, setFormAnswer] = useState<T | null>(null);
  const [isFrozen, setIsFrozen] = useState(false);
  const [formTitle, setFormTitle] = useState('');

  const currentSection = formAnswer?.sections[currentSectionIndex];

  const form = useBuildDynamicForm({
    sectionId: currentSection?.nameId || '',
    components: currentSection?.content.components || [],
    errorTexts,
  });

  const getAnswerMutation = useMutation({
    mutationFn: getAnswerFn,
    onSuccess: (data, ...rest) => {
      setFormAnswer(data);
      setFormTitle(data?.form?.title || '');
      setIsFrozen(!data?.editable || false);
      getAnswerMutationOptions?.onSuccess?.(data, ...rest);
    },
    ...getAnswerMutationOptions,
  });

  const changeStep = ({ isBackStep }: { isBackStep?: boolean }) => {
    if (isBackStep) {
      if (currentSectionIndex === 0) return;
      setCurrentSectionIndex(currentSectionIndex - 1);
    } else {
      if (currentSectionIndex === (formAnswer?.sections?.length || 0) - 1)
        return;
      setCurrentSectionIndex(currentSectionIndex + 1);
    }
  };

  const submitSection = () => {
    changeStep({});
  };

  const isOnFirstSection = currentSectionIndex === 0;
  const isOnLastSection =
    currentSectionIndex === (formAnswer?.sections?.length || 0) - 1;

  useEffect(() => {
    if (currentSection) {
      const { values } = buildFormSchemaAndValues({
        sectionId: currentSection.nameId,
        components: currentSection.content.components || [],
        errorTexts,
      });
      form.reset(values);
    }
  }, [currentSection]);

  return {
    changeStep,
    currentSection,
    form,
    formTitle,
    formAnswer,
    getAnswerMutation,
    isFrozen,
    isLoading: getAnswerMutation.isLoading,
    isOnFirstSection,
    isOnLastSection,
    setFormTitle,
    setIsFrozen,
    submitSection,
  };
};

export default useDynamicFormAnswer;
