package mysql

import (
	"common/config"
	"common/log"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
	"time"
)

type DBName string

var dbs = make(map[DBName]*gorm.DB)

func Init(cfg map[string]*config.MySQLConfig) error {
	for name, oneConfig := range cfg {
		if db, err := initOneDB(oneConfig); err != nil {
			return err
		} else {
			dbs[DBName(name)] = db
		}
	}
	return nil
}

func initOneDB(cfg *config.MySQLConfig) (*gorm.DB, error) {
	db, err := gorm.Open(
		mysql.Open(cfg.Dsn),
		&gorm.Config{
			TranslateError: true,
			Logger:         logger.Default.LogMode(parseLogLevel(cfg.LogLevel)),
		},
	)
	if err != nil {
		return nil, err
	}

	sqlDB, err := db.DB()
	if err != nil {
		return nil, err
	}
	sqlDB.SetMaxOpenConns(int(cfg.MaxOpenConn))
	sqlDB.SetMaxIdleConns(int(cfg.MaxIdleConn))
	sqlDB.SetConnMaxLifetime(time.Duration(cfg.ConnMaxLifetimeSec) * time.Second)
	sqlDB.SetConnMaxIdleTime(time.Duration(cfg.ConnMaxIdleTimeSec) * time.Second)

	return db, nil
}

func parseLogLevel(logLevel string) logger.LogLevel {
	switch logLevel {
	case "silent":
		return logger.Silent
	case "error":
		return logger.Error
	case "warn":
		return logger.Warn
	case "info":
		return logger.Info
	}
	return logger.Info
}

func GetDB(dbName DBName) *gorm.DB {
	if q, ok := dbs[dbName]; ok {
		return q
	}
	log.Errorf("db %s not found", dbName)
	return nil
}

func Close() error {
	if dbs == nil {
		return nil
	}
	for name, db := range dbs {
		if sqlDB, _ := db.DB(); sqlDB != nil {
			if err := sqlDB.Close(); err != nil {
				log.Errorf("close db %s error: %v", name, err)
			}
		}
	}
	return nil
}
