/* global React, SHASTE_API */

const FOCUS_STALE_MS = 30 * 1000;

function createApiHook(apiMethodName) {
  return function useApiResource(...params) {
    const [loading, setLoading] = React.useState(true);
    const [error, setError] = React.useState(null);
    const [data, setData] = React.useState(null);

    const lastFetchedAtRef = React.useRef(0);
    const inFlightRef = React.useRef(false);

    const fetchData = React.useCallback(async (force = false) => {
      const now = Date.now();
      const isStale = now - lastFetchedAtRef.current >= FOCUS_STALE_MS;

      if (!force && !isStale && data !== null) {
        return;
      }

      if (inFlightRef.current) {
        return;
      }

      if (!SHASTE_API || typeof SHASTE_API[apiMethodName] !== 'function') {
        setError(new Error(`SHASTE_API.${apiMethodName} is not available`));
        setLoading(false);
        return;
      }

      inFlightRef.current = true;
      setLoading(true);
      setError(null);

      try {
        const result = await SHASTE_API[apiMethodName](...params);
        setData(result);
        lastFetchedAtRef.current = Date.now();
      } catch (err) {
        setError(err);
      } finally {
        inFlightRef.current = false;
        setLoading(false);
      }
    }, [apiMethodName, data, ...params]);

    React.useEffect(() => {
      fetchData(true);
    }, [fetchData]);

    React.useEffect(() => {
      function onFocus() {
        if (Date.now() - lastFetchedAtRef.current >= FOCUS_STALE_MS) {
          fetchData(true);
        }
      }

      window.addEventListener('focus', onFocus);
      return () => window.removeEventListener('focus', onFocus);
    }, [fetchData]);

    return { loading, error, data, refetch: fetchData };
  };
}

const useProfile = createApiHook('getProfile');
const useProgression = createApiHook('getProgression');
const useReferrals = createApiHook('getReferrals');
const useAchievements = createApiHook('getAchievementsAll');
const useCoins = createApiHook('getCoins');
const useOnboarding = createApiHook('getOnboarding');
const useGameProgress = createApiHook('getGameProgress');
const useGameTokens = createApiHook('getGameTokens');
const useShop = createApiHook('getShop');
const useCurrentVote = createApiHook('getCurrentVote');

Object.assign(window, {
  useProfile,
  useProgression,
  useReferrals,
  useAchievements,
  useCoins,
  useOnboarding,
  useGameProgress,
  useGameTokens,
  useShop,
  useCurrentVote,
});
