import { apiClient } from '@/services/api/client';
import { AxiosError } from 'axios';
import { TrackServiceError as TrackUploadError } from '../errors/trackErrors';

/**
 * Interface pour les statistiques d'un track
 */
export interface TrackStats {
  total_plays: number;
  unique_listeners: number;
  average_duration: number;
  completion_rate: number;
  // Merged from trackStatsService
  views: number;
  likes: number;
  comments: number;
  total_play_time: number;
  downloads: 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: string;
  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: unknown) {
    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: unknown) {
    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: unknown) {
    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: unknown) {
    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: string): Promise<UserStats> {
  try {
    const response = await apiClient.get<{ stats: UserStats }>(
      `/users/${userId}/stats`,
    );
    return response.data.stats;
  } catch (error: unknown) {
    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,
    );
  }
}
