package gorm

import (
	"fmt"

	"github.com/tidbcloud/escalation-base/support-autoshift/pkg/infra/config"

	"github.com/go-logr/logr"
	mysqld "github.com/go-sql-driver/mysql"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	gormlog "gorm.io/gorm/logger"
)

func GenerateDSN(conf config.DatabaseConfig) string {
	dbConf := mysqld.NewConfig()
	dbConf.Net = "tcp"
	dbConf.User = conf.User
	dbConf.Addr = fmt.Sprintf("%s:%d", conf.Host, conf.Port)
	dbConf.Passwd = conf.Password
	dbConf.DBName = conf.Database
	dbConf.ParseTime = true
	dbConf.Timeout = conf.DailTimeout
	dbConf.ReadTimeout = conf.ReadTimeout
	dbConf.WriteTimeout = conf.WriteTimeout
	dbConf.Params = map[string]string{"charset": "utf8mb4"}
	dbConf.Collation = "utf8mb4_bin"
	dbConf.TLSConfig = conf.TLSConfigKey
	return dbConf.FormatDSN()
}

func Connect(conf config.DatabaseConfig, logger logr.Logger) (*gorm.DB, error) {
	logConf := gormlog.Config{
		SlowThreshold:             conf.LogSlowThreshold,
		LogLevel:                  gormlog.LogLevel(conf.LogLevel),
		IgnoreRecordNotFoundError: true,
	}
	dbConf := &gorm.Config{
		Logger: NewGormLogger(logger, logConf, conf.TraceQuerySQL),
	}
	dsn := GenerateDSN(conf)

	db, err := gorm.Open(mysql.Open(dsn), dbConf)
	if err != nil {
		return nil, fmt.Errorf("open database %s:%d failed: %w", conf.Host, conf.Port, err)
	}

	sqlDB, err := db.DB()
	if err != nil {
		return nil, fmt.Errorf("get sql database failed: %w", err)
	}
	sqlDB.SetConnMaxLifetime(conf.ConnMaxLifetime)
	sqlDB.SetMaxIdleConns(conf.MaxIdleConns)
	sqlDB.SetMaxOpenConns(conf.MaxOpenConns)

	logger.Info("connect to db successfully", "host", conf.Host, "port", conf.Port)
	return db, nil
}
