package api

import (
	"dataapps/commons/logger"
	"net/http"

	"github.com/gin-gonic/gin"
	"github.com/tidbcloud/tiinf/errs"
	"go.uber.org/zap"
)

// error return struct definition
type APIError struct {
	Code    int    `json:"code"`
	Message string `json:"message"`
}

func (err APIError) Error() string {
	return err.Message
}

// middleware error handler in sqleditor package
func APIErrorJSONReporter() gin.HandlerFunc {
	return APIErrorJSONReporterHandler(gin.ErrorTypeAny)
}

func APIErrorJSONReporterHandler(errType gin.ErrorType) gin.HandlerFunc {
	return func(c *gin.Context) {
		c.Next()
		innerErrors := c.Errors.ByType(errType)

		if len(innerErrors) > 0 {
			err := innerErrors[0].Err
			httpCode := http.StatusInternalServerError
			parsedError := &APIError{
				Code:    -1,
				Message: "Sorry, some unknown exceptions have occurred. Please try again later",
			}
			if te, ok := errs.AsTiError(err); ok {
				httpCode = te.HTTPCode()
				parsedError.Code = int(te.BizCode())
				parsedError.Message = te.ErrMsg()
			}
			logger.LogWithError(c.Request.Context(), err, "request failed",
				zap.String("path", c.Request.URL.Path),
				zap.Int("http_status", httpCode),
				zap.Any("response", parsedError))

			// Put the error into response
			c.IndentedJSON(httpCode, parsedError)
			c.Abort()
			return
		}

	}
}
