import { apiClient } from '@/services/api/client'; import { Track, PaginatedResponse, TrackDTO } from '@/types/api'; import { trackSchema } from '@/schemas/apiSchemas'; import { uploadService, UploadMetadata } from './uploadService'; const env = { API_URL: import.meta.env.VITE_API_URL || '', }; const mapTrackDTO = (dto: TrackDTO): Track => ({ id: dto.id, title: dto.title, artist: typeof dto.artist === 'object' ? (dto.artist as any).name : dto.artist, album: dto.album || 'Unknown', duration: dto.duration_formatted || '0:00', durationSec: dto.duration || 0, genre: dto.genre || 'None', year: dto.year || new Date().getFullYear(), coverUrl: dto.cover_art_path ? `${env.API_URL}${dto.cover_art_path}` : undefined, cover_art_path: dto.cover_art_path, filePath: dto.file_path, file_path: dto.file_path, file_size: dto.file_size || 0, format: dto.format || 'mp3', bitrate: dto.bitrate || 0, sample_rate: dto.sample_rate || 0, play_count: dto.play_count || 0, like_count: dto.like_count || 0, plays: dto.play_count || 0, likes: dto.like_count || 0, created_at: dto.created_at, updated_at: dto.updated_at, creator_id: dto.creator_id, is_public: dto.is_public ?? true, status: dto.status as any, stream_status: (dto.stream_status as any) || 'pending', stream_manifest_url: dto.stream_manifest_url, } as Track); export const trackService = { list: async (params?: { user_id?: string; artist?: string; genre?: string; page?: number; limit?: number; sort_by?: string; order?: 'asc' | 'desc'; query?: string; search?: string; }) => { const response = await apiClient.get>('/tracks', { params: { ...params, query: params?.query || params?.search } }); const data = response.data; const items = data.items || []; return { tracks: items.map(mapTrackDTO), pagination: { total: data.total, page: data.page, limit: data.limit, total_pages: data.total_pages, has_next: data.has_next, has_prev: data.has_prev } }; }, search: async (query: string) => { const response = await apiClient.get('/tracks/search', { params: { query } }); return { tracks: response.data.map(mapTrackDTO) }; }, get: async (id: string) => { const response = await apiClient.get(`/tracks/${id}`, { validateSchema: trackSchema } as any); return { track: mapTrackDTO(response.data) }; }, update: async (id: string, data: Partial) => { const payload = { title: data.title, artist: data.artist, album: data.album, genre: data.genre, is_public: data.is_public }; const response = await apiClient.put(`/tracks/${id}`, payload, { validateSchema: trackSchema } as any); return { track: mapTrackDTO(response.data) }; }, delete: async (id: string) => apiClient.delete(`/tracks/${id}`), like: async (id: string) => apiClient.post(`/tracks/${id}/like`), unlike: async (id: string) => apiClient.delete(`/tracks/${id}/like`), recordPlay: async (id: string) => apiClient.post(`/tracks/${id}/play`), download: async (id: string) => { const response = await apiClient.get(`/tracks/${id}/download`, { responseType: 'blob' }); return response.data; }, upload: async (file: File, metadata: UploadMetadata, onProgress?: (progress: number) => void) => { return await uploadService.uploadTrack(file, metadata, onProgress); }, getStatus: async (trackId: string) => { return await uploadService.getTrackStatus(trackId); } };