import { createQuery } from '@tanstack/svelte-query'; import { api } from './client'; import { qk } from './queries'; import type { Playlist, PlaylistDetail } from './types'; export type PlaylistKind = 'user' | 'system' | 'all'; export type ListPlaylistsResponse = { owned: Playlist[]; public: Playlist[]; }; export async function listPlaylists(kind?: PlaylistKind): Promise { const k = kind ?? 'user'; return api.get(`/api/playlists?kind=${k}`); } export async function getPlaylist(id: string): Promise { return api.get(`/api/playlists/${encodeURIComponent(id)}`); } // #415 stage 2/3: rotation-aware play order for a system playlist. // Same shape as getPlaylist but tracks are server-ordered (unplayed // this rotation first, then heard; resets when exhausted). // Intentionally uncached — it varies per play, unlike getPlaylist. // {variant} is the raw system_variant (#411 R2: generic by-kind). export async function systemShuffle(variant: string): Promise { return api.get( `/api/playlists/system/${encodeURIComponent(variant)}/shuffle`, ); } // #411 R2: generic by-kind refresh. Rebuilds the caller's system // playlists and returns the named kind's fresh row. Replaces the // former per-kind refreshForYou/refreshDiscover. export type RefreshSystemResponse = { playlist_id: string | null; track_count: number; track_ids: string[]; }; export async function refreshSystem(variant: string): Promise { return api.post( `/api/playlists/system/${encodeURIComponent(variant)}/refresh`, {}, ); } export type CreatePlaylistInput = { name: string; description?: string; is_public?: boolean; }; export async function createPlaylist(input: CreatePlaylistInput): Promise { return api.post('/api/playlists', input); } export type UpdatePlaylistInput = { name?: string; description?: string; is_public?: boolean; }; export async function updatePlaylist(id: string, input: UpdatePlaylistInput): Promise { return api.patch(`/api/playlists/${encodeURIComponent(id)}`, input); } export async function deletePlaylist(id: string): Promise { await api.del(`/api/playlists/${encodeURIComponent(id)}`); } export async function appendTracks(playlistID: string, trackIDs: string[]): Promise { return api.post( `/api/playlists/${encodeURIComponent(playlistID)}/tracks`, { track_ids: trackIDs } ); } export async function removePlaylistTrack(playlistID: string, position: number): Promise { return api.del( `/api/playlists/${encodeURIComponent(playlistID)}/tracks/${position}` ); } export async function reorderPlaylist(playlistID: string, orderedPositions: number[]): Promise { return api.put( `/api/playlists/${encodeURIComponent(playlistID)}/tracks`, { ordered_positions: orderedPositions } ); } export function createPlaylistsQuery(kind?: PlaylistKind) { return createQuery({ queryKey: qk.playlists(kind), queryFn: () => listPlaylists(kind), staleTime: 30_000 }); } export function createPlaylistQuery(id: string) { return createQuery({ queryKey: qk.playlist(id), queryFn: () => getPlaylist(id), staleTime: 30_000 }); }