package notification import ( "time" "github.com/asaskevich/govalidator" ) // EventType represents the type of notification event type EventType string const ( EventTypeEmail EventType = "EMAIL" EventTypeSMS EventType = "SMS" EventTypePush EventType = "PUSH" EventTypeOTP EventType = "OTP" ) // NotificationMethods contains different delivery methods for notifications type NotificationMethods struct { OTP string `json:"otp,omitempty" valid:"optional"` SMS string `json:"sms,omitempty" valid:"optional"` Push string `json:"push,omitempty" valid:"optional"` Email string `json:"email,omitempty" valid:"optional,email"` } // NotificationRequest represents the request structure for sending notifications type NotificationRequest struct { UserID string `json:"user_id"` Title string `json:"title"` Message string `json:"message"` Type string `json:"type"` EventType EventType `json:"event_type"` Priority string `json:"priority"` ScheduledAt int64 `json:"scheduled_at"` Metadata map[string]any `json:"metadata"` Methods NotificationMethods `json:"methods"` } // NotificationResponse represents the successful response from notification service type NotificationResponse struct { Status string `json:"status"` } // DetailedNotificationResponse represents a detailed notification response type DetailedNotificationResponse struct { Data struct { ID string `json:"id"` UserID string `json:"user_id"` Title string `json:"title"` Message string `json:"message"` Link string `json:"link"` Image string `json:"image"` Type string `json:"type"` // info, warning, alert, reject Priority string `json:"priority"` // low, medium, important EventType string `json:"event_type"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` Methods map[string]string `json:"methods"` Metadata map[string]any `json:"metadata"` Status string `json:"status"` // pending, sent, failed Seen bool `json:"seen"` SeenAt int64 `json:"seen_at"` ScheduledAt int64 `json:"scheduled_at"` IsScheduled bool `json:"is_scheduled"` } `json:"data"` } // NotificationErrorResponse represents the error response from notification service type NotificationErrorResponse struct { Error string `json:"error"` } // Validate validates the notification request func (nr *NotificationRequest) Validate() error { // First run govalidator validation if _, err := govalidator.ValidateStruct(nr); err != nil { return ErrValidation{Field: "struct", Message: err.Error()} } // Custom validation: ensure at least one method is provided based on event type switch nr.EventType { case EventTypeEmail: if nr.Methods.Email == "" { return ErrValidation{Field: "methods.email", Message: "email address is required for EMAIL event type"} } case EventTypeSMS: if nr.Methods.SMS == "" { return ErrValidation{Field: "methods.sms", Message: "SMS number is required for SMS event type"} } case EventTypePush: if nr.Methods.Push == "" { return ErrValidation{Field: "methods.push", Message: "push device token is required for PUSH event type"} } case EventTypeOTP: if nr.Methods.OTP == "" { return ErrValidation{Field: "methods.otp", Message: "OTP number is required for OTP event type"} } } // Validate scheduled_at: 0 means immediate delivery, otherwise must be future timestamp if nr.ScheduledAt < 0 { return ErrValidation{Field: "scheduled_at", Message: "scheduled_at cannot be negative"} } return nil } // HasMethod checks if a specific method is configured func (nm *NotificationMethods) HasMethod(eventType EventType) bool { switch eventType { case EventTypeEmail: return nm.Email != "" case EventTypeSMS: return nm.SMS != "" case EventTypePush: return nm.Push != "" case EventTypeOTP: return nm.OTP != "" default: return false } } // GetMethodValue returns the value for a specific method func (nm *NotificationMethods) GetMethodValue(eventType EventType) string { switch eventType { case EventTypeEmail: return nm.Email case EventTypeSMS: return nm.SMS case EventTypePush: return nm.Push case EventTypeOTP: return nm.OTP default: return "" } } // IsImmediate returns true if the notification should be sent immediately (scheduled_at = 0) func (nr *NotificationRequest) IsImmediate() bool { return nr.ScheduledAt == 0 } // NotificationItem represents a single notification in the list response type NotificationItem struct { ID string `json:"id"` UserID string `json:"user_id"` Title string `json:"title"` Message string `json:"message"` Link string `json:"link"` Image string `json:"image"` Type string `json:"type"` Priority string `json:"priority"` EventType string `json:"event_type"` CreatedAt string `json:"created_at"` UpdatedAt string `json:"updated_at"` Methods map[string]string `json:"methods"` Metadata map[string]any `json:"metadata"` Status string `json:"status"` ScheduledAt int64 `json:"scheduled_at"` IsScheduled bool `json:"is_scheduled"` Seen bool `json:"seen"` SeenAt int64 `json:"seen_at"` } // NotificationListResponse represents the response from getting notifications list type NotificationListResponse struct { Data []NotificationItem `json:"data"` Pagination PaginationInfo `json:"pagination"` } // PaginationInfo represents pagination information in responses type PaginationInfo struct { Total int `json:"total"` Count int `json:"count"` PerPage int `json:"per_page"` CurrentPage int `json:"current_page"` TotalPages int `json:"total_pages"` } // GetNotificationsRequest represents the request parameters for getting notifications type GetNotificationsRequest struct { Status string `json:"status,omitempty" valid:"optional"` Method string `json:"method,omitempty" valid:"optional"` EventType string `json:"event_type,omitempty" valid:"optional"` Type string `json:"type,omitempty" valid:"optional"` UserID string `json:"user_id,omitempty" valid:"optional"` Seen *bool `json:"seen,omitempty" valid:"optional"` Priority string `json:"priority,omitempty" valid:"optional"` Page int `json:"page,omitempty" valid:"optional"` PerPage int `json:"per_page,omitempty" valid:"optional"` } // MarkSeenRequest represents the request for marking a notification as seen type MarkSeenRequest struct { NotificationID string `json:"notification_id" valid:"required"` } // MarkSeenResponse represents the response from marking a notification as seen type MarkSeenResponse struct { Status string `json:"status"` }