import jwt_decode from "jwt-decode";
import { useEffect, useRef } from "react";

interface AppToken {
  exp?: number;
  iat?: number;
}

const TIME_BEFORE_REFRESH = 30 * 1000; // 30 seconds

const useTokenRefresh = (token?: string, refetch?: () => void) => {
  let decoded: AppToken = {
    exp: 0,
    iat: 0,
  };

  // For some reason jwt_decode causes seemingly unrelated error in tests
  // It seems like at some point undefined token is passed
  // Wrapping it in try..catch and if fixes the issue
  try {
    if (token) {
      decoded = jwt_decode(token) as AppToken;
    }
  } catch (e) {
    console.warn(e);
  }

  const decodedSuccesfully = !!decoded?.iat && !!decoded?.exp;

  const refreshTimeout = useRef<null | ReturnType<typeof setTimeout>>(null);

  const tokenLife = ((decoded?.exp || 0) - (decoded?.iat || 0)) * 1000; // in ms
  const refreshTime = tokenLife - TIME_BEFORE_REFRESH;

  const setUpTimeout = () => {
    if (refetch) {
      refetch();
    }
    createTimeout();
  };

  const createTimeout = () => {
    refreshTimeout.current = setTimeout(setUpTimeout, refreshTime);
  };

  const deleteTimeout = () => {
    if (refreshTimeout?.current) {
      clearTimeout(refreshTimeout.current);
      refreshTimeout.current = null;
    }
  };

  useEffect(() => {
    if (refetch && decodedSuccesfully) {
      createTimeout();
    }

    return () => {
      if (!!refetch && decodedSuccesfully) {
        deleteTimeout();
      }
    };
  }, [token]);
};

export default useTokenRefresh;
