package v1 import ( "net/http" "github.com/gin-gonic/gin" "github.com/gochat/gochat/internal/model" "github.com/gochat/gochat/internal/service" "github.com/gochat/gochat/pkg/pagination" "github.com/gochat/gochat/pkg/response" ) // BannerHandler handles Platform API banner endpoints (super-admin CRUD) // and account-scoped read-only ListActive endpoint. // Reference: Chatwoot Platform::Api::V1::BannersController — super-admin CRUD, // and api/v1/accounts/:account_id/banners — read-only active banners. type BannerHandler struct { svc *service.BannerService } // NewBannerHandler creates a new BannerHandler with service injection. func NewBannerHandler(svc *service.BannerService) *BannerHandler { return &BannerHandler{svc: svc} } // --- Platform (super-admin) Banner endpoints --- // Reference: Chatwoot Platform::Api::V1::BannersController // List retrieves all banners, paginated (super-admin). // GET /platform/api/v1/banners func (h *BannerHandler) List(c *gin.Context) { pg := pagination.Parse(c) banners, total, err := h.svc.List(c.Request.Context(), pg.Offset, pg.PerPage) if err != nil { handleServiceError(c, err) return } response.OKWithMeta(c, banners, pg.Page, pg.PerPage, total) } // Get retrieves a single banner by ID (super-admin). // GET /platform/api/v1/banners/:id func (h *BannerHandler) Get(c *gin.Context) { id, err := parseUintParam(c, "id") if err != nil { response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrBadRequest, "invalid banner ID") return } banner, svcErr := h.svc.Get(c.Request.Context(), id) if svcErr != nil { handleServiceError(c, svcErr) return } response.OK(c, banner) } // Create creates a new banner (super-admin). // POST /platform/api/v1/banners func (h *BannerHandler) Create(c *gin.Context) { var req struct { Title string `json:"title" binding:"required"` Content string `json:"content" binding:"required"` Active bool `json:"active"` BannerType string `json:"banner_type" binding:"required"` CreatedBy *uint `json:"created_by"` } if err := c.ShouldBindJSON(&req); err != nil { response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrValidation, err.Error()) return } banner := &model.Banner{ Title: req.Title, Content: req.Content, Active: req.Active, BannerType: req.BannerType, CreatedBy: req.CreatedBy, } if svcErr := h.svc.Create(c.Request.Context(), banner); svcErr != nil { handleServiceError(c, svcErr) return } response.Created(c, banner) } // Update patches an existing banner (super-admin). // PUT /platform/api/v1/banners/:id func (h *BannerHandler) Update(c *gin.Context) { id, err := parseUintParam(c, "id") if err != nil { response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrBadRequest, "invalid banner ID") return } var req map[string]interface{} if err := c.ShouldBindJSON(&req); err != nil { response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrValidation, err.Error()) return } if svcErr := h.svc.Update(c.Request.Context(), id, req); svcErr != nil { handleServiceError(c, svcErr) return } // Return updated banner banner, svcErr := h.svc.Get(c.Request.Context(), id) if svcErr != nil { handleServiceError(c, svcErr) return } response.OK(c, banner) } // Delete soft-deletes a banner (super-admin). // DELETE /platform/api/v1/banners/:id func (h *BannerHandler) Delete(c *gin.Context) { id, err := parseUintParam(c, "id") if err != nil { response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrBadRequest, "invalid banner ID") return } if svcErr := h.svc.Delete(c.Request.Context(), id); svcErr != nil { handleServiceError(c, svcErr) return } response.NoContent(c) } // --- Account-scoped (read-only) Banner endpoint --- // Reference: Chatwoot api/v1/accounts/:account_id/banners — only active banners // ListActive returns all active banners visible to account users. // GET /api/v1/accounts/:account_id/banners func (h *BannerHandler) ListActive(c *gin.Context) { banners, err := h.svc.ListActive(c.Request.Context()) if err != nil { handleServiceError(c, err) return } response.OK(c, banners) }