import isEqual from 'lodash/isEqual';
import sumBy from 'lodash/sumBy';

import {
  defaultCourseValues,
  OPTIONS_QUESTION_TYPES,
  QUESTION_DESCRIPTION_MAX_LENGTH,
  QUESTION_MAX_LENGTH,
  QUESTION_MIN_CHECKED,
  QUESTION_MIN_LENGTH,
  QUESTION_MIN_OPTIONS,
  TITLE_MAX_LENGTH,
} from 'src/pages/dashboard/Learning/Courses/New/constants';
import {
  type CourseDetail,
  CourseFunnels,
  CourseNotificationChannel,
  CourseStatus,
  CourseTypes,
  type CreateCourseData,
  type CreateDraftData,
  type CreateEvaluationTaskData,
  type CreateLessonTaskData,
  type CreateModuleData,
  type CreateQuestionData,
  type CreateReadingTaskData,
  type CreateScormTaskData,
  type CreateTaskData,
  type CreateVideoTaskData,
  DeadlinePeriods,
  DeadlineTypes,
  type EvaluationTask,
  type LessonTask,
  type Module,
  type ModuleDetail,
  NotificationTypes,
  type Question,
  type ReadingTask,
  ReadingTypes,
  type ScormTask,
  Steps,
  type StepsTypes,
  type Task,
  type TaskDetail,
  TaskTypes,
  type UpdateCourseData,
  type VideoTask,
  VideoTypes,
} from 'src/pages/dashboard/Learning/Courses/types';
import { type Attachment } from 'src/types/attachments';
import { type Audience } from 'src/types/segmentation';
import { QuestionType } from 'src/types/surveys';
import { nullIfEmpty } from 'src/utils/arrayUtils';
import {
  fileToAttachment,
  formatUploadedAttachment,
  getSignedUploadUrl,
} from 'src/utils/filesUtils';
import { type TCustomFunction } from 'src/utils/i18n';
import { formatDefaultIcon, formatOutgoingIcon } from 'src/utils/icons';
import {
  formatFormSegmentation,
  formatSegmentationIds,
} from 'src/utils/segmentationUtils';
import { urlToFile } from 'src/utils/stringUtils';
import {
  getFormattedDuration,
  getTimeUnitsFromDuration,
} from 'src/utils/timeUtils';

import { FormDropStatus } from 'src/components/FormInputs/FormDropAttachments/types';
import { type Option } from 'src/components/FormInputs/FormOptions/types';
import { isYoutubeLink } from 'src/components/FormInputs/FormYoutubeVideo/utils';

export const isInternalId = (id: number | string) =>
  id.toString().includes('internal');

export const isNewTask = (task: Task) => isInternalId(task.id) || !task.tag;

export const getQuestionElementId = (
  module: number,
  task: number,
  question: number,
) => `${module}-module-${task}-task-${question}-question`;

export const getModuleElementId = (module: number) => `${module}-module-button`;

export const getTaskElementId = (module: number, task: number) =>
  `${module}-module-${task}-task-button`;

export const toNotificationChannel = (
  sendPushNotification: boolean,
  sendEmailNotification: boolean,
): CourseNotificationChannel => {
  if (sendPushNotification && sendEmailNotification)
    return CourseNotificationChannel.PUSH_AND_EMAIL;
  if (sendPushNotification) return CourseNotificationChannel.PUSH;
  if (sendEmailNotification) return CourseNotificationChannel.EMAIL;

  return CourseNotificationChannel.NONE;
};

export const fromNotificationChannel = (
  value?: string | null,
): { sendPushNotification: boolean; sendEmailNotification: boolean } => {
  const channel = value?.toUpperCase();

  return {
    sendPushNotification:
      channel === CourseNotificationChannel.PUSH ||
      channel === CourseNotificationChannel.PUSH_AND_EMAIL,
    sendEmailNotification:
      channel === CourseNotificationChannel.EMAIL ||
      channel === CourseNotificationChannel.PUSH_AND_EMAIL,
  };
};

export const getNotificationChannelLabelKey = (
  sendPushNotification: boolean,
  sendEmailNotification: boolean,
): string => {
  if (sendPushNotification && sendEmailNotification)
    return 'notifications_center:notification_channels.push_and_email';
  if (sendPushNotification)
    return 'notifications_center:notification_channels.push_notifications';
  if (sendEmailNotification)
    return 'notifications_center:notification_channels.email_notifications';

  return 'general:notification.none';
};

