package logging

import (
	"cmdb-backend/pkg/config"
	"github.com/natefinch/lumberjack"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
	"time"
)

var logger *zap.Logger

func init() {
	config.LoadConfig()

	encoderConfig := zapcore.EncoderConfig{
		MessageKey:    "message",                   // 消息字段key值
		LevelKey:      "level",                     // 日志级别字段key值
		TimeKey:       "time",                      // 时间字段key值
		NameKey:       "requestID",                 // 请求ID字段key值
		CallerKey:     "caller",                    // 调用文件字段key值
		StacktraceKey: "stacktrace",                // 错误日志堆栈字段key值
		LineEnding:    zapcore.DefaultLineEnding,   // 写入日志时换行符
		EncodeLevel:   zapcore.CapitalLevelEncoder, // 大写日志级别
		// 格式化时间，这里设置的format
		EncodeTime: func(t time.Time, encoder zapcore.PrimitiveArrayEncoder) {
			encoder.AppendString(t.Format("2006-01-02 15:04:05.000"))
		},
		EncodeDuration: zapcore.NanosDurationEncoder,
		EncodeCaller:   zapcore.ShortCallerEncoder, // 调用文件，以相对路径方式
	}

	// 日志钩子
	hook := lumberjack.Logger{
		Filename:   config.GC.Log.Path,       // 日志文件输出路径
		MaxSize:    config.GC.Log.MaxSize,    // 日志文件最大大小，单位M
		MaxBackups: config.GC.Log.MaxBackups, // 日志文件最大备份数
		MaxAge:     config.GC.Log.MaxAge,     // 日志文件保存最大天数
		Compress:   config.GC.Log.Compress,   // 日志文件是否压缩
	}

	// 设置日志默认级别
	atomicLevel := zap.NewAtomicLevel()
	atomicLevel.SetLevel(zap.DebugLevel)

	encoder := zapcore.NewJSONEncoder(encoderConfig)
	core := zapcore.NewCore(encoder, zapcore.NewMultiWriteSyncer(zapcore.AddSync(&hook)), atomicLevel)

	logger = zap.New(core, zap.AddCallerSkip(1), zap.AddStacktrace(zap.ErrorLevel))
	defer logger.Sync()
	zap.ReplaceGlobals(logger)
}

func Debug(msg string, params ...map[string]interface{}) {
	fields := genFields(params)
	logger.Debug(msg, fields...)
}

func Info(msg string, params ...map[string]interface{}) {
	fields := genFields(params)
	logger.Info(msg, fields...)
}

func Warn(msg string, params ...map[string]interface{}) {
	fields := genFields(params)
	logger.Warn(msg, fields...)
}

func Error(msg string, err error, params ...map[string]interface{}) {
	fields := genFields(params)
	fields = append(fields, zap.String("err", err.Error()))
	logger.Error(msg, fields...)
}

func Panic(msg string, params ...map[string]interface{}) {
	fields := genFields(params)
	logger.Panic(msg, fields...)
}

func Fatal(msg string, params ...map[string]interface{}) {
	fields := genFields(params)
	logger.Fatal(msg, fields...)
}

func genFields(params []map[string]interface{}) []zap.Field {
	fields := make([]zap.Field, 0)
	for _, item := range params {
		for key, value := range item {
			fields = append(fields, zap.Reflect(key, value))
		}
	}
	return fields
}
