import { FormProvider, useForm } from 'react-hook-form';

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

import useEvaluation from 'src/pages/dashboard/learning/courses/hooks/useEvaluation';
import {
  type Course,
  type EvaluationTask,
} from 'src/pages/dashboard/learning/courses/types';
import {
  isCourseFirstTask,
  isEvaluationTaskFinished,
  transformEvaluationFormData,
  validateEvaluationFormData,
} from 'src/pages/dashboard/learning/courses/utils';
import { useLokaliseTranslation } from 'src/utils/i18n';

import MainLayout from '../MainLayout';

import EvaluationStart from './EvaluationStart';
import EvaluationForm from './form';
import EvaluationResult from './result';

type EvaluationProps = {
  course: Course | undefined;
  loadingCourse?: boolean;
  task: EvaluationTask | undefined;
  loadingTask?: boolean;
  onNext: () => Promise<void>;
  onPrevious: () => void;
};

export type EvaluationFormValues = (boolean[] | string)[];
export type EvaluationForm = { formValues: EvaluationFormValues };

const Evaluation = ({
  course,
  loadingCourse = false,
  task,
  loadingTask = false,
  onNext,
  onPrevious,
}: EvaluationProps) => {
  const { t } = useLokaliseTranslation(['learning', 'general']);
  const { enqueueSnackbar } = useHuSnackbar();

  const evaluationForm = useForm<EvaluationForm>({
    mode: 'onChange',
    defaultValues: { formValues: [] },
  });

  const {
    handleSubmit,
    reset,
    formState: { isValid },
  } = evaluationForm;

  const {
    questions,
    isLoading: loadingQuestions,
    loadingSubmission,
    handleSubmitEvaluation,
    handleStartEvaluation,
    handleRetryEvaluation,
    isPending,
    isInProgress,
    isFinished,
    state,
  } = useEvaluation(task);

  const hidePrevious = isCourseFirstTask(course, task?.id);

  const onSubmit = async (
    data: EvaluationForm,
    validatedData: boolean = true,
  ) => {
    const { formValues } = data;

    if (validatedData && !validateEvaluationFormData(formValues, questions))
      return;

    const formattedData = transformEvaluationFormData(formValues, questions);

    handleSubmitEvaluation(formattedData, {
      onSuccess: () => reset(),
      onError: () => {
        enqueueSnackbar({
          title: t('course.lesson.evaluation.error'),
          variant: 'error',
        });
      },
    });
  };

  const handlePrevious = () => onPrevious();

  const handleNext = () => {
    if (isPending) {
      handleStartEvaluation();
    } else if (isInProgress) {
      handleSubmit(data => onSubmit(data))();
    } else {
      onNext();
    }
  };

  const isNextDisabled = () => {
    if (isInProgress) return !isValid;
    if (isFinished) {
      return course?.isSequential && !isEvaluationTaskFinished(task);
    }
    return false;
  };

  const getNextText = () => {
    if (isPending) return t('general:begin');
    if (isInProgress) return t('general:finish');
    return t('general:continue');
  };

  const evaluationContent = () => {
    if (isFinished) {
      return (
        <EvaluationResult
          task={task}
          onRetry={handleRetryEvaluation}
        />
      );
    }

    if (isInProgress) {
      return (
        <FormProvider {...evaluationForm}>
          <EvaluationForm
            task={task}
            questions={questions}
            loadingQuestions={loadingQuestions}
            onSubmit={handleSubmit(data => onSubmit(data, false))}
          />
        </FormProvider>
      );
    }

    return <EvaluationStart task={task} />;
  };

  const nextButton = {
    onClick: handleNext,
    children: getNextText(),
    loading: loadingSubmission,
    disabled: isNextDisabled(),
  };

  const previousButton = {
    onClick: handlePrevious,
    children: t('course.lesson.previous'),
    hide: hidePrevious,
  };

  return (
    <MainLayout
      key={state}
      course={course}
      nextButton={nextButton}
      previousButton={previousButton}
      loading={loadingCourse}
      hideSidebar
    >
      {!loadingTask && evaluationContent()}
    </MainLayout>
  );
};

export default Evaluation;
