package sqluser

import (
	"strconv"
	"testing"

	"github.com/smartystreets/goconvey/convey"
	"go.uber.org/mock/gomock"

	globalserverlessv1 "github.com/tidbcloud/tidb-management-service/api/spec/global/serverless/v1"
	regionalserverlessv1 "github.com/tidbcloud/tidb-management-service/api/spec/regional/serverless/v1"
	"github.com/tidbcloud/tidb-management-service/serverless-global-service/domain/adapter/mock_adapter"
	"github.com/tidbcloud/tidb-management-service/serverless-global-service/domain/constant"
	"github.com/tidbcloud/tidb-management-service/serverless-global-service/domain/repository/mock_repository"
	"github.com/tidbcloud/tidb-management-service/serverless-global-service/domain/testdata"
	"github.com/tidbcloud/tidb-management-service/utilities/clusterevent/mock_clusterevent"
	"github.com/tidbcloud/tidb-management-service/utilities/clusterproxy/mock_clusterproxy"
)

func TestChangeClusterPasswdSvc(t *testing.T) {
	convey.Convey("Test_changeClusterPasswdSvc", t, func() {
		ctrl := gomock.NewController(t)
		defer ctrl.Finish()

		clusterRepo := mock_repository.NewMockClusterRepo(ctrl)
		clusterProxy := mock_clusterproxy.NewMockClusterProxy(ctrl)
		clusterProxyProvider := mock_clusterproxy.NewMockProvider(ctrl)
		encryptSvc := mock_adapter.NewMockEncryptorService(ctrl)
		regionalSvc := mock_adapter.NewMockRegionalService(ctrl)
		sys9Lifecycle := mock_adapter.NewMockSys9Lifecycle(ctrl)
		cluster := testdata.GetCluster()
		regionalCluster := testdata.GetRegionalCluster()
		committer := mock_clusterevent.NewMockWALCommitter(ctrl)

		passwd := "new-passwd"

		clusterIdInt, err := strconv.ParseUint(cluster.ClusterId, 10, 64)
		convey.So(err, convey.ShouldBeNil)

		req := &globalserverlessv1.ChangeSqlUserPasswdRequest{
			ClusterId: cluster.ClusterId,
			UserName:  constant.DBUserRoot,
			Passwd:    passwd,
		}

		svc := NewSqlUserService(encryptSvc, clusterProxyProvider, clusterRepo, regionalSvc, sys9Lifecycle, nil, committer)

		convey.Convey("Change", func() {
			convey.Convey("should be ok if all is well", func() {
				regionalSvc.EXPECT().
					ListCluster(gomock.Any(), gomock.Any(), gomock.Any()).
					Return([]*regionalserverlessv1.ServerlessRegionalServiceClusterInfo{regionalCluster}, nil)
				clusterRepo.EXPECT().Get(gomock.Any(), cluster.ClusterId, false).Return(cluster, nil)
				clusterProxyProvider.EXPECT().
					GetClusterProxy(gomock.Any(), clusterIdInt, regionalCluster.ProxyEndpoint, regionalCluster.Version, gomock.Any()).
					Return(clusterProxy, nil)
				encryptSvc.EXPECT().
					DecryptBase64(gomock.Any(), cluster.EncryptedCloudAdminPassword).
					Return("plaintext password", nil)
				savedCluster := testdata.GetCluster()
				savedCluster.HasSetPwd = true
				clusterProxy.EXPECT().ChangePassword(gomock.Any(), constant.DBUserRoot, passwd).Return(nil)
				clusterRepo.EXPECT().Save(gomock.Any(), savedCluster)

				err := svc.UpdateSqlUserPassword(testdata.Ctx, req)
				convey.So(err, convey.ShouldBeNil)
			})
		})
	})
}
