package dbutil

import (
	"fmt"
	"log"
	"os"
	"time"

	"github.com/spf13/viper"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
)

var MySQLDB *gorm.DB

func InitMySQLDB() {
	config := struct {
		MySQL struct {
			Host         string `mapstructure:"host"`
			Port         int    `mapstructure:"port"`
			User         string `mapstructure:"user"`
			Password     string `mapstructure:"password"`
			Name         string `mapstructure:"name"`
			MaxIdleConns int    `mapstructure:"max_idle_conns"`
			MaxOpenConns int    `mapstructure:"max_open_conns"`
			// 单位：分钟（在配置文件中以整数表示），如果未设置将使用默认值
			ConnMaxLifetimeMinutes int `mapstructure:"conn_max_lifetime_minutes"`
			ConnMaxIdleMinutes     int `mapstructure:"conn_max_idle_minutes"`
		} `mapstructure:"mysql"`
	}{}

	viper.SetConfigFile("./config/config.toml")
	viper.SetConfigType("toml")

	err := viper.ReadInConfig()
	if err != nil {
		panic(fmt.Errorf("fatal error config file: %s", err))
	}

	err = viper.Unmarshal(&config)
	if err != nil {
		panic(fmt.Errorf("fatal error config file: %s", err))
	}

	dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8mb4&parseTime=True&loc=Local",
		config.MySQL.User,
		config.MySQL.Password,
		config.MySQL.Host,
		config.MySQL.Port,
		config.MySQL.Name,
	)

	newLogger := logger.New(
		log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer
		logger.Config{
			SlowThreshold: time.Second,  // Slow SQL threshold
			LogLevel:      logger.Error, // Log level
			Colorful:      true,         // Enable color
		},
	)

	MySQLDB, err = gorm.Open(mysql.Open(dsn), &gorm.Config{
		Logger: newLogger,
	})
	if err != nil {
		panic("连接数据库失败: " + err.Error())
	}

	// MySQLDB.Debug()

	sqlDB, err := MySQLDB.DB()
	if err != nil {
		panic("获取数据库连接失败: " + err.Error())
	}

	// SetMaxIdleConns 设置空闲连接池中连接的最大数量
	if config.MySQL.MaxIdleConns == 0 {
		config.MySQL.MaxIdleConns = 10
	}
	sqlDB.SetMaxIdleConns(config.MySQL.MaxIdleConns)

	// SetMaxOpenConns 设置打开数据库连接的最大数量。
	if config.MySQL.MaxOpenConns == 0 {
		config.MySQL.MaxOpenConns = 100
	}
	sqlDB.SetMaxOpenConns(config.MySQL.MaxOpenConns)

	// 如果配置中未设置超时时间，使用合理默认值（单位：分钟）
	if config.MySQL.ConnMaxLifetimeMinutes == 0 {
		config.MySQL.ConnMaxLifetimeMinutes = 30
	}
	if config.MySQL.ConnMaxIdleMinutes == 0 {
		config.MySQL.ConnMaxIdleMinutes = 10
	}

	// SetConnMaxLifetime 设置了连接可复用的最大时间（分钟）
	sqlDB.SetConnMaxLifetime(time.Duration(config.MySQL.ConnMaxLifetimeMinutes) * time.Minute)

	// SetConnMaxIdleTime 设置连接最大空闲时间（分钟）
	sqlDB.SetConnMaxIdleTime(time.Duration(config.MySQL.ConnMaxIdleMinutes) * time.Minute)

	// 启动一个轻量的监控协程，周期性记录连接池状态，便于调优
	go func() {
		ticker := time.NewTicker(1 * time.Minute)
		defer ticker.Stop()
		for range ticker.C {
			stats := sqlDB.Stats()
			log.Printf("[DB Stats] Open=%d InUse=%d Idle=%d WaitCount=%d", stats.OpenConnections, stats.InUse, stats.Idle, stats.WaitCount)
		}
	}()

}