export const getRevisionValues = (values: StepsTypes) => {
  return {
    title: values.basicInformation.title,
    type: values.configuration.type,
    sequentiality: values.configuration.sequentiality,
    deadline: values.configuration.deadline,
    deadlineType: values.configuration.deadline
      ? values.configuration.deadlineType
      : undefined,
    deadlineDays: values.configuration.deadline
      ? Number(values.configuration.deadlineDays)
      : undefined,
    moduleCount: values.content.modules.length,
    taskCount: sumBy(values.content.modules, 'tasks.length'),
    segmentation: values.configuration.segmentation,
    sendPushNotification: values.configuration.sendPushNotification,
    sendEmailNotification: values.configuration.sendEmailNotification,
    category: values.basicInformation.category,
    duration: values.basicInformation.duration,
    refreshFinishedCourseUsers: values.configuration.refreshFinishedCourseUsers,
    instructor: values.configuration.instructor,
  };
};

export const formatCreateQuestionData = (question: Question) => {
  if (!question) return null;

  const partialQuestion = {
    id: !isInternalId(question.id) ? question.id : undefined,
    title: question.title,
    description: question.description,
    type: question.type,
    explanation: question.hasExplanation ? question.explanation : null,
    points: question.points ? Number(question.points) : 0,
    attachmentReferences: question?.attachments?.map(fileAsset => ({
      id: fileAsset?.id,
      name: fileAsset?.name,
    })),
  };

  if (OPTIONS_QUESTION_TYPES.includes(question.type)) {
    let choices: string[] = [];
    let correctAnswers: string[] = [];

    if (question.choices && question.choices.length > 0) {
      choices = question.choices
        .map(({ value }) => value)
        .filter(value => !!value);
      correctAnswers = question.choices
        .map(({ value, checked }) => (checked ? value : null))
        .filter(answer => answer !== null);
    }

    return {
      ...partialQuestion,
      choices,
      correctAnswers,
    };
  }

  return {
    ...partialQuestion,
    choices: [],
    correctAnswers: null,
  };
};

export const samePartialTask = (a: Task, b: Task) =>
  a.id === b.id &&
  a.title === b.title &&
  a.type === b.type &&
  a.description === b.description &&
  isEqual(a.drops, b.drops);

export const sameChoice = (a: Option, b: Option) =>
  a.value === b.value && a.checked === b.checked;

export const sameQuestion = (a: Question, b: Question) => {
  if (
    a.title !== b.title ||
    a.description !== b.description ||
    a.hasExplanation !== b.hasExplanation ||
    a.explanation !== b.explanation ||
    a.type !== b.type ||
    a.points !== b.points
  )
    return false;

  if (OPTIONS_QUESTION_TYPES.includes(a.type)) {
    return (a.choices || []).every((choice, choiceIndex) => {
      if (!b.choices?.[choiceIndex]) return false;
      return sameChoice(choice, (b.choices || [])[choiceIndex]);
    });
  }

  return true;
};

export const sameEvaluationTask = (a: EvaluationTask, b: EvaluationTask) =>
  samePartialTask(a, b) &&
  a.maximumAttempts === b.maximumAttempts &&
  a.passingGrade === b.passingGrade &&
  a.duration === b.duration &&
  a.showCorrectAnswers === b.showCorrectAnswers &&
  a.form.questions.length === b.form.questions.length &&
  a.form.questions.every((question, questionIndex) =>
    sameQuestion(question, b.form.questions[questionIndex]),
  );

export const sameLessonTask = (a: LessonTask, b: LessonTask) =>
  samePartialTask(a, b) && a.body === b.body;

export const sameVideoTask = (a: VideoTask, b: VideoTask) =>
  samePartialTask(a, b) &&
  a.urlType === b.urlType &&
  a.video.url === b.video.url &&
  a.video.file === b.video.file;

export const sameReadingTask = (a: ReadingTask, b: ReadingTask) =>
  samePartialTask(a, b) &&
  a.reading.type === b.reading.type &&
  a.reading.body === b.reading.body &&
  a.reading.pdf?.url === b.reading.pdf?.url &&
  a.reading.pdf?.file === b.reading.pdf?.file;

