/**
 * Hook React pour gérer les playlists avec React Query
 * T0458: Create Playlist Hook
 */

import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import * as playlistService from '../services/playlistService';
import type { CreatePlaylistRequest, UpdatePlaylistRequest } from '../types';
import type {
  AddCollaboratorRequest,
  UpdateCollaboratorPermissionRequest,
  PlaylistShareLink,
} from '../services/playlistService';

/**
 * Hook pour créer une playlist
 * T0458: Create Playlist Hook
 * T0502: Amélioré avec retry logic
 * T0505: Optimistic updates ajoutés
 */
export function useCreatePlaylist() {
  const queryClient = useQueryClient();
  
  return useMutation({
    mutationFn: (data: CreatePlaylistRequest) => playlistService.createPlaylist(data),
    // T0505: Optimistic update
    onMutate: async (newPlaylist) => {
      // Annuler les requêtes en cours pour éviter les écrasements
      await queryClient.cancelQueries({ queryKey: ['playlists'] });
      
      // Snapshot de la valeur précédente
      const previousPlaylists = queryClient.getQueryData(['playlists']);
      
      // Optimistic update
      queryClient.setQueryData(['playlists'], (old: any) => {
        if (!old) return old;
        const optimisticPlaylist = {
          id: Date.now(), // ID temporaire
          ...newPlaylist,
          track_count: 0,
          created_at: new Date().toISOString(),
          user: { id: 0, username: '...' }, // Sera remplacé par la vraie réponse
        };
        return {
          ...old,
          playlists: [optimisticPlaylist, ...(old.playlists || [])],
          total: (old.total || 0) + 1,
        };
      });
      
      return { previousPlaylists };
    },
    onError: (err, newPlaylist, context) => {
      // Rollback en cas d'erreur
      if (context?.previousPlaylists) {
        queryClient.setQueryData(['playlists'], context.previousPlaylists);
      }
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['playlists'] });
    },
    // T0502: Retry logic pour les erreurs réseau
    retry: (failureCount, error: any) => {
      // Ne pas retry pour les erreurs 400, 401, 403, 404
      if (error?.response?.status && [400, 401, 403, 404].includes(error.response.status)) {
        return false;
      }
      // Retry jusqu'à 3 fois pour les autres erreurs
      return failureCount < 3;
    },
    retryDelay: (attemptIndex) => Math.min(1000 * 2 ** attemptIndex, 30000), // Exponential backoff
  });
}

/**
 * Hook pour récupérer une playlist par son ID
 * T0458: Create Playlist Hook
 */
export function usePlaylist(id: number) {
  return useQuery({
    queryKey: ['playlist', id],
    queryFn: () => playlistService.getPlaylist(id),
    enabled: !!id,
  });
}

/**
 * Hook pour mettre à jour une playlist
 * T0458: Create Playlist Hook
 * T0502: Amélioré avec retry logic
 * T0505: Optimistic updates ajoutés
 */
export function useUpdatePlaylist() {
  const queryClient = useQueryClient();
  
  return useMutation({
    mutationFn: ({ id, data }: { id: number; data: UpdatePlaylistRequest }) =>
      playlistService.updatePlaylist(id, data),
    // T0505: Optimistic update
    onMutate: async ({ id, data }) => {
      await queryClient.cancelQueries({ queryKey: ['playlist', id] });
      await queryClient.cancelQueries({ queryKey: ['playlists'] });
      
      const previousPlaylist = queryClient.getQueryData(['playlist', id]);
      const previousPlaylists = queryClient.getQueryData(['playlists']);
      
      // Optimistic update de la playlist individuelle
      queryClient.setQueryData(['playlist', id], (old: any) => {
        if (!old) return old;
        return { ...old, ...data };
      });
      
      // Optimistic update de la liste
      queryClient.setQueryData(['playlists'], (old: any) => {
        if (!old) return old;
        return {
          ...old,
          playlists: (old.playlists || []).map((p: any) =>
            p.id === id ? { ...p, ...data } : p
          ),
        };
      });
      
      return { previousPlaylist, previousPlaylists };
    },
    onError: (err, variables, context) => {
      // Rollback en cas d'erreur
      if (context?.previousPlaylist) {
        queryClient.setQueryData(['playlist', variables.id], context.previousPlaylist);
      }
      if (context?.previousPlaylists) {
        queryClient.setQueryData(['playlists'], context.previousPlaylists);
      }
    },
    onSuccess: (_, variables) => {
      queryClient.invalidateQueries({ queryKey: ['playlist', variables.id] });
      queryClient.invalidateQueries({ queryKey: ['playlists'] });
    },
    // T0502: Retry logic pour les erreurs réseau
    retry: (failureCount, error: any) => {
      // Ne pas retry pour les erreurs 400, 401, 403, 404
      if (error?.response?.status && [400, 401, 403, 404].includes(error.response.status)) {
        return false;
      }
      // Retry jusqu'à 3 fois pour les autres erreurs
      return failureCount < 3;
    },
    retryDelay: (attemptIndex) => Math.min(1000 * 2 ** attemptIndex, 30000), // Exponential backoff
  });
}

