package webapiserverless

import (
	"testing"
	"time"

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

	"github.com/tidbcloud/tidb-management-service/functional-test/pkg/coreportalapi"
	"github.com/tidbcloud/tidb-management-service/functional-test/pkg/coreportalapi/model"
	serverlessconsole "github.com/tidbcloud/tidb-management-service/functional-test/pkg/serverlessapi/console"
	consolemodel "github.com/tidbcloud/tidb-management-service/functional-test/pkg/serverlessapi/console/model"
	"github.com/tidbcloud/tidb-management-service/functional-test/pkg/tidbcloudlogin"
	"github.com/tidbcloud/tidb-management-service/utilities/randstr"
)

func TestServerlessClusterEncryption(t *testing.T) {
	testSuite := &TestServerlessClusterEncryptionSuite{
		WebApiLoginContext: &tidbcloudlogin.WebApiLoginContext{
			Host:              viper.GetString("host"),
			Auth0Domain:       viper.GetString("auth0_domain"),
			Auth0ClientID:     viper.GetString("auth0_client_id"),
			Auth0ClientSecret: viper.GetString("auth0_client_secret"),
			UserEmail:         viper.GetString("user_email"),
			BearerToken:       viper.GetString("bearer_token"),
		},

		orgID:             viper.GetString("org_id"),
		prjID:             viper.GetString("prj_id"),
		clusterNamePrefix: viper.GetString("cluster_name_prefix"),

		region:            "regions/aws-us-east-1",
		regionDisplayName: "N. Virginia (us-east-1)",
		spendLimit:        1000, // 10 USD
	}

	testSuite.clusterName = testSuite.clusterNamePrefix + randstr.GenWithCharset(4, randstr.AlphabetCharset)

	suite.Run(t, testSuite)
}

type TestServerlessClusterEncryptionSuite struct {
	suite.Suite

	*tidbcloudlogin.WebApiLoginContext

	orgID             string
	prjID             string
	clusterNamePrefix string

	region            string
	regionDisplayName string
	clusterName       string
	spendLimit        int32

	serverlessconsoleCli *serverlessconsole.Cli
	cmCli                *coreportalapi.Cli

	clusterID  string
	userPrefix string
}

func (su *TestServerlessClusterEncryptionSuite) TearDownSuite() {
	if su.clusterID != "" {
		su.cmCli.EnsureDeleteCluster(su.orgID, su.prjID, su.clusterName)
	}
}

func (su *TestServerlessClusterEncryptionSuite) Test_01_LoginAndInitializeClient() {
	token, err := su.LoginAndGetToken(su.orgID)
	su.Require().NoError(err)

	su.cmCli, err = coreportalapi.NewClient(&su.Suite, su.Host, token)
	su.Require().NoError(err)
	su.Require().NotNil(su.cmCli)

	su.serverlessconsoleCli, err = serverlessconsole.NewClient(&su.Suite, su.Host, token)
	su.Require().NoError(err)
	su.Require().NotNil(su.cmCli)
}

func (su *TestServerlessClusterEncryptionSuite) Test_02_ListProvidersAndSelectAwsUsEast1() {
	providers := su.serverlessconsoleCli.ListProviders(su.orgID)

	r, ok := lo.Find(providers, func(r *consolemodel.Commonv1beta1Region) bool {
		return r != nil && r.Name != nil && *r.Name == su.region
	})
	su.Require().True(ok)
	su.Require().Equal(su.regionDisplayName, r.DisplayName)
	su.Require().NotNil(r.Provider)
}

func (su *TestServerlessClusterEncryptionSuite) Test_03_CreateCluster() {
	su.clusterID = su.serverlessconsoleCli.CreateCluster(su.orgID, su.prjID,
		&consolemodel.TidbCloudOpenApiserverlessv1beta1Cluster{
			DisplayName: &su.clusterName,
			Region: &consolemodel.Commonv1beta1Region{
				Name: &su.region,
			},
			SpendingLimit: &consolemodel.ClusterSpendingLimit{
				Monthly: su.spendLimit,
			},
			EncryptionConfig: &consolemodel.V1beta1ClusterEncryptionConfig{
				EnhancedEncryptionEnabled: true,
			},
		},
	)
	su.Require().NotEmpty(su.clusterID)
}

func (su *TestServerlessClusterEncryptionSuite) Test_04_PollClusterStatus() {
	// timeout: 10 minutes (600 seconds)
	for range 60 {
		status := su.cmCli.PollClusterStatus(su.orgID, su.prjID, su.clusterID)
		if *status == model.CentralClusterStatusNORMAL {
			break
		}
		su.T().Logf("cluster status: %s", *status)
		time.Sleep(10 * time.Second)
	}
}

func (su *TestServerlessClusterEncryptionSuite) Test_05_CheckRequired() {
	c := su.cmCli.GetCluster(su.orgID, su.prjID, su.clusterID)
	su.userPrefix = c.Endpoint.Token
	su.Require().False(c.HasSetPwd)
	su.Require().NotNil(c.PrivateEndpoint)
	su.Require().NotNil(c.PrivateEndpoint.Address)
	su.Require().NotEmpty(c.PrivateEndpoint.Address)
	su.Require().NotNil(c.PrivateEndpoint.Port)
	su.Require().NotEmpty(c.Version)
	su.Require().Equal(su.UserEmail, *c.CreatedBy.Email)
	su.Require().True(c.IsDevTier)
}

func (su *TestServerlessClusterEncryptionSuite) Test_06_CheckEncryption() {
	c := su.serverlessconsoleCli.GetCluster(su.orgID, su.prjID, su.clusterID)
	su.Require().NotEmpty(c.ClusterID)
	su.Require().True(c.EncryptionConfig.EnhancedEncryptionEnabled, "cluster Enhanced Encryption not enabled")
}
