package handlers import ( "net/http" "strconv" "time" "github.com/calendarapi/internal/middleware" "github.com/calendarapi/internal/models" "github.com/calendarapi/internal/service" "github.com/calendarapi/internal/utils" "github.com/go-chi/chi/v5" "github.com/google/uuid" ) type EventHandler struct { eventSvc *service.EventService } func NewEventHandler(eventSvc *service.EventService) *EventHandler { return &EventHandler{eventSvc: eventSvc} } func (h *EventHandler) List(w http.ResponseWriter, r *http.Request) { userID, _ := middleware.GetUserID(r.Context()) q := r.URL.Query() startStr := q.Get("start") endStr := q.Get("end") if startStr == "" || endStr == "" { utils.WriteError(w, models.NewValidationError("start and end query params required")) return } start, err := time.Parse(time.RFC3339, startStr) if err != nil { utils.WriteError(w, models.NewValidationError("invalid start time")) return } end, err := time.Parse(time.RFC3339, endStr) if err != nil { utils.WriteError(w, models.NewValidationError("invalid end time")) return } var calendarID *uuid.UUID if cid := q.Get("calendar_id"); cid != "" { id, err := utils.ValidateUUID(cid) if err != nil { utils.WriteError(w, err) return } calendarID = &id } var search *string if s := q.Get("search"); s != "" { search = &s } var tag *string if t := q.Get("tag"); t != "" { tag = &t } limit := 50 if l := q.Get("limit"); l != "" { if v, err := strconv.Atoi(l); err == nil { limit = v } } events, cursor, err := h.eventSvc.List(r.Context(), userID, service.ListEventParams{ RangeStart: start, RangeEnd: end, CalendarID: calendarID, Search: search, Tag: tag, Limit: limit, Cursor: q.Get("cursor"), }) if err != nil { utils.WriteError(w, err) return } utils.WriteList(w, events, models.PageInfo{Limit: int(utils.ClampLimit(limit)), NextCursor: cursor}) } func (h *EventHandler) Create(w http.ResponseWriter, r *http.Request) { userID, _ := middleware.GetUserID(r.Context()) var req struct { CalendarID uuid.UUID `json:"calendar_id"` Title string `json:"title"` Description *string `json:"description"` Location *string `json:"location"` StartTime time.Time `json:"start_time"` EndTime time.Time `json:"end_time"` Timezone string `json:"timezone"` AllDay bool `json:"all_day"` RecurrenceRule *string `json:"recurrence_rule"` Reminders []int32 `json:"reminders"` Tags []string `json:"tags"` } if err := utils.DecodeJSON(r, &req); err != nil { utils.WriteError(w, err) return } event, err := h.eventSvc.Create(r.Context(), userID, service.CreateEventRequest{ CalendarID: req.CalendarID, Title: req.Title, Description: req.Description, Location: req.Location, StartTime: req.StartTime, EndTime: req.EndTime, Timezone: req.Timezone, AllDay: req.AllDay, RecurrenceRule: req.RecurrenceRule, Reminders: req.Reminders, Tags: req.Tags, }) if err != nil { utils.WriteError(w, err) return } utils.WriteJSON(w, http.StatusOK, map[string]interface{}{"event": event}) } func (h *EventHandler) Get(w http.ResponseWriter, r *http.Request) { userID, _ := middleware.GetUserID(r.Context()) eventID, err := utils.ValidateUUID(chi.URLParam(r, "id")) if err != nil { utils.WriteError(w, err) return } event, err := h.eventSvc.Get(r.Context(), userID, eventID) if err != nil { utils.WriteError(w, err) return } utils.WriteJSON(w, http.StatusOK, map[string]interface{}{"event": event}) } func (h *EventHandler) Update(w http.ResponseWriter, r *http.Request) { userID, _ := middleware.GetUserID(r.Context()) eventID, err := utils.ValidateUUID(chi.URLParam(r, "id")) if err != nil { utils.WriteError(w, err) return } var req struct { Title *string `json:"title"` Description *string `json:"description"` Location *string `json:"location"` StartTime *time.Time `json:"start_time"` EndTime *time.Time `json:"end_time"` Timezone *string `json:"timezone"` AllDay *bool `json:"all_day"` RecurrenceRule *string `json:"recurrence_rule"` Tags []string `json:"tags"` } if err := utils.DecodeJSON(r, &req); err != nil { utils.WriteError(w, err) return } event, err := h.eventSvc.Update(r.Context(), userID, eventID, service.UpdateEventRequest{ Title: req.Title, Description: req.Description, Location: req.Location, StartTime: req.StartTime, EndTime: req.EndTime, Timezone: req.Timezone, AllDay: req.AllDay, RecurrenceRule: req.RecurrenceRule, Tags: req.Tags, }) if err != nil { utils.WriteError(w, err) return } utils.WriteJSON(w, http.StatusOK, map[string]interface{}{"event": event}) } func (h *EventHandler) Delete(w http.ResponseWriter, r *http.Request) { userID, _ := middleware.GetUserID(r.Context()) eventID, err := utils.ValidateUUID(chi.URLParam(r, "id")) if err != nil { utils.WriteError(w, err) return } if err := h.eventSvc.Delete(r.Context(), userID, eventID); err != nil { utils.WriteError(w, err) return } utils.WriteOK(w) }