package middleware

import (
	"bytes"
	"encoding/json"
	"gadmin/config"
	"gadmin/internal/admin/consts"
	"gadmin/internal/gorm/model"
	"gadmin/utility/token"
	"github.com/gin-gonic/gin"
	"github.com/sirupsen/logrus"
	"io"
	"net/http"
	"os"
	"time"
)

// Logger 访问日志
func Logger(c *gin.Context) {

	var (
		start = time.Now() // 开始时间
		body  []byte
		err   error
	)
	if c.Request.Method != http.MethodGet {
		body, err = io.ReadAll(c.Request.Body)
		if err != nil {
			logrus.Warnf("read body from request error:%v", err)
		} else {
			c.Request.Body = io.NopCloser(bytes.NewBuffer(body))
		}
	}

	writer := responseBodyWriter{
		ResponseWriter: c.Writer,
		body:           &bytes.Buffer{},
	}
	c.Writer = writer

	// 处理请求
	c.Next()
	// 结束时间

	var (
		adminID   int64 = 0
		user            = token.CurrentUser(c)
		getMap          = make(map[string]interface{})
		headerMap       = make(map[string]interface{})
		end             = time.Now()
	)

	if user != nil {
		adminID = user.ID
	}

	for k, v := range c.Request.URL.Query() {
		getMap[k] = v
	}
	getByte, _ := json.Marshal(getMap)

	for k, v := range c.Request.Header {
		headerMap[k] = v
	}
	headerByte, _ := json.Marshal(headerMap)

	//remark := ""
	//if c.Request.Method == http.MethodPost {
	//	remark = config.GetMenuName(c.Request.URL.Path)
	//}

	models := &model.AdminLog{
		Environment:  os.Getenv("GIN_MODE"),
		AdminID:      adminID,
		AppID:        consts.AppAdmin,
		UserAgent:    c.Request.UserAgent(),
		Method:       c.Request.Method,
		URL:          "http://" + c.Request.Host + c.Request.RequestURI,
		Host:         c.Request.Host,
		Path:         c.Request.URL.Path,
		GetData:      string(getByte),
		PostData:     string(body),
		HeaderData:   string(headerByte),
		AccessIP:     c.ClientIP(),
		StatusCode:   int32(writer.Status()),
		ErrorMessage: c.Errors.ByType(gin.ErrorTypePrivate).String(),
		Data:         writer.body.String(),
		Latency:      int32(end.Sub(start).Milliseconds()),
		//Remark:       remark,
		Timestamp: time.Now(),
	}
	//
	//logrus.Warnf("models:%#v", models)

	// 日志文件
	//config.AccessLog.WithFields(utility.JSONMethod(models)).Infoln()
	data := logrus.Fields{
		"clientIp": c.ClientIP(),     // 访问IP
		"method":   c.Request.Method, // 访问方式
		"get":      c.Request.URL.Query().Encode(),
		"latency":  end.Sub(start),     // 执行事件
		"code":     c.Writer.Status(),  // 状态码
		"path":     c.Request.URL.Path, // 访问路由
		"ua":       c.Request.UserAgent(),
	}
	config.AccessLog.WithFields(data).Infoln()

	// 队列
	go config.Nats.Publish(consts.NatsTopicAdminLog, models)
}

type responseBodyWriter struct {
	gin.ResponseWriter
	body *bytes.Buffer
}

func (r responseBodyWriter) Write(b []byte) (int, error) {
	r.body.Write(b)
	return r.ResponseWriter.Write(b)
}
