package sharedpool

import (
	"context"
	"testing"

	"github.com/stretchr/testify/require"
	apiv1 "github.com/tidbcloud/cluster-service-ng/api/cluster-service-ng/v1beta"
	"github.com/tidbcloud/cluster-service-ng/domain/entity"
	"github.com/tidbcloud/cluster-service-ng/pkg/storage/mysql/schema"
	"gorm.io/driver/sqlite"
	"gorm.io/gorm"
)

type sharedPoolTestDBProvider struct {
	db *gorm.DB
}

func TestSaveDoesNotOverwritePauseResumeFields(t *testing.T) {
	gdb, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})
	require.NoError(t, err)
	require.NoError(t, gdb.AutoMigrate(&schema.SharedPool{}))
	require.NoError(t, gdb.Exec(`CREATE TABLE shared_pool_object_stores (
		id INTEGER PRIMARY KEY AUTOINCREMENT,
		created_at DATETIME, updated_at DATETIME, deleted_at DATETIME,
		shared_pool_id TEXT, store_type TEXT, store_region TEXT,
		store_bucket TEXT, store_prefix TEXT
	)`).Error)
	require.NoError(t, gdb.Create(&schema.SharedPool{ID: "sp-1", DataplaneName: "dp-1"}).Error)

	r := &sharedPoolRepoImpl{provider: sharedPoolTestDBProvider{db: gdb}}
	stale := &entity.SharedPool{SharedPool: apiv1.SharedPool{
		Id: "sp-1", DataplaneName: "dp-1", Provider: &apiv1.Provider{},
		ObjectStorage: &apiv1.SharedPool_ObjectStorage{Bucket: "bucket", Region: "region"},
	}}
	require.NoError(t, r.UpdatePauseResumeState(context.Background(), "sp-1", entity.PauseResumeStatePausing, true))
	require.NoError(t, r.Save(context.Background(), stale))

	var row schema.SharedPool
	require.NoError(t, gdb.First(&row, "id = ?", "sp-1").Error)
	require.NotNil(t, row.PauseResumeState)
	require.Equal(t, schema.PauseResumeDBEnum("pausing"), *row.PauseResumeState)
	require.True(t, row.SuspendComputeDesired)
}

func TestUpdatePauseResumeStateIsIdempotent(t *testing.T) {
	gdb, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})
	require.NoError(t, err)
	require.NoError(t, gdb.AutoMigrate(&schema.SharedPool{}))
	require.NoError(t, gdb.Create(&schema.SharedPool{ID: "sp-1"}).Error)

	r := &sharedPoolRepoImpl{provider: sharedPoolTestDBProvider{db: gdb}}
	require.NoError(t, r.UpdatePauseResumeState(context.Background(), "sp-1", entity.PauseResumeStatePausing, true))
	require.NoError(t, r.UpdatePauseResumeState(context.Background(), "sp-1", entity.PauseResumeStatePausing, true))

	err = r.UpdatePauseResumeState(context.Background(), "missing", entity.PauseResumeStatePausing, true)
	require.Error(t, err)
}

func (p sharedPoolTestDBProvider) ReadDB(context.Context) *gorm.DB {
	return p.db
}

func (p sharedPoolTestDBProvider) WriteDB(context.Context) *gorm.DB {
	return p.db
}

func TestLoadDataplaneNameDoesNotNeedFullSharedPoolConversion(t *testing.T) {
	gdb, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})
	require.NoError(t, err)
	require.NoError(t, gdb.AutoMigrate(&schema.SharedPool{}))

	require.NoError(t, gdb.Create(&schema.SharedPool{
		ID:            "sp-1",
		DataplaneName: "dp-1",
	}).Error)

	r := &sharedPoolRepoImpl{provider: sharedPoolTestDBProvider{db: gdb}}
	dataplaneName, err := r.LoadDataplaneName(context.Background(), "sp-1", false)

	require.NoError(t, err)
	require.Equal(t, "dp-1", dataplaneName)
}
