package handlers import ( "net/http" "github.com/breakpilot/ai-compliance-sdk/internal/maximizer" "github.com/gin-gonic/gin" "github.com/google/uuid" ) // MaximizerHandlers exposes the Compliance Maximizer API. type MaximizerHandlers struct { svc *maximizer.Service } // NewMaximizerHandlers creates handlers backed by a maximizer service. func NewMaximizerHandlers(svc *maximizer.Service) *MaximizerHandlers { return &MaximizerHandlers{svc: svc} } // Optimize evaluates a DimensionConfig and returns optimized variants. func (h *MaximizerHandlers) Optimize(c *gin.Context) { var req maximizer.OptimizeInput if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } req.TenantID, _ = getTenantID(c) req.UserID = maximizerGetUserID(c) result, err := h.svc.Optimize(c.Request.Context(), &req) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, result) } // OptimizeFromIntake maps a UseCaseIntake to dimensions and optimizes. func (h *MaximizerHandlers) OptimizeFromIntake(c *gin.Context) { var req maximizer.OptimizeFromIntakeInput if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } req.TenantID, _ = getTenantID(c) req.UserID = maximizerGetUserID(c) result, err := h.svc.OptimizeFromIntake(c.Request.Context(), &req) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, result) } // OptimizeFromAssessment optimizes an existing UCCA assessment. func (h *MaximizerHandlers) OptimizeFromAssessment(c *gin.Context) { id, err := uuid.Parse(c.Param("id")) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "invalid assessment id"}) return } tid, _ := getTenantID(c) uid := maximizerGetUserID(c) result, err := h.svc.OptimizeFromAssessment(c.Request.Context(), id, tid, uid) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, result) } // Evaluate performs a 3-zone evaluation without persisting. func (h *MaximizerHandlers) Evaluate(c *gin.Context) { var config maximizer.DimensionConfig if err := c.ShouldBindJSON(&config); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } result := h.svc.Evaluate(&config) c.JSON(http.StatusOK, result) } // ListOptimizations returns stored optimizations for the tenant. func (h *MaximizerHandlers) ListOptimizations(c *gin.Context) { f := &maximizer.OptimizationFilters{ Search: c.Query("search"), Limit: maximizerParseInt(c.Query("limit"), 20), Offset: maximizerParseInt(c.Query("offset"), 0), } tid, _ := getTenantID(c) results, total, err := h.svc.ListOptimizations(c.Request.Context(), tid, f) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, gin.H{"optimizations": results, "total": total}) } // GetOptimization returns a single optimization. func (h *MaximizerHandlers) GetOptimization(c *gin.Context) { id, err := uuid.Parse(c.Param("id")) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "invalid id"}) return } result, err := h.svc.GetOptimization(c.Request.Context(), id) if err != nil { c.JSON(http.StatusNotFound, gin.H{"error": "not found"}) return } c.JSON(http.StatusOK, result) } // DeleteOptimization removes an optimization. func (h *MaximizerHandlers) DeleteOptimization(c *gin.Context) { id, err := uuid.Parse(c.Param("id")) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "invalid id"}) return } if err := h.svc.DeleteOptimization(c.Request.Context(), id); err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusNoContent, nil) } // GetDimensionSchema returns the dimension enum values for the frontend. func (h *MaximizerHandlers) GetDimensionSchema(c *gin.Context) { c.JSON(http.StatusOK, h.svc.GetDimensionSchema()) } func maximizerGetUserID(c *gin.Context) uuid.UUID { if id, exists := c.Get("user_id"); exists { if uid, ok := id.(uuid.UUID); ok { return uid } } return uuid.Nil } // maximizerParseInt is a local helper for query param parsing. func maximizerParseInt(s string, def int) int { if s == "" { return def } n := 0 for _, c := range s { if c < '0' || c > '9' { return def } n = n*10 + int(c-'0') } return n }