package services import ( "context" "fmt" "time" "github.com/google/uuid" "go.uber.org/zap" "gorm.io/gorm" ) // GearWarrantyNotifier sends notifications for gear items with expiring warranty type GearWarrantyNotifier struct { db *gorm.DB notificationService *NotificationService logger *zap.Logger interval time.Duration } // NewGearWarrantyNotifier creates a new warranty notifier func NewGearWarrantyNotifier(db *gorm.DB, notificationService *NotificationService, logger *zap.Logger) *GearWarrantyNotifier { return &GearWarrantyNotifier{ db: db, notificationService: notificationService, logger: logger, interval: 24 * time.Hour, } } // Start runs the notifier loop func (n *GearWarrantyNotifier) Start(ctx context.Context) { if n.notificationService == nil { n.logger.Info("Gear warranty notifier: notification service not configured, skipping") return } ticker := time.NewTicker(n.interval) defer ticker.Stop() n.logger.Info("Gear warranty notifier started", zap.Duration("interval", n.interval)) for { select { case <-ctx.Done(): return case <-ticker.C: if err := n.runCheck(ctx); err != nil { n.logger.Error("Gear warranty check failed", zap.Error(err)) } } } } func (n *GearWarrantyNotifier) runCheck(ctx context.Context) error { var items []struct { ID uuid.UUID UserID uuid.UUID Name string WarrantyExpire *time.Time } err := n.db.WithContext(ctx).Raw(` SELECT id, user_id, name, warranty_expire FROM gear_items WHERE warranty_expire IS NOT NULL AND warranty_expire > NOW() AND warranty_expire <= NOW() + INTERVAL '30 days' AND deleted_at IS NULL `).Scan(&items).Error if err != nil { return fmt.Errorf("query expiring gear: %w", err) } for _, item := range items { if item.WarrantyExpire == nil { continue } daysLeft := int(time.Until(*item.WarrantyExpire).Hours() / 24) if daysLeft < 0 { daysLeft = 0 } msg := fmt.Sprintf("Warranty for %s expires in %d days", item.Name, daysLeft) link := fmt.Sprintf("/inventory/gear/%s", item.ID) if err := n.notificationService.CreateNotification(item.UserID, "gear_warranty", "Warranty expiring soon", msg, link); err != nil { n.logger.Warn("failed to send warranty notification", zap.String("gear_id", item.ID.String()), zap.Error(err)) } } if len(items) > 0 { n.logger.Info("Gear warranty notifications sent", zap.Int("count", len(items))) } return nil }