package core

import (
	"fmt"
	"github.com/gin-gonic/gin"
	rotatelogs "github.com/lestrrat-go/file-rotatelogs"
	oplogging "github.com/op/go-logging"
	"hongze/hongze_yb/config"
	"hongze/hongze_yb/global"
	"hongze/hongze_yb/utils"
	"io"
	"os"
	"strings"
	"time"
)

const (
	Module = "hongze_yb"
)

var (
	defaultFormatter = ` %{time:2006/01/02 - 15:04:05.000} %{longfile} %{color:bold}▶ [%{level:.6s}] %{message}%{color:reset}`
)

// 初始化日志
func init() {
	logConfig := global.CONFIG.Log
	logger := oplogging.MustGetLogger(Module)
	var backends []oplogging.Backend
	//注册输出
	registerStdout(logConfig, &backends)

	//注册框架输出（日志文件）
	fileWriter := registerFile(logConfig, &backends, logConfig.LogDirPath, logConfig.LogSoftLink)
	if fileWriter != nil {
		if global.CONFIG.Serve.RunMode == "debug" {
			gin.DefaultWriter = io.MultiWriter(fileWriter, os.Stdout)
		} else {
			gin.DefaultWriter = io.MultiWriter(fileWriter)
		}
	}
	oplogging.SetBackend(backends...)
	global.LOG = logger

	//初始化mysql数据库日志
	initMysqlLog()

	// 初始化自定义输出的日志
	initFileLog()

	// 初始化mongo输出的日志
	initMongoLog()
}

// initMysqlLog 初始化mysql数据库日志
func initMysqlLog() {
	logConfig := global.CONFIG.Log
	var backends []oplogging.Backend
	//注册输出
	registerStdout(logConfig, &backends)

	//注册框架输出（日志文件）
	fileWriter := registerFile(logConfig, &backends, logConfig.BinlogDirPath, logConfig.BinlogSoftLink)
	global.MYSQL_LOG = fileWriter
}

// initFileLog 初始化自定义日志
func initFileLog() {
	logConfig := global.CONFIG.Log

	// 没有单独配置的话，那就走默认的日志输出
	if logConfig.FilelogDirPath == "" || logConfig.FilelogSoftLink == `` {
		global.FILE_LOG = global.LOG
		return
	}

	logger := oplogging.MustGetLogger(Module)
	var backends []oplogging.Backend
	//注册控制台输出
	//registerStdout(logConfig, &backends)

	// 注册文件输出（日志文件）
	_ = registerFile(logConfig, &backends, logConfig.FilelogDirPath, logConfig.FilelogSoftLink)
	defaultBackend := oplogging.AddModuleLevel(backends[0])
	logger.SetBackend(defaultBackend)
	global.FILE_LOG = logger
}

// initFileLog 初始化mongo日志
func initMongoLog() {
	logConfig := global.CONFIG.Log

	// 没有单独配置的话，那就走默认的日志输出
	if logConfig.MongologDirPath == "" || logConfig.MongologSoftLink == `` {
		global.MONGO_LOG = global.LOG
		return
	}

	logger := oplogging.MustGetLogger(Module)
	var backends []oplogging.Backend
	//注册控制台输出
	//registerStdout(logConfig, &backends)

	// 注册文件输出（日志文件）
	_ = registerFile(logConfig, &backends, logConfig.MongologDirPath, logConfig.MongologSoftLink)
	defaultBackend := oplogging.AddModuleLevel(backends[0])
	logger.SetBackend(defaultBackend)
	global.MONGO_LOG = logger
}

func registerStdout(c config.Log, backends *[]oplogging.Backend) {
	if c.Stdout != "" {
		level, err := oplogging.LogLevel(c.Stdout)
		if err != nil {
			fmt.Println(err)
		}
		*backends = append(*backends, createBackend(os.Stdout, c, level))
	}
}

// registerFile 注册文件日志
func registerFile(c config.Log, backends *[]oplogging.Backend, logDir, logSoftLink string) io.Writer {
	if c.FileStdout != "" {
		if ok, _ := utils.PathExists(logDir); !ok {
			// directory not exist
			fmt.Println("create log directory")
			_ = os.Mkdir(logDir, os.ModePerm)
		}

		//日志保留时间
		saveMaxTime := time.Duration(global.CONFIG.Log.SaveMaxDay) * 24 * time.Hour
		//日志切割时间（每隔多久切割一次）
		cuttingTime := time.Duration(global.CONFIG.Log.CuttingDay) * 24 * time.Hour

		//使用rotatelogs
		fileWriter, err := rotatelogs.New(
			logDir+string(os.PathSeparator)+"%Y-%m-%d-%H-%M.log",
			// 生成软链，指向最新日志文件
			rotatelogs.WithLinkName(logSoftLink),
			// 以下两个配置不能同时设置，一个是保留天数，一个是保留分拣份数
			rotatelogs.WithMaxAge(saveMaxTime), //日志保留多久，最小分钟为单位
			//rotatelogs.WithRotationCount(5),        //number 默认7份 大于7份 或到了清理时间 开始清理
			// time period of log file switching
			rotatelogs.WithRotationTime(cuttingTime), //rotate 最小为1分钟轮询。默认60s  低于1分钟就按1分钟来
		)
		if err != nil {
			fmt.Println(err)
		}
		level, err := oplogging.LogLevel(c.FileStdout)
		if err != nil {
			fmt.Println(err)
		}
		*backends = append(*backends, createBackend(fileWriter, c, level))

		return fileWriter
	}
	return nil
}

// createBackend 创建一个新的日志记录器
func createBackend(w io.Writer, c config.Log, level oplogging.Level) oplogging.Backend {
	backend := oplogging.NewLogBackend(w, c.Prefix, 0)
	stdoutWriter := false
	if w == os.Stdout {
		stdoutWriter = true
	}
	format := getLogFormatter(c, stdoutWriter)
	backendLeveled := oplogging.AddModuleLevel(oplogging.NewBackendFormatter(backend, format))
	backendLeveled.SetLevel(level, Module)
	return backendLeveled
}

func getLogFormatter(c config.Log, stdoutWriter bool) oplogging.Formatter {
	pattern := defaultFormatter
	if !stdoutWriter {
		// Color is only required for console output
		// Other writers don't need %{color} tag
		pattern = strings.Replace(pattern, "%{color:bold}", "", -1)
		pattern = strings.Replace(pattern, "%{color:reset}", "", -1)
	}
	if !c.LogFile {
		// Remove %{logfile} tag
		pattern = strings.Replace(pattern, "%{longfile}", "", -1)
	}
	return oplogging.MustStringFormatter(pattern)
}
