package logger

import (
	"encoding/json"
	"fmt"
	"github.com/druidcaesa/gotool"
	"github.com/gin-gonic/gin"
	rotatelogs "github.com/lestrrat-go/file-rotatelogs"
	"github.com/rifflock/lfshook"
	"github.com/sirupsen/logrus"
	"os"
	"path"
	"strconv"
	"time"
	"ulink-admin/config"
	"ulink-admin/frame"
	"ulink-admin/modules/system/models/model"
	"ulink-admin/modules/system/service"
	"ulink-admin/pkg/jwt/admin"
	"ulink-admin/pkg/resp"
)

type Logger struct {
	LogService *service.SysOperLogService `inject:""`
}

func NewLogger() *Logger {
	return &Logger{}
}

// 日志记录到文件
func (v *Logger) LoggerToFile() func(c *frame.Context) {
	logFilePath := config.GetLoggerCfg().LogPath
	logFileName := config.GetLoggerCfg().LogName
	// 日志文件
	fileName := path.Join(logFilePath, logFileName)
	if !gotool.FileUtils.Exists(fileName) {
		create, err := os.Create(fileName)
		if err != nil {
			gotool.Logs.ErrorLog().Println(err)
		}
		defer create.Close()
		//gotool.FileUtils.Create(fileName)
	}
	// 写入文件
	src, err := os.OpenFile(fileName, os.O_APPEND|os.O_WRONLY, os.ModeAppend)
	if err != nil {
		fmt.Println("err", err)
	}
	// 实例化
	logger := logrus.New()
	// 设置输出
	logger.Out = src
	// 设置日志级别
	logger.SetLevel(logrus.DebugLevel)
	// 设置 rotatelogs
	logWriter, err := rotatelogs.New(
		// 分割后的文件名称
		fileName+".%Y%m%d.log",
		// 生成软链,指向最新日志文件
		rotatelogs.WithLinkName(fileName),
		// 设置最大保存时间(7天)
		rotatelogs.WithMaxAge(7*24*time.Hour),
		// 设置日志切割时间间隔(1天)
		rotatelogs.WithRotationTime(24*time.Hour),
	)
	writeMap := lfshook.WriterMap{
		logrus.InfoLevel:  logWriter,
		logrus.FatalLevel: logWriter,
		logrus.DebugLevel: logWriter,
		logrus.WarnLevel:  logWriter,
		logrus.ErrorLevel: logWriter,
		logrus.PanicLevel: logWriter,
	}
	lfHook := lfshook.NewHook(writeMap, &logrus.JSONFormatter{
		TimestampFormat: "2006-01-02 15:04:05",
	})
	// 新增 Hook
	logger.AddHook(lfHook)
	return func(c *frame.Context) {
		c.Get("permission")
		// 开始时间
		startTime := time.Now()
		// 处理请求
		c.Next()
		// 结束时间
		endTime := time.Now()

		// 执行时间
		latencyTime := endTime.Sub(startTime)

		// 请求方式
		reqMethod := c.Request.Method

		// 请求路由
		reqUri := c.Request.RequestURI

		// 状态码
		statusCode := c.Writer.Status()

		// 请求IP
		clientIP := c.ClientIP()

		user := admin.GetUserInfo(c)
		userType := 2
		userName := "游客"
		if user != nil {
			userType, _ = strconv.Atoi(user.UserType)
			userName = user.NickName
		}
		// 日志格式
		logger.WithFields(logrus.Fields{
			"status_code":  statusCode,
			"latency_time": latencyTime,
			"client_ip":    clientIP,
			"req_method":   reqMethod,
			"req_uri":      reqUri,
		}).Info()
		log := model.SysOperLog{}
		log.Status = statusCode
		log.BusinessType = 1
		log.OperatorType = userType

		//log.Method = reqMethod
		log.RequestMethod = reqMethod
		log.OperName = userName
		log.OperIp = clientIP
		log.OperTime = time.Now()
		log.OperUrl = reqUri
		if statusCode == 200 {
			body := c.Writer.(*frame.BodyLogWriter).Body
			var rt resp.Response
			err := json.Unmarshal([]byte(body.String()), &rt)
			if err == nil {
				if rt.Status != 200 {
					log.ErrorMsg = rt.Msg
				}
			}
		}
		if gotool.StrUtils.HasNotEmpty(log.ErrorMsg) {
			v.LogService.Insert(&log)
		}
		//base.Clean()
	}
}

// 日志记录到 MongoDB
func LoggerToMongo() gin.HandlerFunc {
	return func(c *gin.Context) {

	}
}

// 日志记录到 ES
func LoggerToES() gin.HandlerFunc {
	return func(c *gin.Context) {

	}
}

// 日志记录到 MQ
func LoggerToMQ() gin.HandlerFunc {
	return func(c *gin.Context) {

	}
}