import { queryClient } from 'src/config/react-query';
import { Updater, DataUpdateFunction } from 'src/types/queries';

export function functionalUpdate<TData>(
  updater: Updater<TData>,
  input: TData,
): TData {
  return typeof updater === 'function'
    ? (updater as DataUpdateFunction<TData>)(input)
    : updater;
}

/**
 * Optimistic update for queries based on https://tanstack.com/query/v4/docs/framework/react/guides/optimistic-updates
 */
export const optimisticUpdate = async <
  VariableType,
  CacheUpdateFnProps = VariableType,
>(
  variables: VariableType,
  queryKey: string | string[],
  cacheUpdateFn: (variables: CacheUpdateFnProps) => void,
  variablesToCacheUpdateFn?: (variables: VariableType) => CacheUpdateFnProps,
) => {
  // Cancel any outgoing refetches
  // (so they don't overwrite our optimistic update)
  await queryClient.cancelQueries({ queryKey });

  // Snapshot the previous value
  const previousCacheValue = queryClient.getQueryData(queryKey);

  // Optimistically update to the new value
  cacheUpdateFn(
    variablesToCacheUpdateFn
      ? variablesToCacheUpdateFn(variables)
      : (variables as unknown as CacheUpdateFnProps),
  );

  // Return a context with the previous value
  return { previousCacheValue };
};

/**
 * Restore the previous value for queries based on https://tanstack.com/query/v4/docs/framework/react/guides/optimistic-updates
 * This requires the context returned from the optimisticUpdate function
 */
export const optimisticRestore = async (
  queryKey: string | string[],
  context: { previousCacheValue },
) => {
  queryClient.setQueryData(queryKey, context.previousCacheValue);
};
