package middleware

import (
	"bytes"
	"gitee.ltd/lxh/logger/log"
	"github.com/gin-gonic/gin"
	jsoniter "github.com/json-iterator/go"
	"io"
	"regexp"
	"strings"
	"time"
	"wireguard-ui/http/vo"
	"wireguard-ui/model"
	"wireguard-ui/service"
)

// bodyWriter
// @description: 重写ResponseBody
type bodyWriter struct {
	gin.ResponseWriter
	body *bytes.Buffer
}

func RequestLog() gin.HandlerFunc {
	return func(c *gin.Context) {
		var userId string
		if userInfo, ok := c.Get("user"); ok {
			userId = userInfo.(*vo.User).Id
		}

		// 开始时间
		start := time.Now()
		host := c.Request.Host          // 请求域名
		path := c.Request.URL.Path      // 接口地址
		query := c.Request.URL.RawQuery // 参数
		if strings.Contains(path, "/api/dashboard/request/list") {
			c.Next()
			return
		}

		var bodyStr string
		if !strings.Contains(path, "/api/login") {
			body, err := c.GetRawData() // body参数
			if err == nil {
				bodyStr = string(body)
				c.Request.Body = io.NopCloser(bytes.NewBuffer(body))
				reg := regexp.MustCompile("\\s+")
				bodyStr = reg.ReplaceAllString(bodyStr, "")
			}
		}

		method := c.Request.Method // 请求方式
		ip := c.ClientIP()         // 取出IP
		// 处理实际客户端IP
		if c.Request.Header.Get("X-Real-Ip") != "" {
			ip = c.Request.Header.Get("X-Real-Ip") // 这个是网关Nginx自定义的Header头
		} else if c.Request.Header.Get("X-Forwarded-For") != "" {
			ip = c.Request.Header.Get("X-Forwarded-For") // 这个是网关Nginx自定义的Header头
		}
		ua := c.Request.UserAgent() // UA

		// 重写客户端IP
		c.Request.Header.Set("X-Forwarded-For", ip)
		c.Request.Header.Set("X-Real-IP", ip)

		// 拦截response
		bw := &bodyWriter{body: bytes.NewBufferString(""), ResponseWriter: c.Writer}
		c.Writer = bw

		header := c.Request.Header
		headerStr, _ := jsoniter.MarshalToString(header)

		// 执行下一步请求
		c.Next()
		// 计算耗时
		cost := time.Since(start).Milliseconds()

		// 组装实体
		l := model.RequestLog{
			UserId:     userId,
			ClientIP:   ip,
			Host:       host,
			Method:     method,
			Uri:        path,
			Header:     headerStr,
			Body:       bodyStr,
			Form:       "",
			Query:      query,
			UserAgent:  ua,
			Cost:       cost,
			StatusCode: c.Writer.Status(),
			Response:   "",
		}

		// 如果不是返回200，把返回值保存一下
		if c.Writer.Status() != 200 {
			resp := bw.body.String()
			l.Response = resp
		}

		go func() {
			if er := service.Log().CreateLog(l); er != nil {
				log.Debugf("请求日志: %+v", l)
				log.Errorf("保存请求日志失败: %v", er)
			}
		}()
	}
}
