import { useEffect, useState } from 'react';
import { type MutateOptions } from 'react-query';

import useIds from '../../hooks/useIds';
import {
  type EvaluationAnswer,
  EvaluationState,
  type EvaluationTask,
  TaskStatus,
} from '../types';
import {
  exceedsAttempts,
  isEvaluationTaskFinished,
  isEvaluationTaskFinishPending,
} from '../utils';

import useFinishTask, {
  type ErrorResponse,
  type SuccessResponse,
} from './useFinishTask';
import useGetCourse from './useGetCourse';
import useGetEvaluationsQuestions from './useGetEvaluationsQuestions';
import useInitTask from './useInitTask';

const useEvaluation = (task: EvaluationTask | undefined) => {
  const { courseId } = useIds();
  const [startedEvaluation, setStartedEvaluation] = useState(false);
  const [showEvaluationResults, setShowEvaluationResults] = useState(false);

  const { course } = useGetCourse({ courseId });
  const { data: questions, isLoading } = useGetEvaluationsQuestions({
    task,
    options: { enabled: startedEvaluation },
  });

  const { mutateAsync: initiateTask, isLoading: loadingInitEvaluation } =
    useInitTask(course, task);

  const { mutateAsync: finishTask, isLoading: loadingSubmission } =
    useFinishTask(course, task);

  const handleStartEvaluation = async () => {
    if (exceedsAttempts(task)) return;

    await initiateTask();
    setStartedEvaluation(true);
    setShowEvaluationResults(false);
  };

  const handleRetryEvaluation = () => {
    setStartedEvaluation(false);
    setShowEvaluationResults(false);
  };

  const handleSubmitEvaluation = async (
    data?: EvaluationAnswer,
    options?: MutateOptions<
      SuccessResponse,
      ErrorResponse,
      { data?: EvaluationAnswer }
    >,
  ) => {
    const isTaskNotInProgress = task?.status !== TaskStatus.IN_PROGRESS;
    const hasExceededAttempts = exceedsAttempts(task);

    if (isTaskNotInProgress && !hasExceededAttempts) {
      await initiateTask();
    }

    await finishTask({ data }, options);
    setShowEvaluationResults(true);
  };

  useEffect(() => {
    if (isEvaluationTaskFinishPending(task)) {
      handleSubmitEvaluation();
    }
  }, [task]);

  const isFinished = isEvaluationTaskFinished(task) || showEvaluationResults;
  const isPending = !startedEvaluation && !isFinished;
  const isInProgress = startedEvaluation && !isFinished;

  const getState = () => {
    if (isFinished) return EvaluationState.FINISHED;
    if (isPending) return EvaluationState.PENDING;
    if (isInProgress) return EvaluationState.IN_PROGRESS;
  };

  return {
    questions,
    isLoading,
    startedEvaluation,
    handleStartEvaluation,
    handleSubmitEvaluation,
    handleRetryEvaluation,
    loadingSubmission,
    loadingInitEvaluation,
    isPending,
    isInProgress,
    isFinished,
    state: getState(),
  };
};

export default useEvaluation;
