package inits

import (
	"github.com/natefinch/lumberjack"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
	"os"
	"ppms-fj/configs/models"
	"ppms-fj/global"
)

// LoggerOption 日志配置结构体
type LoggerOption struct {
	Appname    string // 项目名称
	Runmode    string // 运行模式
	Path       string // 文件路径
	Name       string // 文件名
	Level      string // 日志级别(debug,info,warn,error,dpanic,panic,fatal)
	Maxsize    int    // 最大存储大小
	Maxage     int    // 最大存储时间
	Maxbackups int    // 备份数量
}

// NewLoggerOption 新建日志配置
func NewLoggerOption(conf *models.Config) *LoggerOption {
	appConf := conf.App
	logConf := conf.Logger
	return &LoggerOption{
		Appname:    appConf.Appname,
		Runmode:    appConf.Runmode,
		Path:       logConf.LogPath,
		Name:       logConf.LogName,
		Level:      logConf.LogLevel,
		Maxsize:    logConf.MaxSize,
		Maxage:     logConf.MaxAge,
		Maxbackups: logConf.MaxBackups,
	}
}

// BuildLogger 初始化日志系统
func (opt *LoggerOption) BuildLogger() {
	// 创建Core三大件，进行初始化
	filename := opt.Path + "/logger/" + opt.Appname + "/" + opt.Name
	writeSyncer := GetLogWriter(filename, opt.Maxsize, opt.Maxbackups, opt.Maxage)
	encoder := getEncoder()
	// 创建核心-->如果是dev模式，就在控制台和文件都打印，否则就只写到文件中
	var core zapcore.Core
	level := opt.getLevel()
	if opt.Runmode == "dev" || opt.Runmode == "" {
		// 开发模式，日志输出到终端
		consoleEncoder := zapcore.NewConsoleEncoder(zap.NewDevelopmentEncoderConfig())
		// NewTee创建一个核心，将日志条目复制到两个或多个底层核心中。
		core = zapcore.NewTee(
			zapcore.NewCore(encoder, writeSyncer, level),
			zapcore.NewCore(consoleEncoder, zapcore.Lock(os.Stdout), level),
		)
	} else {
		core = zapcore.NewCore(encoder, writeSyncer, level)
	}

	// 创建 logger 对象
	log := zap.New(core, zap.AddCaller())
	// 替换全局的 logger, 后续在其他包中只需使用zap.L()调用即可
	zap.ReplaceGlobals(log)
	global.Logger = log
}

func (opt *LoggerOption) getLevel() zapcore.Level {
	var level zapcore.Level
	switch opt.Level {
	case "debug":
		level = zapcore.DebugLevel
		break
	case "info":
		level = zapcore.InfoLevel
		break
	case "warn":
		level = zapcore.WarnLevel
		break
	case "error":
		level = zapcore.ErrorLevel
		break
	case "dpanic":
		level = zapcore.DPanicLevel
		break
	case "panic":
		level = zapcore.PanicLevel
		break
	case "fatal":
		level = zapcore.FatalLevel
		break
	default:
		level = zapcore.DebugLevel
	}
	return level
}

// 获取Encoder，给初始化logger使用的
func getEncoder() zapcore.Encoder {
	// 使用zap提供的 NewProductionEncoderConfig
	encoderConfig := zap.NewProductionEncoderConfig()
	// 设置时间格式
	encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder
	// 时间的key
	encoderConfig.TimeKey = "time"
	// 级别
	encoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder
	// 显示调用者信息
	encoderConfig.EncodeCaller = zapcore.ShortCallerEncoder
	// 返回json 格式的 日志编辑器
	return zapcore.NewConsoleEncoder(encoderConfig)
}

// GetLogWriter 获取切割的问题，给初始化logger使用的
func GetLogWriter(filename string, maxSize, maxBackup, maxAge int) zapcore.WriteSyncer {
	// 使用 lumberjack 归档切片日志
	lumberJackLogger := &lumberjack.Logger{
		Filename:   filename,
		MaxSize:    maxSize,
		MaxBackups: maxBackup,
		MaxAge:     maxAge,
	}
	return zapcore.AddSync(lumberJackLogger)
}
