import {
  QueryClient,
  QueryKey,
  SetDataOptions,
  useQueries,
  useQuery,
} from '@tanstack/react-query';
import { WritableDraft, produce } from 'immer';
import {
  deepCamelKeys, // deepSnakeKeys,
} from 'string-ts';

import { useStores } from '@/app/(root)/AppProviders';
import { ClipEntity } from '@/state/clipStore';

export const clipsKeys = {
  all: [{ scope: 'clips' }] as const,
  clips: () => [{ ...clipsKeys.all[0], entity: 'clips' }] as const,
  clip: ({ clipId }: { clipId?: string } = {}) =>
    [{ ...clipsKeys.clips()[0], clipId }] as const,
};

/**
 * Updates a specific comment using the given mutation function
 */
export function updateClipData(
  queryClient: QueryClient,
  queryKey: QueryKey,
  clip: ClipEntity | ((clip: WritableDraft<ClipEntity>) => void),
  options: SetDataOptions | null = { updatedAt: Date.now() }
) {
  const prevData = queryClient.getQueryData<ClipEntity>(queryKey);
  queryClient.setQueryData<ClipEntity>(
    queryKey,
    typeof clip === 'function' ? (prevData) => produce(prevData, clip) : clip,
    options ?? undefined
  );
  return prevData;
}

export function useClipById(
  clipId?: string | null,
  options?: { enabled?: boolean }
) {
  const { enabled = !!clipId } = options || {};

  const { clips: clipsStore } = useStores();

  const result = useQuery({
    enabled,
    queryKey: clipsKeys.clip({ clipId: clipId || '' }),
    queryFn: async () => {
      if (!clipId) {
        return undefined;
      }
      const data = await clipsStore.loadClipById(clipId);
      // Preserve response as-is for legacy clipById
      clipsStore.updateClipById(data);
      // camelCase the version in query cache
      return deepCamelKeys(data);
    },
    staleTime: 5 * 60 * 1000,
  });
  return result;
}

export function useClipsByIds(
  clipIds: string[],
  options?: { enabled?: boolean }
) {
  const { enabled = true } = options || {};
  const { clips: clipsStore } = useStores();

  const result = useQueries({
    queries: clipIds.map((clipId) => ({
      enabled: enabled || !!clipId,
      queryKey: clipsKeys.clip({ clipId: clipId || '' }),
      queryFn: async () => {
        if (!clipId) {
          return undefined;
        }
        const data = await clipsStore.loadClipById(clipId);
        // Preserve response as-is for legacy clipById
        clipsStore.updateClipById(data);
        // camelCase the version in query cache
        return deepCamelKeys(data);
      },
      staleTime: 5 * 60 * 1000,
    })),
  });

  const isLoading = result.some((query) => query.isLoading);
  return {
    clips: result
      .map((query) => query.data)
      .filter((clip): clip is ClipEntity => clip != null),
    isLoading,
  };
}
