package handlers import ( "net/http" "strconv" "github.com/labstack/echo/v4" "github.com/treytartt/casera-api/internal/apperrors" "github.com/treytartt/casera-api/internal/middleware" "github.com/treytartt/casera-api/internal/services" ) // NotificationHandler handles notification-related HTTP requests type NotificationHandler struct { notificationService *services.NotificationService } // NewNotificationHandler creates a new notification handler func NewNotificationHandler(notificationService *services.NotificationService) *NotificationHandler { return &NotificationHandler{notificationService: notificationService} } // ListNotifications handles GET /api/notifications/ func (h *NotificationHandler) ListNotifications(c echo.Context) error { user, err := middleware.MustGetAuthUser(c) if err != nil { return err } limit := 50 offset := 0 if l := c.QueryParam("limit"); l != "" { if parsed, err := strconv.Atoi(l); err == nil && parsed > 0 { limit = parsed } } if limit > 200 { limit = 200 } if o := c.QueryParam("offset"); o != "" { if parsed, err := strconv.Atoi(o); err == nil && parsed >= 0 { offset = parsed } } notifications, err := h.notificationService.GetNotifications(user.ID, limit, offset) if err != nil { return err } return c.JSON(http.StatusOK, map[string]interface{}{ "count": len(notifications), "results": notifications, }) } // GetUnreadCount handles GET /api/notifications/unread-count/ func (h *NotificationHandler) GetUnreadCount(c echo.Context) error { user, err := middleware.MustGetAuthUser(c) if err != nil { return err } count, err := h.notificationService.GetUnreadCount(user.ID) if err != nil { return err } return c.JSON(http.StatusOK, map[string]interface{}{"unread_count": count}) } // MarkAsRead handles POST /api/notifications/:id/read/ func (h *NotificationHandler) MarkAsRead(c echo.Context) error { user, err := middleware.MustGetAuthUser(c) if err != nil { return err } notificationID, err := strconv.ParseUint(c.Param("id"), 10, 32) if err != nil { return apperrors.BadRequest("error.invalid_notification_id") } err = h.notificationService.MarkAsRead(uint(notificationID), user.ID) if err != nil { return err } return c.JSON(http.StatusOK, map[string]interface{}{"message": "message.notification_marked_read"}) } // MarkAllAsRead handles POST /api/notifications/mark-all-read/ func (h *NotificationHandler) MarkAllAsRead(c echo.Context) error { user, err := middleware.MustGetAuthUser(c) if err != nil { return err } err = h.notificationService.MarkAllAsRead(user.ID) if err != nil { return err } return c.JSON(http.StatusOK, map[string]interface{}{"message": "message.all_notifications_marked_read"}) } // GetPreferences handles GET /api/notifications/preferences/ func (h *NotificationHandler) GetPreferences(c echo.Context) error { user, err := middleware.MustGetAuthUser(c) if err != nil { return err } prefs, err := h.notificationService.GetPreferences(user.ID) if err != nil { return err } return c.JSON(http.StatusOK, prefs) } // UpdatePreferences handles PUT/PATCH /api/notifications/preferences/ func (h *NotificationHandler) UpdatePreferences(c echo.Context) error { user, err := middleware.MustGetAuthUser(c) if err != nil { return err } var req services.UpdatePreferencesRequest if err := c.Bind(&req); err != nil { return apperrors.BadRequest("error.invalid_request") } if err := c.Validate(&req); err != nil { return err } prefs, err := h.notificationService.UpdatePreferences(user.ID, &req) if err != nil { return err } return c.JSON(http.StatusOK, prefs) } // RegisterDevice handles POST /api/notifications/devices/ func (h *NotificationHandler) RegisterDevice(c echo.Context) error { user, err := middleware.MustGetAuthUser(c) if err != nil { return err } var req services.RegisterDeviceRequest if err := c.Bind(&req); err != nil { return apperrors.BadRequest("error.invalid_request") } if err := c.Validate(&req); err != nil { return err } device, err := h.notificationService.RegisterDevice(user.ID, &req) if err != nil { return err } return c.JSON(http.StatusCreated, device) } // ListDevices handles GET /api/notifications/devices/ func (h *NotificationHandler) ListDevices(c echo.Context) error { user, err := middleware.MustGetAuthUser(c) if err != nil { return err } devices, err := h.notificationService.ListDevices(user.ID) if err != nil { return err } return c.JSON(http.StatusOK, devices) } // UnregisterDevice handles POST /api/notifications/devices/unregister/ // Accepts {registration_id, platform} and deactivates the matching device func (h *NotificationHandler) UnregisterDevice(c echo.Context) error { user, err := middleware.MustGetAuthUser(c) if err != nil { return err } var req struct { RegistrationID string `json:"registration_id"` Platform string `json:"platform"` } if err := c.Bind(&req); err != nil { return apperrors.BadRequest("error.invalid_request") } if req.RegistrationID == "" { return apperrors.BadRequest("error.registration_id_required") } if req.Platform == "" { req.Platform = "ios" // Default to iOS } err = h.notificationService.UnregisterDevice(req.RegistrationID, req.Platform, user.ID) if err != nil { return err } return c.JSON(http.StatusOK, map[string]interface{}{"message": "message.device_unregistered"}) } // DeleteDevice handles DELETE /api/notifications/devices/:id/ func (h *NotificationHandler) DeleteDevice(c echo.Context) error { user, err := middleware.MustGetAuthUser(c) if err != nil { return err } deviceID, err := strconv.ParseUint(c.Param("id"), 10, 32) if err != nil { return apperrors.BadRequest("error.invalid_device_id") } platform := c.QueryParam("platform") if platform == "" { platform = "ios" // Default to iOS } err = h.notificationService.DeleteDevice(uint(deviceID), platform, user.ID) if err != nil { return err } return c.JSON(http.StatusOK, map[string]interface{}{"message": "message.device_removed"}) }