package repository import ( "context" "encoding/json" dbgen "github.com/SamuelTariku/FortuneBet-Backend/gen/db" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain" "github.com/jackc/pgx/v5/pgtype" "golang.org/x/net/websocket" ) type NotificationRepository interface { CreateNotification(ctx context.Context, notification *domain.Notification) (*domain.Notification, error) UpdateNotificationStatus(ctx context.Context, id, status string, isRead bool, metadata []byte) (*domain.Notification, error) ListNotifications(ctx context.Context, recipientID int64, limit, offset int) ([]domain.Notification, error) ListFailedNotifications(ctx context.Context, limit int) ([]domain.Notification, error) ListRecipientIDs(ctx context.Context, receiver domain.NotificationRecieverSide) ([]int64, error) CountUnreadNotifications(ctx context.Context, recipient_id int64) (int64, error) GetAllNotifications(ctx context.Context, limit, offset int) ([]domain.Notification, error) } type Repository struct { store *Store } func NewNotificationRepository(store *Store) NotificationRepository { return &Repository{store: store} } func (r *Repository) ConnectWebSocket(ctx context.Context, recipientID int64, c *websocket.Conn) error { return nil } func (r *Repository) CreateNotification(ctx context.Context, notification *domain.Notification) (*domain.Notification, error) { var errorSeverity pgtype.Text if notification.ErrorSeverity != nil { errorSeverity.String = string(*notification.ErrorSeverity) errorSeverity.Valid = true } var deliveryChannel pgtype.Text if notification.DeliveryChannel != "" { deliveryChannel.String = string(notification.DeliveryChannel) deliveryChannel.Valid = true } var priority pgtype.Int4 if notification.Priority != 0 { priority.Int32 = int32(notification.Priority) priority.Valid = true } params := dbgen.CreateNotificationParams{ ID: notification.ID, RecipientID: notification.RecipientID, Type: string(notification.Type), Level: string(notification.Level), ErrorSeverity: errorSeverity, Reciever: string(notification.Reciever), IsRead: notification.IsRead, DeliveryStatus: string(notification.DeliveryStatus), DeliveryChannel: deliveryChannel, Payload: marshalPayload(notification.Payload), Priority: priority, Timestamp: pgtype.Timestamptz{Time: notification.Timestamp, Valid: true}, Metadata: notification.Metadata, } dbNotification, err := r.store.queries.CreateNotification(ctx, params) if err != nil { return nil, err } return r.mapDBToDomain(&dbNotification), nil } func (r *Repository) UpdateNotificationStatus(ctx context.Context, id, status string, isRead bool, metadata []byte) (*domain.Notification, error) { params := dbgen.UpdateNotificationStatusParams{ ID: id, DeliveryStatus: status, IsRead: isRead, Metadata: metadata, } dbNotification, err := r.store.queries.UpdateNotificationStatus(ctx, params) if err != nil { return nil, err } return r.mapDBToDomain(&dbNotification), nil } func (r *Repository) ListNotifications(ctx context.Context, recipientID int64, limit, offset int) ([]domain.Notification, error) { params := dbgen.ListNotificationsParams{ RecipientID: recipientID, Limit: int32(limit), Offset: int32(offset), } dbNotifications, err := r.store.queries.ListNotifications(ctx, params) if err != nil { return nil, err } var result []domain.Notification for _, dbNotif := range dbNotifications { domainNotif := r.mapDBToDomain(&dbNotif) result = append(result, *domainNotif) } return result, nil } func (r *Repository) GetAllNotifications(ctx context.Context, limit, offset int) ([]domain.Notification, error) { dbNotifications, err := r.store.queries.GetAllNotifications(ctx, dbgen.GetAllNotificationsParams{ Limit: int32(limit), Offset: int32(offset), }) if err != nil { return nil, err } var result []domain.Notification = make([]domain.Notification, 0, len(dbNotifications)) for _, dbNotif := range dbNotifications { domainNotif := r.mapDBToDomain(&dbNotif) result = append(result, *domainNotif) } return result, nil } func (r *Repository) ListFailedNotifications(ctx context.Context, limit int) ([]domain.Notification, error) { dbNotifications, err := r.store.queries.ListFailedNotifications(ctx, int32(limit)) if err != nil { return nil, err } var result []domain.Notification for _, dbNotif := range dbNotifications { domainNotif := r.mapDBToDomain(&dbNotif) result = append(result, *domainNotif) } return result, nil } func (r *Repository) ListRecipientIDs(ctx context.Context, receiver domain.NotificationRecieverSide) ([]int64, error) { return r.store.queries.ListRecipientIDsByReceiver(ctx, string(receiver)) } func (r *Repository) mapDBToDomain(dbNotif *dbgen.Notification) *domain.Notification { var errorSeverity *domain.NotificationErrorSeverity if dbNotif.ErrorSeverity.Valid { s := domain.NotificationErrorSeverity(dbNotif.ErrorSeverity.String) errorSeverity = &s } var deliveryChannel domain.DeliveryChannel if dbNotif.DeliveryChannel.Valid { deliveryChannel = domain.DeliveryChannel(dbNotif.DeliveryChannel.String) } else { deliveryChannel = "" } var priority int if dbNotif.Priority.Valid { priority = int(dbNotif.Priority.Int32) } payload, err := unmarshalPayload(dbNotif.Payload) if err != nil { payload = domain.NotificationPayload{} } return &domain.Notification{ ID: dbNotif.ID, RecipientID: dbNotif.RecipientID, Type: domain.NotificationType(dbNotif.Type), Level: domain.NotificationLevel(dbNotif.Level), ErrorSeverity: errorSeverity, Reciever: domain.NotificationRecieverSide(dbNotif.Reciever), IsRead: dbNotif.IsRead, DeliveryStatus: domain.NotificationDeliveryStatus(dbNotif.DeliveryStatus), DeliveryChannel: deliveryChannel, Payload: payload, Priority: priority, Timestamp: dbNotif.Timestamp.Time, Metadata: dbNotif.Metadata, } } func marshalPayload(payload domain.NotificationPayload) []byte { data, _ := json.Marshal(payload) return data } func unmarshalPayload(data []byte) (domain.NotificationPayload, error) { var payload domain.NotificationPayload if err := json.Unmarshal(data, &payload); err != nil { return domain.NotificationPayload{}, err } return payload, nil } func (r *Repository) CountUnreadNotifications(ctx context.Context, recipient_id int64) (int64, error) { return r.store.queries.CountUnreadNotifications(ctx, recipient_id) }