import { apiClient } from '@/services/api/client';
import { AxiosError } from 'axios';

/**
 * Track Version Service
 * T0324: Service frontend pour gérer les versions de tracks
 */

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

/**
 * Interface pour une version de track
 */
export interface TrackVersion {
  id: string;
  track_id: string;
  version_number: number;
  file_path: string;
  file_size: number;
  changelog?: string;
  created_at: string;
  updated_at: string;
}

/**
 * Interface pour la requête de création d'une version
 */
export interface CreateVersionRequest {
  file_path: string;
  file_size: number;
  changelog?: string;
}

/**
 * Crée une nouvelle version d'un track
 * @param trackId ID du track
 * @param data Données de la version (file_path, file_size, changelog)
 * @returns La version créée
 * @throws TrackVersionError si la requête échoue
 */
export async function createVersion(
  trackId: string,
  data: CreateVersionRequest,
): Promise<TrackVersion> {
  try {
    const response = await apiClient.post<{ version: TrackVersion }>(
      `/tracks/${trackId}/versions`,
      data,
    );
    return response.data.version;
  } catch (error) {
    if (error instanceof AxiosError) {
      if (error.response?.status === 400) {
        const errorMessage = error.response?.data?.error || 'Données invalides';
        throw new TrackVersionError(errorMessage, 'VALIDATION', false, error);
      }
      if (error.response?.status === 401) {
        throw new TrackVersionError(
          'Non autorisé: Veuillez vous connecter pour créer une version',
          'VALIDATION',
          false,
          error,
        );
      }
      if (error.response?.status === 403) {
        throw new TrackVersionError(
          'Accès refusé: Vous ne pouvez créer des versions que pour vos propres tracks',
          'FORBIDDEN',
          false,
          error,
        );
      }
      if (error.response?.status === 404) {
        throw new TrackVersionError(
          'Track introuvable',
          'NOT_FOUND',
          false,
          error,
        );
      }
      if (error.response?.status === 500) {
        throw new TrackVersionError(
          'Erreur serveur: Impossible de créer la version. Veuillez réessayer plus tard.',
          'SERVER',
          true,
          error,
        );
      }
      if (
        error.code === 'ECONNABORTED' ||
        error.code === 'ETIMEDOUT' ||
        !error.response
      ) {
        throw new TrackVersionError(
          'Erreur réseau: Impossible de se connecter au serveur. Veuillez vérifier votre connexion.',
          'NETWORK',
          true,
          error,
        );
      }
      const errorMessage =
        error.response?.data?.error ||
        error.message ||
        'Échec de la création de la version';
      throw new TrackVersionError(errorMessage, 'UNKNOWN', false, error);
    }
    if (error instanceof TrackVersionError) {
      throw error;
    }
    throw new TrackVersionError(
      'Erreur inconnue lors de la création de la version',
      'UNKNOWN',
      false,
      error,
    );
  }
}

/**
 * Récupère toutes les versions d'un track
 * @param trackId ID du track
 * @returns Liste des versions du track
 * @throws TrackVersionError si la requête échoue
 */
export async function listVersions(trackId: string): Promise<TrackVersion[]> {
  try {
    const response = await apiClient.get<{ versions: TrackVersion[] }>(
      `/tracks/${trackId}/versions`,
    );
    return response.data.versions;
  } catch (error) {
    if (error instanceof AxiosError) {
      if (error.response?.status === 400) {
        throw new TrackVersionError(
          'Requête invalide: ID de track invalide',
          'VALIDATION',
          false,
          error,
        );
      }
      if (error.response?.status === 404) {
        throw new TrackVersionError(
          'Track introuvable',
          'NOT_FOUND',
          false,
          error,
        );
      }
      if (error.response?.status === 500) {
        throw new TrackVersionError(
          'Erreur serveur: Impossible de récupérer les versions. Veuillez réessayer plus tard.',
          'SERVER',
          true,
          error,
        );
      }
      if (
        error.code === 'ECONNABORTED' ||
        error.code === 'ETIMEDOUT' ||
        !error.response
      ) {
        throw new TrackVersionError(
          'Erreur réseau: Impossible de se connecter au serveur. Veuillez vérifier votre connexion.',
          'NETWORK',
          true,
          error,
        );
      }
      const errorMessage =
        error.response?.data?.error ||
        error.message ||
        'Échec de la récupération des versions';
      throw new TrackVersionError(errorMessage, 'UNKNOWN', false, error);
    }
    if (error instanceof TrackVersionError) {
      throw error;
    }
    throw new TrackVersionError(
      'Erreur inconnue lors de la récupération des versions',
      'UNKNOWN',
      false,
      error,
    );
  }
}

