import { useEffect, useMemo, useState } from 'react';
import { useMutation, useQuery, useQueryClient } from 'react-query';
import { useNavigate, useParams } from 'react-router-dom';

import { AxiosError } from 'axios';
import { concat, initial, once } from 'lodash-es';
import { IconCheck } from '@material-hu/icons/tabler';
import Stack from '@material-hu/mui/Stack';
import { useTheme } from '@material-hu/mui/styles';
import { typographyClasses } from '@material-hu/mui/Typography';

import HuAvatar from '@material-hu/components/design-system/Avatar';
import Button from '@material-hu/components/design-system/Buttons/Button';
import HuTaskFocusHeader from '@material-hu/components/design-system/Header/TaskFocus';
import useHuSnackbar from '@material-hu/components/design-system/Snackbar';
import HuTitle from '@material-hu/components/design-system/Title';

import { logEvent } from 'src/config/amplitude';
import useHuGoTheme from 'src/hooks/useHuGoTheme';
import useNetworkStatus from 'src/hooks/useNetworkStatus';
import useTimer from 'src/hooks/useTimer';
import { getSurveyDetail, respondSurvey } from '../services';
import { EventName } from 'src/types/amplitude';
import {
  CollaboratorSurveyStatus,
  ErrorType,
  type QuestionAnswer,
  type SurveyFormValues,
  type TransformedSurvey,
} from '../types';
import { useLokaliseTranslation } from 'src/utils/i18n';

import QuestionForm from '../components/QuestionForm';
import SurveySkeleton from '../components/SurveySkeleton';
import useBackupAnswerMutation from '../hooks/useBackupAnswerMutation';
import { pxKeys } from '../queries';
import { pxRoutes } from '../routes';
import { transformSurvey } from '../utils';

import { bounceInDown } from './animations';
import ErrorMessage from './components/ErrorMessage';
import SurveyWelcome from './components/SurveyWelcome';
import { getPillPropsFromStatus, getStartQuestionIndex } from './utils';

