package openapiserverless

import (
	"testing"
	"time"

	"github.com/spf13/viper"
	"github.com/stretchr/testify/suite"

	serverlessapi "github.com/tidbcloud/tidb-management-service/functional-test/pkg/serverlessapi/api"
	"github.com/tidbcloud/tidb-management-service/functional-test/pkg/serverlessapi/api/client/serverless_service"
	"github.com/tidbcloud/tidb-management-service/functional-test/pkg/serverlessapi/api/model"
	"github.com/tidbcloud/tidb-management-service/utilities/randstr"
)

func TestClusterEncryption(t *testing.T) {
	testSuite := &TestClusterEncryptionSuite{
		host:              viper.GetString("host"),
		apiKey:            viper.GetString("api_key"),
		prjID:             viper.GetString("prj_id"),
		clusterNamePrefix: viper.GetString("cluster_name_prefix"),

		region:     "regions/aws-us-east-1",
		spendLimit: 1000, // 10 USD
	}

	testSuite.clusterName = testSuite.clusterNamePrefix + randstr.GenWithCharset(4, randstr.AlphabetCharset)
	suite.Run(t, testSuite)
}

type TestClusterEncryptionSuite struct {
	suite.Suite

	host   string
	apiKey string

	prjID             string
	clusterNamePrefix string

	region      string
	clusterName string
	spendLimit  int32

	serverlessCli *serverlessapi.Cli

	clusterID string
}

func (su *TestClusterEncryptionSuite) TearDownSuite() {
	if su.clusterID != "" {
		su.serverlessCli.EnsureDeleteCluster(su.prjID, su.clusterName)
	}
}

func (su *TestClusterEncryptionSuite) Test_01_InitializeClient() {
	var err error
	su.serverlessCli, err = serverlessapi.NewClient(&su.Suite, su.host, su.apiKey)
	su.Require().NoError(err)
	su.Require().NotNil(su.serverlessCli)
}

func (su *TestClusterEncryptionSuite) Test_02_CreateCluster_Encryption() {
	su.clusterID = su.serverlessCli.CreateCluster(
		&model.TidbCloudOpenApiserverlessv1beta1Cluster{
			DisplayName: &su.clusterName,
			Region: &model.Commonv1beta1Region{
				Name: &su.region,
			},
			SpendingLimit: &model.ClusterSpendingLimit{
				Monthly: su.spendLimit,
			},
			Labels: map[string]string{
				"tidb.cloud/project": su.prjID,
			},
			EncryptionConfig: &model.V1beta1ClusterEncryptionConfig{
				EnhancedEncryptionEnabled: true,
			},
		},
	)
	su.Require().NotEmpty(su.clusterID)
}

func (su *TestClusterEncryptionSuite) Test_03_PollClusterStatus() {
	// timeout: 10 minutes (600 seconds)
	for range 60 {
		state := su.serverlessCli.PollClusterStatus(su.clusterID)
		if *state == model.Commonv1beta1ClusterStateACTIVE {
			break
		}
		su.T().Logf("cluster status: %s", *state)
		time.Sleep(10 * time.Second)
	}
}

func (su *TestClusterEncryptionSuite) Test_04_Check_Encryption() {
	c := su.serverlessCli.GetCluster(su.clusterID)

	su.Require().NotEmpty(c.ClusterID)
	su.Require().True(c.EncryptionConfig.EnhancedEncryptionEnabled, "cluster Enhanced Encryption not enabled")
}

func (su *TestClusterEncryptionSuite) Test_05_UpdateCluster_Encryption_NotSupport() {
	resp, err := su.serverlessCli.UpdateClusterAllowErr(su.clusterID, "encryptionConfig.encryptionEnabled",
		&serverless_service.ServerlessServicePartialUpdateClusterParamsBodyCluster{
			EncryptionConfig: &model.V1beta1ClusterEncryptionConfig{
				EnhancedEncryptionEnabled: true,
			},
		},
	)
	su.Require().Nil(resp, "The cluster should be nil")
	su.Require().Error(err, "The error should not be nil")
	su.Require().
		Contains(err.Error(), "Update mask is not supported", "The error msg should be contains 'Update mask is not supported'")
}
