// Package config 配置包，负责应用程序的配置管理
package config

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

	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
)

// DB 全局数据库连接实例
var DB *gorm.DB

// getLogWriter 获取日志输出目标
func getLogWriter() io.Writer {
	logConfig := AppConfig.Log
	if logConfig.Dir == "" {
		return os.Stdout
	}

	if err := os.MkdirAll(logConfig.Dir, 0755); err != nil {
		fmt.Printf("创建日志目录失败: %v\n", err)
		return os.Stdout
	}

	filename := fmt.Sprintf("sql-%s.log", time.Now().Format("2006-01-02"))
	logPath := filepath.Join(logConfig.Dir, filename)

	file, err := os.OpenFile(logPath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
	if err != nil {
		fmt.Printf("打开SQL日志文件失败: %v\n", err)
		return os.Stdout
	}

	if logConfig.Console {
		return io.MultiWriter(file, os.Stdout)
	}
	return file
}

// InitDB 初始化数据库连接
func InitDB() {
	dbConfig := AppConfig.Database
	dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=%s&parseTime=True&loc=Asia%%2FShanghai",
		dbConfig.Username,
		dbConfig.Password,
		dbConfig.Host,
		dbConfig.Port,
		dbConfig.Database,
		dbConfig.Charset,
	)

	var gormConfig *gorm.Config
	if dbConfig.LogMode {
		writer := getLogWriter()
		newLogger := logger.New(
			log.New(writer, "\r\n", log.LstdFlags), // io writer
			logger.Config{
				SlowThreshold:             time.Second, // Slow SQL threshold
				LogLevel:                  logger.Info, // Log level
				IgnoreRecordNotFoundError: true,        // Ignore ErrRecordNotFound error for logger
				ParameterizedQueries:      false,       // 包含参数在 SQL 日志中
				Colorful:                  false,       // 写入文件时建议关闭彩色打印，否则会有乱码
			},
		)
		gormConfig = &gorm.Config{
			Logger: newLogger,
		}
	} else {
		gormConfig = &gorm.Config{
			Logger: logger.Default.LogMode(logger.Silent),
		}
	}

	var err error
	DB, err = gorm.Open(mysql.Open(dsn), gormConfig)
	if err != nil {
		log.Fatal("数据库连接失败:", err)
	}

	// 获取底层 sql.DB 以配置连接池
	sqlDB, err := DB.DB()
	if err != nil {
		log.Fatal("获取数据库实例失败:", err)
	}

	// 连接池配置
	sqlDB.SetMaxIdleConns(dbConfig.MaxIdleConns)
	sqlDB.SetMaxOpenConns(dbConfig.MaxOpenConns)
	sqlDB.SetConnMaxLifetime(time.Duration(dbConfig.ConnMaxLifetime) * time.Hour)

	fmt.Println("数据库连接成功")
}

// CloseDB 关闭数据库连接
// 在程序退出时调用，释放所有连接
func CloseDB() {
	if DB != nil {
		sqlDB, err := DB.DB()
		if err == nil {
			sqlDB.Close()
			fmt.Println("数据库连接已关闭")
		}
	}
}
