package fakedb

import (
	"database/sql"
	"fmt"
	"time"

	sqle "github.com/dolthub/go-mysql-server"
	"github.com/dolthub/go-mysql-server/memory"
	"github.com/dolthub/go-mysql-server/server"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"

	"github.com/tidbcloud/pkgv2/gormutil"
)

// StartFakeDB4Test starts a fake mysql server for testing and return the gorm.DB
// NOTE that this test db is not threadsafe
func StartFakeDB4Test(cfg gormutil.Config) (*gorm.DB, error) {
	db := memory.NewDatabase(cfg.Database)
	memoryProvider := memory.NewMemoryDBProvider(db)
	engine := sqle.NewDefault(memoryProvider)
	config := server.Config{
		Protocol: "tcp",
		Address:  fmt.Sprintf("%s:%d", cfg.Host, cfg.Port),
	}
	s, err := server.NewDefaultServer(config, engine)
	if err != nil {
		return nil, err
	}

	go func() {
		if err = s.Start(); err != nil {
			panic(err)
		}
	}()

	// wait server start
	dsn := cfg.DSNWithTestDB()
	testDB, err := sql.Open("mysql", dsn)
	if err != nil {
		return nil, err
	}
	for i := 0; i < 10; i++ {
		// sever is ready
		if err := testDB.Ping(); err == nil {
			break
		}
		time.Sleep(time.Second)
	}
	return gorm.Open(mysql.Open(dsn), &gorm.Config{DisableForeignKeyConstraintWhenMigrating: true})
}