const SurveyForm = () => {
  const navigate = useNavigate();
  const [questionIndex, setQuestionIndex] = useState<number>(-1);
  const urlParams = useParams();
  const surveyId = Number(urlParams.id);
  const queryClient = useQueryClient();
  const { t } = useLokaliseTranslation('people_experience');
  const { getDuration } = useTimer();
  const { enqueueSnackbar } = useHuSnackbar();
  const theme = useTheme();

  const logEventOnce = useMemo(() => once(logEvent), [surveyId]);
  const setInitQuestionIdx = useMemo(() => once(setQuestionIndex), []);

  const surveyQuery = useQuery(
    pxKeys.surveyDetail(surveyId),
    () => getSurveyDetail(surveyId),
    {
      enabled: !!surveyId,
      onError: () => {},
      onSuccess: (data: TransformedSurvey) => {
        logEventOnce(EventName.SURVEY_ANSWER_STARTED, {
          surveyID: data.id,
          questionQuantity: data.questions.length,
        });
      },
      select: response => transformSurvey(response.data),
    },
  );

  useEffect(() => {
    if (surveyQuery.data?.questions) {
      setInitQuestionIdx(getStartQuestionIndex(surveyQuery.data?.questions));
    }
  }, [surveyQuery.data, setInitQuestionIdx]);

  const backupMutation = useBackupAnswerMutation({
    questionIndex,
    surveyId,
    onUpdateQuestionIndex: setQuestionIndex,
  });

  const respondMutation = useMutation(respondSurvey, {
    onError: () => {},
    onSuccess: () => {
      queryClient.invalidateQueries(pxKeys.surveyDetail(surveyId));
      queryClient.invalidateQueries(pxKeys.collaboratorSurveysBase());
      logEvent(EventName.SURVEY_SENT, {
        surveyID: surveyQuery.data?.id,
        questionsQuantity: surveyQuery.data?.questions.length,
      });
    },
  });

  const { title, description, questions, status, anonymityThreshold } =
    surveyQuery.data ?? {
      title: '',
      description: '',
      questions: [],
    };

  const currentQuestion = questions[questionIndex];

  const handleGoToSurveyList = () => {
    queryClient.invalidateQueries(pxKeys.collaboratorSurveysBase());
    navigate(pxRoutes.collaboratorSurveysBase());
  };

  const handleSubmit = (formValues: SurveyFormValues) => {
    const allAnswers = surveyQuery.data?.questions.map(
      ({ id, answer, comment }) => ({ questionId: id, answer, comment }),
    );

    const questionAnswers: QuestionAnswer[] = concat(initial(allAnswers), {
      questionId: currentQuestion.id,
      answer: formValues.answer,
      comment: formValues.comment ?? '',
    });

    respondMutation.mutate({
      surveyId: surveyQuery.data?.id ?? 0,
      questionAnswers: questionAnswers,
      fillingTime: getDuration(),
    });
  };

  const errorType = useMemo(() => {
    if (surveyQuery.isError) {
      return (surveyQuery.error as AxiosError).code === AxiosError.ERR_NETWORK
        ? ErrorType.Connection
        : ErrorType.Access;
    }

    if (respondMutation.isError) {
      return (respondMutation.error as AxiosError).code ===
        AxiosError.ERR_NETWORK
        ? ErrorType.Connection
        : ErrorType.RespondSurvey;
    }

    return null;
  }, [
    surveyQuery.isError,
    surveyQuery.error,
    respondMutation.isError,
    respondMutation.error,
  ]);

  useNetworkStatus({
    onOffline: () => {
      enqueueSnackbar({
        title: t('CONNECTION_ERROR_DESCRIPTION'),
        variant: 'warning',
      });
    },
  });

  const isFirstQuestion = questionIndex === 0;

  if (surveyQuery.isLoading) {
    return <SurveySkeleton />;
  }

  const isSurveyAnswered =
    surveyQuery.data?.status === CollaboratorSurveyStatus.FINISHED &&
    !errorType;

  return (
    <Stack
      sx={{
        height: '100%',
        overflow: 'hidden',
      }}
    >
      <HuTaskFocusHeader
        title={title}
        slotProps={{
          pill: getPillPropsFromStatus({
            status,
            t,
          }),
        }}
        onBack={handleGoToSurveyList}
        onClose={handleGoToSurveyList}
      />
      {errorType && <ErrorMessage type={errorType} />}
      {isSurveyAnswered && (
        <Stack
          sx={{
            backgroundColor: theme.palette.new.background.elements.inverted,
            justifyContent: 'center',
            alignItems: 'center',
            textAlign: 'center',
            height: 'calc(100% - 64px)',
            gap: 3,
            animation: `${bounceInDown} 500ms ease-in-out`,
          }}
        >
          <HuAvatar
            size="large"
            Icon={IconCheck}
            color="success"
          />
          <HuTitle
            variant="L"
            title={t('ALREADY_ANSWERED', { title })}
            sx={{
              [`.${typographyClasses.root}`]: {
                color: theme.palette.new.text.neutral.inverted,
              },
            }}
          />
          <Button
            variant="secondary"
            onClick={handleGoToSurveyList}
          >
            {t('BACK_SECTION')}
          </Button>
        </Stack>
      )}
      {!isSurveyAnswered && questionIndex !== -1 && (
        <>
          {isFirstQuestion && (
            <SurveyWelcome
              title={title}
              description={description}
              hasAlert={anonymityThreshold !== 0}
            />
          )}
          <QuestionForm
            key={currentQuestion.id}
            question={currentQuestion}
            sx={{ pt: description && isFirstQuestion ? undefined : 9 }}
            onChangeIndex={setQuestionIndex}
            questionIndex={questionIndex}
            questionsCount={questions.length}
            surveyId={surveyId}
            onSubmit={handleSubmit}
            isLoading={respondMutation.isLoading}
            onBackupAnswer={backupMutation.mutate}
          />
        </>
      )}
    </Stack>
  );
};

const SurveyWithHuGoTheme = () => {
  const HuGoThemeProvider = useHuGoTheme();
  return (
    <HuGoThemeProvider>
      <SurveyForm />
    </HuGoThemeProvider>
  );
};

export default SurveyWithHuGoTheme;
