package v1 import ( "net/http" "strconv" "time" "github.com/gin-gonic/gin" "github.com/gochat/gochat/internal/service" "github.com/gochat/gochat/pkg/response" ) // ReportingEventHandler handles reporting event API endpoints. // Reference: Chatwoot app/controllers/api/v1/accounts/reporting_events_controller.rb type ReportingEventHandler struct { svc *service.ReportingEventService } // NewReportingEventHandler creates a new ReportingEventHandler. func NewReportingEventHandler(svc *service.ReportingEventService) *ReportingEventHandler { return &ReportingEventHandler{svc: svc} } const chatwootReportingEventsPerPage = 25 // List retrieves reporting events for an account with Chatwoot filters and pagination. // GET /api/v1/accounts/:account_id/reporting_events?since=...&until=...&inbox_id=...&user_id=...&name=...&page=... func (h *ReportingEventHandler) List(c *gin.Context) { accountID, err := parseUintParam(c, "account_id") if err != nil { response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrBadRequest, "invalid account_id") return } filter, ok := parseReportingEventListFilter(c) if !ok { return } result, svcErr := h.svc.ListAccountEvents(c.Request.Context(), accountID, filter) if svcErr != nil { handleServiceError(c, svcErr) return } payload := make([]gin.H, 0, len(result.Events)) for i := range result.Events { payload = append(payload, serializeReportingEvent(result.Events[i])) } c.JSON(http.StatusOK, gin.H{ "payload": payload, "meta": gin.H{ "count": result.Total, "current_page": result.CurrentPage, "total_pages": result.TotalPages, }, }) } func parseReportingEventListFilter(c *gin.Context) (service.ReportingEventListFilter, bool) { page, err := strconv.Atoi(c.DefaultQuery("page", "1")) if err != nil || page < 1 { page = 1 } inboxID, err := parseOptionalUintQueryParam(c, "inbox_id") if err != nil { response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrBadRequest, "invalid inbox_id") return service.ReportingEventListFilter{}, false } userID, err := parseOptionalUintQueryParam(c, "user_id") if err != nil { response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrBadRequest, "invalid user_id") return service.ReportingEventListFilter{}, false } filter := service.ReportingEventListFilter{ InboxID: inboxID, UserID: userID, Name: c.Query("name"), Page: page, PerPage: chatwootReportingEventsPerPage, } sinceStr := c.Query("since") untilStr := c.Query("until") if sinceStr == "" || untilStr == "" { return filter, true } since, err := parseUnixTimestamp(sinceStr) if err != nil { response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrBadRequest, "invalid since date format") return service.ReportingEventListFilter{}, false } until, err := parseUnixTimestamp(untilStr) if err != nil { response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrBadRequest, "invalid until date format") return service.ReportingEventListFilter{}, false } filter.Since = &since filter.Until = &until return filter, true } func parseUnixTimestamp(value string) (time.Time, error) { seconds, err := strconv.ParseInt(value, 10, 64) if err != nil { return time.Time{}, err } return time.Unix(seconds, 0).UTC(), nil }