import type { Song, PlaylistNode } from '../types/interfaces'; const API_BASE_URL = import.meta.env.VITE_API_URL || 'http://localhost:3000/api'; export interface PaginationInfo { page: number; limit: number; totalSongs: number; totalPages: number; hasNextPage: boolean; hasPrevPage: boolean; } export interface SongsResponse { songs: Song[]; pagination: PaginationInfo; totalDuration?: number; // Total duration of the entire playlist in seconds } class Api { // Legacy method for backward compatibility async getSongs(): Promise { const response = await fetch(`${API_BASE_URL}/songs`); if (!response.ok) throw new Error('Failed to fetch songs'); return response.json(); } // New paginated method for all songs async getSongsPaginated(page: number = 1, limit: number = 100, search: string = ''): Promise { const params = new URLSearchParams({ page: page.toString(), limit: limit.toString(), ...(search && { search }) }); const response = await fetch(`${API_BASE_URL}/songs?${params}`); if (!response.ok) throw new Error('Failed to fetch songs'); return response.json(); } // New paginated method for playlist songs async getPlaylistSongsPaginated(playlistName: string, page: number = 1, limit: number = 100, search: string = ''): Promise { const params = new URLSearchParams({ page: page.toString(), limit: limit.toString(), ...(search && { search }) }); const encodedPlaylistName = encodeURIComponent(playlistName); const response = await fetch(`${API_BASE_URL}/songs/playlist/${encodedPlaylistName}?${params}`); if (!response.ok) throw new Error('Failed to fetch playlist songs'); return response.json(); } // Get total song count async getSongCount(): Promise { const response = await fetch(`${API_BASE_URL}/songs/count`); if (!response.ok) throw new Error('Failed to fetch song count'); const data = await response.json(); return data.count; } async saveSongs(songs: Song[]): Promise { const response = await fetch(`${API_BASE_URL}/songs/batch`, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(songs), }); if (!response.ok) throw new Error('Failed to save songs'); return response.json(); } async getPlaylists(): Promise { const response = await fetch(`${API_BASE_URL}/playlists`); if (!response.ok) throw new Error('Failed to fetch playlists'); return response.json(); } // Get playlist structure only (without track data) for faster loading async getPlaylistStructure(): Promise { const response = await fetch(`${API_BASE_URL}/playlists/structure`); if (!response.ok) throw new Error('Failed to fetch playlist structure'); return response.json(); } async savePlaylists(playlists: PlaylistNode[]): Promise { const response = await fetch(`${API_BASE_URL}/playlists/batch`, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(playlists), }); if (!response.ok) throw new Error('Failed to save playlists'); return response.json(); } async resetDatabase(): Promise { try { const response = await fetch(`${API_BASE_URL}/reset`, { method: 'POST', }); if (!response.ok) { throw new Error('Failed to reset database'); } return true; } catch (error) { console.error('Error resetting database:', error); throw error; } } // Background job methods async startBackgroundJob(type: 's3-sync' | 'song-matching', options?: any): Promise<{ jobId: string; type: string }> { const response = await fetch(`${API_BASE_URL}/background-jobs/start`, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ type, options }), }); if (!response.ok) throw new Error('Failed to start background job'); return response.json(); } async getJobProgress(jobId: string): Promise { const response = await fetch(`${API_BASE_URL}/background-jobs/progress/${jobId}`); if (!response.ok) throw new Error('Failed to get job progress'); return response.json(); } async getAllJobs(): Promise { const response = await fetch(`${API_BASE_URL}/background-jobs/jobs`); if (!response.ok) throw new Error('Failed to get jobs'); const data = await response.json(); return data.jobs; } // Duplicates API async getDuplicateSongs(minGroupSize: number = 2): Promise<{ groups: Array<{ key: string; normalizedTitle: string; normalizedArtist: string; count: number; items: Array<{ songId: string; title: string; artist: string; location?: string; totalTime?: string; averageBpm?: string; bitRate?: string; playlists: string[]; }>; }>; }> { const params = new URLSearchParams({ minGroupSize: String(minGroupSize) }); const response = await fetch(`${API_BASE_URL}/songs/duplicates?${params}`); if (!response.ok) throw new Error('Failed to fetch duplicates'); return response.json(); } async deleteDuplicateSongs(targetSongId: string, redundantSongIds: string[], deleteMusicFiles: boolean): Promise<{ deletedSongs: number; unlinkedOrDeletedMusicFiles: number; }>{ const response = await fetch(`${API_BASE_URL}/songs/delete-duplicates`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ targetSongId, redundantSongIds, deleteMusicFiles }) }); if (!response.ok) throw new Error('Failed to delete duplicates'); return response.json(); } } export const api = new Api();