package middlewares

import (
	"bytes"
	"io"
	"time"

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

func CommonLogging(ctx *gin.Context) {
	// Starting time
	startTime := time.Now()

	var body []byte
	if tilog.GetLevel().Enabled(zap.DebugLevel) {
		// copy body for logging
		body, _ = io.ReadAll(ctx.Request.Body)
		ctx.Request.Body = io.NopCloser(bytes.NewBuffer(body))
	}
	// Request method
	reqMethod := ctx.Request.Method

	// Request route
	reqUri := ctx.Request.RequestURI

	// Request IP
	clientIP := ctx.ClientIP()
	logger := tilog.WithContextL(ctx.Request.Context()).With(
		zap.String("method", reqMethod),
		zap.String("uri", reqUri),
		zap.String("client", clientIP),
	)
	logger.Info("begin")

	// Processing request
	ctx.Next()

	// End Time
	endTime := time.Now()

	// execution time
	latencyTime := endTime.Sub(startTime)

	// status code
	statusCode := ctx.Writer.Status()

	logger = logger.With(
		zap.Int("status", statusCode),
		zap.Duration("latency", latencyTime),
		zap.Any("params", ctx.Request.URL.Query()),
	)
	if errs := ctx.Errors.ByType(gin.ErrorTypePrivate); len(errs) > 0 {
		logger = logger.With(zap.String("error", errs.String()))
	}

	if tilog.GetLevel().Enabled(zap.DebugLevel) {
		logger = logger.With(zap.ByteString("body", body))
		logger.Debug("end")
	} else {
		logger.Info("end")
	}
}
