package utils

import (
	"context"
	"fmt"
	"io"
	"log/slog"
	"os"
	"path/filepath"
	"strings"
	"sync"
)

var logLevelMap = map[string]slog.Level{
	"debug": slog.LevelDebug,
	"info":  slog.LevelInfo,
	"warn":  slog.LevelWarn,
	"error": slog.LevelError,
}

// 自定义格式处理器，以 [时间] [级别] [消息] 格式输出日志
type CustomFormatHandler struct {
	mu     sync.Mutex
	w      io.Writer
	level  slog.Level
	attrs  []slog.Attr
	groups []string
}

// NewCustomFormatHandler 创建一个新的自定义格式处理器
func NewCustomFormatHandler(w io.Writer, opts *slog.HandlerOptions) *CustomFormatHandler {
	if opts == nil {
		opts = &slog.HandlerOptions{}
	}

	// 获取日志级别，如果opts.Level是nil则默认为Info
	var level slog.Level
	if opts.Level != nil {
		level = opts.Level.Level()
	} else {
		level = slog.LevelInfo
	}

	return &CustomFormatHandler{
		w:     w,
		level: level,
	}
}

// Enabled 实现 slog.Handler 接口
func (h *CustomFormatHandler) Enabled(ctx context.Context, level slog.Level) bool {
	return level >= h.level
}

// Handle 实现 slog.Handler 接口，以自定义格式输出日志
func (h *CustomFormatHandler) Handle(ctx context.Context, record slog.Record) error {
	h.mu.Lock()
	defer h.mu.Unlock()

	// 时间格式
	timeStr := record.Time.Format("2006-01-02 15:04:05.000")

	// 日志级别
	var levelStr string
	switch {
	case record.Level >= slog.LevelError:
		levelStr = "ERROR"
	case record.Level >= slog.LevelWarn:
		levelStr = "WARN "
	case record.Level >= slog.LevelInfo:
		levelStr = "INFO "
	default:
		levelStr = "DEBUG"
	}

	// 构建日志行
	logLine := fmt.Sprintf("[%s] [%s] %s", timeStr, levelStr, record.Message)

	// 处理其他属性
	var attrs []string
	record.Attrs(func(attr slog.Attr) bool {
		attrs = append(attrs, fmt.Sprintf("%s=%v", attr.Key, attr.Value))
		return true
	})

	if len(attrs) > 0 {
		logLine += " " + strings.Join(attrs, " ")
	}

	// 写入日志
	_, err := fmt.Fprintln(h.w, logLine)
	return err
}

// WithAttrs 实现 slog.Handler 接口
func (h *CustomFormatHandler) WithAttrs(attrs []slog.Attr) slog.Handler {
	h2 := *h
	h2.attrs = append(h.attrs[:], attrs...)
	return &h2
}

// WithGroup 实现 slog.Handler 接口
func (h *CustomFormatHandler) WithGroup(name string) slog.Handler {
	h2 := *h
	h2.groups = append(h.groups[:], name)
	return &h2
}

// MultiHandler 实现了 slog.Handler 接口，将日志同时发送到多个处理器
type MultiHandler struct {
	handlers []slog.Handler
}

// Enabled 实现 slog.Handler 接口
func (h *MultiHandler) Enabled(ctx context.Context, level slog.Level) bool {
	// 如果任何一个处理器启用了该级别，则返回 true
	for _, handler := range h.handlers {
		if handler.Enabled(ctx, level) {
			return true
		}
	}
	return false
}

// Handle 实现 slog.Handler 接口
func (h *MultiHandler) Handle(ctx context.Context, record slog.Record) error {
	// 将记录发送到所有处理器
	for _, handler := range h.handlers {
		if handler.Enabled(ctx, record.Level) {
			if err := handler.Handle(ctx, record); err != nil {
				return err
			}
		}
	}
	return nil
}

// WithAttrs 实现 slog.Handler 接口
func (h *MultiHandler) WithAttrs(attrs []slog.Attr) slog.Handler {
	newHandlers := make([]slog.Handler, len(h.handlers))
	for i, handler := range h.handlers {
		newHandlers[i] = handler.WithAttrs(attrs)
	}
	return &MultiHandler{handlers: newHandlers}
}

// WithGroup 实现 slog.Handler 接口
func (h *MultiHandler) WithGroup(name string) slog.Handler {
	newHandlers := make([]slog.Handler, len(h.handlers))
	for i, handler := range h.handlers {
		newHandlers[i] = handler.WithGroup(name)
	}
	return &MultiHandler{handlers: newHandlers}
}

// SetupLogger 设置日志输出
func SetupLogger(logLevel string, logFile string) error {
	// 创建标准错误输出的处理器，使用自定义格式
	stdHandler := NewCustomFormatHandler(os.Stderr, &slog.HandlerOptions{
		Level: logLevelMap[logLevel],
	})

	// 如果没有指定日志文件，则仅使用标准错误处理器
	if logFile == "" {
		slog.SetDefault(slog.New(stdHandler))
		return nil
	}

	// 确保日志文件所在目录存在
	logDir := filepath.Dir(logFile)
	if err := os.MkdirAll(logDir, 0755); err != nil {
		return err
	}

	// 打开日志文件，如果不存在则创建，追加写入模式
	file, err := os.OpenFile(logFile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
	if err != nil {
		return err
	}

	// 创建文件输出的处理器，使用自定义格式
	fileHandler := NewCustomFormatHandler(file, &slog.HandlerOptions{
		Level: logLevelMap[logLevel],
	})

	// 创建多输出处理器
	multiHandler := &MultiHandler{
		handlers: []slog.Handler{stdHandler, fileHandler},
	}

	// 设置全局日志处理器
	slog.SetDefault(slog.New(multiHandler))
	return nil
}

// InitDefaultLogger 初始化默认日志处理器
func InitDefaultLogger(level slog.Level) {
	slog.SetDefault(slog.New(NewCustomFormatHandler(os.Stderr, &slog.HandlerOptions{
		Level: level,
	})))
}
