// Package common 日志工具
package common

import (
	"fmt"
	"io"
	"os"
	"path/filepath"
	"sync"
	"time"

	"server/config"
)

// 日志级别
const (
	LevelDebug = iota
	LevelInfo
	LevelWarn
	LevelError
)

var levelNames = map[int]string{
	LevelDebug: "DEBUG",
	LevelInfo:  "INFO",
	LevelWarn:  "WARN",
	LevelError: "ERROR",
}

var levelValues = map[string]int{
	"debug": LevelDebug,
	"info":  LevelInfo,
	"warn":  LevelWarn,
	"error": LevelError,
}

// Logger 日志记录器
type Logger struct {
	level      int
	file       *os.File
	htmlWriter *htmlLogWriter
	mu         sync.Mutex
	console    bool
}

var (
	defaultLogger *Logger
	startCount    int
	onceInit      sync.Once
)

// InitLogger 初始化日志
func InitLogger() {
	once.Do(func() {
		cfg := config.AppConfig.Log
		level := levelValues[cfg.Level]

		// 创建日志目录
		if err := os.MkdirAll(cfg.Dir, 0755); err != nil {
			fmt.Println("创建日志目录失败:", err)
			return
		}

		// 计算启动次数
		startCount = getStartCount(cfg.Dir)

		// 创建日志文件
		filename := fmt.Sprintf("%s-%d.html", time.Now().Format("2006-01-02"), startCount)
		logFilepath := filepath.Join(cfg.Dir, filename)

		file, err := os.OpenFile(logFilepath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
		if err != nil {
			fmt.Println("创建日志文件失败:", err)
			return
		}

		htmlWriter := newHtmlLogWriter(file)

		defaultLogger = &Logger{
			level:      level,
			file:       file,
			htmlWriter: htmlWriter,
			console:    cfg.Console,
		}

		fmt.Printf("日志文件: %s\n", logFilepath)
	})
}

// getStartCount 获取今日启动次数
func getStartCount(dir string) int {
	today := time.Now().Format("2006-01-02")
	pattern := filepath.Join(dir, today+"*.html")
	matches, _ := filepath.Glob(pattern)
	return len(matches) + 1
}

// CloseLogger 关闭日志
func CloseLogger() {
	if defaultLogger != nil && defaultLogger.file != nil {
		defaultLogger.htmlWriter.writeFooter()
		defaultLogger.file.Close()
	}
}

func (l *Logger) log(level int, format string, args ...interface{}) {
	if l == nil || level < l.level {
		return
	}

	l.mu.Lock()
	defer l.mu.Unlock()

	msg := fmt.Sprintf(format, args...)
	timestamp := time.Now().Format("2006-01-02 15:04:05.000")
	levelName := levelNames[level]

	// 写入HTML文件
	l.htmlWriter.writeLog(timestamp, levelName, msg)

	// 输出到控制台
	if l.console {
		fmt.Printf("[%s] [%s] %s\n", timestamp, levelName, msg)
	}
}

// LogDebug 调试日志
func LogDebug(format string, args ...interface{}) {
	if defaultLogger != nil {
		defaultLogger.log(LevelDebug, format, args...)
	}
}

// LogInfo 信息日志
func LogInfo(format string, args ...interface{}) {
	if defaultLogger != nil {
		defaultLogger.log(LevelInfo, format, args...)
	}
}

// LogWarn 警告日志
func LogWarn(format string, args ...interface{}) {
	if defaultLogger != nil {
		defaultLogger.log(LevelWarn, format, args...)
	}
}

// LogError 错误日志
func LogError(format string, args ...interface{}) {
	if defaultLogger != nil {
		defaultLogger.log(LevelError, format, args...)
	}
}

// 简短别名
var (
	Debug = LogDebug
	Info  = LogInfo
	Warn  = LogWarn
)

// htmlLogWriter HTML日志写入器
type htmlLogWriter struct {
	writer      io.Writer
	initialized bool
}

func newHtmlLogWriter(w io.Writer) *htmlLogWriter {
	hw := &htmlLogWriter{writer: w}
	hw.writeHeader()
	return hw
}

func (h *htmlLogWriter) writeHeader() {
	html := `<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>应用日志</title>
<style>
body { font-family: Consolas, monospace; background: #1e1e1e; color: #d4d4d4; padding: 20px; }
.log { margin: 2px 0; padding: 4px 8px; border-radius: 3px; }
.DEBUG { background: #2d2d2d; color: #9cdcfe; }
.INFO { background: #1e3a1e; color: #4ec9b0; }
.WARN { background: #3a3a1e; color: #dcdcaa; }
.ERROR { background: #3a1e1e; color: #f14c4c; }
.time { color: #808080; }
.level { font-weight: bold; width: 60px; display: inline-block; }
</style>
</head>
<body>
<h2>应用日志 - ` + time.Now().Format("2006-01-02") + `</h2>
<div id="logs">
`
	h.writer.Write([]byte(html))
	h.initialized = true
}

func (h *htmlLogWriter) writeLog(timestamp, level, msg string) {
	html := fmt.Sprintf(`<div class="log %s"><span class="time">[%s]</span> <span class="level">[%s]</span> %s</div>
`, level, timestamp, level, msg)
	h.writer.Write([]byte(html))
}

func (h *htmlLogWriter) writeFooter() {
	html := `</div>
</body>
</html>`
	h.writer.Write([]byte(html))
}
