package config

import (
	"go.uber.org/zap/zapcore"
	"time"
)

type Zap struct {
	Level         string `mapstructure:"level" json:"level" yaml:"level"`
	Prefix        string `mapstructure:"prefix" json:"prefix" yaml:"prefix"`
	Format        string `mapstructure:"format" json:"format" yaml:"format"`
	Director      string `mapstructure:"director" json:"director"  yaml:"director"`
	EncodeLevel   string `mapstructure:"encode-level" json:"encode-level" yaml:"encode-level"`
	StacktraceKey string `mapstructure:"stacktrace-key" json:"stacktrace-key" yaml:"stacktrace-key"`
	ShowLine      bool   `mapstructure:"show-line" json:"show-line" yaml:"show-line"`
	LogInConsole  bool   `mapstructure:"log-in-console" json:"log-in-console" yaml:"log-in-console"`
	RetentionDay  int    `mapstructure:"retention-day" json:"retention-day" yaml:"retention-day"`
}

// Levels 返回一个基于 Zap 实例中配置的日志级别的 zapcore.Level 切片。
// 该切片从配置的日志级别开始，包含所有更高严重性级别，直到 FatalLevel。
// 如果无法解析配置的日志级别，则默认使用 DebugLevel。
//
// 返回值:
//   - []zapcore.Level: 包含从配置的日志级别（或解析失败时的 DebugLevel）到 FatalLevel 的所有日志级别的切片。
func (c *Zap) Levels() []zapcore.Level {
	// 初始化一个容量为 7 的空切片，用于存储日志级别。
	levels := make([]zapcore.Level, 0, 7)

	// 解析配置的日志级别。如果解析失败，则默认使用 DebugLevel。
	level, err := zapcore.ParseLevel(c.Level)
	if err != nil {
		level = zapcore.DebugLevel
	}

	// 从解析的（或默认的）日志级别开始，迭代到 FatalLevel，并将每个级别追加到切片中 按照日志级别分片存储
	for ; level <= zapcore.FatalLevel; level++ {
		levels = append(levels, level)
	}

	// 返回填充好的日志级别切片
	return levels
}

// Encoder 返回一个 zapcore.Encoder，用于编码日志记录。
func (c *Zap) Encoder() zapcore.Encoder {
	config := zapcore.EncoderConfig{
		TimeKey:       "time",
		NameKey:       "name",
		LevelKey:      "level",
		CallerKey:     "caller",
		MessageKey:    "message",
		StacktraceKey: c.StacktraceKey,
		LineEnding:    zapcore.DefaultLineEnding,
		EncodeTime: func(t time.Time, encoder zapcore.PrimitiveArrayEncoder) {
			encoder.AppendString(c.Prefix + t.Format("2006-01-02 15:04:05"))
		},
		EncodeLevel:    c.LevelEncoder(),
		EncodeCaller:   zapcore.FullCallerEncoder,
		EncodeDuration: zapcore.SecondsDurationEncoder,
	}
	if c.Format == "json" {
		return zapcore.NewJSONEncoder(config)
	}
	return zapcore.NewConsoleEncoder(config)
}

func (c *Zap) LevelEncoder() zapcore.LevelEncoder {
	switch {
	case c.EncodeLevel == "LowercaseLevelEncoder":
		return zapcore.LowercaseLevelEncoder
	case c.EncodeLevel == "LowercaseColorLevelEncoder":
		return zapcore.LowercaseColorLevelEncoder
	case c.EncodeLevel == "CapitalLevelEncoder":
		return zapcore.CapitalLevelEncoder
	case c.EncodeLevel == "CapitalColorLevelEncoder":
		return zapcore.CapitalColorLevelEncoder
	default:
		return zapcore.LowercaseLevelEncoder
	}
}
