package services import ( "context" "fmt" "github.com/google/uuid" "veza-backend-api/internal/repositories" "go.uber.org/zap" ) // PlaylistNotificationService handles playlist-specific notifications // T0508: Create Playlist Notifications type PlaylistNotificationService struct { notificationService *NotificationService playlistRepo repositories.PlaylistRepository collaboratorRepo repositories.PlaylistCollaboratorRepository logger *zap.Logger } // NewPlaylistNotificationService creates a new playlist notification service func NewPlaylistNotificationService( notificationService *NotificationService, playlistRepo repositories.PlaylistRepository, collaboratorRepo repositories.PlaylistCollaboratorRepository, logger *zap.Logger, ) *PlaylistNotificationService { if logger == nil { logger = zap.NewNop() } return &PlaylistNotificationService{ notificationService: notificationService, playlistRepo: playlistRepo, collaboratorRepo: collaboratorRepo, logger: logger, } } // NotifyCollaboratorAdded notifies a user when they are added as a collaborator // T0508: Create Playlist Notifications // MIGRATION UUID: Completée. func (pns *PlaylistNotificationService) NotifyCollaboratorAdded(ctx context.Context, playlistID uuid.UUID, collaboratorUserID uuid.UUID, addedByUserID uuid.UUID) error { // Get playlist info playlist, err := pns.playlistRepo.GetByID(ctx, playlistID) if err != nil { return fmt.Errorf("failed to get playlist: %w", err) } // Get collaborator info using GetCollaborator (which takes playlistID and userID) _, err = pns.collaboratorRepo.GetCollaborator(ctx, playlistID, collaboratorUserID) if err != nil { return fmt.Errorf("failed to get collaborator: %w", err) } // Get added by user info (we'll use a simple query for now) // In a real implementation, you might want to get the username title := "Nouveau collaborateur" content := fmt.Sprintf("Vous avez été ajouté comme collaborateur à la playlist \"%s\"", playlist.Title) link := fmt.Sprintf("/playlists/%s", playlistID.String()) return pns.notificationService.CreateNotification( collaboratorUserID, "playlist_collaborator_added", title, content, link, ) } // NotifyTrackAdded notifies playlist owner and collaborators when a track is added // T0508: Create Playlist Notifications // trackTitle can be empty if not available, will use a generic message // MIGRATION UUID: Completée. func (pns *PlaylistNotificationService) NotifyTrackAdded(ctx context.Context, playlistID uuid.UUID, trackTitle string, addedByUserID uuid.UUID) error { // Get playlist info playlist, err := pns.playlistRepo.GetByID(ctx, playlistID) if err != nil { return fmt.Errorf("failed to get playlist: %w", err) } // Notify playlist owner (if not the one who added the track) if playlist.UserID != addedByUserID { title := "Track ajouté" var content string if trackTitle != "" { content = fmt.Sprintf("Un nouveau track \"%s\" a été ajouté à votre playlist \"%s\"", trackTitle, playlist.Title) } else { content = fmt.Sprintf("Un nouveau track a été ajouté à votre playlist \"%s\"", playlist.Title) } link := fmt.Sprintf("/playlists/%s", playlistID.String()) if err := pns.notificationService.CreateNotification( playlist.UserID, "playlist_track_added", title, content, link, ); err != nil { pns.logger.Warn("Failed to notify playlist owner", zap.Error(err)) } } // Notify all collaborators (except the one who added the track) collaborators, err := pns.collaboratorRepo.GetCollaborators(ctx, playlistID) if err != nil { pns.logger.Warn("Failed to get collaborators", zap.Error(err)) return nil // Don't fail the whole operation if we can't notify collaborators } title := "Track ajouté" var content string if trackTitle != "" { content = fmt.Sprintf("Un nouveau track \"%s\" a été ajouté à la playlist \"%s\"", trackTitle, playlist.Title) } else { content = fmt.Sprintf("Un nouveau track a été ajouté à la playlist \"%s\"", playlist.Title) } link := fmt.Sprintf("/playlists/%s", playlistID.String()) for _, collaborator := range collaborators { // Skip the user who added the track if collaborator.UserID == addedByUserID { continue } if err := pns.notificationService.CreateNotification( collaborator.UserID, "playlist_track_added", title, content, link, ); err != nil { pns.logger.Warn("Failed to notify collaborator", zap.String("userID", collaborator.UserID.String()), zap.Error(err)) } } return nil } // NotifyPlaylistShared notifies when a playlist is shared via a share link // T0508: Create Playlist Notifications // MIGRATION UUID: Completée. func (pns *PlaylistNotificationService) NotifyPlaylistShared(ctx context.Context, playlistID uuid.UUID, sharedByUserID uuid.UUID) error { // Get playlist info playlist, err := pns.playlistRepo.GetByID(ctx, playlistID) if err != nil { return fmt.Errorf("failed to get playlist: %w", err) } // Notify playlist owner (if not the one who shared) if playlist.UserID != sharedByUserID { title := "Playlist partagée" content := fmt.Sprintf("Votre playlist \"%s\" a été partagée", playlist.Title) link := fmt.Sprintf("/playlists/%s", playlistID.String()) return pns.notificationService.CreateNotification( playlist.UserID, "playlist_shared", title, content, link, ) } return nil } // NotifyPlaylistUpdated notifies collaborators when a playlist is updated // T0508: Create Playlist Notifications // MIGRATION UUID: Completée. func (pns *PlaylistNotificationService) NotifyPlaylistUpdated(ctx context.Context, playlistID uuid.UUID, updatedByUserID uuid.UUID) error { // Get playlist info playlist, err := pns.playlistRepo.GetByID(ctx, playlistID) if err != nil { return fmt.Errorf("failed to get playlist: %w", err) } // Notify playlist owner (if not the one who updated) if playlist.UserID != updatedByUserID { title := "Playlist mise à jour" content := fmt.Sprintf("La playlist \"%s\" a été mise à jour", playlist.Title) link := fmt.Sprintf("/playlists/%s", playlistID.String()) if err := pns.notificationService.CreateNotification( playlist.UserID, "playlist_updated", title, content, link, ); err != nil { pns.logger.Warn("Failed to notify playlist owner", zap.Error(err)) } } // Notify all collaborators (except the one who updated) collaborators, err := pns.collaboratorRepo.GetCollaborators(ctx, playlistID) if err != nil { pns.logger.Warn("Failed to get collaborators", zap.Error(err)) return nil } title := "Playlist mise à jour" content := fmt.Sprintf("La playlist \"%s\" a été mise à jour", playlist.Title) link := fmt.Sprintf("/playlists/%s", playlistID.String()) for _, collaborator := range collaborators { // Skip the user who updated if collaborator.UserID == updatedByUserID { continue } if err := pns.notificationService.CreateNotification( collaborator.UserID, "playlist_updated", title, content, link, ); err != nil { pns.logger.Warn("Failed to notify collaborator", zap.String("userID", collaborator.UserID.String()), zap.Error(err)) } } return nil }