import { apiClient } from '@/services/api/client';
import { Track, UploadProgress } from '../types/track';
import { AxiosError, AxiosProgressEvent } from 'axios';

/**
 * Track Service
 * T0260: Service frontend pour gérer l'upload de tracks
 * T0264: Amélioration gestion erreurs upload
 * T0275: Service frontend pour lister et récupérer les tracks
 * T0278: Service frontend pour mettre à jour les tracks
 * T0279: Service frontend pour supprimer les tracks
 * T0284: Service frontend pour gérer les likes de tracks
 * T0294: Service frontend pour analytics de lecture de tracks
 */

/**
 * Classe d'erreur personnalisée pour les uploads de tracks
 */
export class TrackUploadError extends Error {
  constructor(
    message: string,
    public code: 'VALIDATION' | 'QUOTA' | 'NETWORK' | 'SERVER' | 'UNKNOWN',
    public retryable: boolean = false,
    public originalError?: unknown
  ) {
    super(message);
    this.name = 'TrackUploadError';
  }
}

/**
 * Upload un fichier audio
 * @param file Fichier audio à uploader
 * @param onProgress Callback optionnel pour suivre la progression de l'upload
 * @returns Le track créé
 * @throws Error si la requête échoue
 */
export async function uploadTrack(
  file: File,
  onProgress?: (progress: number) => void
): Promise<Track> {
  try {
    const formData = new FormData();
    formData.append('file', file);

    const response = await apiClient.post<{ track: Track }>(
      '/tracks',
      formData,
      {
        headers: {
          'Content-Type': 'multipart/form-data',
        },
        onUploadProgress: (progressEvent: AxiosProgressEvent) => {
          if (progressEvent.total && onProgress) {
            const progress = Math.round((progressEvent.loaded * 100) / progressEvent.total);
            onProgress(progress);
          }
        },
        timeout: 300000, // 5 minutes timeout for large files
      }
    );

    return response.data.track;
  } catch (error) {
    if (error instanceof AxiosError) {
      // Gérer les erreurs spécifiques selon le code de statut HTTP
      if (error.response?.status === 400) {
        const errorMessage = error.response?.data?.error || 'Format ou taille invalide';
        throw new TrackUploadError(errorMessage, 'VALIDATION', false, error);
      }
// ... (keep existing error handling)
// ...
    }
    // Erreur inconnue
    throw new TrackUploadError(
      'Erreur inconnue lors de l\'upload',
      'UNKNOWN',
      false,
      error
    );
  }
}

/**
 * Initialise un upload par chunks
 * @param totalChunks Nombre total de chunks
 * @param totalSize Taille totale du fichier
 * @param filename Nom du fichier
 * @returns ID de l'upload
 */
export async function initiateChunkedUpload(
  totalChunks: number,
  totalSize: number,
  filename: string
): Promise<string> {
  const response = await apiClient.post<{ upload_id: string }>('/tracks/initiate', {
    total_chunks: totalChunks,
    total_size: totalSize,
    filename,
  });
  return response.data.upload_id;
}

/**
 * Upload un chunk
 * @param uploadId ID de l'upload
 * @param chunkNumber Numéro du chunk (1-based)
 * @param totalChunks Nombre total de chunks
 * @param totalSize Taille totale du fichier
 * @param filename Nom du fichier
 * @param chunk Blob du chunk
 * @param onProgress Callback de progression
 */
export async function uploadChunk(
  uploadId: string,
  chunkNumber: number,
  totalChunks: number,
  totalSize: number,
  filename: string,
  chunk: Blob,
  onProgress?: (progress: number) => void
): Promise<void> {
  const formData = new FormData();
  formData.append('upload_id', uploadId);
  formData.append('chunk_number', chunkNumber.toString());
  formData.append('total_chunks', totalChunks.toString());
  formData.append('total_size', totalSize.toString());
  formData.append('filename', filename);
  formData.append('chunk', chunk);

  await apiClient.post('/tracks/chunk', formData, {
    headers: {
      'Content-Type': 'multipart/form-data',
    },
    onUploadProgress: (progressEvent: AxiosProgressEvent) => {
      if (progressEvent.total && onProgress) {
        const progress = Math.round((progressEvent.loaded * 100) / progressEvent.total);
        onProgress(progress);
      }
    },
  });
}

/**
 * Complète un upload par chunks
 * @param uploadId ID de l'upload
 * @returns Le track créé
 */
export async function completeChunkedUpload(uploadId: string): Promise<Track> {
  const response = await apiClient.post<{ track: Track }>('/tracks/complete', {
    upload_id: uploadId,
  });
  return response.data.track;
}

