import { Fragment, type ReactNode, useState } from 'react';
import { useNavigate } from 'react-router';

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

import useSnackbar from '../../hooks/useSnackbar';
import { serviceManagementRoutes } from '../../routes';
import { type ServiceItemDraft, ServiceItemStatus, Step } from '../../types';
import { isValidName } from '../../utils';
import useActiveServiceItemHasChangesModal from '../components/modals/useActiveServiceItemHasChangesModal';
import useCantActivateModal from '../components/modals/useCantActivateModal';
import useConfirmActiveServiceItemChangesModal from '../components/modals/useConfirmActiveServiceItemChangesModal';
import useExitOrContinueModal from '../components/modals/useExitOrContinueModal';
import useExitOrSaveModal from '../components/modals/useExitOrSaveModal';

import type useServiceItem from './useServiceItem';

type ServiceItemBag = ReturnType<typeof useServiceItem>;

type Args = {
  isEdit: boolean;
  nameValue: string | undefined;
  serviceItem?: ServiceItemDraft;
  hasEditedForm: boolean;
  isServiceItemDirty: boolean;
  /**
   * `true` when arriving at this screen from a category-filtered catalog page.
   * Drives back-navigation behaviour.
   */
  navigatedFromCatalog: boolean;
  /** Provided by the parent so it can also be passed to `useServiceItem`. */
  navigateToServiceItems: () => void;
  service: Pick<
    ServiceItemBag,
    | 'createDraftMutation'
    | 'updateDraftMutation'
    | 'deleteDraftMutation'
    | 'changeStatusMutation'
  >;
  isValidStep: (step: Step) => boolean;
  setShowCreationValidations: (value: boolean) => void;
};

const useServiceItemActions = ({
  isEdit,
  nameValue,
  serviceItem,
  hasEditedForm,
  isServiceItemDirty,
  navigatedFromCatalog,
  navigateToServiceItems,
  service,
  isValidStep,
  setShowCreationValidations,
}: Args) => {
  const { t } = useLokaliseTranslation(['service_management', 'general']);
  const { showSnackbar } = useSnackbar();
  const navigate = useNavigate();

  const {
    createDraftMutation,
    updateDraftMutation,
    deleteDraftMutation,
    changeStatusMutation,
  } = service;

  // Catalog items not voluntarily saved are deleted when the user exits without saving.
  const [voluntarySaved, setVoluntarySaved] = useState(isEdit);

  // Routes ----------------------------------------------------------------

  const handleNavigateToServiceItems = () => {
    if (window.history.length > 2 && navigatedFromCatalog) {
      navigate(-1);
    } else {
      navigate(serviceManagementRoutes.serviceItems());
    }
  };

  // Lifecycle handlers ----------------------------------------------------

  const handleSave = () => {
    setVoluntarySaved(true);
    if (isEdit) {
      updateDraftMutation.mutate();
    } else {
      createDraftMutation.mutate(undefined, {
        onSuccess: () =>
          showSnackbar({
            title: t('saved_as_draft_success'),
            variant: 'success',
          }),
      });
    }
  };

  const exitCreateCatalogItem = () => {
    if (!voluntarySaved && isEdit) {
      deleteDraftMutation.mutate(undefined, {
        onSettled: handleNavigateToServiceItems,
      });
      return;
    }
    handleNavigateToServiceItems();
  };

  // Modals ----------------------------------------------------------------

  const { open: openExitOrSaveModal, modal: exitOrSaveModal } =
    useExitOrSaveModal({
      voluntarySaved,
      isLoading: createDraftMutation.isLoading || updateDraftMutation.isLoading,
      onSave: () =>
        isEdit
          ? updateDraftMutation.mutateAsync()
          : createDraftMutation.mutateAsync(undefined, {
              onSuccess: () =>
                showSnackbar({
                  title: t('saved_as_draft_success'),
                  variant: 'success',
                }),
            }),
      onExit: handleNavigateToServiceItems,
      onExitWithoutSaving: exitCreateCatalogItem,
    });

  const { open: openExitOrContinueModal, modal: exitOrContinueModal } =
    useExitOrContinueModal({ onExitWithoutSaving: exitCreateCatalogItem });

  const { open: openCantActivateModal, modal: cantActivateModal } =
    useCantActivateModal();

  const {
    open: openActiveServiceItemHasChangesModal,
    modal: activeServiceItemHasChangesModal,
  } = useActiveServiceItemHasChangesModal({
    onExit: () => navigate(serviceManagementRoutes.serviceItems()),
  });

  const {
    open: openConfirmActiveServiceItemChangesModal,
    modal: confirmActiveServiceItemChangesModal,
  } = useConfirmActiveServiceItemChangesModal({
    isLoading: updateDraftMutation.isLoading,
    onConfirm: () =>
      updateDraftMutation.mutateAsync(undefined, {
        onSuccess: navigateToServiceItems,
      }),
  });

  // Top-level entry points ------------------------------------------------

  const handleExit = () => {
    if (isValidName(nameValue ?? '')) {
      // Active service item has changes -> needs to be saved before exiting
      // to create a new version.
      const isActiveAndHasChanges =
        serviceItem?.status === ServiceItemStatus.ACTIVE &&
        (hasEditedForm || isServiceItemDirty);

      if (isActiveAndHasChanges) {
        openActiveServiceItemHasChangesModal();
        return;
      }

      if (!serviceItem || isServiceItemDirty || !voluntarySaved) {
        openExitOrSaveModal();
      } else {
        handleNavigateToServiceItems();
      }
    } else {
      openExitOrContinueModal();
    }
  };

  const handleActivate = () => {
    if (
      !isValidStep(Step.BASIC_INFORMATION) ||
      !isValidStep(Step.FORM) ||
      !isValidStep(Step.ASSIGNMENT) ||
      !isValidStep(Step.COLLABORATORS)
    ) {
      setShowCreationValidations(true);
      openCantActivateModal();
      return;
    }

    if (serviceItem?.status === ServiceItemStatus.ACTIVE) {
      openConfirmActiveServiceItemChangesModal();
      return;
    }

    // At this point the service item is not yet ACTIVE — update the draft and
    // then transition its status. The early return above guarantees the
    // service item, if it exists, is in a non-ACTIVE state.
    updateDraftMutation.mutate(undefined, {
      onSuccess: () => changeStatusMutation.mutate(ServiceItemStatus.ACTIVE),
    });
  };

  const modals: ReactNode = (
    <Fragment>
      {cantActivateModal}
      {exitOrSaveModal}
      {exitOrContinueModal}
      {activeServiceItemHasChangesModal}
      {confirmActiveServiceItemChangesModal}
    </Fragment>
  );

  return {
    voluntarySaved,
    handlers: {
      onSave: handleSave,
      onActivate: handleActivate,
      onExit: handleExit,
    },
    modals,
  };
};

export default useServiceItemActions;
