package region

import (
	"context"
	"sync/atomic"
	"testing"

	pkgv2db "github.com/tidbcloud/pkgv2/db"
	"github.com/tidbcloud/pkgv2/gormutil"

	"github.com/tidbcloud/tidb-management-service/nextgen-global-service/infra/repoimpl/db"
	migrate "github.com/tidbcloud/tidb-management-service/nextgen-global-service/infra/repoimpl/migration"
	"github.com/tidbcloud/tidb-management-service/nextgen-global-service/pkg/config"
	"github.com/tidbcloud/tidb-management-service/nextgen-global-service/pkg/testdata"
	featgatesvc "github.com/tidbcloud/tidb-management-service/utilities/featuregate"
)

var (
	dbProvider atomic.Pointer[pkgv2db.TransProvider]
	globalConf atomic.Pointer[config.Config]
)

// Tests in this package will test repo functions that interact with the schema.
// Third-party service dependencies are mocked and not tested.
func TestMain(m *testing.M) {
	var (
		ctx = context.Background()
		c   = &config.Config{
			MysqlConfig: gormutil.Config{
				User:     "root",
				Database: "local_test",
				Password: "password",
				LogLevel: "warn",
			},
			ServerConfig: config.ServerConfig{
				FeatureGates: map[string]featgatesvc.FeatureGate{
					// Force arm since the testdata is arm.
					featgatesvc.PreferArm: {All: true},
				},
			},
		}
	)

	mysqlContainer, host, port, err := testdata.StartMysqlContainer(
		ctx,
		c.MysqlConfig.Database,
		c.MysqlConfig.User,
		c.MysqlConfig.Password,
	)
	if err != nil {
		panic(err)
	}
	defer func() {
		if err := mysqlContainer.Terminate(ctx); err != nil {
			panic(err)
		}
	}()

	c.MysqlConfig.Host = host
	c.MysqlConfig.Port = port

	globalConf.Store(c)

	// Create schemas.
	_, pvd, _ := db.NewDBProvider(db.NewDB(c))
	if err := migrate.RunDBMigrate(pvd.WriteDB(ctx)); err != nil {
		panic(err)
	}

	// Save back dbProvider to test global.
	dbProvider.Store(&pvd)

	if err := initDBRegionRecord(ctx, pvd); err != nil {
		panic(err)
	}

	m.Run()
}

func initDBRegionRecord(ctx context.Context, d pkgv2db.Provider) error {
	providers := testdata.GetProviderRecords()
	for i := range providers {
		if err := d.WriteDB(ctx).Create(providers[i]).Error; err != nil {
			return err
		}
	}

	regions := testdata.GetRegionRecords()
	for i := range regions {
		regions[i].Status = "active"
		if err := d.WriteDB(ctx).Create(regions[i]).Error; err != nil {
			return err
		}
	}

	regionTenants := testdata.GetRegionTenantRecords()
	for i := range regionTenants {
		if err := d.WriteDB(ctx).Create(regionTenants[i]).Error; err != nil {
			return err
		}
	}

	regionServicePlans := testdata.GetRegionServicePlanRecords()
	for i := range regionServicePlans {
		if err := d.WriteDB(ctx).Create(regionServicePlans[i]).Error; err != nil {
			return err
		}
	}

	return nil
}