/**
 * Récupère la progression d'un upload de track
 * @param trackId ID du track
 * @returns Les informations de progression
 * @throws Error si la requête échoue
 */
export async function getUploadProgress(trackId: number): Promise<UploadProgress> {
  try {
    const response = await apiClient.get<{ progress: UploadProgress }>(
      `/tracks/${trackId}/status`
    );
    return response.data.progress;
  } catch (error) {
    if (error instanceof AxiosError) {
      if (error.response?.status === 401) {
        throw new TrackUploadError(
          'Non autorisé: Veuillez vous connecter pour voir la progression',
          'VALIDATION',
          false,
          error
        );
      }
      if (error.response?.status === 404) {
        throw new TrackUploadError('Track introuvable', 'VALIDATION', false, error);
      }
      if (error.response?.status === 500) {
        throw new TrackUploadError(
          'Erreur serveur: Impossible de récupérer la progression. Veuillez réessayer plus tard.',
          'SERVER',
          true,
          error
        );
      }
      // Erreurs réseau
      if (error.code === 'ECONNABORTED' || error.code === 'ETIMEDOUT' || !error.response) {
        throw new TrackUploadError(
          'Erreur réseau: Impossible de se connecter au serveur.',
          'NETWORK',
          true,
          error
        );
      }
      const errorMessage = error.response?.data?.error || error.message || 'Échec de la récupération de la progression';
      throw new TrackUploadError(errorMessage, 'UNKNOWN', false, error);
    }
    if (error instanceof TrackUploadError) {
      throw error;
    }
    throw new TrackUploadError(
      'Erreur inconnue lors de la récupération de la progression',
      'UNKNOWN',
      false,
      error
    );
  }
}

/**
 * Interface pour les informations de quota d'un utilisateur
 */
export interface UserQuota {
  tracks_count: number;
  tracks_limit: number;
  storage_used: number; // bytes
  storage_limit: number; // bytes
}

/**
 * Récupère les informations de quota d'upload pour un utilisateur
 * @param userId ID de l'utilisateur (ou "me" pour l'utilisateur authentifié)
 * @returns Les informations de quota
 * @throws Error si la requête échoue
 */
export async function getUserQuota(userId: number | string): Promise<UserQuota> {
  try {
    const userIdParam = userId === 'me' || userId === 'current' ? 'me' : String(userId);
    const response = await apiClient.get<{ quota: UserQuota }>(
      `/users/${userIdParam}/upload-quota`
    );
    return response.data.quota;
  } catch (error) {
    if (error instanceof AxiosError) {
      if (error.response?.status === 401) {
        throw new TrackUploadError(
          'Non autorisé: Veuillez vous connecter pour voir votre quota',
          'VALIDATION',
          false,
          error
        );
      }
      if (error.response?.status === 403) {
        throw new TrackUploadError(
          'Accès refusé: Vous ne pouvez voir que votre propre quota',
          'VALIDATION',
          false,
          error
        );
      }
      if (error.response?.status === 404) {
        throw new TrackUploadError('Utilisateur introuvable', 'VALIDATION', false, error);
      }
      if (error.response?.status === 500) {
        throw new TrackUploadError(
          'Erreur serveur: Impossible de récupérer le quota. Veuillez réessayer plus tard.',
          'SERVER',
          true,
          error
        );
      }
      // Erreurs réseau
      if (error.code === 'ECONNABORTED' || error.code === 'ETIMEDOUT' || !error.response) {
        throw new TrackUploadError(
          'Erreur réseau: Impossible de se connecter au serveur.',
          'NETWORK',
          true,
          error
        );
      }
      const errorMessage = error.response?.data?.error || error.message || 'Échec de la récupération du quota';
      throw new TrackUploadError(errorMessage, 'UNKNOWN', false, error);
    }
    if (error instanceof TrackUploadError) {
      throw error;
    }
    throw new TrackUploadError(
      'Erreur inconnue lors de la récupération du quota',
      'UNKNOWN',
      false,
      error
    );
  }
}

/**
 * Interface pour l'état d'un upload résumable
 */
export interface UploadResumeState {
  upload_id: string;
  user_id: number;
  total_chunks: number;
  total_size: number;
  filename: string;
  chunks_received: number[];
  received_count: number;
  last_chunk: number;
  progress: number;
  created_at: string;
  updated_at: string;
}

/**
 * Récupère l'état d'un upload pour permettre la reprise
 * @param uploadId ID de l'upload
 * @returns L'état de l'upload
 * @throws Error si la requête échoue
 */
