import { useMutation } from 'react-query';

import { queryClient } from 'src/config/react-query';
import { type RequestError, type RequestSuccess } from 'src/types/services';

import {
  CertificateAction,
  CertificateInUseToastNeutral,
  CertificateStatus,
} from '../constants';
import { learningCertificatesKeys } from '../queries';
import { patchLearningCertificateStatus } from '../services';
import { type PatchLearningCertificateStatusParams } from '../types';
import {
  getCertificateActionFromStatus,
  isLearningCertificateInUseError,
} from '../utils';
import {
  type LearningCertificatesListSnapshot,
  optimisticallyUpdateLearningCertificatesList,
  restoreLearningCertificatesListQueries,
} from '../utils/queries';

import { useCertificateActionSnackbars } from './useCertificateActionSnackbars';

export type TSuccess = RequestSuccess<typeof patchLearningCertificateStatus>;
export type TError = RequestError;
export type TValues = PatchLearningCertificateStatusParams;
type TContext = { previousQueries: LearningCertificatesListSnapshot };

export const usePatchLearningCertificateStatus = () => {
  const snackbars = useCertificateActionSnackbars();

  return useMutation<TSuccess, TError, TValues, TContext>({
    mutationFn: patchLearningCertificateStatus,
    onMutate: async ({ certificateId, status }) => {
      const previousQueries =
        await optimisticallyUpdateLearningCertificatesList(items =>
          items.map(certificate => ({
            ...certificate,
            status:
              certificate.id === certificateId ? status : certificate.status,
          })),
        );

      return { previousQueries };
    },
    onSuccess: (_, { certificateName, status }) => {
      snackbars.success(
        getCertificateActionFromStatus(status),
        certificateName,
      );
    },
    onError: (error, { status }, context) => {
      if (context?.previousQueries) {
        restoreLearningCertificatesListQueries(context.previousQueries);
      }

      const action = getCertificateActionFromStatus(status);

      if (isLearningCertificateInUseError(error)) {
        snackbars.inUseError(
          status === CertificateStatus.INACTIVE
            ? CertificateAction.DEACTIVATE
            : CertificateInUseToastNeutral,
        );
        return;
      }

      snackbars.error(action);
    },
    onSettled: () => {
      queryClient.invalidateQueries(learningCertificatesKeys.list.all());
    },
  });
};