/**
 * Hook pour supprimer une playlist
 * T0458: Create Playlist Hook
 * T0502: Amélioré avec retry logic
 */
export function useDeletePlaylist() {
  const queryClient = useQueryClient();
  
  return useMutation({
    mutationFn: (id: number) => playlistService.deletePlaylist(id),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['playlists'] });
    },
    // T0502: Retry logic pour les erreurs réseau
    retry: (failureCount, error: any) => {
      // Ne pas retry pour les erreurs 400, 401, 403, 404
      if (error?.response?.status && [400, 401, 403, 404].includes(error.response.status)) {
        return false;
      }
      // Retry jusqu'à 3 fois pour les autres erreurs
      return failureCount < 3;
    },
    retryDelay: (attemptIndex) => Math.min(1000 * 2 ** attemptIndex, 30000), // Exponential backoff
  });
}

/**
 * Hook pour lister les playlists avec pagination
 * T0458: Create Playlist Hook
 */
// usePlaylists récupère la liste des playlists avec pagination
// T0501: Optimisé avec pagination efficace
// T0502: Amélioré avec retry logic
export function usePlaylists(limit = 20, offset = 0) {
  return useQuery({
    queryKey: ['playlists', limit, offset],
    queryFn: () => playlistService.listPlaylists(limit, offset),
    // T0501: Optimisation - Garder les données en cache plus longtemps
    staleTime: 30000, // 30 secondes
    cacheTime: 300000, // 5 minutes
    // T0502: Retry logic pour les erreurs réseau
    retry: (failureCount, error: any) => {
      // Ne pas retry pour les erreurs 400, 401, 403, 404
      if (error?.response?.status && [400, 401, 403, 404].includes(error.response.status)) {
        return false;
      }
      // Retry jusqu'à 3 fois pour les autres erreurs
      return failureCount < 3;
    },
    retryDelay: (attemptIndex) => Math.min(1000 * 2 ** attemptIndex, 30000), // Exponential backoff
  });
}

/**
 * Hook pour ajouter un track à une playlist
 * T0470: Create PlaylistTrack Hooks
 * T0505: Optimistic updates ajoutés
 */
export function useAddTrackToPlaylist() {
  const queryClient = useQueryClient();
  
  return useMutation({
    mutationFn: ({ playlistId, trackId, position }: { playlistId: number; trackId: number; position?: number }) =>
      playlistService.addTrackToPlaylist(playlistId, trackId, position),
    // T0505: Optimistic update
    onMutate: async ({ playlistId }) => {
      await queryClient.cancelQueries({ queryKey: ['playlist', playlistId] });
      
      const previousPlaylist = queryClient.getQueryData(['playlist', playlistId]);
      
      // Note: On ne peut pas faire d'optimistic update complet car on n'a pas les données du track
      // On incrémente juste le compteur
      queryClient.setQueryData(['playlist', playlistId], (old: any) => {
        if (!old) return old;
        return {
          ...old,
          track_count: (old.track_count || 0) + 1,
        };
      });
      
      return { previousPlaylist };
    },
    onError: (err, variables, context) => {
      if (context?.previousPlaylist) {
        queryClient.setQueryData(['playlist', variables.playlistId], context.previousPlaylist);
      }
    },
    onSuccess: (_, variables) => {
      queryClient.invalidateQueries({ queryKey: ['playlist', variables.playlistId] });
      queryClient.invalidateQueries({ queryKey: ['playlists'] });
    },
  });
}

/**
 * Hook pour retirer un track d'une playlist
 * T0470: Create PlaylistTrack Hooks
 * T0505: Optimistic updates ajoutés
 */