export async function resumeUpload(uploadId: string): Promise<UploadResumeState> {
  try {
    const response = await apiClient.get<UploadResumeState>(
      `/tracks/upload/resume/${uploadId}`
    );
    return response.data;
  } catch (error) {
    if (error instanceof AxiosError) {
      if (error.response?.status === 401) {
        throw new TrackUploadError(
          'Non autorisé: Veuillez vous connecter pour reprendre l\'upload',
          'VALIDATION',
          false,
          error
        );
      }
      if (error.response?.status === 403) {
        throw new TrackUploadError(
          'Accès refusé: Vous ne pouvez reprendre que vos propres uploads',
          'VALIDATION',
          false,
          error
        );
      }
      if (error.response?.status === 404) {
        throw new TrackUploadError('Upload introuvable ou expiré', 'VALIDATION', false, error);
      }
      if (error.response?.status === 500) {
        throw new TrackUploadError(
          'Erreur serveur: Impossible de récupérer l\'état de l\'upload. Veuillez réessayer plus tard.',
          'SERVER',
          true,
          error
        );
      }
      // Erreurs réseau
      if (error.code === 'ECONNABORTED' || error.code === 'ETIMEDOUT' || !error.response) {
        throw new TrackUploadError(
          'Erreur réseau: Impossible de se connecter au serveur.',
          'NETWORK',
          true,
          error
        );
      }
      const errorMessage = error.response?.data?.error || error.message || 'Échec de la récupération de l\'état de l\'upload';
      throw new TrackUploadError(errorMessage, 'UNKNOWN', false, error);
    }
    if (error instanceof TrackUploadError) {
      throw error;
    }
    throw new TrackUploadError(
      'Erreur inconnue lors de la récupération de l\'état de l\'upload',
      'UNKNOWN',
      false,
      error
    );
  }
}

/**
 * Interface pour les paramètres de liste des tracks
 */
export interface TrackListParams {
  page?: number;
  limit?: number;
  userId?: number;
  genre?: string;
  format?: string;
  sortBy?: 'created_at' | 'title' | 'popularity';
  sortOrder?: 'asc' | 'desc';
}

/**
 * Interface pour la réponse de liste des tracks
 */
export interface TrackListResponse {
  tracks: Track[];
  pagination: {
    page: number;
    limit: number;
    total: number;
    total_pages: number;
  };
}

/**
 * Liste les tracks avec pagination, filtres et tri
 * @param params Paramètres de filtrage et pagination
 * @returns La liste des tracks avec les métadonnées de pagination
 * @throws Error si la requête échoue
 */
export async function listTracks(params: TrackListParams = {}): Promise<TrackListResponse> {
  try {
    const queryParams = new URLSearchParams();
    if (params.page !== undefined) queryParams.append('page', params.page.toString());
    if (params.limit !== undefined) queryParams.append('limit', params.limit.toString());
    if (params.userId !== undefined) queryParams.append('user_id', params.userId.toString());
    if (params.genre) queryParams.append('genre', params.genre);
    if (params.format) queryParams.append('format', params.format);
    if (params.sortBy) queryParams.append('sort_by', params.sortBy);
    if (params.sortOrder) queryParams.append('sort_order', params.sortOrder);

    const queryString = queryParams.toString();
    const url = `/tracks${queryString ? `?${queryString}` : ''}`;

    const response = await apiClient.get<TrackListResponse>(url);
    return response.data;
  } catch (error) {
    if (error instanceof AxiosError) {
      if (error.response?.status === 401) {
        throw new TrackUploadError(
          'Non autorisé: Veuillez vous connecter pour voir les tracks',
          'VALIDATION',
          false,
          error
        );
      }
      if (error.response?.status === 500) {
        throw new TrackUploadError(
          'Erreur serveur: Impossible de récupérer les tracks. Veuillez réessayer plus tard.',
          'SERVER',
          true,
          error
        );
      }
      // Erreurs réseau
      if (error.code === 'ECONNABORTED' || error.code === 'ETIMEDOUT' || !error.response) {
        throw new TrackUploadError(
          'Erreur réseau: Impossible de se connecter au serveur.',
          'NETWORK',
          true,
          error
        );
      }
      const errorMessage = error.response?.data?.error || error.message || 'Échec de la récupération des tracks';
      throw new TrackUploadError(errorMessage, 'UNKNOWN', false, error);
    }
    if (error instanceof TrackUploadError) {
      throw error;
    }
    throw new TrackUploadError(
      'Erreur inconnue lors de la récupération des tracks',
      'UNKNOWN',
      false,
      error
    );
  }
}

/**
 * Récupère les détails d'un track par son ID
 * @param id ID du track
 * @returns Le track
 * @throws Error si la requête échoue
 */
