import { AxiosError } from 'axios';
import { useLocation, useNavigate } from 'react-router';
import { SearchParamKeys } from '../lib/constants';
import { useQueryMessage } from './useQueryMessage';
import { QueryMessageCode, QueryMessageType } from '../lib/QueryMessages';
import { useCallback } from 'react';
import { displayForbiddenErrorToast, displayNetworkErrorToast, displayUnexpectedErrorToast } from '../lib/toasts';

export enum ResponseErrorToastId {
  NetworkError = 'network-error',
}

export type DefaultResponseErrorHandlerOptions = {
  disableUnauthorizedHandling?: boolean;
  disableHandleUnexpectedErrors?: boolean;
  disableIgnoreCanceledRequests?: boolean;
};

/**
 *
 * @param err error value
 * @returns {boolean} true if the error was handled, false otherwise
 */

export function useResponseErrorHandler(): {
  defaultResponseErrorHandler: typeof defaultResponseErrorHandler;
} {
  const navigate = useNavigate();
  const location = useLocation();
  const { toSearchParamQueryMessage } = useQueryMessage();

  const defaultResponseErrorHandler = useCallback(
    (err: unknown, options?: DefaultResponseErrorHandlerOptions): boolean => {
      if (!(err instanceof AxiosError) && !options?.disableHandleUnexpectedErrors) {
        displayUnexpectedErrorToast();
        return true;
      }

      if (!(err instanceof AxiosError)) return false;

      if (err.message === 'canceled') {
        // request was aborted, ignore but return true to indicate it was handled
        return !options?.disableIgnoreCanceledRequests;
      }

      if (err.message === 'Network Error') {
        displayNetworkErrorToast();
        return true;
      }

      // handle 401 Unauthorized globally
      if (err.status === 401 && !options?.disableUnauthorizedHandling) {
        // store current path for redirect after login
        const currentPath = location.pathname + location.search;
        const searchParam = new URLSearchParams();
        searchParam.set(SearchParamKeys.Redirect, currentPath);
        searchParam.set(SearchParamKeys.Message, toSearchParamQueryMessage(QueryMessageCode.SessionExpired, QueryMessageType.Info));
        navigate(`/login?${searchParam.toString()}`);
        return true;
      }

      if (err.status === 403) {
        displayForbiddenErrorToast();
        return true;
      }

      return false;
    },
    [location, navigate, toSearchParamQueryMessage]
  );

  return { defaultResponseErrorHandler };
}
