package repositories import ( "context" "github.com/google/uuid" "veza-backend-api/internal/models" "gorm.io/gorm" ) // PlaylistRepository définit l'interface pour les opérations sur les playlists type PlaylistRepository interface { // Create crée une nouvelle playlist Create(ctx context.Context, playlist *models.Playlist) error // GetByID récupère une playlist par son ID GetByID(ctx context.Context, id uuid.UUID) (*models.Playlist, error) // GetByUserID récupère les playlists d'un utilisateur GetByUserID(ctx context.Context, userID uuid.UUID, limit, offset int) ([]*models.Playlist, int64, error) // Update met à jour une playlist Update(ctx context.Context, playlist *models.Playlist) error // Delete supprime une playlist Delete(ctx context.Context, id uuid.UUID) error // List récupère une liste de playlists avec pagination List(ctx context.Context, filterUserID *uuid.UUID, isPublic *bool, limit, offset int) ([]*models.Playlist, int64, error) // Exists vérifie si une playlist existe Exists(ctx context.Context, id uuid.UUID) (bool, error) // GetByIDWithTracks récupère une playlist avec ses tracks // T0501: Create Playlist Performance Optimization GetByIDWithTracks(ctx context.Context, id uuid.UUID) (*models.Playlist, error) // Search recherche des playlists selon des critères // T0496: Create Playlist Search Backend Search(ctx context.Context, query string, filterUserID *uuid.UUID, isPublic *bool, limit, offset int) ([]*models.Playlist, int64, error) } // playlistRepository implémente PlaylistRepository avec GORM type playlistRepository struct { db *gorm.DB } // NewPlaylistRepository crée une nouvelle instance de PlaylistRepository func NewPlaylistRepository(db *gorm.DB) PlaylistRepository { return &playlistRepository{ db: db, } } // Create crée une nouvelle playlist func (r *playlistRepository) Create(ctx context.Context, playlist *models.Playlist) error { return r.db.WithContext(ctx).Create(playlist).Error } // GetByID récupère une playlist par son ID // T0501: Optimisé avec lazy loading des tracks func (r *playlistRepository) GetByID(ctx context.Context, id uuid.UUID) (*models.Playlist, error) { var playlist models.Playlist // T0501: Ne pas charger les tracks par défaut (lazy loading) // Les tracks seront chargés à la demande via GetTracks si nécessaire if err := r.db.WithContext(ctx). Preload("User"). First(&playlist, "id = ?", id).Error; err != nil { return nil, err } return &playlist, nil } // GetByIDWithTracks récupère une playlist avec ses tracks (pour les cas où on en a besoin) // T0501: Méthode séparée pour charger les tracks à la demande func (r *playlistRepository) GetByIDWithTracks(ctx context.Context, id uuid.UUID) (*models.Playlist, error) { var playlist models.Playlist if err := r.db.WithContext(ctx). Preload("User"). Preload("Tracks"). Preload("Tracks.Track"). First(&playlist, "id = ?", id).Error; err != nil { return nil, err } return &playlist, nil } // GetByUserID récupère les playlists d'un utilisateur // MIGRATION UUID: userID migré vers uuid.UUID func (r *playlistRepository) GetByUserID(ctx context.Context, userID uuid.UUID, limit, offset int) ([]*models.Playlist, int64, error) { var playlists []*models.Playlist var total int64 query := r.db.WithContext(ctx).Model(&models.Playlist{}).Where("user_id = ?", userID) if err := query.Count(&total).Error; err != nil { return nil, 0, err } if err := query.Preload("User"). Order("created_at DESC"). Offset(offset). Limit(limit). Find(&playlists).Error; err != nil { return nil, 0, err } return playlists, total, nil } // Update met à jour une playlist func (r *playlistRepository) Update(ctx context.Context, playlist *models.Playlist) error { return r.db.WithContext(ctx).Save(playlist).Error } // Delete supprime une playlist func (r *playlistRepository) Delete(ctx context.Context, id uuid.UUID) error { return r.db.WithContext(ctx).Delete(&models.Playlist{}, "id = ?", id).Error } // List récupère une liste de playlists avec pagination // MIGRATION UUID: filterUserID migré vers *uuid.UUID func (r *playlistRepository) List(ctx context.Context, filterUserID *uuid.UUID, isPublic *bool, limit, offset int) ([]*models.Playlist, int64, error) { var playlists []*models.Playlist var total int64 query := r.db.WithContext(ctx).Model(&models.Playlist{}) if filterUserID != nil { query = query.Where("user_id = ?", *filterUserID) } if isPublic != nil { query = query.Where("is_public = ?", *isPublic) } if err := query.Count(&total).Error; err != nil { return nil, 0, err } if err := query.Preload("User"). Order("created_at DESC"). Offset(offset). Limit(limit). Find(&playlists).Error; err != nil { return nil, 0, err } return playlists, total, nil } // Exists vérifie si une playlist existe func (r *playlistRepository) Exists(ctx context.Context, id uuid.UUID) (bool, error) { var count int64 err := r.db.WithContext(ctx).Model(&models.Playlist{}).Where("id = ?", id).Count(&count).Error return count > 0, err } // Search recherche des playlists selon des critères // T0496: Create Playlist Search Backend // MIGRATION UUID: filterUserID migré vers *uuid.UUID func (r *playlistRepository) Search(ctx context.Context, query string, filterUserID *uuid.UUID, isPublic *bool, limit, offset int) ([]*models.Playlist, int64, error) { var playlists []*models.Playlist var total int64 dbQuery := r.db.WithContext(ctx).Model(&models.Playlist{}) // Recherche par titre ou description if query != "" { searchPattern := "%" + query + "%" dbQuery = dbQuery.Where("(title LIKE ? OR description LIKE ?)", searchPattern, searchPattern) } // Filtrer par utilisateur if filterUserID != nil { dbQuery = dbQuery.Where("user_id = ?", *filterUserID) } // Filtrer par statut public/privé if isPublic != nil { dbQuery = dbQuery.Where("is_public = ?", *isPublic) } // Compter le total if err := dbQuery.Count(&total).Error; err != nil { return nil, 0, err } // Récupérer les playlists avec pagination if err := dbQuery. Preload("User"). Order("created_at DESC"). Offset(offset). Limit(limit). Find(&playlists).Error; err != nil { return nil, 0, err } return playlists, total, nil }