export async function getTrack(id: number): Promise<Track> {
  try {
    const response = await apiClient.get<{ track: Track }>(`/tracks/${id}`);
    return response.data.track;
  } catch (error) {
    if (error instanceof AxiosError) {
      if (error.response?.status === 401) {
        throw new TrackUploadError(
          'Non autorisé: Veuillez vous connecter pour voir ce track',
          'VALIDATION',
          false,
          error
        );
      }
      if (error.response?.status === 404) {
        throw new TrackUploadError('Track introuvable', 'VALIDATION', false, error);
      }
      if (error.response?.status === 500) {
        throw new TrackUploadError(
          'Erreur serveur: Impossible de récupérer le track. Veuillez réessayer plus tard.',
          'SERVER',
          true,
          error
        );
      }
      // Erreurs réseau
      if (error.code === 'ECONNABORTED' || error.code === 'ETIMEDOUT' || !error.response) {
        throw new TrackUploadError(
          'Erreur réseau: Impossible de se connecter au serveur.',
          'NETWORK',
          true,
          error
        );
      }
      const errorMessage = error.response?.data?.error || error.message || 'Échec de la récupération du track';
      throw new TrackUploadError(errorMessage, 'UNKNOWN', false, error);
    }
    if (error instanceof TrackUploadError) {
      throw error;
    }
    throw new TrackUploadError(
      'Erreur inconnue lors de la récupération du track',
      'UNKNOWN',
      false,
      error
    );
  }
}

/**
 * Interface pour les paramètres de mise à jour d'un track
 */
export interface UpdateTrackParams {
  title?: string;
  artist?: string;
  album?: string;
  genre?: string;
  year?: number;
  is_public?: boolean;
}

/**
 * Met à jour les métadonnées d'un track
 * @param id ID du track
 * @param params Paramètres de mise à jour
 * @returns Le track mis à jour
 * @throws Error si la requête échoue
 */
export async function updateTrack(id: number, params: UpdateTrackParams): Promise<Track> {
  try {
    const response = await apiClient.put<{ track: Track }>(`/tracks/${id}`, params);
    return response.data.track;
  } catch (error) {
    if (error instanceof AxiosError) {
      if (error.response?.status === 401) {
        throw new TrackUploadError(
          'Non autorisé: Veuillez vous connecter pour modifier ce track',
          'VALIDATION',
          false,
          error
        );
      }
      if (error.response?.status === 403) {
        throw new TrackUploadError(
          'Accès refusé: Vous ne pouvez modifier que vos propres tracks',
          'VALIDATION',
          false,
          error
        );
      }
      if (error.response?.status === 404) {
        throw new TrackUploadError('Track introuvable', 'VALIDATION', false, error);
      }
      if (error.response?.status === 400) {
        const errorMessage = error.response?.data?.error || 'Données invalides';
        throw new TrackUploadError(errorMessage, 'VALIDATION', false, error);
      }
      if (error.response?.status === 500) {
        throw new TrackUploadError(
          'Erreur serveur: Impossible de mettre à jour le track. Veuillez réessayer plus tard.',
          'SERVER',
          true,
          error
        );
      }
      // Erreurs réseau
      if (error.code === 'ECONNABORTED' || error.code === 'ETIMEDOUT' || !error.response) {
        throw new TrackUploadError(
          'Erreur réseau: Impossible de se connecter au serveur.',
          'NETWORK',
          true,
          error
        );
      }
      const errorMessage = error.response?.data?.error || error.message || 'Échec de la mise à jour du track';
      throw new TrackUploadError(errorMessage, 'UNKNOWN', false, error);
    }
    if (error instanceof TrackUploadError) {
      throw error;
    }
    throw new TrackUploadError(
      'Erreur inconnue lors de la mise à jour du track',
      'UNKNOWN',
      false,
      error
    );
  }
}

/**
 * Supprime un track
 * @param id ID du track
 * @throws Error si la requête échoue
 */
