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

/**
 * Comment Service
 * T0289: Service frontend pour gérer les commentaires de tracks
 */

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

/**
 * Interface pour un commentaire de track
 */
export interface TrackComment {
  id: string;
  track_id: string;
  user_id: string;
  parent_id?: string;
  content: string;
  is_edited: boolean;
  created_at: string;
  updated_at: string;
  user: {
    id: string;
    username: string;
    avatar?: string;
  };
  replies?: TrackComment[];
}

/**
 * Interface pour la réponse de liste de commentaires
 */
export interface CommentListResponse {
  comments: TrackComment[];
  total: number;
  page: number;
  limit: number;
}

/**
 * Interface pour la réponse de réponses d'un commentaire
 */
export interface ReplyListResponse {
  replies: TrackComment[];
  total: number;
  page: number;
  limit: number;
}

/**
 * Crée un commentaire sur un track
 * @param trackId ID du track
 * @param content Contenu du commentaire
 * @param parentId ID du commentaire parent (optionnel, pour les réponses)
 * @returns Le commentaire créé
 * @throws CommentError si la requête échoue
 */
export async function createComment(
  trackId: string,
  content: string,
  parentId?: string,
): Promise<TrackComment> {
  try {
    const response = await apiClient.post<{ comment: TrackComment }>(
      `/tracks/${trackId}/comments`,
      { content, parent_id: parentId },
    );
    return response.data.comment;
  } catch (error) {
    if (error instanceof AxiosError) {
      if (error.response?.status === 401) {
        throw new CommentError(
          'Non autorisé: Veuillez vous connecter pour commenter',
          'VALIDATION',
          false,
          error,
        );
      }
      if (error.response?.status === 404) {
        throw new CommentError(
          'Track ou commentaire parent introuvable',
          'VALIDATION',
          false,
          error,
        );
      }
      if (error.response?.status === 400) {
        const errorMessage = error.response?.data?.error || 'Données invalides';
        throw new CommentError(errorMessage, 'VALIDATION', false, error);
      }
      if (error.response?.status === 500) {
        throw new CommentError(
          'Erreur serveur: Impossible de créer le commentaire. Veuillez réessayer plus tard.',
          'SERVER',
          true,
          error,
        );
      }
      if (
        error.code === 'ECONNABORTED' ||
        error.code === 'ETIMEDOUT' ||
        !error.response
      ) {
        throw new CommentError(
          'Erreur réseau: Impossible de se connecter au serveur.',
          'NETWORK',
          true,
          error,
        );
      }
      const errorMessage =
        error.response?.data?.error ||
        error.message ||
        'Échec de la création du commentaire';
      throw new CommentError(errorMessage, 'UNKNOWN', false, error);
    }
    if (error instanceof CommentError) {
      throw error;
    }
    throw new CommentError(
      'Erreur inconnue lors de la création du commentaire',
      'UNKNOWN',
      false,
      error,
    );
  }
}

/**
 * Récupère les commentaires d'un track
 * @param trackId ID du track
 * @param page Numéro de page (défaut: 1)
 * @param limit Nombre de commentaires par page (défaut: 20)
 * @returns La liste des commentaires avec pagination
 * @throws CommentError si la requête échoue
 */
