172 lines
5.7 KiB
Go
172 lines
5.7 KiB
Go
package services
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"github.com/google/uuid"
|
|
|
|
"go.uber.org/zap"
|
|
"gorm.io/gorm"
|
|
"veza-backend-api/internal/models"
|
|
)
|
|
|
|
// TrackLikeService gère les opérations sur les likes de tracks
|
|
type TrackLikeService struct {
|
|
db *gorm.DB
|
|
logger *zap.Logger
|
|
}
|
|
|
|
// NewTrackLikeService crée un nouveau service de likes de tracks
|
|
func NewTrackLikeService(db *gorm.DB, logger *zap.Logger) *TrackLikeService {
|
|
if logger == nil {
|
|
logger = zap.NewNop()
|
|
}
|
|
return &TrackLikeService{
|
|
db: db,
|
|
logger: logger,
|
|
}
|
|
}
|
|
|
|
// LikeTrack ajoute un like d'un utilisateur sur un track
|
|
// MIGRATION UUID: userID migré vers uuid.UUID, trackID reste int64 - Corrected: trackID est maintenant uuid.UUID
|
|
func (s *TrackLikeService) LikeTrack(ctx context.Context, userID uuid.UUID, trackID uuid.UUID) error { // Changed trackID to uuid.UUID
|
|
// Vérifier si le track existe
|
|
var track models.Track
|
|
if err := s.db.WithContext(ctx).First(&track, "id = ?", trackID).Error; err != nil { // Updated query
|
|
if err == gorm.ErrRecordNotFound {
|
|
return fmt.Errorf("track not found")
|
|
}
|
|
return fmt.Errorf("failed to check track: %w", err)
|
|
}
|
|
|
|
// Vérifier si l'utilisateur a déjà liké ce track
|
|
var existing models.TrackLike
|
|
if err := s.db.WithContext(ctx).Where("user_id = ? AND track_id = ?", userID, trackID).First(&existing).Error; err == nil {
|
|
// Déjà liké, retourner nil (idempotent)
|
|
return nil
|
|
} else if err != gorm.ErrRecordNotFound {
|
|
return fmt.Errorf("failed to check existing like: %w", err)
|
|
}
|
|
|
|
// Créer le like
|
|
like := models.TrackLike{
|
|
UserID: userID,
|
|
TrackID: trackID,
|
|
}
|
|
if err := s.db.WithContext(ctx).Create(&like).Error; err != nil {
|
|
return fmt.Errorf("failed to create like: %w", err)
|
|
}
|
|
|
|
// Mettre à jour le compteur de likes du track
|
|
if err := s.db.WithContext(ctx).Model(&track).UpdateColumn("like_count", gorm.Expr("like_count + ?", 1)).Error; err != nil {
|
|
s.logger.Warn("Failed to update track like_count",
|
|
zap.Any("track_id", trackID), // Changed to zap.Any for uuid.UUID
|
|
zap.Error(err),
|
|
)
|
|
// Ne pas retourner l'erreur, le like a été créé avec succès
|
|
}
|
|
|
|
s.logger.Info("Track liked",
|
|
zap.String("user_id", userID.String()),
|
|
zap.Any("track_id", trackID), // Changed to zap.Any for uuid.UUID
|
|
)
|
|
|
|
return nil
|
|
}
|
|
|
|
// UnlikeTrack supprime un like d'un utilisateur sur un track
|
|
// MIGRATION UUID: userID migré vers uuid.UUID, trackID reste int64 - Corrected: trackID est maintenant uuid.UUID
|
|
func (s *TrackLikeService) UnlikeTrack(ctx context.Context, userID uuid.UUID, trackID uuid.UUID) error { // Changed trackID to uuid.UUID
|
|
// Vérifier si le like existe
|
|
var like models.TrackLike
|
|
if err := s.db.WithContext(ctx).Where("user_id = ? AND track_id = ?", userID, trackID).First(&like).Error; err != nil {
|
|
if err == gorm.ErrRecordNotFound {
|
|
// Pas de like à supprimer, retourner nil (idempotent)
|
|
return nil
|
|
}
|
|
return fmt.Errorf("failed to check like: %w", err)
|
|
}
|
|
|
|
// Supprimer le like
|
|
if err := s.db.WithContext(ctx).Delete(&like).Error; err != nil {
|
|
return fmt.Errorf("failed to delete like: %w", err)
|
|
}
|
|
|
|
// Mettre à jour le compteur de likes du track
|
|
var track models.Track
|
|
if err := s.db.WithContext(ctx).First(&track, "id = ?", trackID).Error; err == nil { // Updated query
|
|
if err := s.db.WithContext(ctx).Model(&track).UpdateColumn("like_count", gorm.Expr("GREATEST(like_count - 1, 0)")).Error; err != nil {
|
|
s.logger.Warn("Failed to update track like_count",
|
|
zap.Any("track_id", trackID), // Changed to zap.Any for uuid.UUID
|
|
zap.Error(err),
|
|
)
|
|
// Ne pas retourner l'erreur, le like a été supprimé avec succès
|
|
}
|
|
}
|
|
|
|
s.logger.Info("Track unliked",
|
|
zap.String("user_id", userID.String()),
|
|
zap.Any("track_id", trackID), // Changed to zap.Any for uuid.UUID
|
|
)
|
|
|
|
return nil
|
|
}
|
|
|
|
// IsLiked vérifie si un utilisateur a liké un track
|
|
func (s *TrackLikeService) IsLiked(ctx context.Context, userID uuid.UUID, trackID uuid.UUID) (bool, error) { // Changed trackID to uuid.UUID
|
|
var count int64
|
|
err := s.db.WithContext(ctx).Model(&models.TrackLike{}).
|
|
Where("user_id = ? AND track_id = ?", userID, trackID).
|
|
Count(&count).Error
|
|
if err != nil {
|
|
return false, fmt.Errorf("failed to check like: %w", err)
|
|
}
|
|
return count > 0, nil
|
|
}
|
|
|
|
// GetTrackLikesCount retourne le nombre de likes d'un track
|
|
func (s *TrackLikeService) GetTrackLikesCount(ctx context.Context, trackID uuid.UUID) (int64, error) { // Changed trackID to uuid.UUID
|
|
var count int64
|
|
err := s.db.WithContext(ctx).Model(&models.TrackLike{}).
|
|
Where("track_id = ?", trackID).
|
|
Count(&count).Error
|
|
if err != nil {
|
|
return 0, fmt.Errorf("failed to get likes count: %w", err)
|
|
}
|
|
return count, nil
|
|
}
|
|
|
|
// GetUserLikedTracks retourne la liste des tracks likés par un utilisateur
|
|
func (s *TrackLikeService) GetUserLikedTracks(ctx context.Context, userID uuid.UUID, limit, offset int) ([]models.Track, error) {
|
|
var tracks []models.Track
|
|
|
|
query := s.db.WithContext(ctx).
|
|
Joins("INNER JOIN track_likes ON tracks.id = track_likes.track_id").
|
|
Where("track_likes.user_id = ?", userID).
|
|
Order("track_likes.created_at DESC")
|
|
|
|
if limit > 0 {
|
|
query = query.Limit(limit)
|
|
}
|
|
if offset > 0 {
|
|
query = query.Offset(offset)
|
|
}
|
|
|
|
if err := query.Find(&tracks).Error; err != nil {
|
|
return nil, fmt.Errorf("failed to get user liked tracks: %w", err)
|
|
}
|
|
|
|
return tracks, nil
|
|
}
|
|
|
|
// GetUserLikedTracksCount retourne le nombre total de tracks likés par un utilisateur
|
|
func (s *TrackLikeService) GetUserLikedTracksCount(ctx context.Context, userID uuid.UUID) (int64, error) {
|
|
var count int64
|
|
err := s.db.WithContext(ctx).Model(&models.TrackLike{}).
|
|
Where("user_id = ?", userID).
|
|
Count(&count).Error
|
|
if err != nil {
|
|
return 0, fmt.Errorf("failed to get user liked tracks count: %w", err)
|
|
}
|
|
return count, nil
|
|
}
|