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

import { useClient } from '@/hooks/use-client';
import { useFeatures } from '@/hooks/use-features';

import type { DriveFolder } from 'pl-api';

const useDriveFolderQuery = (folderId?: string) => {
  const client = useClient();
  const features = useFeatures();

  return useQuery({
    queryKey: ['drive', 'folders', folderId],
    queryFn: () => (folderId ? client.drive.getFolder(folderId) : client.drive.getDrive()),
    enabled: features.drive,
  });
};

const useCreateDriveFolderMutation = () => {
  const client = useClient();
  const queryClient = useQueryClient();

  return useMutation({
    mutationKey: ['drive', 'folders'],
    mutationFn: ({ name, parentId }: { name: string; parentId?: string }) =>
      client.drive.createFolder(name, parentId),
    onSuccess: (folder) => {
      queryClient.setQueryData(['drive', 'folders', folder.id], folder);
      queryClient.invalidateQueries({
        queryKey: ['drive', 'folders', folder.parent_id ?? undefined],
        exact: true,
      });
    },
  });
};

const useUpdateDriveFolderMutation = (folderId: string) => {
  const client = useClient();
  const queryClient = useQueryClient();

  let previousParentId: string | null;

  return useMutation({
    mutationKey: ['drive', 'folders'],
    mutationFn: (name: string) => {
      const oldFolder = queryClient.getQueryData<DriveFolder>(['drive', 'folders', folderId]);
      if (oldFolder) {
        previousParentId = oldFolder.parent_id;
      } else {
        previousParentId = null;
      }
      return client.drive.updateFolder(folderId, name);
    },
    onSuccess: (folder) => {
      queryClient.setQueryData(['drive', 'folders', folder.id], folder);
      queryClient.invalidateQueries({
        queryKey: ['drive', 'folders', previousParentId],
        exact: true,
      });
    },
  });
};

const useDeleteDriveFolderMutation = (folderId: string) => {
  const client = useClient();
  const queryClient = useQueryClient();

  let previousParentId: string | null;

  return useMutation({
    mutationKey: ['drive', 'folders'],
    mutationFn: () => {
      const oldFolder = queryClient.getQueryData<DriveFolder>(['drive', 'folders', folderId]);
      if (oldFolder) {
        previousParentId = oldFolder.parent_id;
      } else {
        previousParentId = null;
      }
      return client.drive.deleteFolder(folderId);
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['drive', 'folders', folderId], exact: true });
      queryClient.invalidateQueries({
        queryKey: ['drive', 'folders', previousParentId],
        exact: true,
      });
    },
  });
};

const useMoveDriveFolderMutation = (folderId: string) => {
  const client = useClient();
  const queryClient = useQueryClient();

  let previousParentId: string | null;

  return useMutation({
    mutationKey: ['drive', 'folders'],
    mutationFn: (targetFolderId?: string) => {
      const oldFolder = queryClient.getQueryData<DriveFolder>(['drive', 'folders', folderId]);
      if (oldFolder) {
        previousParentId = oldFolder.parent_id;
      } else {
        previousParentId = null;
      }
      return client.drive.moveFolder(folderId, targetFolderId);
    },
    onSuccess: (_, targetFolderId) => {
      queryClient.invalidateQueries({ queryKey: ['drive', 'folders', folderId], exact: true });
      queryClient.invalidateQueries({
        queryKey: ['drive', 'folders', targetFolderId],
        exact: true,
      });
      if (previousParentId)
        queryClient.invalidateQueries({
          queryKey: ['drive', 'folders', previousParentId || undefined],
          exact: true,
        });
    },
  });
};

export {
  useDriveFolderQuery,
  useCreateDriveFolderMutation,
  useUpdateDriveFolderMutation,
  useDeleteDriveFolderMutation,
  useMoveDriveFolderMutation,
};