export async function getComments(
  trackId: string,
  page: number = 1,
  limit: number = 20,
): Promise<CommentListResponse> {
  try {
    const response = await apiClient.get<CommentListResponse>(
      `/tracks/${trackId}/comments?page=${page}&limit=${limit}`,
    );
    return response.data;
  } catch (error) {
    if (error instanceof AxiosError) {
      if (error.response?.status === 404) {
        throw new CommentError('Track introuvable', 'VALIDATION', false, error);
      }
      if (error.response?.status === 500) {
        throw new CommentError(
          'Erreur serveur: Impossible de récupérer les commentaires. Veuillez réessayer plus tard.',
          'SERVER',
          true,
          error,
        );
      }
      if (
        error.code === 'ECONNABORTED' ||
        error.code === 'ETIMEDOUT' ||
        !error.response
      ) {
        throw new CommentError(
          '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 commentaires';
      throw new CommentError(errorMessage, 'UNKNOWN', false, error);
    }
    if (error instanceof CommentError) {
      throw error;
    }
    throw new CommentError(
      'Erreur inconnue lors de la récupération des commentaires',
      'UNKNOWN',
      false,
      error,
    );
  }
}

/**
 * Met à jour un commentaire
 * @param commentId ID du commentaire
 * @param content Nouveau contenu
 * @returns Le commentaire mis à jour
 * @throws CommentError si la requête échoue
 */
export async function updateComment(
  commentId: string,
  content: string,
): Promise<TrackComment> {
  try {
    const response = await apiClient.put<{ comment: TrackComment }>(
      `/comments/${commentId}`,
      { content },
    );
    return response.data.comment;
  } catch (error) {
    if (error instanceof AxiosError) {
      if (error.response?.status === 401) {
        throw new CommentError(
          'Non autorisé: Veuillez vous connecter pour modifier ce commentaire',
          'VALIDATION',
          false,
          error,
        );
      }
      if (error.response?.status === 403) {
        throw new CommentError(
          'Non autorisé: Vous ne pouvez modifier que vos propres commentaires',
          'VALIDATION',
          false,
          error,
        );
      }
      if (error.response?.status === 404) {
        throw new CommentError(
          'Commentaire introuvable',
          'VALIDATION',
          false,
          error,
        );
      }
      if (error.response?.status === 400) {
        const errorMessage = error.response?.data?.error || 'Données invalides';
        throw new CommentError(errorMessage, 'VALIDATION', false, error);
      }
      if (error.response?.status === 500) {
        throw new CommentError(
          'Erreur serveur: Impossible de mettre à jour le commentaire. Veuillez réessayer plus tard.',
          'SERVER',
          true,
          error,
        );
      }
      if (
        error.code === 'ECONNABORTED' ||
        error.code === 'ETIMEDOUT' ||
        !error.response
      ) {
        throw new CommentError(
          '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 commentaire';
      throw new CommentError(errorMessage, 'UNKNOWN', false, error);
    }
    if (error instanceof CommentError) {
      throw error;
    }
    throw new CommentError(
      'Erreur inconnue lors de la mise à jour du commentaire',
      'UNKNOWN',
      false,
      error,
    );
  }
}

/**
 * Supprime un commentaire
 * @param commentId ID du commentaire
 * @throws CommentError si la requête échoue
 */
export async function deleteComment(commentId: string): Promise<void> {
  try {
    await apiClient.delete(`/comments/${commentId}`);
  } catch (error) {
    if (error instanceof AxiosError) {
      if (error.response?.status === 401) {
        throw new CommentError(
          'Non autorisé: Veuillez vous connecter pour supprimer ce commentaire',
          'VALIDATION',
          false,
          error,
        );
      }
      if (error.response?.status === 403) {
        throw new CommentError(
          'Non autorisé: Vous ne pouvez supprimer que vos propres commentaires',
          'VALIDATION',
          false,
          error,
        );
      }
      if (error.response?.status === 404) {
        throw new CommentError(
          'Commentaire introuvable',
          'VALIDATION',
          false,
          error,
        );
      }
      if (error.response?.status === 500) {
        throw new CommentError(
          'Erreur serveur: Impossible de supprimer le commentaire. Veuillez réessayer plus tard.',
          'SERVER',
          true,
          error,
        );
      }
      if (
        error.code === 'ECONNABORTED' ||
        error.code === 'ETIMEDOUT' ||
        !error.response
      ) {
        throw new CommentError(
          '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 commentaire';
      throw new CommentError(errorMessage, 'UNKNOWN', false, error);
    }
    if (error instanceof CommentError) {
      throw error;
    }
    throw new CommentError(
      'Erreur inconnue lors de la suppression du commentaire',
      'UNKNOWN',
      false,
      error,
    );
  }
}

/**
 * Récupère les réponses d'un commentaire
 * @param parentId ID du commentaire parent
 * @param page Numéro de page (défaut: 1)
 * @param limit Nombre de réponses par page (défaut: 20)
 * @returns La liste des réponses avec pagination
 * @throws CommentError si la requête échoue
 */
export async function getReplies(
  parentId: string,
  page: number = 1,
  limit: number = 20,
): Promise<ReplyListResponse> {
  try {
    const response = await apiClient.get<ReplyListResponse>(
      `/comments/${parentId}/replies?page=${page}&limit=${limit}`,
    );
    return response.data;
  } catch (error) {
    if (error instanceof AxiosError) {
      if (error.response?.status === 404) {
        throw new CommentError(
          'Commentaire parent introuvable',
          'VALIDATION',
          false,
          error,
        );
      }
      if (error.response?.status === 500) {
        throw new CommentError(
          'Erreur serveur: Impossible de récupérer les réponses. Veuillez réessayer plus tard.',
          'SERVER',
          true,
          error,
        );
      }
      if (
        error.code === 'ECONNABORTED' ||
        error.code === 'ETIMEDOUT' ||
        !error.response
      ) {
        throw new CommentError(
          '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 réponses';
      throw new CommentError(errorMessage, 'UNKNOWN', false, error);
    }
    if (error instanceof CommentError) {
      throw error;
    }
    throw new CommentError(
      'Erreur inconnue lors de la récupération des réponses',
      'UNKNOWN',
      false,
      error,
    );
  }
}