export const sameScormTask = (a: ScormTask, b: ScormTask) => {
  const samePartial = samePartialTask(a, b);
  const sameScorm =
    a.scorm.zip.url === b.scorm.zip.url &&
    a.scorm.zip.file === b.scorm.zip.file;

  return samePartial && sameScorm;
};
export const sameTask = (a?: Task, b?: Task) => {
  if (!a || !b) return false;

  const sameByType = {
    [TaskTypes.QUESTIONNAIRE]: () =>
      sameEvaluationTask(a as EvaluationTask, b as EvaluationTask),
    [TaskTypes.BLANK]: () => sameLessonTask(a as LessonTask, b as LessonTask),
    [TaskTypes.VIDEO]: () => sameVideoTask(a as VideoTask, b as VideoTask),
    [TaskTypes.READING]: () =>
      sameReadingTask(a as ReadingTask, b as ReadingTask),
    [TaskTypes.SCORM]: () => sameScormTask(a as ScormTask, b as ScormTask),
  };

  return (
    a.type === b.type &&
    !!sameByType[a.type as keyof typeof sameByType] &&
    sameByType[a.type as keyof typeof sameByType]()
  );
};

export const sameStepsTypes = (a: StepsTypes, b: StepsTypes) => {
  if (!a || !b) return false;

  return isEqual(a, b);
};

export const isTextQuestions = (questions: Question[]) =>
  !!questions?.every(question => question?.type === QuestionType.TEXT);

export const formatCreateEvaluationTaskData = (task: EvaluationTask) => {
  const { maximumAttempts, passingGrade, duration, showCorrectAnswers, form } =
    task;

  const formatedForm = {
    id: !isInternalId(form.id) ? form.id : undefined,
    tag: form.tag,
    title: form.title,
    description: form.description,
    questions: form?.questions?.map(formatCreateQuestionData),
  };

  const withConfiguration = !isTextQuestions(form?.questions);

  if (!withConfiguration) {
    return {
      form: formatedForm,
      passingGrade: null,
      maximumAttempts: null,
      duration: null,
      showCorrectAnswers: true,
    };
  }

  return {
    form: formatedForm,
    passingGrade: passingGrade < 0 ? undefined : passingGrade,
    maximumAttempts: maximumAttempts < 0 ? undefined : maximumAttempts,
    duration: duration < 0 ? undefined : duration,
    showCorrectAnswers,
  };
};

export const formatCreateTaskData = async (
  task: Task,
  index: number,
  prevTask?: Task,
) => {
  const attachments = task.drops
    ?.map(drop => {
      if (!drop.isSuccess) return null;
      return formatUploadedAttachment(drop.attachment);
    })
    ?.filter(attachment => !!attachment);

  const formattedAttachments =
    attachments && attachments?.length > 0 ? attachments : undefined;

  const partialTask = {
    id: !isNewTask(task) ? task.id : undefined,
    tag: !isNewTask(task) ? task.tag : undefined,
    title: task.title,
    type: task.type,
    description: task.description,
    attachments: formattedAttachments,
    position: index,
    hasNewChanges: !sameTask(task, prevTask),
  };

  if (task.type === TaskTypes.QUESTIONNAIRE) {
    return {
      ...formatCreateEvaluationTaskData(task as EvaluationTask),
      ...partialTask,
    };
  }

  if (task.type === TaskTypes.VIDEO) {
    const { id, video, ...videoTask } = task as VideoTask;

    let url: string | undefined | null;
    if (video) {
      url = video.url;

      if (videoTask.urlType === VideoTypes.INTERNAL) {
        url = await getSignedUploadUrl(video);
      }
    }

    return {
      ...videoTask,
      ...partialTask,
      url,
    };
  }

  if (task.type === TaskTypes.READING) {
    const { id, reading, ...readingTask } = task as ReadingTask;

    if (reading.type === ReadingTypes.PDF) {
      return {
        ...readingTask,
        ...partialTask,
        url: reading.pdf ? await getSignedUploadUrl(reading.pdf) : undefined,
      };
    }

    return {
      ...readingTask,
      ...partialTask,
      body: reading.body,
    };
  }

  if (task.type === TaskTypes.SCORM) {
    const { scorm } = task as ScormTask;

    return {
      url: await getSignedUploadUrl(scorm?.zip),
      ...partialTask,
    };
  }

  const { id, ...taskData } = task as Exclude<
    Task,
    EvaluationTask | ReadingTask | VideoTask
  >;

  return {
    ...taskData,
    ...partialTask,
  };
};

