import { createQuery, createInfiniteQuery } from '@tanstack/svelte-query';
import { api } from './client';
import { pageGetNextPageParam } from './paging';
import type {
  ArtistRef,
  ArtistDetail,
  AlbumRef,
  AlbumDetail,
  Page,
  SearchResponse,
  TrackRef
} from './types';

export type ArtistSort = 'alpha' | 'newest';
export const ARTIST_PAGE_SIZE = 50;
export const SEARCH_SUMMARY_LIMIT = 10;
export const SEARCH_FACET_PAGE_SIZE = 50;

export const qk = {
  artists: (sort: ArtistSort) => ['artists', { sort }] as const,
  artist:  (id: string)       => ['artist', id] as const,
  album:   (id: string)       => ['album', id] as const,
  search:        (q: string) => ['search', { q }] as const,
  searchArtists: (q: string) => ['searchArtists', { q }] as const,
  searchAlbums:  (q: string) => ['searchAlbums',  { q }] as const,
  searchTracks:  (q: string) => ['searchTracks',  { q }] as const,
  likedIds:      ()          => ['likedIds'] as const,
  likedTracks:   ()          => ['likedTracks'] as const,
  likedAlbums:   ()          => ['likedAlbums'] as const,
  likedArtists:  ()          => ['likedArtists'] as const,
  history:       ()          => ['history'] as const,
  // Lidarr / requests / admin.
  lidarrSearch:          (q: string, kind: string) =>
    ['lidarrSearch', { q, kind }] as const,
  myRequests:            () => ['myRequests'] as const,
  lidarrConfig:          () => ['lidarrConfig'] as const,
  lidarrQualityProfiles:  () => ['lidarrQualityProfiles'] as const,
  lidarrMetadataProfiles: () => ['lidarrMetadataProfiles'] as const,
  lidarrRootFolders:      () => ['lidarrRootFolders'] as const,
  adminRequests:         (status?: string) =>
    ['adminRequests', { status: status ?? 'all' }] as const,
  myQuarantine:           ()              => ['myQuarantine'] as const,
  adminQuarantine:        ()              => ['adminQuarantine'] as const,
  adminQuarantineActions: (limit?: number) =>
    ['adminQuarantineActions', { limit: limit ?? 50 }] as const,
  adminPlaybackErrors:    (resolved?: boolean) =>
    ['adminPlaybackErrors', { resolved: resolved ?? false }] as const,
  scanStatus:             ()              => ['scanStatus'] as const,
  coverage:               ()              => ['coverage'] as const,
  coverProviders:         ()              => ['coverProviders'] as const,
  tagProviders:           ()              => ['tagProviders'] as const,
  adminUsers:             ()              => ['adminUsers'] as const,
  adminInvites:           ()              => ['adminInvites'] as const,
  adminDiagnostics:       (f: Record<string, string | number | undefined>) =>
    ['adminDiagnostics', f] as const,
  adminDiagnosticDevices: (userId?: string) =>
    ['adminDiagnosticDevices', { userId: userId ?? 'all' }] as const,
  smtpConfig:             ()              => ['smtpConfig'] as const,
  suggestions:            (limit?: number) =>
    ['suggestions', { limit: limit ?? 12 }] as const,
  suggestionSnoozes:      ()              => ['suggestionSnoozes'] as const,
  home:         ()                 => ['home'] as const,
  albumsAlpha:  ()                 => ['albumsAlpha'] as const,
  artistTracks: (artistId: string) => ['artistTracks', artistId] as const,
  similarArtists:  (artistId: string) => ['similarArtists', artistId] as const,
  artistTopTracks: (artistId: string) => ['artistTopTracks', artistId] as const,
  playlists:                (kind?: 'user' | 'system' | 'all') =>
    ['playlists', { kind: kind ?? 'user' }] as const,
  playlist:                 (id: string) => ['playlist', id] as const,
  systemPlaylistsStatus:    () => ['systemPlaylistsStatus'] as const,
  // Browse indexes (#367). Keys carry no arguments — both are whole-library
  // indexes, and the per-genre / per-year album lists are fetched outside
  // svelte-query because their selection comes from the URL.
  genres:                   () => ['genres'] as const,
  albumYears:               () => ['albumYears'] as const,
};

export function createArtistsQuery(sort: ArtistSort) {
  return createInfiniteQuery({
    queryKey: qk.artists(sort),
    queryFn: ({ pageParam = 0 }) =>
      api.get<Page<ArtistRef>>(
        `/api/artists?sort=${sort}&limit=${ARTIST_PAGE_SIZE}&offset=${pageParam}`
      ),
    initialPageParam: 0,
    getNextPageParam: pageGetNextPageParam<ArtistRef>(),
  });
}

export function createArtistQuery(id: string) {
  return createQuery({
    queryKey: qk.artist(id),
    queryFn: () => api.get<ArtistDetail>(`/api/artists/${id}`),
  });
}

export function createAlbumQuery(id: string) {
  return createQuery({
    queryKey: qk.album(id),
    queryFn: () => api.get<AlbumDetail>(`/api/albums/${id}`),
  });
}

export function createSimilarArtistsQuery(id: string) {
  return createQuery({
    queryKey: qk.similarArtists(id),
    queryFn: () => api.get<ArtistRef[]>(`/api/artists/${id}/similar`),
    enabled: id.length > 0,
  });
}

export function createArtistTopTracksQuery(id: string) {
  return createQuery({
    queryKey: qk.artistTopTracks(id),
    queryFn: () => api.get<TrackRef[]>(`/api/artists/${id}/top-tracks`),
    enabled: id.length > 0,
  });
}

export function createSearchQuery(q: string) {
  return createQuery({
    queryKey: qk.search(q),
    queryFn: () =>
      api.get<SearchResponse>(
        `/api/search?q=${encodeURIComponent(q)}&limit=${SEARCH_SUMMARY_LIMIT}`
      ),
    enabled: q.length > 0
  });
}

export function createSearchArtistsInfiniteQuery(q: string) {
  return createInfiniteQuery({
    queryKey: qk.searchArtists(q),
    queryFn: ({ pageParam = 0 }) =>
      api.get<SearchResponse>(
        `/api/search?q=${encodeURIComponent(q)}&limit=${SEARCH_FACET_PAGE_SIZE}&offset=${pageParam}`
      ).then((r) => r.artists),
    initialPageParam: 0,
    getNextPageParam: pageGetNextPageParam<ArtistRef>(),
    enabled: q.length > 0
  });
}

export function createSearchAlbumsInfiniteQuery(q: string) {
  return createInfiniteQuery({
    queryKey: qk.searchAlbums(q),
    queryFn: ({ pageParam = 0 }) =>
      api.get<SearchResponse>(
        `/api/search?q=${encodeURIComponent(q)}&limit=${SEARCH_FACET_PAGE_SIZE}&offset=${pageParam}`
      ).then((r) => r.albums),
    initialPageParam: 0,
    getNextPageParam: pageGetNextPageParam<AlbumRef>(),
    enabled: q.length > 0
  });
}

export function createSearchTracksInfiniteQuery(q: string) {
  return createInfiniteQuery({
    queryKey: qk.searchTracks(q),
    queryFn: ({ pageParam = 0 }) =>
      api.get<SearchResponse>(
        `/api/search?q=${encodeURIComponent(q)}&limit=${SEARCH_FACET_PAGE_SIZE}&offset=${pageParam}`
      ).then((r) => r.tracks),
    initialPageParam: 0,
    getNextPageParam: pageGetNextPageParam<TrackRef>(),
    enabled: q.length > 0
  });
}