export async function deleteTrack(id: number): Promise<void> {
  try {
    await apiClient.delete(`/tracks/${id}`);
  } catch (error) {
    if (error instanceof AxiosError) {
      if (error.response?.status === 401) {
        throw new TrackUploadError(
          'Non autorisé: Veuillez vous connecter pour supprimer ce track',
          'VALIDATION',
          false,
          error
        );
      }
      if (error.response?.status === 403) {
        throw new TrackUploadError(
          'Accès refusé: Vous ne pouvez supprimer que vos propres tracks',
          'VALIDATION',
          false,
          error
        );
      }
      if (error.response?.status === 404) {
        throw new TrackUploadError('Track introuvable', 'VALIDATION', false, error);
      }
      if (error.response?.status === 500) {
        throw new TrackUploadError(
          'Erreur serveur: Impossible de supprimer le track. Veuillez réessayer plus tard.',
          'SERVER',
          true,
          error
        );
      }
      // Erreurs réseau
      if (error.code === 'ECONNABORTED' || error.code === 'ETIMEDOUT' || !error.response) {
        throw new TrackUploadError(
          'Erreur réseau: Impossible de se connecter au serveur.',
          'NETWORK',
          true,
          error
        );
      }
      const errorMessage = error.response?.data?.error || error.message || 'Échec de la suppression du track';
      throw new TrackUploadError(errorMessage, 'UNKNOWN', false, error);
    }
    if (error instanceof TrackUploadError) {
      throw error;
    }
      throw new TrackUploadError(
      'Erreur inconnue lors de la suppression du track',
      'UNKNOWN',
      false,
      error
    );
  }
}

/**
 * Interface pour la réponse de likes d'un track
 */
export interface TrackLikesResponse {
  count: number;
  is_liked: boolean;
}

/**
 * Interface pour la réponse de tracks likés par un utilisateur
 */
export interface UserLikedTracksResponse {
  tracks: Track[];
  total: number;
  limit: number;
  offset: number;
}

/**
 * Like un track
 * @param trackId ID du track à liker
 * @throws Error si la requête échoue
 */
export async function likeTrack(trackId: number): Promise<void> {
  try {
    await apiClient.post(`/tracks/${trackId}/like`);
  } catch (error) {
    if (error instanceof AxiosError) {
      if (error.response?.status === 401) {
        throw new TrackUploadError(
          'Non autorisé: Veuillez vous connecter pour liker ce track',
          'VALIDATION',
          false,
          error
        );
      }
      if (error.response?.status === 404) {
        throw new TrackUploadError('Track introuvable', 'VALIDATION', false, error);
      }
      if (error.response?.status === 500) {
        throw new TrackUploadError(
          'Erreur serveur: Impossible de liker le track. Veuillez réessayer plus tard.',
          'SERVER',
          true,
          error
        );
      }
      if (error.code === 'ECONNABORTED' || error.code === 'ETIMEDOUT' || !error.response) {
        throw new TrackUploadError(
          'Erreur réseau: Impossible de se connecter au serveur.',
          'NETWORK',
          true,
          error
        );
      }
      const errorMessage = error.response?.data?.error || error.message || 'Échec du like du track';
      throw new TrackUploadError(errorMessage, 'UNKNOWN', false, error);
    }
    if (error instanceof TrackUploadError) {
      throw error;
    }
    throw new TrackUploadError(
      'Erreur inconnue lors du like du track',
      'UNKNOWN',
      false,
      error
    );
  }
}

/**
 * Unlike un track
 * @param trackId ID du track à unliker
 * @throws Error si la requête échoue
 */
export async function unlikeTrack(trackId: number): Promise<void> {
  try {
    await apiClient.delete(`/tracks/${trackId}/like`);
  } catch (error) {
    if (error instanceof AxiosError) {
      if (error.response?.status === 401) {
        throw new TrackUploadError(
          'Non autorisé: Veuillez vous connecter pour unliker ce track',
          'VALIDATION',
          false,
          error
        );
      }
      if (error.response?.status === 404) {
        throw new TrackUploadError('Track introuvable', 'VALIDATION', false, error);
      }
      if (error.response?.status === 500) {
        throw new TrackUploadError(
          'Erreur serveur: Impossible de unliker le track. Veuillez réessayer plus tard.',
          'SERVER',
          true,
          error
        );
      }
      if (error.code === 'ECONNABORTED' || error.code === 'ETIMEDOUT' || !error.response) {
        throw new TrackUploadError(
          'Erreur réseau: Impossible de se connecter au serveur.',
          'NETWORK',
          true,
          error
        );
      }
      const errorMessage = error.response?.data?.error || error.message || 'Échec de l\'unlike du track';
      throw new TrackUploadError(errorMessage, 'UNKNOWN', false, error);
    }
    if (error instanceof TrackUploadError) {
      throw error;
    }
    throw new TrackUploadError(
      'Erreur inconnue lors de l\'unlike du track',
      'UNKNOWN',
      false,
      error
    );
  }
}

/**
 * Récupère le nombre de likes et si l'utilisateur a liké un track
 * @param trackId ID du track
 * @returns Le nombre de likes et si l'utilisateur a liké
 * @throws Error si la requête échoue
 */
