package services import ( "context" "fmt" "github.com/google/uuid" "veza-backend-api/internal/database" "go.uber.org/zap" ) // NotificationService handles notification operations type NotificationService struct { db *database.Database logger *zap.Logger } // Notification represents a notification type Notification struct { ID uuid.UUID `json:"id" db:"id"` UserID uuid.UUID `json:"user_id" db:"user_id"` Type string `json:"type" db:"type"` Title string `json:"title" db:"title"` Content string `json:"content" db:"content"` Link string `json:"link" db:"link"` Read bool `json:"read" db:"read"` CreatedAt string `json:"created_at" db:"created_at"` } // NewNotificationService creates a new notification service func NewNotificationService(db *database.Database, logger *zap.Logger) *NotificationService { return &NotificationService{ db: db, logger: logger, } } // CreateNotification creates a new notification func (ns *NotificationService) CreateNotification(userID uuid.UUID, notificationType, title, content, link string) error { ctx := context.Background() _, err := ns.db.ExecContext(ctx, ` INSERT INTO notifications (user_id, type, title, content, link) VALUES ($1, $2, $3, $4, $5) `, userID, notificationType, title, content, link) if err != nil { return fmt.Errorf("failed to create notification: %w", err) } return nil } // GetNotifications retrieves notifications for a user func (ns *NotificationService) GetNotifications(userID uuid.UUID, unreadOnly bool) ([]Notification, error) { ctx := context.Background() query := ` SELECT id, user_id, type, title, content, link, read, created_at FROM notifications WHERE user_id = $1 ` args := []interface{}{userID} if unreadOnly { query += " AND read = FALSE" } query += " ORDER BY created_at DESC LIMIT 50" rows, err := ns.db.QueryContext(ctx, query, args...) if err != nil { return nil, fmt.Errorf("failed to get notifications: %w", err) } defer rows.Close() var notifications []Notification for rows.Next() { var notification Notification if err := rows.Scan( ¬ification.ID, ¬ification.UserID, ¬ification.Type, ¬ification.Title, ¬ification.Content, ¬ification.Link, ¬ification.Read, ¬ification.CreatedAt, ); err != nil { continue } notifications = append(notifications, notification) } return notifications, nil } // MarkAsRead marks a notification as read func (ns *NotificationService) MarkAsRead(userID uuid.UUID, notificationID uuid.UUID) error { ctx := context.Background() _, err := ns.db.ExecContext(ctx, ` UPDATE notifications SET read = TRUE WHERE id = $1 AND user_id = $2 `, notificationID, userID) if err != nil { return fmt.Errorf("failed to mark notification as read: %w", err) } return nil } // MarkAllAsRead marks all notifications as read for a user func (ns *NotificationService) MarkAllAsRead(userID uuid.UUID) error { ctx := context.Background() _, err := ns.db.ExecContext(ctx, ` UPDATE notifications SET read = TRUE WHERE user_id = $1 AND read = FALSE `, userID) if err != nil { return fmt.Errorf("failed to mark all notifications as read: %w", err) } return nil } // GetUnreadCount returns the count of unread notifications func (ns *NotificationService) GetUnreadCount(userID uuid.UUID) (int, error) { ctx := context.Background() var count int err := ns.db.QueryRowContext(ctx, ` SELECT COUNT(*) FROM notifications WHERE user_id = $1 AND read = FALSE `, userID).Scan(&count) if err != nil { return 0, fmt.Errorf("failed to get unread count: %w", err) } return count, nil } // DeleteNotification deletes a notification func (ns *NotificationService) DeleteNotification(userID uuid.UUID, notificationID uuid.UUID) error { ctx := context.Background() _, err := ns.db.ExecContext(ctx, ` DELETE FROM notifications WHERE id = $1 AND user_id = $2 `, notificationID, userID) if err != nil { return fmt.Errorf("failed to delete notification: %w", err) } return nil } // DeleteAllNotifications deletes all notifications for a user func (ns *NotificationService) DeleteAllNotifications(userID uuid.UUID) error { ctx := context.Background() _, err := ns.db.ExecContext(ctx, ` DELETE FROM notifications WHERE user_id = $1 `, userID) if err != nil { return fmt.Errorf("failed to delete all notifications: %w", err) } return nil }