import { useState } from 'react';
import { type UseFormReturn } from 'react-hook-form';
import { useMutation, useQuery } from 'react-query';
import { useNavigate } from 'react-router';

import { type AxiosError, type AxiosResponse } from 'axios';

import useSnackbar from '@material-hu/components/design-system/Snackbar';

import { logEvent } from 'src/config/logging';
import { queryClient } from 'src/config/react-query';
import useGeneralError from 'src/hooks/useGeneralError';
import { createForm, getForm, getFormAnswer } from 'src/services/forms';
import { EventName } from 'src/types/amplitude';
import {
  type FormItemResponseCompleted,
  type FormSubmitData,
} from 'src/types/forms';
import { ResponseCode, type ResponseError } from 'src/types/services';
import { getQuestions } from 'src/utils/form';
import { useLokaliseTranslation } from 'src/utils/i18n';

import { surveysKeys } from '../queries';
import { surveysRoutes } from '../routes';

type BodyData = FormSubmitData & { id: number };

export type SurveySuccessData = {
  formTemplateId: number;
  formId: number;
};

type Props = {
  id: string | undefined;
  templateId: string | undefined;
  answerId: string | undefined;
  form?: UseFormReturn<Record<string, unknown>>;
};

const useSurveyCompletionAndEdit = ({
  id,
  templateId,
  answerId,
  form,
}: Props) => {
  const { t } = useLokaliseTranslation('forms');
  const { enqueueSnackbar } = useSnackbar();
  const showGeneralError = useGeneralError();
  const navigate = useNavigate();
  const [successData, setSuccessData] = useState<SurveySuccessData | null>(
    null,
  );

  const templateInfo = useQuery(
    surveysKeys.surveys.form(Number(id)),
    () => getForm(Number(id)),
    {
      onSuccess: () => {
        logEvent(EventName.FORM_START, { formId: id, formPDF: false });
      },
      onError: (err: AxiosError<ResponseError>) => {
        if (
          err.response?.data.code === ResponseCode.NO_FORM_ATTEMPTS_AVAILABLE
        ) {
          enqueueSnackbar({
            title: t('no_survey_attempts_available'),
            variant: 'info',
          });
          navigate('..', { replace: true });
        } else {
          showGeneralError(err, t('detail_form_error'));
        }
      },
      enabled: !!id && !Number.isNaN(Number(id)),
    },
  );

  const answerInfo = useQuery(
    surveysKeys.surveys.answer(templateId ?? '', answerId ?? ''),
    () => getFormAnswer(templateId, answerId),
    {
      select: data => {
        return {
          ...data,
          data: {
            ...data.data,
            steps: data.data.steps.map(step => {
              return {
                ...step,
                questions: getQuestions(step.questions),
              };
            }),
          },
        };
      },
      onError: err => showGeneralError(err, t('no_form_info')),
      enabled: !!answerId && !!templateId,
    },
  );

  const { mutate: mutateCompletion, isLoading: isLoadingCompletion } =
    useMutation(
      (body: BodyData): Promise<AxiosResponse<FormItemResponseCompleted>> => {
        const { id: createId, ...formData } = body;
        return createForm(createId, formData);
      },
      {
        onSuccess: response => {
          logEvent(EventName.SURVEY_ANSWER, {
            surveyFilledId: templateId,
            surveyId: response.data?.form.templateId,
            surveyName: response.data?.form.title,
          });

          const { templateId: formTemplateId, id: formId } = response.data.form;

          form?.reset?.();

          setSuccessData({
            formTemplateId,
            formId,
          });
        },
      },
    );

  const handleShowResponse = () => {
    if (!successData) return;
    navigate(
      surveysRoutes.survey.completedDetail(
        successData.formTemplateId,
        successData.formId,
      ),
      {
        replace: true,
      },
    );
  };

  const handleBackToSurveys = () => {
    queryClient.invalidateQueries(surveysKeys.surveys.all());
    navigate(surveysRoutes.base());
  };

  return {
    templateInfo: templateInfo.data,
    isLoadingTemplate: templateInfo.isLoading,
    isLoadingAnswer: answerInfo.isLoading,
    mutateCompletion,
    isLoadingCompletion,
    answerInfo: answerInfo.data,
    successData,
    handleShowResponse,
    handleBackToSurveys,
  };
};

export default useSurveyCompletionAndEdit;
