package testhelpers

import (
	"context"
	"time"

	mysqlDriver "github.com/go-sql-driver/mysql"
	mysqlDialect "gorm.io/driver/mysql"

	"github.com/testcontainers/testcontainers-go"
	"github.com/testcontainers/testcontainers-go/modules/mysql"
	"github.com/testcontainers/testcontainers-go/wait"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
	"gorm.io/gorm/schema"
)

type MysqlContainer struct {
	*mysql.MySQLContainer
	DSN string
}

func CreateMysqlContainer(ctx context.Context) (*MysqlContainer, error) {
	mysqlContainer, err := mysql.RunContainer(ctx,
		testcontainers.WithImage("mysql:8.0.18"),
		mysql.WithDatabase("test"),
		mysql.WithUsername("test"),
		mysql.WithPassword("test"),
		testcontainers.WithWaitStrategy(
			wait.ForLog("ready for connections").
				WithOccurrence(3).WithStartupTimeout(60*time.Second)),
	)
	if err != nil {
		return nil, err
	}
	connStr, err := mysqlContainer.ConnectionString(ctx)
	if err != nil {
		return nil, err
	}
	dsn, err := GetTestDSNFromConnectionString(connStr)
	if err != nil {
		return nil, err
	}
	return &MysqlContainer{
		MySQLContainer: mysqlContainer,
		DSN:            dsn,
	}, nil
}

func GetTestDSNFromConnectionString(connStr string) (string, error) {
	cfg, err := mysqlDriver.ParseDSN(connStr)
	if err != nil {
		return "", err
	}
	cfg.Params = map[string]string{"charset": "utf8mb4"}
	cfg.Collation = "utf8mb4_bin"
	cfg.ParseTime = true
	cfg.Loc = time.UTC
	return cfg.FormatDSN(), nil
}

func MustGetTestDB(dsn string) *gorm.DB {
	conn, err := gorm.Open(mysqlDialect.Open(dsn), &gorm.Config{
		NamingStrategy: schema.NamingStrategy{
			TablePrefix: "auth_server_",
		},
		Logger: logger.Default.LogMode(logger.Error),
	})
	if err != nil {
		panic(err.Error())
	}
	sqlDB, err := conn.DB()
	if err != nil {
		panic(err.Error())
	}
	sqlDB.SetMaxIdleConns(20)
	sqlDB.SetMaxOpenConns(100)
	sqlDB.SetConnMaxLifetime(time.Second * 600)
	return conn
}