export const formatCreateModuleData = async (
  module: Module,
  index: number,
  prevModule?: Module,
): Promise<CreateModuleData> => {
  const tasks = await Promise.all(
    module.tasks.map((task, taskIndex) =>
      formatCreateTaskData(task, taskIndex, prevModule?.tasks[taskIndex]),
    ),
  );

  return {
    id: !isInternalId(module.id) ? (module.id as number) : undefined,
    title: module.title,
    icon: formatOutgoingIcon(module.icon),
    position: index,
    tasks: tasks.length > 0 ? (tasks as CreateTaskData[]) : undefined,
  };
};

export const formatCreateCourseData = async (
  values: StepsTypes,
  prevValues?: StepsTypes,
): Promise<CreateCourseData> => {
  const modules = await Promise.all(
    values.content.modules.map((module, moduleIndex) =>
      formatCreateModuleData(
        module,
        moduleIndex,
        prevValues?.content?.modules[moduleIndex],
      ),
    ),
  );

  const { basicInformation, configuration } = values;

  const croppedPicture = basicInformation.image?.cropped;

  let pictureUrl = basicInformation.image?.url;

  if (!pictureUrl) {
    if (croppedPicture) {
      const attachment = await fileToAttachment(croppedPicture);
      pictureUrl = await getSignedUploadUrl(attachment);
    } else {
      pictureUrl = null;
    }
  }

  const formattedStatus =
    basicInformation.status === CourseStatus.DRAFT
      ? CourseStatus.ACTIVE
      : basicInformation.status;

  const formattedDueDate = {
    dueDateType: configuration.deadline
      ? DeadlineTypes.FROM_ASSIGNMENT
      : DeadlineTypes.NO_DEADLINE,
    customDueDateAmount: configuration.deadline
      ? Number(values.configuration.deadlineDays)
      : undefined,
    customDueDatePeriod: configuration.deadline
      ? DeadlinePeriods.DAYS
      : undefined,
  };

  const formattedModules = modules.length > 0 ? modules : [];

  const { hours: durationHours, minutes: durationMinutes } =
    getTimeUnitsFromDuration(basicInformation.duration);

  const courseCategoryId = basicInformation.category?.value ?? null;

  return {
    title: basicInformation.title,
    body: basicInformation.body,
    pictureUrl,
    durationHours,
    durationMinutes,
    courseCategoryId,
    isSequential: configuration.sequentiality,
    isObligatory: configuration.type === CourseTypes.REQUIRED,
    status: formattedStatus,
    dueDate: formattedDueDate,
    sendNotification: toNotificationChannel(
      configuration.sendPushNotification,
      configuration.sendEmailNotification,
    ),
    hasSurvey: configuration.hasSurvey,
    issueCertificate: configuration.issueCertificate,
    refreshFinishedCourseUsers: configuration.refreshFinishedCourseUsers,
    digitalSignature: configuration.digitalSignature,
    instructor: configuration.instructor.trim() || null,
    modules: formattedModules,
  };
};

export const courseHasNewContent = (
  newModules: Module[],
  oldModules: Module[],
) => {
  if (newModules.length > oldModules.length) return true;

  const newTasksCount = newModules.reduce(
    (acc, module) => acc + module.tasks.length,
    0,
  );
  const oldTasksCount = oldModules.reduce(
    (acc, module) => acc + module.tasks.length,
    0,
  );

  if (newTasksCount > oldTasksCount) return true;

  return false;
};

export const formatUpdateCourseData = async (
  values: StepsTypes,
  prevValues?: StepsTypes,
): Promise<UpdateCourseData> => {
  const data = await formatCreateCourseData(values, prevValues);

  return {
    ...data,
    status: values.basicInformation.status,
  };
};

export const formatCreateDraftData = async (
  basicInformation: StepsTypes['basicInformation'],
): Promise<CreateDraftData> => {
  return {
    title: basicInformation.title,
    body: basicInformation.body,
    durationHours: undefined,
    durationMinutes: undefined,
  };
};

