package handlers import ( "encoding/json" "net/http" "strconv" "github.com/jmoiron/sqlx" "mgit.msbls.de/m/KanzlAI-mGMT/internal/auth" "mgit.msbls.de/m/KanzlAI-mGMT/internal/services" ) // NotificationHandler handles notification API endpoints. type NotificationHandler struct { svc *services.NotificationService db *sqlx.DB } // NewNotificationHandler creates a new notification handler. func NewNotificationHandler(svc *services.NotificationService, db *sqlx.DB) *NotificationHandler { return &NotificationHandler{svc: svc, db: db} } // List returns paginated notifications for the authenticated user. func (h *NotificationHandler) List(w http.ResponseWriter, r *http.Request) { tenantID, ok := auth.TenantFromContext(r.Context()) if !ok { writeError(w, http.StatusUnauthorized, "unauthorized") return } userID, ok := auth.UserFromContext(r.Context()) if !ok { writeError(w, http.StatusUnauthorized, "unauthorized") return } limit, _ := strconv.Atoi(r.URL.Query().Get("limit")) offset, _ := strconv.Atoi(r.URL.Query().Get("offset")) notifications, total, err := h.svc.ListForUser(r.Context(), tenantID, userID, limit, offset) if err != nil { writeError(w, http.StatusInternalServerError, "failed to list notifications") return } writeJSON(w, http.StatusOK, map[string]any{ "data": notifications, "total": total, }) } // UnreadCount returns the count of unread notifications. func (h *NotificationHandler) UnreadCount(w http.ResponseWriter, r *http.Request) { tenantID, ok := auth.TenantFromContext(r.Context()) if !ok { writeError(w, http.StatusUnauthorized, "unauthorized") return } userID, ok := auth.UserFromContext(r.Context()) if !ok { writeError(w, http.StatusUnauthorized, "unauthorized") return } count, err := h.svc.UnreadCount(r.Context(), tenantID, userID) if err != nil { writeError(w, http.StatusInternalServerError, "failed to count notifications") return } writeJSON(w, http.StatusOK, map[string]int{"unread_count": count}) } // MarkRead marks a single notification as read. func (h *NotificationHandler) MarkRead(w http.ResponseWriter, r *http.Request) { tenantID, ok := auth.TenantFromContext(r.Context()) if !ok { writeError(w, http.StatusUnauthorized, "unauthorized") return } userID, ok := auth.UserFromContext(r.Context()) if !ok { writeError(w, http.StatusUnauthorized, "unauthorized") return } notifID, err := parsePathUUID(r, "id") if err != nil { writeError(w, http.StatusBadRequest, "invalid notification ID") return } if err := h.svc.MarkRead(r.Context(), tenantID, userID, notifID); err != nil { writeError(w, http.StatusNotFound, err.Error()) return } writeJSON(w, http.StatusOK, map[string]string{"status": "ok"}) } // MarkAllRead marks all notifications as read. func (h *NotificationHandler) MarkAllRead(w http.ResponseWriter, r *http.Request) { tenantID, ok := auth.TenantFromContext(r.Context()) if !ok { writeError(w, http.StatusUnauthorized, "unauthorized") return } userID, ok := auth.UserFromContext(r.Context()) if !ok { writeError(w, http.StatusUnauthorized, "unauthorized") return } if err := h.svc.MarkAllRead(r.Context(), tenantID, userID); err != nil { writeError(w, http.StatusInternalServerError, "failed to mark all read") return } writeJSON(w, http.StatusOK, map[string]string{"status": "ok"}) } // GetPreferences returns notification preferences for the authenticated user. func (h *NotificationHandler) GetPreferences(w http.ResponseWriter, r *http.Request) { tenantID, ok := auth.TenantFromContext(r.Context()) if !ok { writeError(w, http.StatusUnauthorized, "unauthorized") return } userID, ok := auth.UserFromContext(r.Context()) if !ok { writeError(w, http.StatusUnauthorized, "unauthorized") return } pref, err := h.svc.GetPreferences(r.Context(), tenantID, userID) if err != nil { writeError(w, http.StatusInternalServerError, "failed to get preferences") return } writeJSON(w, http.StatusOK, pref) } // UpdatePreferences updates notification preferences for the authenticated user. func (h *NotificationHandler) UpdatePreferences(w http.ResponseWriter, r *http.Request) { tenantID, ok := auth.TenantFromContext(r.Context()) if !ok { writeError(w, http.StatusUnauthorized, "unauthorized") return } userID, ok := auth.UserFromContext(r.Context()) if !ok { writeError(w, http.StatusUnauthorized, "unauthorized") return } var input services.UpdatePreferencesInput if err := json.NewDecoder(r.Body).Decode(&input); err != nil { writeError(w, http.StatusBadRequest, "invalid request body") return } pref, err := h.svc.UpdatePreferences(r.Context(), tenantID, userID, input) if err != nil { writeError(w, http.StatusInternalServerError, "failed to update preferences") return } writeJSON(w, http.StatusOK, pref) }