export async function getTrackLikes(trackId: number): Promise<{ count: number; isLiked: boolean }> {
  try {
    const response = await apiClient.get<TrackLikesResponse>(`/tracks/${trackId}/likes`);
    return {
      count: response.data.count,
      isLiked: response.data.is_liked,
    };
  } catch (error) {
    if (error instanceof AxiosError) {
      if (error.response?.status === 404) {
        throw new TrackUploadError('Track introuvable', 'VALIDATION', false, error);
      }
      if (error.response?.status === 500) {
        throw new TrackUploadError(
          'Erreur serveur: Impossible de récupérer les likes. Veuillez réessayer plus tard.',
          'SERVER',
          true,
          error
        );
      }
      if (error.code === 'ECONNABORTED' || error.code === 'ETIMEDOUT' || !error.response) {
        throw new TrackUploadError(
          'Erreur réseau: Impossible de se connecter au serveur.',
          'NETWORK',
          true,
          error
        );
      }
      const errorMessage = error.response?.data?.error || error.message || 'Échec de la récupération des likes';
      throw new TrackUploadError(errorMessage, 'UNKNOWN', false, error);
    }
    if (error instanceof TrackUploadError) {
      throw error;
    }
    throw new TrackUploadError(
      'Erreur inconnue lors de la récupération des likes',
      'UNKNOWN',
      false,
      error
    );
  }
}

/**
 * Récupère les tracks likés par un utilisateur
 * @param userId ID de l'utilisateur
 * @param limit Nombre de tracks à récupérer (défaut: 20)
 * @param offset Offset pour la pagination (défaut: 0)
 * @returns La liste des tracks likés avec pagination
 * @throws Error si la requête échoue
 */
export async function getUserLikedTracks(
  userId: number,
  limit: number = 20,
  offset: number = 0
): Promise<UserLikedTracksResponse> {
  try {
    const response = await apiClient.get<UserLikedTracksResponse>(
      `/users/${userId}/liked-tracks?limit=${limit}&offset=${offset}`
    );
    return response.data;
  } catch (error) {
    if (error instanceof AxiosError) {
      if (error.response?.status === 401) {
        throw new TrackUploadError(
          'Non autorisé: Veuillez vous connecter pour voir les tracks likés',
          'VALIDATION',
          false,
          error
        );
      }
      if (error.response?.status === 404) {
        throw new TrackUploadError('Utilisateur introuvable', 'VALIDATION', false, error);
      }
      if (error.response?.status === 500) {
        throw new TrackUploadError(
          'Erreur serveur: Impossible de récupérer les tracks likés. Veuillez réessayer plus tard.',
          'SERVER',
          true,
          error
        );
      }
      if (error.code === 'ECONNABORTED' || error.code === 'ETIMEDOUT' || !error.response) {
        throw new TrackUploadError(
          'Erreur réseau: Impossible de se connecter au serveur.',
          'NETWORK',
          true,
          error
        );
      }
      const errorMessage = error.response?.data?.error || error.message || 'Échec de la récupération des tracks likés';
      throw new TrackUploadError(errorMessage, 'UNKNOWN', false, error);
    }
    if (error instanceof TrackUploadError) {
      throw error;
    }
    throw new TrackUploadError(
      'Erreur inconnue lors de la récupération des tracks likés',
      'UNKNOWN',
      false,
      error
    );
  }
}

/**
 * Interface pour les statistiques d'un track
 */
export interface TrackStats {
  total_plays: number;
  unique_listeners: number;
  average_duration: number;
  completion_rate: number;
}

/**
 * Interface pour un point de données temporel
 */
export interface PlayTimePoint {
  date: string;
  count: number;
}

/**
 * Interface pour un track dans le classement
 */
export interface TopTrack {
  track_id: number;
  title: string;
  artist: string;
  total_plays: number;
  unique_listeners: number;
  average_duration: number;
}

/**
 * Interface pour la réponse des top tracks
 */
export interface TopTracksResponse {
  tracks: TopTrack[];
}

/**
 * Interface pour la réponse des statistiques utilisateur
 */
export interface UserStats {
  total_plays: number;
  unique_tracks: number;
  total_duration: number;
  average_duration: number;
}

/**
 * Enregistre une lecture de track
 * @param trackId ID du track
 * @param duration Durée de lecture en secondes
 * @param device Device optionnel (défaut: navigator.userAgent)
 * @throws Error si la requête échoue
 */
