package logger

import (
	"os"

	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
	"gopkg.in/natefinch/lumberjack.v2"
)

var (
	// appLogger 应用日志记录器
	appLogger *zap.Logger
	// accessLogger 访问日志记录器
	accessLogger *zap.Logger
)

// InitLoggers 初始化应用和访问日志记录器
func InitLoggers(
	level string,
	development bool,
	appLogConfig LogRotationConfig,
	accessLogConfig LogRotationConfig,
) error {
	// 解析日志级别
	zapLevel := parseLevel(level)

	// 创建编码器配置
	encoderConfig := zapcore.EncoderConfig{
		TimeKey:        "time",
		LevelKey:       "level",
		NameKey:        "logger",
		CallerKey:      "caller",
		MessageKey:     "msg",
		StacktraceKey:  "stacktrace",
		LineEnding:     zapcore.DefaultLineEnding,
		EncodeLevel:    zapcore.CapitalLevelEncoder, // 使用无颜色级别编码器，避免文件日志出现 ANSI 转义码乱码
		EncodeTime:     zapcore.ISO8601TimeEncoder,  // 2025-11-11T17:50:52.830+0800 格式
		EncodeDuration: zapcore.SecondsDurationEncoder,
		EncodeCaller:   zapcore.ShortCallerEncoder, // 输出 middleware/trace.go:58 格式
	}

	// 选择编码器（开发模式使用控制台，生产使用 JSON）
	var encoder zapcore.Encoder
	if development {
		encoder = zapcore.NewConsoleEncoder(encoderConfig)
	} else {
		encoder = zapcore.NewJSONEncoder(encoderConfig)
	}

	// 创建应用日志写入器
	appWriter := zapcore.AddSync(newLumberjackLogger(appLogConfig))

	// 开发模式下同时输出到控制台
	if development {
		appWriter = zapcore.NewMultiWriteSyncer(
			appWriter,
			zapcore.AddSync(os.Stdout),
		)
	}

	// 创建应用日志核心
	appCore := zapcore.NewCore(
		encoder,
		appWriter,
		zapLevel,
	)

	// 创建访问日志核心（始终使用 JSON）
	accessCore := zapcore.NewCore(
		zapcore.NewJSONEncoder(encoderConfig),
		zapcore.AddSync(newLumberjackLogger(accessLogConfig)),
		zapcore.InfoLevel, // 访问日志始终使用 info 级别
	)

	// 构建日志记录器
	if development {
		// 开发模式：添加调用者信息和堆栈跟踪
		appLogger = zap.New(appCore, zap.AddCaller(), zap.AddStacktrace(zapcore.ErrorLevel), zap.Development())
	} else {
		// 生产模式：添加调用者信息，仅在 error 时添加堆栈跟踪
		appLogger = zap.New(appCore, zap.AddCaller(), zap.AddStacktrace(zapcore.ErrorLevel))
	}

	// 访问日志不需要调用者信息
	accessLogger = zap.New(accessCore)

	return nil
}

// GetAppLogger 返回应用日志记录器
func GetAppLogger() *zap.Logger {
	if appLogger == nil {
		// 如果未初始化，返回 nop logger
		return zap.NewNop()
	}
	return appLogger
}

// GetAccessLogger 返回访问日志记录器
func GetAccessLogger() *zap.Logger {
	if accessLogger == nil {
		// 如果未初始化，返回 nop logger
		return zap.NewNop()
	}
	return accessLogger
}

// Sync 刷新所有日志缓冲区
func Sync() error {
	if appLogger != nil {
		if err := appLogger.Sync(); err != nil {
			return err
		}
	}
	if accessLogger != nil {
		if err := accessLogger.Sync(); err != nil {
			return err
		}
	}
	return nil
}

// parseLevel 解析日志级别字符串
func parseLevel(level string) zapcore.Level {
	switch level {
	case "debug":
		return zapcore.DebugLevel
	case "info":
		return zapcore.InfoLevel
	case "warn":
		return zapcore.WarnLevel
	case "error":
		return zapcore.ErrorLevel
	default:
		return zapcore.InfoLevel
	}
}

// newLumberjackLogger 创建 Lumberjack 日志轮转器
func newLumberjackLogger(config LogRotationConfig) *lumberjack.Logger {
	return &lumberjack.Logger{
		Filename:   config.Filename,
		MaxSize:    config.MaxSize,
		MaxBackups: config.MaxBackups,
		MaxAge:     config.MaxAge,
		Compress:   config.Compress,
		LocalTime:  true, // 使用本地时间
	}
}

// LogRotationConfig 日志轮转配置（从 config 包复制以避免循环依赖）
type LogRotationConfig struct {
	Filename   string
	MaxSize    int
	MaxBackups int
	MaxAge     int
	Compress   bool
}
