package v1 import ( "errors" "net/http" "strings" "github.com/gin-gonic/gin" "github.com/gochat/gochat/internal/service" "github.com/gochat/gochat/pkg/response" ) // ShopifyIntegrationHandler handles Shopify integration endpoints. // Reference: Chatwoot Integrations::ShopifyController type ShopifyIntegrationHandler struct { svc *service.ShopifyIntegrationService } // NewShopifyIntegrationHandler creates a new ShopifyIntegrationHandler. func NewShopifyIntegrationHandler(svc *service.ShopifyIntegrationService) *ShopifyIntegrationHandler { return &ShopifyIntegrationHandler{svc: svc} } // Delete removes a Shopify integration for an account. // DELETE /api/v1/accounts/:account_id/integrations/shopify func (h *ShopifyIntegrationHandler) Delete(c *gin.Context) { accountID, err := parseUintParam(c, "account_id") if err != nil { response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrBadRequest, "invalid account_id") return } if svcErr := h.svc.Delete(c.Request.Context(), accountID); svcErr != nil { handleShopifyServiceError(c, svcErr) return } c.Status(http.StatusOK) } // Auth returns the Shopify OAuth authorize URL. // POST /api/v1/accounts/:account_id/integrations/shopify/auth func (h *ShopifyIntegrationHandler) Auth(c *gin.Context) { accountID, err := parseUintParam(c, "account_id") if err != nil { response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrBadRequest, "invalid account_id") return } var req service.CreateShopifyAuthRequest if err := c.ShouldBind(&req); err != nil { response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrBadRequest, err.Error()) return } if strings.TrimSpace(req.ShopDomain) == "" { c.JSON(http.StatusUnprocessableEntity, gin.H{"error": "Shop domain is required"}) return } redirect, svcErr := h.svc.BuildAuthRedirect(c.Request.Context(), accountID, req) if svcErr != nil { handleShopifyServiceError(c, svcErr) return } c.JSON(http.StatusOK, redirect) } // GetOrders retrieves Shopify orders for an account. // GET /api/v1/accounts/:account_id/integrations/shopify/orders func (h *ShopifyIntegrationHandler) GetOrders(c *gin.Context) { accountID, err := parseUintParam(c, "account_id") if err != nil { response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrBadRequest, "invalid account_id") return } contactID, err := parseOptionalUintQueryParam(c, "contact_id") if err != nil { response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrBadRequest, "invalid contact_id") return } orders, svcErr := h.svc.GetOrders(c.Request.Context(), accountID, contactID) if svcErr != nil { handleShopifyServiceError(c, svcErr) return } c.JSON(http.StatusOK, gin.H{"orders": orders}) } // RegisterShopifyIntegrationRoutes registers Shopify integration routes. func RegisterShopifyIntegrationRoutes(g *gin.RouterGroup, h *ShopifyIntegrationHandler) { g.DELETE("/shopify", h.Delete) shopify := g.Group("/shopify") { shopify.DELETE("/", h.Delete) shopify.POST("/auth", h.Auth) shopify.GET("/orders", h.GetOrders) } } func handleShopifyServiceError(c *gin.Context, err error) { var providerErr *service.ShopifyProviderError if errors.As(err, &providerErr) { c.JSON(http.StatusUnprocessableEntity, gin.H{"error": providerErr.Message}) return } handleServiceError(c, err) }