export async function recordPlay(trackId: number, duration: number, device?: string): Promise<void> {
  try {
    await apiClient.post(`/tracks/${trackId}/play`, {
      duration,
      device: device || (typeof navigator !== 'undefined' ? navigator.userAgent : ''),
    });
  } catch (error) {
    if (error instanceof AxiosError) {
      if (error.response?.status === 404) {
        throw new TrackUploadError('Track introuvable', 'VALIDATION', false, error);
      }
      if (error.response?.status === 500) {
        throw new TrackUploadError(
          'Erreur serveur: Impossible d\'enregistrer la lecture. Veuillez réessayer plus tard.',
          'SERVER',
          true,
          error
        );
      }
      // Erreurs réseau
      if (error.code === 'ECONNABORTED' || error.code === 'ETIMEDOUT' || !error.response) {
        throw new TrackUploadError(
          'Erreur réseau: Impossible de se connecter au serveur.',
          'NETWORK',
          true,
          error
        );
      }
      const errorMessage = error.response?.data?.error || error.message || 'Échec de l\'enregistrement de la lecture';
      throw new TrackUploadError(errorMessage, 'UNKNOWN', false, error);
    }
    if (error instanceof TrackUploadError) {
      throw error;
    }
    throw new TrackUploadError(
      'Erreur inconnue lors de l\'enregistrement de la lecture',
      'UNKNOWN',
      false,
      error
    );
  }
}

/**
 * Récupère les statistiques d'un track
 * @param trackId ID du track
 * @returns Les statistiques du track
 * @throws Error si la requête échoue
 */
export async function getTrackStats(trackId: number): Promise<TrackStats> {
  try {
    const response = await apiClient.get<{ stats: TrackStats }>(`/tracks/${trackId}/stats`);
    return response.data.stats;
  } catch (error) {
    if (error instanceof AxiosError) {
      if (error.response?.status === 404) {
        throw new TrackUploadError('Track introuvable', 'VALIDATION', false, error);
      }
      if (error.response?.status === 500) {
        throw new TrackUploadError(
          'Erreur serveur: Impossible de récupérer les statistiques. Veuillez réessayer plus tard.',
          'SERVER',
          true,
          error
        );
      }
      // Erreurs réseau
      if (error.code === 'ECONNABORTED' || error.code === 'ETIMEDOUT' || !error.response) {
        throw new TrackUploadError(
          'Erreur réseau: Impossible de se connecter au serveur.',
          'NETWORK',
          true,
          error
        );
      }
      const errorMessage = error.response?.data?.error || error.message || 'Échec de la récupération des statistiques';
      throw new TrackUploadError(errorMessage, 'UNKNOWN', false, error);
    }
    if (error instanceof TrackUploadError) {
      throw error;
    }
    throw new TrackUploadError(
      'Erreur inconnue lors de la récupération des statistiques',
      'UNKNOWN',
      false,
      error
    );
  }
}

/**
 * Récupère les tracks les plus écoutés
 * @param limit Nombre de tracks à récupérer (défaut: 10, max: 100)
 * @param startDate Date de début optionnelle (format ISO 8601)
 * @param endDate Date de fin optionnelle (format ISO 8601)
 * @returns La liste des tracks les plus écoutés
 * @throws Error si la requête échoue
 */
export async function getTopTracks(
  limit: number = 10,
  startDate?: string,
  endDate?: string
): Promise<TopTrack[]> {
  try {
    const queryParams = new URLSearchParams();
    if (limit > 0 && limit <= 100) {
      queryParams.append('limit', limit.toString());
    }
    if (startDate) {
      queryParams.append('start_date', startDate);
    }
    if (endDate) {
      queryParams.append('end_date', endDate);
    }

    const queryString = queryParams.toString();
    const url = `/analytics/top-tracks${queryString ? `?${queryString}` : ''}`;

    const response = await apiClient.get<TopTracksResponse>(url);
    return response.data.tracks;
  } catch (error) {
    if (error instanceof AxiosError) {
      if (error.response?.status === 400) {
        const errorMessage = error.response?.data?.error || 'Paramètres invalides';
        throw new TrackUploadError(errorMessage, 'VALIDATION', false, error);
      }
      if (error.response?.status === 500) {
        throw new TrackUploadError(
          'Erreur serveur: Impossible de récupérer les tracks populaires. Veuillez réessayer plus tard.',
          'SERVER',
          true,
          error
        );
      }
      // Erreurs réseau
      if (error.code === 'ECONNABORTED' || error.code === 'ETIMEDOUT' || !error.response) {
        throw new TrackUploadError(
          'Erreur réseau: Impossible de se connecter au serveur.',
          'NETWORK',
          true,
          error
        );
      }
      const errorMessage = error.response?.data?.error || error.message || 'Échec de la récupération des tracks populaires';
      throw new TrackUploadError(errorMessage, 'UNKNOWN', false, error);
    }
    if (error instanceof TrackUploadError) {
      throw error;
    }
    throw new TrackUploadError(
      'Erreur inconnue lors de la récupération des tracks populaires',
      'UNKNOWN',
      false,
      error
    );
  }
}

