import { useCallback, useMemo, useState } from 'react';

import { DynamicFormType } from 'src/types/dynamicForms';
import { type TCustomFunction } from 'src/utils/i18n';

import {
  type SectionCreationSteps,
  type ServiceItemDraft,
  ServiceItemStatus,
  Step,
} from '../../types';
import {
  isValidAgentAssignment,
  isValidBasicInformation,
  isValidCollaborators,
  isValidForm,
  isValidName,
  isValidServiceItemName,
} from '../../utils';
import { isValidPdfForm } from '../components/FormCreation/pdf/utils';

import type useDynamicForm from './useDynamicForm';
import type useServiceItem from './useServiceItem';

type DynamicFormBag = ReturnType<typeof useDynamicForm>;
type CreateDraftMutation = ReturnType<
  typeof useServiceItem
>['createDraftMutation'];

type Args = {
  formValues: SectionCreationSteps;
  nameValue: string | undefined;
  dynamic: DynamicFormBag;
  serviceItem?: ServiceItemDraft;
  createDraftMutation: CreateDraftMutation;
  isServiceItemDirty: boolean;
  isDynamicFormDirty: boolean;
  isEdit: boolean;
  actionLoading: boolean;
  t: TCustomFunction;
};

const useStepNavigation = ({
  formValues,
  nameValue,
  dynamic,
  serviceItem,
  createDraftMutation,
  isServiceItemDirty,
  isDynamicFormDirty,
  isEdit,
  actionLoading,
  t,
}: Args) => {
  const {
    dynamicForm,
    formTag,
    creatingForm,
    setCreatingForm,
    setCreatingPdfForm,
  } = dynamic;

  const [selectedNavItem, setSelectedNavItem] = useState<Step>(
    Step.BASIC_INFORMATION,
  );
  const [showCreationValidations, setShowCreationValidations] = useState(false);

  const isValidStep = useCallback(
    (step: Step) => {
      switch (step) {
        case Step.BASIC_INFORMATION:
          return !!isValidBasicInformation(formValues[Step.BASIC_INFORMATION]);
        case Step.FORM:
          return dynamicForm?.type === DynamicFormType.REGULAR
            ? isValidForm(formValues[Step.FORM])
            : isValidPdfForm(formValues[Step.FORM]);
        case Step.ASSIGNMENT:
          return isValidAgentAssignment(formValues[Step.ASSIGNMENT]);
        case Step.COLLABORATORS:
          return isValidCollaborators(formValues[Step.COLLABORATORS]);
        case Step.REVISION:
          return true;
        default:
          return false;
      }
    },
    [formValues, dynamicForm?.type],
  );

  // These handlers are passed to potentially-memoised children (SidebarNavigation,
  // Revision, Form). Wrapping them in useCallback keeps their reference stable
  // across renders so React.memo can do its job.
  const handleNavItemSelect = useCallback(
    (sectionToNavigateTo: Step) => {
      // If not in edit mode (either draft already exists or editing an already
      // created service item), create a draft and then navigate to the selected step.
      if (!isEdit && sectionToNavigateTo !== Step.BASIC_INFORMATION) {
        createDraftMutation.mutateAsync(undefined, {
          onSuccess: () => setSelectedNavItem(sectionToNavigateTo),
        });
      } else {
        setSelectedNavItem(sectionToNavigateTo);
      }
    },
    [isEdit, createDraftMutation],
  );

  const handleNavigateToSection = useCallback((section: Step) => {
    setSelectedNavItem(section);
  }, []);

  const handleNavigateToEditForm = useCallback(
    (type: DynamicFormType = DynamicFormType.REGULAR) => {
      setSelectedNavItem(Step.FORM);
      if (type === DynamicFormType.PDF) {
        setCreatingPdfForm(true);
      } else {
        setCreatingForm(true);
      }
    },
    [setCreatingPdfForm, setCreatingForm],
  );

  const handleContinue = () => {
    switch (selectedNavItem) {
      case Step.BASIC_INFORMATION:
        if (!isEdit) {
          createDraftMutation.mutateAsync(undefined, {
            onSuccess: () => setSelectedNavItem(Step.FORM),
          });
        } else {
          setSelectedNavItem(Step.FORM);
        }
        break;
      case Step.FORM:
        setSelectedNavItem(Step.ASSIGNMENT);
        break;
      case Step.ASSIGNMENT:
        setSelectedNavItem(Step.COLLABORATORS);
        break;
      case Step.COLLABORATORS:
        setSelectedNavItem(Step.REVISION);
        break;
      default:
        break;
    }
  };

  const sidebarItems = useMemo(() => {
    const validServiceName = isValidServiceItemName(nameValue ?? '');
    const validBasicInformation = isValidStep(Step.BASIC_INFORMATION);
    const validForm = isValidStep(Step.FORM);
    const validAssignment = isValidStep(Step.ASSIGNMENT);
    const validCollaborators = isValidStep(Step.COLLABORATORS);
    const hasForm = isEdit && !!formTag && !!dynamicForm;

    const canNavigateToNonInitialStep =
      !actionLoading && (validServiceName || hasForm);

    return [
      {
        label: t(`${Step.BASIC_INFORMATION}`),
        value: Step.BASIC_INFORMATION,
        canNavigate: !actionLoading,
        hasError: showCreationValidations && !validBasicInformation,
      },
      {
        label: t(`${Step.FORM}`),
        value: Step.FORM,
        canNavigate: canNavigateToNonInitialStep,
        hasError: showCreationValidations && !validForm,
      },
      {
        label: t(`${Step.ASSIGNMENT}`),
        value: Step.ASSIGNMENT,
        canNavigate: canNavigateToNonInitialStep,
        hasError: showCreationValidations && !validAssignment,
      },
      {
        label: t(`${Step.COLLABORATORS}`),
        value: Step.COLLABORATORS,
        canNavigate: canNavigateToNonInitialStep,
        hasError: showCreationValidations && !validCollaborators,
      },
      {
        label: t(`${Step.REVISION}`),
        value: Step.REVISION,
        canNavigate: canNavigateToNonInitialStep,
        hasError: false,
      },
    ];
  }, [
    isValidStep,
    t,
    actionLoading,
    showCreationValidations,
    nameValue,
    dynamicForm,
    formTag,
    isEdit,
  ]);

  const saveButtonDisabled = useMemo(() => {
    if (selectedNavItem === Step.FORM && creatingForm) {
      return !isDynamicFormDirty;
    }
    return !isValidName(nameValue ?? '') || !isServiceItemDirty;
  }, [
    isDynamicFormDirty,
    nameValue,
    selectedNavItem,
    isServiceItemDirty,
    creatingForm,
  ]);

  const continueButtonDisabled = useMemo(() => {
    const hasForm = isEdit && !!formTag && !!dynamicForm;
    if (selectedNavItem === Step.BASIC_INFORMATION) {
      return !isValidServiceItemName(nameValue ?? '') && !hasForm;
    }
    return false;
  }, [selectedNavItem, nameValue, isEdit, formTag, dynamicForm]);

  const inRevision = selectedNavItem === Step.REVISION;

  const continueButtonText = useMemo(() => {
    if (inRevision) {
      return serviceItem?.status === ServiceItemStatus.ACTIVE
        ? t('save_changes')
        : t('general:activate');
    }
    return t('general:continue');
  }, [inRevision, serviceItem?.status, t]);

  return {
    selectedNavItem,
    showCreationValidations,
    setShowCreationValidations,
    isValidStep,
    sidebarItems,
    saveButtonDisabled,
    continueButtonDisabled,
    continueButtonText,
    inRevision,
    handlers: {
      onNavItemSelect: handleNavItemSelect,
      onNavigateToSection: handleNavigateToSection,
      onNavigateToEditForm: handleNavigateToEditForm,
      onContinue: handleContinue,
    },
  };
};

export default useStepNavigation;
