import { useCallback, useEffect } from 'react';
import { useFormContext, useWatch } from 'react-hook-form';
import { useBeforeUnload } from 'react-router-dom';

import { TaskTypes } from '@material-hu/components/composed-components/learning';
import useHuSnackbar from '@material-hu/components/design-system/Snackbar';

import useGeneralError from 'src/hooks/useGeneralError';
import { useLokaliseTranslation } from 'src/utils/i18n';

import useFinishTask from '../../hooks/useFinishTask';
import useInitTask from '../../hooks/useInitTask';
import {
  type Course,
  FinishTaskErrors,
  type Task,
  TaskFinishedReason,
  type TaskLayoutForm,
  TaskStatus,
} from '../../types';
import { isCourseFirstTask, isTaskFinished } from '../../utils';

import MainLayout from './MainLayout';
import TaskContent from './TaskContent';
import TaskDetail from './TaskDetail';
import TaskFinishedToggle from './TaskFinishedToggle';
import TaskSupplementaryContent from './TaskSupplementaryContent';

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

const TaskLayout = ({
  course,
  loadingCourse = false,
  task,
  loadingTask = false,
  onNext,
  onPrevious,
}: TaskLayoutProps) => {
  const { t } = useLokaliseTranslation(['learning', 'general']);
  const { enqueueSnackbar } = useHuSnackbar();
  const showGeneralError = useGeneralError();
  const { setValue, control } = useFormContext<TaskLayoutForm>();

  const finished = useWatch({ name: 'finished', control });

  const finishMutation = useFinishTask(course, task);
  const initMutation = useInitTask(course, task);

  const canFinish = task?.type === TaskTypes.SCORM || finished;
  const nextDisabled =
    (course?.isSequential && !canFinish) || loadingTask || loadingCourse;
  const hidePrevious = isCourseFirstTask(course, task?.id);

  useBeforeUnload(
    useCallback(() => {
      if (!task || isTaskFinished(task) || task?.type !== TaskTypes.SCORM)
        return;

      finishMutation.mutate({ reason: TaskFinishedReason.BACK });
    }, [task]),
  );

  useEffect(() => {
    setValue('finished', isTaskFinished(task));
  }, [task?.status]);

  useEffect(() => {
    if (task?.status === TaskStatus.PENDING) {
      initMutation.mutate();
    }
  }, [task?.status]);

  const handleNext = () => {
    if (isTaskFinished(task) || !canFinish) {
      onNext();
      return;
    }

    finishMutation.mutate(
      { reason: TaskFinishedReason.NEXT },
      {
        onSuccess: () => onNext(),
        onError: err => {
          if (!course?.isSequential && !finished) {
            onNext();
            return;
          }

          const { code } = err?.response?.data ?? {};

          if (code === FinishTaskErrors.SCORM_IN_PROGRESS) {
            enqueueSnackbar({
              title: t('course.lesson.error_task_in_progress'),
              variant: 'error',
            });
          } else {
            showGeneralError({ errorData: err });
          }
        },
      },
    );
  };

  const handlePrevious = () => onPrevious();

  const nextButton = {
    onClick: handleNext,
    children: t('general:continue'),
    loading: finishMutation.isLoading,
    disabled: nextDisabled,
  };

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

  return (
    <MainLayout
      nextButton={nextButton}
      previousButton={previousButton}
      course={course}
      loading={loadingCourse}
    >
      {!loadingTask && (
        <>
          <TaskDetail task={task} />
          <TaskContent task={task} />
          <TaskSupplementaryContent task={task} />
          <TaskFinishedToggle task={task} />
        </>
      )}
    </MainLayout>
  );
};

export default TaskLayout;
