package logger

import (
	"context"
	"fmt"
	"github.com/sirupsen/logrus"
	"go-admin/tools/config"
	"gopkg.in/natefinch/lumberjack.v2"
	"path/filepath"
	"time"
)

var l *Logx

var TraceIdKey = "trace_id"

type Logx struct {
	*logrus.Logger
	ctx *context.Context
}

type LogField struct {
	Key   string
	Value interface{}
}

func init() {
	Setup()
}

func Setup() {
	ctx := context.Background()
	l = &Logx{
		Logger: logrus.New(),
		ctx:    &ctx,
	}

	// 设置json格式
	l.SetFormatter(&logrus.JSONFormatter{TimestampFormat: "2006-01-02 15:04:05"})

	// 设置最低loglevel
	l.SetLevel(logrus.InfoLevel)

	// 设置输出到文件
	logFileName := getLogFileName()
	fileLogger := &lumberjack.Logger{
		Filename:   logFileName,
		MaxSize:    100,   // 每个日志文件的最大尺寸，单位为 MB
		MaxBackups: 5,     // 保留旧日志文件的最大个数
		MaxAge:     60,    // 保留旧日志文件的最大天数
		Compress:   false, // 是否压缩旧日志文件
	}
	defer fileLogger.Close()

	// 将日志同时输出到文件和控制台
	//l.SetOutput(io.MultiWriter(os.Stdout, fileLogger))
	l.SetOutput(fileLogger)
}

// 获取日志文件名，按照 server-2023-12-01.log 的格式
func getLogFileName() string {
	currentTime := time.Now().Format("2006-01-02")
	logFileName := fmt.Sprintf("server-%s.log", currentTime)
	// 可以指定日志文件存储的路径
	logFilePath := config.LoggerConfig.Path
	return filepath.Join(logFilePath, logFileName)
}

func WithContext(ctx context.Context) {
	l.ctx = &ctx
}

func Field(key string, value interface{}) *LogField {
	return &LogField{Key: key, Value: value}
}

func Info(msg string, fields ...*LogField) {
	e := newEntry(fields...)
	e.Info(msg)
}

func Error(msg string, fields ...*LogField) {
	e := newEntry(fields...)
	e.Error(msg)
}

func Debug(msg string, fields ...*LogField) {
	e := newEntry(fields...)
	e.Debug(msg)
}

func Warning(msg string, fields ...*LogField) {
	e := newEntry(fields...)
	e.Warning(msg)
}

func newEntry(fields ...*LogField) *logrus.Entry {
	e := logrus.NewEntry(l.Logger)
	traceId, ok := (*l.ctx).Value(TraceIdKey).(string)
	if ok {
		e = e.WithField("trace_id", traceId)
	}
	for _, field := range fields {
		e = e.WithField(field.Key, field.Value)
	}
	return e
}

func Errorf(format string, args ...interface{}) {
	l.Errorf(format, args)
}

func Fatal(args ...interface{}) {
	l.Fatal(args)
}

func Println(args ...interface{}) {
	l.Println(args)
}
