import { type AxiosRequestConfig } from 'axios';
import { jwtDecode } from 'jwt-decode';
import { throttle, unescape } from 'lodash-es';

import { clearInactivityStorage } from 'src/components/InactivityTimer/utils';
import { clearUser, logEvent } from 'src/config/logging';
import { requestManager } from 'src/config/RequestManager';
import { queryClient } from 'src/config/react-query';
import { tokenManager } from 'src/config/tokens';
import { EventName } from 'src/types/amplitude';
import { type TokenPayload } from 'src/types/login';

import wait from './wait';

export const getDecodedToken = () => {
  const { accessToken } = tokenManager.getCorrectToken();
  return jwtDecode<TokenPayload>(accessToken!);
};

const kickOutUser = async (hardRedirect = false) => {
  requestManager.abortAllRequests();
  clearInactivityStorage();
  queryClient.clear();
  logEvent(EventName.USER_LOGOUT);
  await wait(250);
  tokenManager.removeTokens();
  clearUser();
  // Hard redirect is only used for forced session expiry (API interceptors) so that tokens
  // and user state are fully cleared before the page navigates. Intentional logout
  // (JWTContext) passes false and lets React Router handle navigation via auth state,
  // avoiding a jarring full page reload.
  if (hardRedirect) {
    window.location.replace('/');
  }
};

export const kickOutUserThrottled = throttle(kickOutUser, 5000);

export const unescapeStrings = (data: unknown): unknown => {
  if (typeof data === 'string') {
    return unescape(data);
  } else if (Array.isArray(data)) {
    return data.map(unescapeStrings);
  } else if (data !== null && typeof data === 'object') {
    return Object.keys(data).reduce((acc: Record<string, unknown>, key) => {
      acc[key] = unescapeStrings(data[key as keyof typeof data]);
      return acc;
    }, {});
  }
  return data;
};