/**
 * Récupère les lectures sur une période pour un track
 * @param trackId ID du track
 * @param startDate Date de début (format ISO 8601, défaut: 30 jours avant)
 * @param endDate Date de fin (format ISO 8601, défaut: maintenant)
 * @param interval Intervalle de regroupement: 'hour', 'day', 'week', 'month' (défaut: 'day')
 * @returns Les points de données temporels
 * @throws Error si la requête échoue
 */
export async function getPlaysOverTime(
  trackId: number,
  startDate?: string,
  endDate?: string,
  interval: 'hour' | 'day' | 'week' | 'month' = 'day'
): Promise<PlayTimePoint[]> {
  try {
    const queryParams = new URLSearchParams();
    if (startDate) {
      queryParams.append('start_date', startDate);
    }
    if (endDate) {
      queryParams.append('end_date', endDate);
    }
    queryParams.append('interval', interval);

    const queryString = queryParams.toString();
    const url = `/tracks/${trackId}/plays-over-time${queryString ? `?${queryString}` : ''}`;

    const response = await apiClient.get<{ points: PlayTimePoint[] }>(url);
    return response.data.points;
  } catch (error) {
    if (error instanceof AxiosError) {
      if (error.response?.status === 404) {
        throw new TrackUploadError('Track introuvable', 'VALIDATION', false, error);
      }
      if (error.response?.status === 400) {
        const errorMessage = error.response?.data?.error || 'Paramètres invalides';
        throw new TrackUploadError(errorMessage, 'VALIDATION', false, error);
      }
      if (error.response?.status === 500) {
        throw new TrackUploadError(
          'Erreur serveur: Impossible de récupérer les données temporelles. Veuillez réessayer plus tard.',
          'SERVER',
          true,
          error
        );
      }
      // Erreurs réseau
      if (error.code === 'ECONNABORTED' || error.code === 'ETIMEDOUT' || !error.response) {
        throw new TrackUploadError(
          'Erreur réseau: Impossible de se connecter au serveur.',
          'NETWORK',
          true,
          error
        );
      }
      const errorMessage = error.response?.data?.error || error.message || 'Échec de la récupération des données temporelles';
      throw new TrackUploadError(errorMessage, 'UNKNOWN', false, error);
    }
    if (error instanceof TrackUploadError) {
      throw error;
    }
    throw new TrackUploadError(
      'Erreur inconnue lors de la récupération des données temporelles',
      'UNKNOWN',
      false,
      error
    );
  }
}

/**
 * Récupère les statistiques d'un utilisateur
 * @param userId ID de l'utilisateur
 * @returns Les statistiques de l'utilisateur
 * @throws Error si la requête échoue
 */
export async function getUserStats(userId: number): Promise<UserStats> {
  try {
    const response = await apiClient.get<{ stats: UserStats }>(`/users/${userId}/stats`);
    return response.data.stats;
  } catch (error) {
    if (error instanceof AxiosError) {
      if (error.response?.status === 401) {
        throw new TrackUploadError(
          'Non autorisé: Veuillez vous connecter pour voir les statistiques',
          'VALIDATION',
          false,
          error
        );
      }
      if (error.response?.status === 403) {
        throw new TrackUploadError(
          'Accès refusé: Vous ne pouvez voir que vos propres statistiques',
          'VALIDATION',
          false,
          error
        );
      }
      if (error.response?.status === 404) {
        throw new TrackUploadError('Utilisateur introuvable', 'VALIDATION', false, error);
      }
      if (error.response?.status === 500) {
        throw new TrackUploadError(
          'Erreur serveur: Impossible de récupérer les statistiques. Veuillez réessayer plus tard.',
          'SERVER',
          true,
          error
        );
      }
      // Erreurs réseau
      if (error.code === 'ECONNABORTED' || error.code === 'ETIMEDOUT' || !error.response) {
        throw new TrackUploadError(
          'Erreur réseau: Impossible de se connecter au serveur.',
          'NETWORK',
          true,
          error
        );
      }
      const errorMessage = error.response?.data?.error || error.message || 'Échec de la récupération des statistiques';
      throw new TrackUploadError(errorMessage, 'UNKNOWN', false, error);
    }
    if (error instanceof TrackUploadError) {
      throw error;
    }
    throw new TrackUploadError(
      'Erreur inconnue lors de la récupération des statistiques',
      'UNKNOWN',
      false,
      error
    );
  }
}

