import { useQuery, useQueryClient } from '@tanstack/react-query';

/**
 * Where a `useGlobal` slot lives in the query cache. Exported so a value can be put there before anything
 * renders — `initialData` only applies to whichever component reads the slot first, so a slot that must be
 * populated regardless of mount order has to be written, not defaulted.
 */
export const globalQueryKey = (key: string | string[]) =>
  Array.isArray(key) ? ['USE_GLOBAL', ...key] : ['USE_GLOBAL', key];

export const useGlobal = <T>(key: string | string[], initialData: T | (() => T)) => {
  const queryClient = useQueryClient();

  const theKey = globalQueryKey(key);
  const theInitialData = typeof initialData === 'function' ? (initialData as () => T)() : initialData;

  const { data } = useQuery<T>({
    queryKey: theKey,
    enabled: false,
    queryFn: () => theInitialData,
    initialData: theInitialData,
    staleTime: Infinity,
  });

  const setData: React.Dispatch<React.SetStateAction<T>> = (arg) => {
    const val = typeof arg === 'function' ? (arg as (arg0: T) => T)(data as T) : arg;
    queryClient.setQueryData(theKey, () => val);
  };

  const reset = () => {
    queryClient.removeQueries({ queryKey: theKey });
  };

  const refresh = () => {
    queryClient.invalidateQueries({ queryKey: theKey });
  };

  return [data!, setData, refresh, reset] as const;
};
