package v1 import ( "errors" "net/http" "github.com/gin-gonic/gin" "github.com/gochat/gochat/internal/llm" "github.com/gochat/gochat/internal/service" "github.com/gochat/gochat/pkg/response" ) // CopilotConfigHandler exposes typed platform and account configuration APIs. // Platform mutations are registered behind middleware.SuperAdmin; account // configuration remains administrator scoped. type CopilotConfigHandler struct { platform *service.CopilotConfigService account *service.CaptainPreferenceService } func NewCopilotConfigHandler(platform *service.CopilotConfigService, account *service.CaptainPreferenceService) *CopilotConfigHandler { return &CopilotConfigHandler{platform: platform, account: account} } func (h *CopilotConfigHandler) PlatformGet(c *gin.Context) { payload, err := h.platform.Get(c.Request.Context()) if err != nil { handleServiceError(c, err) return } c.JSON(http.StatusOK, payload) } func (h *CopilotConfigHandler) PlatformUpdate(c *gin.Context) { var input service.CopilotProviderConfigInput if err := c.ShouldBindJSON(&input); err != nil { response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrValidation, err.Error()) return } payload, err := h.platform.Update(c.Request.Context(), input) if err != nil { c.JSON(http.StatusUnprocessableEntity, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, payload) } func (h *CopilotConfigHandler) PlatformTest(c *gin.Context) { var input service.CopilotProviderConfigInput if err := c.ShouldBindJSON(&input); err != nil { response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrValidation, err.Error()) return } payload, err := h.platform.Test(c.Request.Context(), input) if err != nil { status := http.StatusUnprocessableEntity if errors.Is(err, llm.ErrProviderNotConfigured) { status = http.StatusConflict } c.JSON(status, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, payload) } func (h *CopilotConfigHandler) AccountGet(c *gin.Context) { if !captainPreferencesCanUpdate(c) { response.AbortWithStatusError(c, http.StatusForbidden, response.ErrForbidden, "administrator role required") return } accountID := parseAccountIDParam(c) if accountID == 0 { response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrBadRequest, "invalid account_id") return } payload, err := h.account.GetConfig(c.Request.Context(), accountID) if err != nil { handleServiceError(c, err) return } c.JSON(http.StatusOK, payload) } func (h *CopilotConfigHandler) AccountUpdate(c *gin.Context) { if !captainPreferencesCanUpdate(c) { response.AbortWithStatusError(c, http.StatusForbidden, response.ErrForbidden, "administrator role required") return } accountID := parseAccountIDParam(c) if accountID == 0 { response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrBadRequest, "invalid account_id") return } var input service.UpdateCaptainConfigRequest if err := c.ShouldBindJSON(&input); err != nil { response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrValidation, err.Error()) return } payload, err := h.account.UpdateConfig(c.Request.Context(), accountID, &input) if err != nil { c.JSON(http.StatusUnprocessableEntity, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, payload) }