export const formatEditCourseAudienceData = (values: StepsTypes) => {
  const { segmentation, sendPushNotification, sendEmailNotification } =
    values.configuration;
  const { segmentationUserIds, segmentationItemIds } =
    formatSegmentationIds(segmentation);

  return {
    segmentationUserIds: nullIfEmpty<number>(segmentationUserIds),
    segmentationItemIds: nullIfEmpty<number>(segmentationItemIds),
    sendNotification: sendPushNotification || sendEmailNotification,
  };
};

export const getChoiceDefaultValues = (
  choice: string,
  correctAnswers: string[],
) => {
  if (!choice) return null;

  return {
    value: choice,
    checked: correctAnswers.includes(choice),
  };
};

export const getQuestionDefaultValues = (question: CreateQuestionData) => {
  if (!question) return null;

  const partialQuestion = {
    id: question.id,
    title: question.title,
    description: question.description,
    type: question.type,
    hasExplanation: !!question.explanation,
    explanation: question.explanation,
    points: question.points || 0,
    attachments: question.attachments,
  };

  if (OPTIONS_QUESTION_TYPES.includes(question.type)) {
    return {
      ...partialQuestion,
      choices: question.choices.map(choice =>
        getChoiceDefaultValues(choice, question.correctAnswers),
      ),
    };
  }

  return partialQuestion;
};

export const getAttachmentDefaultValues = (attachment: Attachment) => {
  return {
    id: attachment.id,
    isError: false,
    isSuccess: true,
    isLoading: false,
    status: FormDropStatus.SUCCESS,
    attachment: attachment,
  };
};

export const getTaskDefaultValues = (task: TaskDetail) => {
  const partialTask = {
    id: task.id,
    tag: task.tag,
    title: task.title,
    type: task.type,
    description: task.description,
    drops: task.attachments?.map(getAttachmentDefaultValues),
  };

  if (task.type === TaskTypes.BLANK) {
    const blankTask = task as CreateLessonTaskData;

    return {
      ...partialTask,
      body: blankTask.body,
    };
  }

  if (task.type === TaskTypes.VIDEO) {
    const videoTask = task as CreateVideoTaskData;

    return {
      ...partialTask,
      urlType: videoTask.urlType,
      video: { url: videoTask.url },
    };
  }

  if (task.type === TaskTypes.READING) {
    const readingTask = task as CreateReadingTaskData;

    if (readingTask.url) {
      return {
        ...partialTask,
        reading: {
          type: ReadingTypes.PDF,
          pdf: { url: readingTask.url },
        },
      };
    }

    return {
      ...partialTask,
      reading: {
        type: ReadingTypes.MANUAL,
        body: readingTask.body,
      },
    };
  }

  if (task.type === TaskTypes.QUESTIONNAIRE) {
    const evaluationTask = task as CreateEvaluationTaskData;

    return {
      ...partialTask,
      form: {
        id: evaluationTask.form.id,
        tag: evaluationTask.form.tag,
        title: evaluationTask.form.title,
        description: evaluationTask.form.description,
        questions: evaluationTask.form?.questions?.map(
          getQuestionDefaultValues,
        ),
      },
      maximumAttempts: evaluationTask.maximumAttempts || -1,
      passingGrade: evaluationTask.passingGrade || -1,
      duration: evaluationTask.duration || -1,
      showCorrectAnswers: evaluationTask.showCorrectAnswers,
    };
  }

  if (task.type === TaskTypes.SCORM) {
    const scormTask = task as CreateScormTaskData;

    return {
      ...partialTask,
      scorm: { zip: { url: scormTask.url } },
    };
  }

  return partialTask as Task;
};

export const getModuleDefaultValues = (module: ModuleDetail): Module => {
  return {
    id: module.id,
    title: module.title || '',
    icon: formatDefaultIcon(module.icon),
    tasks: module.tasks
      .filter(task => !!task)
      .sort((a, b) => a.position - b.position)
      .map(getTaskDefaultValues) as Task[],
  };
};