export function useRemoveTrackFromPlaylist() {
  const queryClient = useQueryClient();
  
  return useMutation({
    mutationFn: ({ playlistId, trackId }: { playlistId: number; trackId: number }) =>
      playlistService.removeTrackFromPlaylist(playlistId, trackId),
    // T0505: Optimistic update
    onMutate: async ({ playlistId, trackId }) => {
      await queryClient.cancelQueries({ queryKey: ['playlist', playlistId] });
      
      const previousPlaylist = queryClient.getQueryData(['playlist', playlistId]);
      
      // Optimistic update: retirer le track de la liste
      queryClient.setQueryData(['playlist', playlistId], (old: any) => {
        if (!old) return old;
        return {
          ...old,
          tracks: (old.tracks || []).filter((pt: any) => pt.track_id !== trackId),
          track_count: Math.max(0, (old.track_count || 0) - 1),
        };
      });
      
      return { previousPlaylist };
    },
    onError: (err, variables, context) => {
      if (context?.previousPlaylist) {
        queryClient.setQueryData(['playlist', variables.playlistId], context.previousPlaylist);
      }
    },
    onSuccess: (_, variables) => {
      queryClient.invalidateQueries({ queryKey: ['playlist', variables.playlistId] });
      queryClient.invalidateQueries({ queryKey: ['playlists'] });
    },
  });
}

/**
 * Hook pour réorganiser les tracks d'une playlist
 * T0470: Create PlaylistTrack Hooks
 */
export function useReorderPlaylistTracks() {
  const queryClient = useQueryClient();
  
  return useMutation({
    mutationFn: ({ playlistId, trackPositions }: { playlistId: number; trackPositions: Record<number, number> }) =>
      playlistService.reorderPlaylistTracks(playlistId, trackPositions),
    onSuccess: (_, variables) => {
      queryClient.invalidateQueries({ queryKey: ['playlist', variables.playlistId] });
      queryClient.invalidateQueries({ queryKey: ['playlists'] });
    },
  });
}

/**
 * Hook pour ajouter un collaborateur à une playlist
 * T0482: Create Playlist Share Hooks
 */
export function useAddCollaborator() {
  const queryClient = useQueryClient();
  
  return useMutation({
    mutationFn: ({ playlistId, data }: { playlistId: number; data: AddCollaboratorRequest }) =>
      playlistService.addCollaborator(playlistId, data),
    onSuccess: (_, variables) => {
      queryClient.invalidateQueries({ queryKey: ['playlist', variables.playlistId] });
      queryClient.invalidateQueries({ queryKey: ['playlist', variables.playlistId, 'collaborators'] });
      queryClient.invalidateQueries({ queryKey: ['playlists'] });
    },
  });
}

/**
 * Hook pour retirer un collaborateur d'une playlist
 * T0482: Create Playlist Share Hooks
 */
export function useRemoveCollaborator() {
  const queryClient = useQueryClient();
  
  return useMutation({
    mutationFn: ({ playlistId, userId }: { playlistId: number; userId: number }) =>
      playlistService.removeCollaborator(playlistId, userId),
    onSuccess: (_, variables) => {
      queryClient.invalidateQueries({ queryKey: ['playlist', variables.playlistId] });
      queryClient.invalidateQueries({ queryKey: ['playlist', variables.playlistId, 'collaborators'] });
      queryClient.invalidateQueries({ queryKey: ['playlists'] });
    },
  });
}

/**
 * Hook pour mettre à jour la permission d'un collaborateur
 * T0482: Create Playlist Share Hooks
 */
export function useUpdateCollaboratorPermission() {
  const queryClient = useQueryClient();
  
  return useMutation({
    mutationFn: ({
      playlistId,
      userId,
      data,
    }: {
      playlistId: number;
      userId: number;
      data: UpdateCollaboratorPermissionRequest;
    }) => playlistService.updateCollaboratorPermission(playlistId, userId, data),
    onSuccess: (_, variables) => {
      queryClient.invalidateQueries({ queryKey: ['playlist', variables.playlistId] });
      queryClient.invalidateQueries({ queryKey: ['playlist', variables.playlistId, 'collaborators'] });
      queryClient.invalidateQueries({ queryKey: ['playlists'] });
    },
  });
}

/**
 * Hook pour récupérer les collaborateurs d'une playlist
 * T0482: Create Playlist Share Hooks
 */
export function useCollaborators(playlistId: number) {
  return useQuery({
    queryKey: ['playlist', playlistId, 'collaborators'],
    queryFn: () => playlistService.getCollaborators(playlistId),
    enabled: !!playlistId,
  });
}

/**
 * Hook pour créer un lien de partage public pour une playlist
 * T0488: Create Playlist Public Share Link
 */
export function useCreateShareLink() {
  const queryClient = useQueryClient();
  
  return useMutation({
    mutationFn: (playlistId: number) => playlistService.createShareLink(playlistId),
    onSuccess: (_, playlistId) => {
      queryClient.invalidateQueries({ queryKey: ['playlist', playlistId] });
    },
  });
}