/**
 * Récupère une version spécifique d'un track
 * @param trackId ID du track
 * @param versionId ID ou numéro de la version
 * @returns La version demandée
 * @throws TrackVersionError si la requête échoue
 */
export async function getVersion(
  trackId: string,
  versionId: string,
): Promise<TrackVersion> {
  try {
    const response = await apiClient.get<{ version: TrackVersion }>(
      `/tracks/${trackId}/versions/${versionId}`,
    );
    return response.data.version;
  } catch (error) {
    if (error instanceof AxiosError) {
      if (error.response?.status === 400) {
        throw new TrackVersionError(
          'Requête invalide: Identifiant de version invalide',
          'VALIDATION',
          false,
          error,
        );
      }
      if (error.response?.status === 404) {
        throw new TrackVersionError(
          'Version introuvable',
          'NOT_FOUND',
          false,
          error,
        );
      }
      if (error.response?.status === 500) {
        throw new TrackVersionError(
          'Erreur serveur: Impossible de récupérer la version. Veuillez réessayer plus tard.',
          'SERVER',
          true,
          error,
        );
      }
      if (
        error.code === 'ECONNABORTED' ||
        error.code === 'ETIMEDOUT' ||
        !error.response
      ) {
        throw new TrackVersionError(
          'Erreur réseau: Impossible de se connecter au serveur. Veuillez vérifier votre connexion.',
          'NETWORK',
          true,
          error,
        );
      }
      const errorMessage =
        error.response?.data?.error ||
        error.message ||
        'Échec de la récupération de la version';
      throw new TrackVersionError(errorMessage, 'UNKNOWN', false, error);
    }
    if (error instanceof TrackVersionError) {
      throw error;
    }
    throw new TrackVersionError(
      'Erreur inconnue lors de la récupération de la version',
      'UNKNOWN',
      false,
      error,
    );
  }
}

/**
 * Restaure une version spécifique d'un track
 * @param trackId ID du track
 * @param versionId ID de la version à restaurer
 * @throws TrackVersionError si la requête échoue
 */
export async function restoreVersion(
  trackId: string,
  versionId: string,
): Promise<void> {
  try {
    await apiClient.post(`/tracks/${trackId}/versions/${versionId}/restore`);
  } catch (error) {
    if (error instanceof AxiosError) {
      if (error.response?.status === 400) {
        const errorMessage = error.response?.data?.error || 'Données invalides';
        throw new TrackVersionError(errorMessage, 'VALIDATION', false, error);
      }
      if (error.response?.status === 401) {
        throw new TrackVersionError(
          'Non autorisé: Veuillez vous connecter pour restaurer une version',
          'VALIDATION',
          false,
          error,
        );
      }
      if (error.response?.status === 403) {
        throw new TrackVersionError(
          'Accès refusé: Vous ne pouvez restaurer des versions que pour vos propres tracks',
          'FORBIDDEN',
          false,
          error,
        );
      }
      if (error.response?.status === 404) {
        const errorMessage =
          error.response?.data?.error || 'Version ou track introuvable';
        throw new TrackVersionError(errorMessage, 'NOT_FOUND', false, error);
      }
      if (error.response?.status === 500) {
        throw new TrackVersionError(
          'Erreur serveur: Impossible de restaurer la version. Veuillez réessayer plus tard.',
          'SERVER',
          true,
          error,
        );
      }
      if (
        error.code === 'ECONNABORTED' ||
        error.code === 'ETIMEDOUT' ||
        !error.response
      ) {
        throw new TrackVersionError(
          'Erreur réseau: Impossible de se connecter au serveur. Veuillez vérifier votre connexion.',
          'NETWORK',
          true,
          error,
        );
      }
      const errorMessage =
        error.response?.data?.error ||
        error.message ||
        'Échec de la restauration de la version';
      throw new TrackVersionError(errorMessage, 'UNKNOWN', false, error);
    }
    if (error instanceof TrackVersionError) {
      throw error;
    }
    throw new TrackVersionError(
      'Erreur inconnue lors de la restauration de la version',
      'UNKNOWN',
      false,
      error,
    );
  }
}
