import type { Album } from './shared';
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { useClient } from 'hooks/useClient';
import { toast } from 'sonner';

// Every mutation the /photos panels can perform, in one place.
//
// All of them are bulk-shaped even when the UI is acting on a single tile: Immich's own API is
// `PUT /assets {ids, …}` / `DELETE /assets {ids}`, and having one code path means the selection bar and the
// lightbox's single-asset buttons cannot drift into behaving differently.
//
// Invalidation is broad — the whole ['photos'] key. Favoriting an asset changes the favorites bucket index,
// the timeline tile, the album cover and the asset detail; the queries are cheap and correctness is worth
// more than a surgical cache patch.

export function useAssetActions() {
  const { put, post, patch, delete: del } = useClient();
  const qc = useQueryClient();
  const invalidate = () => qc.invalidateQueries({ queryKey: ['photos'] });

  const fail = (verb: string) => (err: unknown) =>
    toast.error(`Could not ${verb}: ${err instanceof Error ? err.message : String(err)}`);

  const setFavorite = useMutation({
    mutationFn: ({ ids, isFavorite }: { ids: string[]; isFavorite: boolean }) =>
      put('/photos/_officer/assets', { ids, isFavorite }),
    onSuccess: invalidate,
    onError: fail('update favorites'),
  });

  const setArchived = useMutation({
    mutationFn: ({ ids, archived }: { ids: string[]; archived: boolean }) =>
      put('/photos/_officer/assets', { ids, visibility: archived ? 'archive' : 'timeline' }),
    onSuccess: () => {
      invalidate();
      toast.success('Moved');
    },
    onError: fail('archive'),
  });

  // Immich's delete is a move to trash unless `force`. Keep those as two named actions rather than one with a
  // boolean at the call site — "delete" and "delete permanently" should not look alike in the code either.
  const trash = useMutation({
    mutationFn: (ids: string[]) => del('/photos/_officer/assets', { ids }),
    onSuccess: (_data, ids) => {
      invalidate();
      toast.success(`${ids.length} moved to trash`);
    },
    onError: fail('delete'),
  });

  const deleteForever = useMutation({
    mutationFn: (ids: string[]) => del('/photos/_officer/assets', { ids, force: true }),
    onSuccess: (_data, ids) => {
      invalidate();
      toast.success(`${ids.length} permanently deleted`);
    },
    onError: fail('delete permanently'),
  });

  const restore = useMutation({
    mutationFn: (ids: string[]) => post('/photos/_officer/trash/restore/assets', { ids }),
    onSuccess: (_data, ids) => {
      invalidate();
      toast.success(`${ids.length} restored`);
    },
    onError: fail('restore'),
  });

  const emptyTrash = useMutation({
    mutationFn: () => post('/photos/_officer/trash/empty'),
    onSuccess: () => {
      invalidate();
      toast.success('Trash emptied');
    },
    onError: fail('empty the trash'),
  });

  const addToAlbum = useMutation({
    mutationFn: ({ albumId, ids }: { albumId: string; ids: string[] }) =>
      put(`/photos/_officer/albums/${albumId}/assets`, { ids }),
    onSuccess: (_data, { ids }) => {
      invalidate();
      toast.success(`${ids.length} added to album`);
    },
    onError: fail('add to the album'),
  });

  const removeFromAlbum = useMutation({
    mutationFn: ({ albumId, ids }: { albumId: string; ids: string[] }) =>
      del(`/photos/_officer/albums/${albumId}/assets`, { ids }),
    onSuccess: () => {
      invalidate();
      toast.success('Removed from album');
    },
    onError: fail('remove from the album'),
  });

  const createAlbum = useMutation({
    mutationFn: ({ albumName, assetIds }: { albumName: string; assetIds?: string[] }) =>
      post<Album>('/photos/_officer/albums', { albumName, assetIds: assetIds ?? [] }),
    onSuccess: invalidate,
    onError: fail('create the album'),
  });

  const deleteAlbum = useMutation({
    mutationFn: (albumId: string) => del(`/photos/_officer/albums/${albumId}`),
    onSuccess: () => {
      invalidate();
      toast.success('Album deleted');
    },
    onError: fail('delete the album'),
  });

  // PATCH, not PUT: on Immich, PUT /albums/{id}/assets means "add assets" — the album itself is patched.
  const renameAlbum = useMutation({
    mutationFn: ({ albumId, albumName }: { albumId: string; albumName: string }) =>
      patch(`/photos/_officer/albums/${albumId}`, { albumName }),
    onSuccess: invalidate,
    onError: fail('rename the album'),
  });

  return {
    setFavorite,
    setArchived,
    trash,
    deleteForever,
    restore,
    emptyTrash,
    addToAlbum,
    removeFromAlbum,
    createAlbum,
    deleteAlbum,
    renameAlbum,
  };
}
