package v1 import ( "net/http" "github.com/gin-gonic/gin" "github.com/gochat/gochat/internal/service" applogger "github.com/gochat/gochat/pkg/logger" "github.com/gochat/gochat/pkg/response" ) // AssignmentPolicyV2Handler handles AssignmentPolicy V2 CRUD + inbox associations. // Reference: Chatwoot app/controllers/api/v1/assignment_policies_controller.rb (V2) type AssignmentPolicyV2Handler struct { svc *service.AssignmentPolicyV2Service } // NewAssignmentPolicyV2Handler creates a new AssignmentPolicyV2 handler. func NewAssignmentPolicyV2Handler(svc *service.AssignmentPolicyV2Service) *AssignmentPolicyV2Handler { return &AssignmentPolicyV2Handler{svc: svc} } // Create creates a new assignment policy V2. // POST /api/v1/accounts/:account_id/assignment_policies func (h *AssignmentPolicyV2Handler) Create(c *gin.Context) { accountID := getAccountID(c) if accountID == 0 { response.AbortWithStatusError(c, http.StatusUnauthorized, response.ErrUnauthorized, "account not identified") return } var req service.CreatePolicyV2Request if err := c.ShouldBindJSON(&req); err != nil { response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrValidation, err.Error()) return } policy, svcErr := h.svc.Create(c.Request.Context(), accountID, &req) if svcErr != nil { applogger.L().Errorf("Create assignment policy V2 for account %d: %v", accountID, svcErr) handleServiceError(c, svcErr) return } response.Created(c, policy) } // Get retrieves an assignment policy V2 by ID. // GET /api/v1/accounts/:account_id/assignment_policies/:id func (h *AssignmentPolicyV2Handler) Get(c *gin.Context) { accountID := getAccountID(c) if accountID == 0 { response.AbortWithStatusError(c, http.StatusUnauthorized, response.ErrUnauthorized, "account not identified") return } policyID, err := parseUintParam(c, "id") if err != nil { response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrValidation, "invalid policy id") return } policy, svcErr := h.svc.Get(c.Request.Context(), accountID, policyID) if svcErr != nil { applogger.L().Errorf("Get assignment policy V2 %d for account %d: %v", policyID, accountID, svcErr) handleServiceError(c, svcErr) return } response.OK(c, policy) } // List retrieves all assignment policies V2 for an account. // GET /api/v1/accounts/:account_id/assignment_policies func (h *AssignmentPolicyV2Handler) List(c *gin.Context) { accountID := getAccountID(c) if accountID == 0 { response.AbortWithStatusError(c, http.StatusUnauthorized, response.ErrUnauthorized, "account not identified") return } policies, svcErr := h.svc.List(c.Request.Context(), accountID) if svcErr != nil { applogger.L().Errorf("List assignment policies V2 for account %d: %v", accountID, svcErr) handleServiceError(c, svcErr) return } response.OK(c, policies) } // Update updates an assignment policy V2. // PUT /api/v1/accounts/:account_id/assignment_policies/:id func (h *AssignmentPolicyV2Handler) Update(c *gin.Context) { accountID := getAccountID(c) if accountID == 0 { response.AbortWithStatusError(c, http.StatusUnauthorized, response.ErrUnauthorized, "account not identified") return } policyID, err := parseUintParam(c, "id") if err != nil { response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrValidation, "invalid policy id") return } var req service.UpdatePolicyV2Request if err := c.ShouldBindJSON(&req); err != nil { response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrValidation, err.Error()) return } policy, svcErr := h.svc.Update(c.Request.Context(), accountID, policyID, &req) if svcErr != nil { applogger.L().Errorf("Update assignment policy V2 %d for account %d: %v", policyID, accountID, svcErr) handleServiceError(c, svcErr) return } response.OK(c, policy) } // Delete deletes an assignment policy V2. // DELETE /api/v1/accounts/:account_id/assignment_policies/:id func (h *AssignmentPolicyV2Handler) Delete(c *gin.Context) { accountID := getAccountID(c) if accountID == 0 { response.AbortWithStatusError(c, http.StatusUnauthorized, response.ErrUnauthorized, "account not identified") return } policyID, err := parseUintParam(c, "id") if err != nil { response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrValidation, "invalid policy id") return } svcErr := h.svc.Delete(c.Request.Context(), accountID, policyID) if svcErr != nil { applogger.L().Errorf("Delete assignment policy V2 %d for account %d: %v", policyID, accountID, svcErr) handleServiceError(c, svcErr) return } response.NoContent(c) } // ListInboxes retrieves all inboxes associated with a policy. // GET /api/v1/accounts/:account_id/assignment_policies/:id/inboxes func (h *AssignmentPolicyV2Handler) ListInboxes(c *gin.Context) { accountID := getAccountID(c) if accountID == 0 { response.AbortWithStatusError(c, http.StatusUnauthorized, response.ErrUnauthorized, "account not identified") return } policyID, err := parseUintParam(c, "id") if err != nil { response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrValidation, "invalid policy id") return } apInboxes, svcErr := h.svc.ListInboxes(c.Request.Context(), accountID, policyID) if svcErr != nil { applogger.L().Errorf("List inboxes for assignment policy V2 %d: %v", policyID, svcErr) handleServiceError(c, svcErr) return } response.OK(c, apInboxes) } // AddInbox associates an inbox with a policy. // POST /api/v1/accounts/:account_id/assignment_policies/:id/inboxes func (h *AssignmentPolicyV2Handler) AddInbox(c *gin.Context) { accountID := getAccountID(c) if accountID == 0 { response.AbortWithStatusError(c, http.StatusUnauthorized, response.ErrUnauthorized, "account not identified") return } policyID, err := parseUintParam(c, "id") if err != nil { response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrValidation, "invalid policy id") return } var req service.AddInboxRequestV2 if err := c.ShouldBindJSON(&req); err != nil { response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrValidation, err.Error()) return } apInbox, svcErr := h.svc.AddInbox(c.Request.Context(), accountID, policyID, &req) if svcErr != nil { applogger.L().Errorf("Add inbox to assignment policy V2 %d: %v", policyID, svcErr) handleServiceError(c, svcErr) return } response.Created(c, apInbox) } // RemoveInbox removes an inbox association from a policy. // DELETE /api/v1/accounts/:account_id/assignment_policies/:id/inboxes/:inbox_id func (h *AssignmentPolicyV2Handler) RemoveInbox(c *gin.Context) { accountID := getAccountID(c) if accountID == 0 { response.AbortWithStatusError(c, http.StatusUnauthorized, response.ErrUnauthorized, "account not identified") return } policyID, err := parseUintParam(c, "id") if err != nil { response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrValidation, "invalid policy id") return } inboxID, err := parseUintParam(c, "inbox_id") if err != nil { response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrValidation, "invalid inbox id") return } svcErr := h.svc.RemoveInbox(c.Request.Context(), accountID, policyID, inboxID) if svcErr != nil { applogger.L().Errorf("Remove inbox %d from assignment policy V2 %d: %v", inboxID, policyID, svcErr) handleServiceError(c, svcErr) return } response.NoContent(c) } // GetInboxPolicy retrieves the assignment policy for a specific inbox. // GET /api/v1/accounts/:account_id/inboxes/:inbox_id/assignment_policy func (h *AssignmentPolicyV2Handler) GetInboxPolicy(c *gin.Context) { accountID := getAccountID(c) if accountID == 0 { response.AbortWithStatusError(c, http.StatusUnauthorized, response.ErrUnauthorized, "account not identified") return } inboxID, err := parseUintParam(c, "inbox_id") if err != nil { response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrValidation, "invalid inbox id") return } policy, svcErr := h.svc.GetInboxPolicy(c.Request.Context(), accountID, inboxID) if svcErr != nil { applogger.L().Errorf("Get assignment policy V2 for inbox %d: %v", inboxID, svcErr) handleServiceError(c, svcErr) return } response.OK(c, policy) } // SetInboxPolicy sets the assignment policy for a specific inbox. // POST /api/v1/accounts/:account_id/inboxes/:inbox_id/assignment_policy func (h *AssignmentPolicyV2Handler) SetInboxPolicy(c *gin.Context) { accountID := getAccountID(c) if accountID == 0 { response.AbortWithStatusError(c, http.StatusUnauthorized, response.ErrUnauthorized, "account not identified") return } inboxID, err := parseUintParam(c, "inbox_id") if err != nil { response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrValidation, "invalid inbox id") return } var req struct { PolicyID uint `json:"policy_id" validate:"required"` } if err := c.ShouldBindJSON(&req); err != nil { response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrValidation, err.Error()) return } apInbox, svcErr := h.svc.SetInboxPolicy(c.Request.Context(), accountID, inboxID, req.PolicyID) if svcErr != nil { applogger.L().Errorf("Set assignment policy V2 for inbox %d: %v", inboxID, svcErr) handleServiceError(c, svcErr) return } response.Created(c, apInbox) } // DeleteInboxPolicy removes the assignment policy association from an inbox. // DELETE /api/v1/accounts/:account_id/inboxes/:inbox_id/assignment_policy func (h *AssignmentPolicyV2Handler) DeleteInboxPolicy(c *gin.Context) { accountID := getAccountID(c) if accountID == 0 { response.AbortWithStatusError(c, http.StatusUnauthorized, response.ErrUnauthorized, "account not identified") return } inboxID, err := parseUintParam(c, "inbox_id") if err != nil { response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrValidation, "invalid inbox id") return } svcErr := h.svc.DeleteInboxPolicy(c.Request.Context(), accountID, inboxID) if svcErr != nil { applogger.L().Errorf("Delete assignment policy V2 from inbox %d: %v", inboxID, svcErr) handleServiceError(c, svcErr) return } response.NoContent(c) }