package controller

import (
	"enterprise/common/config"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/gogap/errors"
	log "github.com/sirupsen/logrus"
	"github.com/smbrave/goutil"
	"net/http"
	"runtime"
	"time"
)

type Response struct {
	Code    int         `json:"code"`
	Message string      `json:"message"`
	Data    interface{} `json:"data"`
}

type Base struct {
}

func (c *Base) Recovery(ctx *gin.Context) {
	defer func() {
		if err := recover(); err != nil {
			var rsp Response
			if e, ok := err.(errors.ErrCode); ok {
				rsp.Code = int(e.Code())
				rsp.Message = e.Error()
				ctx.JSON(http.StatusOK, rsp)
				log.Errorf("[%s][%s][%s] %s", ctx.Request.Method, ctx.Request.URL.Path, ctx.Request.URL.RawQuery, e.Error())
			} else {
				var buf [2 << 10]byte
				stack := string(buf[:runtime.Stack(buf[:], true)])
				log.Errorf("[%s][%s][%s] Internal ERROR:::%v stack:%s", ctx.Request.Method, ctx.Request.URL.Path, ctx.Request.URL.RawQuery, err, stack)
				rsp.Code = -1
				rsp.Message = fmt.Sprintf("%v", err)
				ctx.JSON(http.StatusOK, rsp)
			}
			ctx.Abort()
		}
	}()
	start := time.Now()
	ctx.Next()

	log.Infof("[%s][%s] cost[%s] query[%s] params[%s]",
		ctx.Request.Method, ctx.Request.URL.Path, time.Since(start),
		ctx.Request.URL.RawQuery, goutil.EncodeJSON(ctx.Keys[config.ContextParam]))
}