package v1 import ( "errors" "net/http" "github.com/gin-gonic/gin" "github.com/gochat/gochat/internal/service" "github.com/gochat/gochat/pkg/response" ) // InboxCsatTemplateHandler handles CSAT template endpoints for inboxes. // Reference: Chatwoot app/controllers/api/v1/accounts/inboxes/inbox_csat_templates_controller.rb // CSAT template is a singular resource per inbox: show, create, and analyze actions. type InboxCsatTemplateHandler struct { svc *service.CsatTemplateService } // NewInboxCsatTemplateHandler creates a new InboxCsatTemplateHandler. func NewInboxCsatTemplateHandler(svc *service.CsatTemplateService) *InboxCsatTemplateHandler { return &InboxCsatTemplateHandler{svc: svc} } // Show retrieves the CSAT template status for an inbox. // GET /api/v1/accounts/:account_id/inboxes/:inbox_id/csat_template // If no template exists, returns an empty object (Chatwoot returns nil in this case). func (h *InboxCsatTemplateHandler) Show(c *gin.Context) { inboxID, err := parseUintParam(c, "inbox_id") if err != nil { response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrBadRequest, "invalid inbox_id") return } status, svcErr := h.svc.ShowTemplateStatusResult(c.Request.Context(), inboxID) if svcErr != nil { handleServiceError(c, svcErr) return } response.OK(c, status) } // Create creates or updates a CSAT template for an inbox. // POST /api/v1/accounts/:account_id/inboxes/:inbox_id/csat_template // Body: { "message": "..." } func (h *InboxCsatTemplateHandler) Create(c *gin.Context) { inboxID, err := parseUintParam(c, "inbox_id") if err != nil { response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrBadRequest, "invalid inbox_id") return } req, err := bindCreateCsatTemplateRequest(c) if err != nil { response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrBadRequest, "invalid request body") return } template, svcErr := h.svc.CreateTemplate(c.Request.Context(), inboxID, req) if svcErr != nil { handleServiceError(c, svcErr) return } c.JSON(http.StatusCreated, template) } // Analyze analyzes a CSAT template message for quality. // POST /api/v1/accounts/:account_id/inboxes/:inbox_id/csat_template/analyze // Body: { "message": "..." } func (h *InboxCsatTemplateHandler) Analyze(c *gin.Context) { inboxID, err := parseUintParam(c, "inbox_id") if err != nil { response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrBadRequest, "invalid inbox_id") return } req, err := bindAnalyzeCsatTemplateRequest(c) if err != nil { response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrBadRequest, "invalid request body") return } result, svcErr := h.svc.AnalyzeTemplate(c.Request.Context(), inboxID, req) if svcErr != nil { handleServiceError(c, svcErr) return } response.OK(c, result) } func bindCreateCsatTemplateRequest(c *gin.Context) (service.CreateCsatTemplateRequest, error) { var body struct { Message string `json:"message"` ButtonText string `json:"button_text"` Language string `json:"language"` Template service.CreateCsatTemplateRequest `json:"template"` } if err := c.ShouldBindJSON(&body); err != nil { return service.CreateCsatTemplateRequest{}, err } req := body.Template if req.Message == "" { req.Message = body.Message } if req.ButtonText == "" { req.ButtonText = body.ButtonText } if req.Language == "" { req.Language = body.Language } if req.Message == "" { return req, errors.New("message is required") } return req, nil } func bindAnalyzeCsatTemplateRequest(c *gin.Context) (service.AnalyzeCsatTemplateRequest, error) { var body struct { Message string `json:"message"` ButtonText string `json:"button_text"` Language string `json:"language"` Template service.AnalyzeCsatTemplateRequest `json:"template"` } if err := c.ShouldBindJSON(&body); err != nil { return service.AnalyzeCsatTemplateRequest{}, err } req := body.Template if req.Message == "" { req.Message = body.Message } if req.ButtonText == "" { req.ButtonText = body.ButtonText } if req.Language == "" { req.Language = body.Language } if req.Message == "" { return req, errors.New("message is required") } return req, nil }