package response import ( "net/http" "github.com/gin-gonic/gin" ) // APIResponse is the unified response structure for all API endpoints. // Pattern follows Chatwoot's JSON response format in controllers. type APIResponse struct { Success bool `json:"success"` Data interface{} `json:"data,omitempty"` Error *ErrorBody `json:"error,omitempty"` Meta *MetaBody `json:"meta,omitempty"` } type ErrorBody struct { Code ErrorCode `json:"code"` Message string `json:"message"` Detail string `json:"detail,omitempty"` } type MetaBody struct { Page int `json:"page,omitempty"` PerPage int `json:"per_page,omitempty"` TotalCount int64 `json:"total_count,omitempty"` } // OK sends a successful response with data func OK(c *gin.Context, data interface{}) { c.JSON(http.StatusOK, APIResponse{ Success: true, Data: data, }) } // OKWithMeta sends a successful paginated response func OKWithMeta(c *gin.Context, data interface{}, page, perPage int, total int64) { c.JSON(http.StatusOK, APIResponse{ Success: true, Data: data, Meta: &MetaBody{ Page: page, PerPage: perPage, TotalCount: total, }, }) } // Created sends a 201 response func Created(c *gin.Context, data interface{}) { c.JSON(http.StatusCreated, APIResponse{ Success: true, Data: data, }) } // NoContent sends a 204 response func NoContent(c *gin.Context) { c.Status(http.StatusNoContent) } // AbortWithError sends an error response and aborts the Gin context func AbortWithError(c *gin.Context, appErr *AppError) { c.AbortWithStatusJSON(appErr.Status, APIResponse{ Success: false, Error: &ErrorBody{ Code: appErr.Code, Message: appErr.Message, Detail: appErr.Detail, }, }) } // AbortWithStatusError sends a generic error with just HTTP status and message func AbortWithStatusError(c *gin.Context, status int, code ErrorCode, message string) { c.AbortWithStatusJSON(status, APIResponse{ Success: false, Error: &ErrorBody{ Code: code, Message: message, }, }) }