import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { useClient } from 'hooks/useClient';
import type { FavoriteKind, GroupedFavorites } from './shared';

const KEY = ['music', 'favorites'] as const;
const EMPTY: GroupedFavorites = { tracks: [], albums: [], artists: [] };
const groupOf = (kind: FavoriteKind): keyof GroupedFavorites =>
  kind === 'track' ? 'tracks' : kind === 'album' ? 'albums' : 'artists';

/**
 * The user's music favorites (tracks / albums / artists) for the /music workspace, backed by the
 * platform's `/api/music/favorites`. One shared react-query cache, so every heart reflects the same
 * state; toggling is optimistic (flips instantly, rolls back on failure).
 */
export function useMusicFavorites() {
  const { get, post, delete: del } = useClient();
  const qc = useQueryClient();

  const { data } = useQuery({
    queryKey: KEY,
    queryFn: () => get<GroupedFavorites>('/music/favorites'),
    staleTime: 60_000,
  });

  const mutation = useMutation({
    mutationFn: ({ on, kind, key }: { on: boolean; kind: FavoriteKind; key: string }) =>
      on
        ? post('/music/favorites', { kind, key })
        : del(`/music/favorites?kind=${encodeURIComponent(kind)}&key=${encodeURIComponent(key)}`),
    onMutate: async ({ on, kind, key }) => {
      await qc.cancelQueries({ queryKey: KEY });
      const prev = qc.getQueryData<GroupedFavorites>(KEY) ?? EMPTY;
      const g = groupOf(kind);
      qc.setQueryData<GroupedFavorites>(KEY, {
        ...prev,
        [g]: on ? [key, ...prev[g].filter((k) => k !== key)] : prev[g].filter((k) => k !== key),
      });
      return { prev };
    },
    onError: (_e, _v, ctx) => {
      if (ctx?.prev) qc.setQueryData(KEY, ctx.prev);
    },
  });

  const isFavorite = (kind: FavoriteKind, key: string) => (data ?? EMPTY)[groupOf(kind)].includes(key);
  const toggle = (kind: FavoriteKind, key: string) => {
    if (!key) return;
    mutation.mutate({ on: !isFavorite(kind, key), kind, key });
  };

  return { favorites: data ?? EMPTY, isFavorite, toggle };
}