export const getCourseDefaultValues = async (
  course: CourseDetail | undefined,
  audience: Audience | undefined,
  t: TCustomFunction,
): Promise<StepsTypes> => {
  if (!course) return defaultCourseValues(t);

  const formattedCategory = course.category
    ? {
        value: course.category.id,
        label: course.category.name,
      }
    : null;

  const formattedDuration = getFormattedDuration(course.durationTime);

  let coverPictureFile: File | undefined;
  try {
    coverPictureFile = course.pictureUrl
      ? await urlToFile(course.pictureUrl)
      : undefined;
  } catch {
    coverPictureFile = undefined;
  }

  const formattedCoverPicture = coverPictureFile
    ? {
        cropped: coverPictureFile,
        original: coverPictureFile,
        url: course.pictureUrl,
      }
    : undefined;

  return {
    [Steps.BASIC_INFORMATION]: {
      title: course.title,
      body: course.body,
      status: course.status,
      isCourseStarted: course.isCourseStarted,
      duration: formattedDuration,
      category: formattedCategory,
      image: formattedCoverPicture,
    },
    [Steps.CONTENT]: {
      modules: (course.modules ?? [])
        .sort((a, b) => a.position - b.position)
        .map(getModuleDefaultValues),
    },
    [Steps.CONFIGURATION]: {
      type: course.isObligatory ? CourseTypes.REQUIRED : CourseTypes.OPTIONAL,
      sequentiality: course.isSequential,
      deadline: course.dueDate?.dueDateType !== DeadlineTypes.NO_DEADLINE,
      deadlineType:
        course.dueDate?.dueDateType || DeadlineTypes.FROM_ASSIGNMENT,
      deadlineDays: course.dueDate?.customDueDateAmount?.toString(),
      segmentation: audience
        ? formatFormSegmentation(audience) || undefined
        : undefined,
      ...fromNotificationChannel(course.sendNotification),
      hasSurvey: course.hasSurvey,
      issueCertificate: course.issueCertificate,
      digitalSignature: course.digitalSignature,
      refreshFinishedCourseUsers: course.refreshFinishedCourseUsers,
      instructor: course.instructor ?? '',
    },
  };
};

export const validateChoice = (choice: Option) =>
  !!choice && !!choice.value && choice.value.length <= QUESTION_MAX_LENGTH;

export const validateQuestion = (question: Question) => {
  if (
    !question ||
    !question.title ||
    question.title.length > QUESTION_MAX_LENGTH ||
    question.title.length < QUESTION_MIN_LENGTH ||
    question.points === undefined ||
    question.points === null ||
    Number(question.points) < 0
  ) {
    return false;
  }

  if (
    question.description &&
    question.description.length > QUESTION_DESCRIPTION_MAX_LENGTH
  ) {
    return false;
  }

  if (OPTIONS_QUESTION_TYPES.includes(question.type)) {
    const choices = question?.choices;

    if (!choices?.length) return false;

    const minOptions = QUESTION_MIN_OPTIONS[question.type];

    return (
      choices.length >= (minOptions || 0) &&
      choices.every(validateChoice) &&
      choices.some(choice => choice.checked) &&
      !choices.some(
        a =>
          choices.filter(b => a.value === b.value).length >
          QUESTION_MIN_CHECKED,
      )
    );
  }

  return true;
};

const isValidReadingTask = (task: ReadingTask) => {
  const { reading } = task as ReadingTask;

  if (reading?.type === ReadingTypes.MANUAL) {
    const body = reading?.body;
    return body && body.length > 0;
  }

  const pdfUrl = reading?.pdf?.url;
  const pdfFile = reading?.pdf?.file;

  return (pdfUrl && pdfUrl.length > 0) || !!pdfFile;
};

const isValidVideoTask = (videoTask: VideoTask) => {
  if (videoTask.urlType === VideoTypes.EXTERNAL) {
    if (!videoTask.video?.url) return false;
    return isYoutubeLink(videoTask.video.url);
  }

  const videoUrl = videoTask.video?.url;
  const videoFile = videoTask.video?.file;

  return (videoUrl && videoUrl.length > 0) || !!videoFile;
};

const isValidQuestionnaireTask = (evaluationTask: EvaluationTask) =>
  evaluationTask?.form?.questions?.length > 0 &&
  evaluationTask?.form?.questions?.every(validateQuestion);

const isValidBlankTask = (task: LessonTask) => !!task.body;

const isValidScormTask = (task: ScormTask) => {
  if (!task.scorm.zip) return false;

  const zipUrl = task.scorm.zip.url;
  const zipFile = task.scorm.zip.file;

  return (zipUrl && zipUrl.length > 0) || !!zipFile;
};

export const validateTask = (task: Task) => {
  if (!task || !task.title || task.title?.length > TITLE_MAX_LENGTH) {
    return false;
  }

  switch (task.type) {
    case TaskTypes.BLANK:
      return isValidBlankTask(task as LessonTask);
    case TaskTypes.VIDEO:
      return isValidVideoTask(task as VideoTask);
    case TaskTypes.READING:
      return isValidReadingTask(task as ReadingTask);
    case TaskTypes.QUESTIONNAIRE:
      return isValidQuestionnaireTask(task as EvaluationTask);
    case TaskTypes.SCORM:
      return isValidScormTask(task as ScormTask);
    default:
      return false; // Task of type NEW is not a valid
  }
};

export const isValidContent = (
  values: StepsTypes[Steps.CONTENT],
  partial?: boolean,
) => {
  if (!values) return false;

  const validModules = values?.modules?.every(module =>
    validateModule(module, partial),
  );

  if (partial) return validModules;
  return values?.modules?.length > 0 && validModules;
};

export const isValidConfiguration = (
  values: StepsTypes[Steps.CONFIGURATION],
) => {
  if (!values) return false;

  if (values.deadline) {
    return (
      values.deadlineType !== DeadlineTypes.NO_DEADLINE &&
      Number(values.deadlineDays) > 0
    );
  }

  return true;
};

export const validateStep = (
  step: Steps,
  values: StepsTypes,
  partial: boolean = false,
) => {
  if (!step || !values) return false;

  switch (step) {
    case Steps.CONTENT:
      return isValidContent(values[step], partial);
    case Steps.CONFIGURATION:
      return isValidConfiguration(values[step]);
    default:
      return true; // Task of type NEW is not a valid
  }
};

export const validateDraft = (values: StepsTypes) => {
  if (!values) return false;

  return (
    validateStep(Steps.BASIC_INFORMATION, values, true) &&
    validateStep(Steps.CONTENT, values, true) &&
    validateStep(Steps.CONFIGURATION, values, true)
  );
};

export const validateModule = (module: Module, partial?: boolean) => {
  if (!module) return false;

  const validTasks = module?.tasks?.every(validateTask);

  if (partial) return validTasks;
  return module?.tasks?.length > 0 && validTasks;
};

export const getCourseFunnel = (isEdit: boolean, isDuplicate: boolean) => {
  if (isEdit) return CourseFunnels.EDIT;
  if (isDuplicate) return CourseFunnels.DUPLICATE;
  return CourseFunnels.CREATE;
};

export const getNotificationType = (isEdit: boolean, isDuplicate: boolean) => {
  if (isEdit) return NotificationTypes.EDIT;
  if (isDuplicate) return NotificationTypes.DUPLICATE;
  return NotificationTypes.CREATE;
};

export const getCompletedSteps = (isEdit: boolean, isDuplicate: boolean) => {
  if (isEdit) {
    return {
      [Steps.BASIC_INFORMATION]: true,
      [Steps.CONTENT]: true,
      [Steps.CONFIGURATION]: true,
      [Steps.FINAL_REVISION]: true,
    };
  }

  if (isDuplicate) {
    return {
      [Steps.BASIC_INFORMATION]: true,
      [Steps.CONTENT]: true,
      [Steps.CONFIGURATION]: false,
      [Steps.FINAL_REVISION]: false,
    };
  }

  return {
    [Steps.BASIC_INFORMATION]: false,
    [Steps.CONTENT]: false,
    [Steps.CONFIGURATION]: false,
    [Steps.FINAL_REVISION]: false,
  };
};

const duplicateRegex = /\([0-9]+\)$/;

export const isDuplicateTitle = (title: string) => title.match(duplicateRegex);

export const getDuplicateTitleCount = (title: string) =>
  Number(title.match(duplicateRegex)?.[0]?.slice(1, -1));

export const replaceDuplicateTitleCount = (title: string, count: number) =>
  title.replace(duplicateRegex, `(${count})`);

export const getDuplicateTitle = (title: string) => {
  if (isDuplicateTitle(title)) {
    const count = getDuplicateTitleCount(title) + 1;
    return replaceDuplicateTitleCount(title, count);
  }

  return `${title} (1)`;
};

export const getEvaluationScore = (questions: Question[]) =>
  sumBy(questions, question => Number(question.points));
