package main

import (
	"context"
	"encoding/json"
	"fmt"
	"time"

	"github.com/AlekSi/pointer"
	"github.com/tidbcloud/account/idl/pbgen/proto/account"
	"github.com/tidbcloud/core-svc/idl/pbgen/proto/core"
	"github.com/tidbcloud/pkgv2/logid"
	globaldedicatedv1 "github.com/tidbcloud/tidb-management-service/api/spec/global/dedicated/v1"
	"go.buf.build/protocolbuffers/go/linuxgit/tidbcloud/base"
	"google.golang.org/grpc"
	grpcMetadata "google.golang.org/grpc/metadata"
	"google.golang.org/protobuf/types/known/timestamppb"
)

var (
	AwsRegionName           = "us-west-2"
	GcpRegionName           = "us-east1"
	TenantID         uint64 = 30060 // dev stage: PingCAP - Storage
	ProjectID        uint64 = 43562 // TiDB Service
	ClusterID        uint64 = 2609081
	DevTierClusterID uint64 = 390012
	OperatorUserID   uint64 = 69984 // liuzhi@pingcap.com
	BackupID         uint64 = 330015
	DeployType              = core.DeployType_DEPLOY_TYPE_DEDICATED
	ClusterJobType          = core.ClusterJobType_CLUSTER_JOB_TYPE_BACKUP
	jwks                    = `{
    "keys": [
{
    "kty": "RSA",
    "e": "AQAB",
    "use": "sig",
    "kid": "chenfei_test",
    "alg": "RS256",
    "n": "sOVN_QDBqJrLsqUFL10q0Ub4Gh5-CGmZZc2_iOXk0pjWF9n01bvnPYrGQe6u3HKNfLL2kse5a_xlJ5l4dTOtercE0WCxPAEwA6oJESxEfhaJm7Kb4e7uu2A6dFazdoq1AeZQoOpcyFQGBsSk9SnySHJQz7yTVzOeztbfOlFKzfk7UtOfEUwuxWgaLHnsW1NMgH10ACOWSBpCqre55313OsAZzG44B7SKVYNCeycpLiWyinMwhFUlYgexlGFpL3Z7uncttZhcpI6isxb7-J3jusfeNVxUSn3IERNG1dWTWFZmZfYmEXunTjKKWmAND8XhN7EvUrTdWJkoQTEHrA9u4w"
}
    ]
}`
	operatorUsername = "4LR8zj3VxidVXhN.fei.ch_vFCQoFrN"
	jwt              = ""
)

func getAccountClient() account.AccountAPIServiceClient {
	connectTo := "127.0.0.1:10000"
	fmt.Println("Connecting to", connectTo)
	conn, err := grpc.Dial(connectTo, grpc.WithBlock(), grpc.WithInsecure())
	if err != nil {
		panic(err)
	}
	fmt.Println("Connected to", connectTo)
	cli := account.NewAccountAPIServiceClient(conn)
	return cli
}

func getCoreClient() core.CoreServiceClient {
	connectTo := "127.0.0.1:20000"
	fmt.Println("Connecting to", connectTo)
	conn, err := grpc.Dial(connectTo, grpc.WithBlock(), grpc.WithInsecure())
	if err != nil {
		panic(err)
	}
	fmt.Println("Connected to", connectTo)
	cli := core.NewCoreServiceClient(conn)
	return cli
}

func getDedicatedGlobalClient() globaldedicatedv1.ClusterServiceClient {
	connectTo := "127.0.0.1:20000"
	fmt.Println("Connecting to", connectTo)
	conn, err := grpc.Dial(connectTo, grpc.WithBlock(), grpc.WithInsecure())
	if err != nil {
		panic(err)
	}
	fmt.Println("Connected to", connectTo)
	cli := globaldedicatedv1.NewClusterServiceClient(conn)
	return cli
}

func main() {
	ctx := context.TODO()
	requestID := logid.GenLogid()
	fmt.Println("requestID: ", requestID)
	ctx = logid.WithLogid(ctx, requestID)

	BaseReq := &base.BaseReq{
		Tags: map[string]string{
			logid.GRPCHeaderKey: requestID,
		},
	}

	var resp, err interface{}
	_ = resp
	_ = BaseReq
	//resp, err = CreateCluster(ctx, getCoreClient(), BaseReq)
	//resp, err = DeleteCluster(ctx, getCoreClient(), BaseReq)
	//resp, err = GetAwsCmek(ctx, getCoreClient(), BaseReq)
	//resp, err = CreateAwsCmek(ctx, getCoreClient(), BaseReq)
	//resp, err = ListClusterJobs(ctx, getCoreClient(), BaseReq)
	//resp, err = ChangeClusterPassword(ctx, getCoreClient(), BaseReq)
	//resp, err = CreateDevTierCluster(ctx, getCoreClient(), BaseReq)
	//resp,err = ScaleOutCluster(ctx, getCoreClient(), BaseReq)
	//resp,err = ScaleInCluster(ctx, getCoreClient(), BaseReq)
	//resp,err = ScaleOutClusterWithTiFlash(ctx, getCoreClient(), BaseReq)
	//resp, err = ScaleCluster(ctx, getCoreClient(), BaseReq)
	//resp,err = RestoreCluster(ctx, getCoreClient(), BaseReq)
	//resp, err = ListCluster(ctx, getCoreClient(), BaseReq)
	//resp, err = ListRegionCIDROfProject(ctx, getCoreClient(), BaseReq)

	//resp, err = ExecuteCtlCommand(ctx, getCoreClient(), BaseReq)
	//resp, err = GetClusterTopology(ctx, getCoreClient(), BaseReq)

	//resp, err = Measure(ctx, getCoreClient(), BaseReq)
	//resp, err = ListBackupsOfCluster(ctx, getCoreClient(), BaseReq)

	//resp, err = ListProfile4Tenant(ctx, getCoreClient(), BaseReq)
	//resp, err = ListCloudProviders(ctx, getCoreClient(), BaseReq)
	//resp, err = CalcClusterFee(ctx, getCoreClient(), BaseReq)
	//resp, err = ListClusterSnapshots(ctx, getCoreClient(), BaseReq)
	//resp, err = BatchGetTiers(ctx, getCoreClient(), BaseReq)
	//resp, err = CreateClusterJob(ctx, getCoreClient(), BaseReq)
	//resp, err = DeleteClusterJob(ctx, getCoreClient(), BaseReq)
	//resp, err = IsClusterJobRegistered(ctx, getCoreClient(), BaseReq)
	//resp, err = ListCloudRegions(ctx, getCoreClient(), BaseReq)
	//resp, err = QueryCloudProviders(ctx, getCoreClient(), BaseReq)

	// network related //
	//resp, err = DeletePrivateLinkService(ctx, getCoreClient(), BaseReq)
	//resp, err = CreatePrivateLinkEndpoint(ctx, getCoreClient(), BaseReq)
	//resp, err = DeletePrivateLinkEndpoint(ctx, getCoreClient(), BaseReq)
	//resp, err = ListPrivateLinkEndpoints(ctx, getCoreClient(), BaseReq)

	//resp, err = GetMaintenanceWindowByProjectID(ctx, getCoreClient(), BaseReq)
	//resp, err = UpdateMaintenanceWindow(ctx, getCoreClient(), BaseReq)
	//resp, err = CreateMaintenanceTask(ctx, getCoreClient(), BaseReq)
	//resp, err = QueryMaintenanceTasks(ctx, getCoreClient(), BaseReq)
	//resp, err = DeferMaintenanceTask(ctx, getCoreClient(), BaseReq)
	//resp, err = SyncMaintenanceWindow(ctx, getCoreClient(), BaseReq)
	//resp, err = QueryMaintenanceTaskExecutions(ctx, getCoreClient(), BaseReq)
	//resp, err = UpdateMaintenanceTaskExecutionStatus(ctx, getCoreClient(), BaseReq)
	//resp, err = UpdateMaintenanceTaskStatus(ctx, getCoreClient(), BaseReq)

	//resp, err = CreateDBUser(ctx, getCoreClient(), BaseReq)
	//resp, err = CreateDBDelegateUser(ctx, getCoreClient(), BaseReq)
	//resp, err = UpdateDBUser(ctx, getCoreClient(), BaseReq)
	//resp, err = DeleteDBUser(ctx, getCoreClient(), BaseReq)
	//resp, err = GetDBUser(ctx, getCoreClient(), BaseReq)
	//resp, err = IsDBUserExisting(ctx, getCoreClient(), BaseReq)
	//resp, err = CreateDBRole(ctx, getCoreClient(), BaseReq)
	//resp, err = UpdateDBRole(ctx, getCoreClient(), BaseReq)
	//resp, err = SetClusterAuthPubKey(ctx, getCoreClient(), BaseReq)

	//resp, err = CreateAccessPoint(ctx, getCoreClient(), BaseReq)
	//resp, err = UpdateAccessPoint(ctx, getCoreClient(), BaseReq)
	//resp, err = DeleteAccessPoint(ctx, getCoreClient(), BaseReq)

	//resp, err = GetDefaultCidr(ctx, getCoreClient(), BaseReq)

	// account service
	//resp, err = GetDBUsers(ctx, getAccountClient(), BaseReq)
	//resp, err = ListUsersByFilter(ctx, getAccountClient(), BaseReq)
	//resp, err = SendEmail(ctx, getAccountClient(), BaseReq)
	//resp, err = ClearEmailUniqueID(ctx, getAccountClient(), BaseReq)

	// dedicated global service
	resp, err = GetBillableClustersCount(ctx, getDedicatedGlobalClient())

	if err != nil {
		fmt.Println(err)
	} else {
		b, _ := json.MarshalIndent(resp, "", "  ")
		fmt.Println(string(b))
	}
}

func ListRegionCIDROfProject(ctx context.Context, cli core.CoreServiceClient, baseReq *base.BaseReq) (interface{}, error) {
	req := &core.ListRegionCIDROfProjectReq{
		ProjectId:     ProjectID,
		CloudProvider: "gcp",
		BaseReq:       baseReq,
	}
	return cli.ListRegionCIDROfProject(ctx, req)
}

func CreateCluster(ctx context.Context, cli core.CoreServiceClient, baseReq *base.BaseReq) (interface{}, error) {
	req := &core.CreateClusterReq{
		TenantId:      TenantID,
		ProjectId:     ProjectID,
		Name:          "Cluster-test",
		RootPassword:  "12345678",
		CloudProvider: "aws",
		Region:        AwsRegionName,
		DeployType:    core.DeployType_DEPLOY_TYPE_DEDICATED,
		IsDevTier:     false,
		Components: []*core.ClusterComponent{
			{
				ComponentType:   core.ComponentType_COMPONENT_TYPE_TIDB,
				NodeProfileName: "2C4G",
				Replicas:        1,
				StorageSizeGi:   20,
			},
			{
				ComponentType:   core.ComponentType_COMPONENT_TYPE_TIKV,
				NodeProfileName: "2C4G",
				Replicas:        3,
				StorageSizeGi:   10,
			},
		},
		CreateById:       OperatorUserID,
		PrimaryClusterId: 0,
		Port:             4000,
		XaccountDeployId: 0,
		TrafficFilter:    nil,
		RestoreId:        nil,
		Dryrun:           false,
		BaseReq:          baseReq,
	}

	//restoreID := uint64(123)
	//req.RestoreId = &restoreID
	return cli.CreateCluster(ctx, req)
}

func ChangeClusterPassword(ctx context.Context, cli core.CoreServiceClient, baseReq *base.BaseReq) (interface{}, error) {
	req := &core.ChangeClusterPasswdReq{
		ClusterId: ClusterID,
		Passwd:    "12345678",
		BaseReq:   baseReq,
	}

	//restoreID := uint64(123)
	//req.RestoreId = &restoreID
	return cli.ChangeClusterPasswd(ctx, req)
}

func CreateDevTierCluster(ctx context.Context, cli core.CoreServiceClient, baseReq *base.BaseReq) (interface{}, error) {
	req := &core.CreateClusterReq{
		BaseReq:          baseReq,
		TenantId:         1,         // management
		ProjectId:        ProjectID, // louis1
		Name:             "sct-devtier-1",
		RootPassword:     "12345678",
		CloudProvider:    "aws",
		Region:           "us-east-1",
		DeployType:       core.DeployType_DEPLOY_TYPE_SHARED,
		IsDevTier:        true,
		PrimaryClusterId: 0,
		Components: []*core.ClusterComponent{
			{
				ComponentType:   core.ComponentType_COMPONENT_TYPE_TIDB,
				NodeProfileName: "", // s1.dev
				Replicas:        1,
				StorageSizeGi:   20,
			},
			{
				ComponentType:   core.ComponentType_COMPONENT_TYPE_TIKV,
				NodeProfileName: "", // s1.dev
				Replicas:        1,
				StorageSizeGi:   20,
			},
		},
		CreateById: OperatorUserID, // fei.chen
	}

	return cli.CreateCluster(ctx, req)
}

func ScaleOutCluster(ctx context.Context, cli core.CoreServiceClient, baseReq *base.BaseReq) (interface{}, error) {
	req := &core.ScaleClusterReq{
		BaseReq:   baseReq,
		ClusterId: uint64(ClusterID),
		NewComponents: []*core.ClusterComponent{
			{
				ComponentType:   core.ComponentType_COMPONENT_TYPE_TIDB,
				NodeProfileName: "", // t3.medium
				Replicas:        2,
				StorageSizeGi:   20,
			},
			{
				ComponentType:   core.ComponentType_COMPONENT_TYPE_TIKV,
				NodeProfileName: "", // t3.medium
				Replicas:        3,
				StorageSizeGi:   20,
			},
		},
	}

	return cli.ScaleCluster(ctx, req)
}

func ScaleOutClusterWithTiFlash(ctx context.Context, cli core.CoreServiceClient, baseReq *base.BaseReq) (interface{}, error) {
	req := &core.ScaleClusterReq{
		BaseReq:   baseReq,
		ClusterId: uint64(DevTierClusterID),
		NewComponents: []*core.ClusterComponent{
			{
				ComponentType:   core.ComponentType_COMPONENT_TYPE_TIDB,
				NodeProfileName: "", // s1.dev
				Replicas:        1,
				StorageSizeGi:   20,
			},
			{
				ComponentType:   core.ComponentType_COMPONENT_TYPE_TIKV,
				NodeProfileName: "", // s1.dev
				Replicas:        3,
				StorageSizeGi:   20,
			},
			{
				ComponentType:   core.ComponentType_COMPONENT_TYPE_TIFLASH,
				NodeProfileName: "", // s1.dev
				Replicas:        3,
				StorageSizeGi:   20,
			},
		},
	}

	return cli.ScaleCluster(ctx, req)
}

func ScaleInCluster(ctx context.Context, cli core.CoreServiceClient, baseReq *base.BaseReq) (interface{}, error) {
	req := &core.ScaleClusterReq{
		BaseReq:   baseReq,
		ClusterId: uint64(ClusterID),
		NewComponents: []*core.ClusterComponent{
			{
				ComponentType:   core.ComponentType_COMPONENT_TYPE_TIDB,
				NodeProfileName: "", // t3.medium
				Replicas:        1,
				StorageSizeGi:   20,
			},
			{
				ComponentType:   core.ComponentType_COMPONENT_TYPE_TIKV,
				NodeProfileName: "", // t3.medium
				Replicas:        3,
				StorageSizeGi:   20,
			},
		},
	}

	return cli.ScaleCluster(ctx, req)
}

func ScaleCluster(ctx context.Context, cli core.CoreServiceClient, baseReq *base.BaseReq) (interface{}, error) {
	req := &core.ScaleClusterReq{
		ClusterId: uint64(3839812),
		NewComponents: []*core.ClusterComponent{
			{
				ComponentType:   core.ComponentType_COMPONENT_TYPE_TIDB,
				NodeProfileName: "8C16G",
				Replicas:        1,
			},
			{
				ComponentType:   core.ComponentType_COMPONENT_TYPE_TIKV,
				NodeProfileName: "8C32G",
				Replicas:        3,
				StorageSizeGi:   10,
			},
			{
				ComponentType:   core.ComponentType_COMPONENT_TYPE_TIFLASH,
				NodeProfileName: "2C4G",
				Replicas:        0,
				StorageSizeGi:   100,
			},
		},
		AllowScaleIn:        true,
		AllowScaleSecondary: false,
		AllowScaleDown:      false,
		OperatorId:          0,
		BaseReq:             baseReq,
	}

	return cli.ScaleCluster(ctx, req)
}

func ListCluster(ctx context.Context, cli core.CoreServiceClient, baseReq *base.BaseReq) (interface{}, error) {
	req := &core.ListClustersReq{
		Filter: &core.ClusterFilter{
			ClusterIds: []uint64{3778953},
		},
		BaseReq: baseReq,
	}

	return cli.ListClusters(ctx, req)
}

func ListProfile4Tenant(ctx context.Context, cli core.CoreServiceClient, baseReq *base.BaseReq) (interface{}, error) {
	req := &core.ListNodeProfiles4TenantReq{
		TenantId:          TenantID,
		CloudProviderName: "aws",
		//CloudProviderName: "gcp",
		RegionName: AwsRegionName, // for dedicated on aws
		//RegionName: "us-east-1", // for shared on aws
		//RegionName: "us-west1", // for dedicated on gcp
		DeployType: core.DeployType_DEPLOY_TYPE_DEDICATED,
		//DeployType: core.DeployType_DEPLOY_TYPE_SHARED,
		BaseReq: baseReq,
	}
	return cli.ListNodeProfiles4Tenant(ctx, req)
}

func BatchGetTiers(ctx context.Context, cli core.CoreServiceClient, baseReq *base.BaseReq) (interface{}, error) {
	req := &core.BatchGetTiersReq{
		Identifiers: []*core.TierIdentifier{
			{
				Name:          "2C4G",
				DeployType:    core.DeployType_DEPLOY_TYPE_DEDICATED,
				ComponentType: core.ComponentType_COMPONENT_TYPE_TIDB,
			},
			{
				Name:          "2C4G",
				DeployType:    core.DeployType_DEPLOY_TYPE_DEDICATED,
				ComponentType: core.ComponentType_COMPONENT_TYPE_TIKV,
			},
		},
		BaseReq: baseReq,
	}
	return cli.BatchGetTiers(ctx, req)
}

func ListCloudProviders(ctx context.Context, cli core.CoreServiceClient, baseReq *base.BaseReq) (interface{}, error) {
	//tenantID := &TenantID
	req := &core.ListCloudProvidersReq{
		SpecificTenantId:            &TenantID,
		FilterOutEmptyCloudProvider: true,
		FilterOutEmptyRegion:        true,
		DeployType:                  &DeployType,
		FilterOutInactiveRegion:     true,
		FilterOutInactiveProvider:   true,
		WithXaccountDeployId:        true,
		SpecificProjectId:           &ProjectID,
		BaseReq:                     baseReq,
	}
	return cli.ListCloudProviders(ctx, req)
}

func CalcClusterFee(ctx context.Context, cli core.CoreServiceClient, baseReq *base.BaseReq) (interface{}, error) {
	req := &core.CalcClusterFeeReq{
		TenantId:          1,
		ProjectId:         ProjectID,
		DeployType:        core.DeployType_DEPLOY_TYPE_DEDICATED,
		CloudProviderName: "aws",
		RegionName:        AwsRegionName,
		Duration:          int64(10 * time.Hour),
		Components: []*core.ClusterComponent{
			{
				ComponentType:   core.ComponentType_COMPONENT_TYPE_TIDB,
				NodeProfileName: "",
				Replicas:        1,
				StorageSizeGi:   0,
			}, {
				ComponentType:   core.ComponentType_COMPONENT_TYPE_TIKV,
				NodeProfileName: "",
				Replicas:        3,
				StorageSizeGi:   20,
			},
		},
		BaseReq: baseReq,
	}
	return cli.CalcClusterFee(ctx, req)
}

func ListClusterSnapshots(ctx context.Context, cli core.CoreServiceClient, baseReq *base.BaseReq) (interface{}, error) {
	//tenantID := &TenantID
	req := &core.ListClusterSnapshotsReq{
		Filter: &core.ClusterSnapshotFilter{
			TenantIds:   []uint64{TenantID},
			ProjectIds:  []uint64{ProjectID},
			ClusterIds:  []uint64{63274},
			SnapshotIds: nil,
		},
		Pager:   nil,
		Sorters: nil,
		BaseReq: baseReq,
	}
	return cli.ListClusterSnapshots(ctx, req)
}

func CreateClusterJob(ctx context.Context, cli core.CoreServiceClient, baseReq *base.BaseReq) (interface{}, error) {
	req := &core.CreateClusterJobReq{
		ClusterId: ClusterID,
		JobType:   ClusterJobType,
		Name:      "job-1",
		BaseReq:   baseReq,
	}
	return cli.CreateClusterJob(ctx, req)
}

func DeleteClusterJob(ctx context.Context, cli core.CoreServiceClient, baseReq *base.BaseReq) (interface{}, error) {
	// identify cluster job by unique key "cluster_id:job_type:name"
	//req := &core.DeleteClusterJobReq{
	//	Identifier: &core.ClusterJobIdentifier{
	//		JobId:     0, // unspecified
	//		ClusterId: ClusterID,
	//		JobType:   ClusterJobType,
	//		Name:      "job-1",
	//	},
	//	BaseReq: baseReq,
	//}
	// identify cluster job by job id
	req := &core.DeleteClusterJobReq{
		Identifier: &core.ClusterJobIdentifier{
			JobId:     2,
			ClusterId: ClusterID,
			JobType:   0,  // unspecified
			Name:      "", // unspecified
		},
		BaseReq: baseReq,
	}
	return cli.DeleteClusterJob(ctx, req)
}

func IsClusterJobRegistered(ctx context.Context, cli core.CoreServiceClient, baseReq *base.BaseReq) (interface{}, error) {
	// identify cluster job by unique key "cluster_id:job_type:name"
	//req := &core.IsClusterJobRegisteredReq{
	//	Identifier: &core.ClusterJobIdentifier{
	//		JobId:     0, // unspecified
	//		ClusterId: ClusterID,
	//		JobType:   ClusterJobType,
	//		Name:      "job-1",
	//	},
	//	BaseReq: baseReq,
	//}
	// identify cluster job by job id
	req := &core.IsClusterJobRegisteredReq{
		Identifier: &core.ClusterJobIdentifier{
			JobId:     1,
			ClusterId: ClusterID,
			JobType:   0,  // unspecified
			Name:      "", // unspecified
		},
		BaseReq: baseReq,
	}
	return cli.IsClusterJobRegistered(ctx, req)
}

func ListCloudRegions(ctx context.Context, cli core.CoreServiceClient, baseReq *base.BaseReq) (interface{}, error) {
	req := &core.ListCloudRegionsReq{
		Filter: &core.CloudRegionFilter{
			//CloudProviderNames: []string{"aws"},
			//Names:              []string{AwsRegionName},
			Ids: []uint64{1},
		},
		BaseReq: baseReq,
	}
	return cli.ListCloudRegions(ctx, req)
}

func CreateDBUser(ctx context.Context, cli core.CoreServiceClient, baseReq *base.BaseReq) (interface{}, error) {
	//tenantID := &TenantID
	req := &core.CreateDBUserReq{
		Operator: &core.DBUserOperator{
			Username:   operatorUsername,
			AuthMethod: core.DBUser_AUTH_METHOD_TOKEN,
			Credential: jwt,
		},
		ClusterId:   ClusterID,
		UserType:    core.DBUser_TYPE_USER_DEFINED,
		Username:    operatorUsername,
		Email:       nil,
		AuthMethod:  core.DBUser_AUTH_METHOD_PASSWORD,
		Credential:  pointer.ToString("12345678"),
		BuiltinRole: core.DBUser_BUILTIN_ROLE_USER_ADMIN,
		Settings: &core.CreateDBUserReq_Settings{
			IgnoreExists: true,
		},
		BaseReq: baseReq,
	}
	return cli.CreateDBUser(ctx, req)
}

func CreateDBDelegateUser(ctx context.Context, cli core.CoreServiceClient, baseReq *base.BaseReq) (interface{}, error) {
	//tenantID := &TenantID
	username := "chenfei@pingcap.com"
	req := &core.CreateDBUserReq{
		Operator: &core.DBUserOperator{
			Username:   "123",
			AuthMethod: core.DBUser_AUTH_METHOD_TOKEN,
			Credential: "",
		},
		ClusterId:   ClusterID,
		UserType:    core.DBUser_TYPE_DELEGATE,
		Username:    username,
		Email:       pointer.ToString(username),
		AuthMethod:  core.DBUser_AUTH_METHOD_TOKEN,
		Credential:  nil,
		BuiltinRole: core.DBUser_BUILTIN_ROLE_USER_ADMIN,
		BaseReq:     baseReq,
	}
	return cli.CreateDBUser(ctx, req)
}

func UpdateDBUser(ctx context.Context, cli core.CoreServiceClient, baseReq *base.BaseReq) (interface{}, error) {
	//tenantID := &TenantID
	role := core.DBUser_BUILTIN_ROLE_USER_ADMIN
	req := &core.UpdateDBUserReq{
		Operator: &core.DBUserOperator{
			Username:   operatorUsername,
			AuthMethod: core.DBUser_AUTH_METHOD_TOKEN,
			Credential: jwt,
		},
		ClusterId:   ClusterID,
		Username:    operatorUsername,
		BuiltinRole: &role,
		CustomRoles: []string{"role1"},
		BaseReq:     baseReq,
	}
	return cli.UpdateDBUser(ctx, req)
}

func DeleteDBUser(ctx context.Context, cli core.CoreServiceClient, baseReq *base.BaseReq) (interface{}, error) {
	req := &core.DeleteDBUserReq{
		Operator: &core.DBUserOperator{
			Username:   "chenfei@pingcap.com",
			AuthMethod: core.DBUser_AUTH_METHOD_TOKEN,
			Credential: jwt,
		},
		ClusterId: ClusterID,
		Username:  "test",
		BaseReq:   baseReq,
	}
	return cli.DeleteDBUser(ctx, req)
}

func GetDBUser(ctx context.Context, cli core.CoreServiceClient, baseReq *base.BaseReq) (interface{}, error) {
	req := &core.GetDBUserReq{
		Operator: &core.DBUserOperator{
			Username:   operatorUsername,
			AuthMethod: core.DBUser_AUTH_METHOD_TOKEN,
			Credential: jwt,
		},
		ClusterId: ClusterID,
		Username:  operatorUsername,
		BaseReq:   baseReq,
	}
	return cli.GetDBUser(ctx, req)
}

func IsDBUserExisting(ctx context.Context, cli core.CoreServiceClient, baseReq *base.BaseReq) (interface{}, error) {
	req := &core.IsDBUserExistingReq{
		Operator: &core.DBUserOperator{
			Username:   operatorUsername,
			AuthMethod: core.DBUser_AUTH_METHOD_TOKEN,
			Credential: jwt,
		},
		ClusterId: ClusterID,
		Username:  operatorUsername,
		BaseReq:   baseReq,
	}
	return cli.IsDBUserExisting(ctx, req)
}

func CreateDBRole(ctx context.Context, cli core.CoreServiceClient, baseReq *base.BaseReq) (interface{}, error) {
	//tenantID := &TenantID
	req := &core.CreateDBRoleReq{
		Operator: &core.DBUserOperator{
			Username:   "123",
			AuthMethod: core.DBUser_AUTH_METHOD_TOKEN,
			Credential: "",
		},
		ClusterId: ClusterID,
		RoleName:  "role1",
		Grants:    "grant select,insert,update on test.* to 'role1'",
		BaseReq:   baseReq,
	}
	return cli.CreateDBRole(ctx, req)
}

func UpdateDBRole(ctx context.Context, cli core.CoreServiceClient, baseReq *base.BaseReq) (interface{}, error) {
	//tenantID := &TenantID
	req := &core.UpdateDBRoleReq{
		Operator: &core.DBUserOperator{
			Username:   "123",
			AuthMethod: core.DBUser_AUTH_METHOD_TOKEN,
			Credential: "",
		},
		ClusterId:  ClusterID,
		RoleName:   "role1",
		Grants:     pointer.ToString("grant select,delete on test.* to 'role1'"),
		Revocation: pointer.ToString("revoke insert on test.* from 'role1'"),
		BaseReq:    baseReq,
	}
	return cli.UpdateDBRole(ctx, req)
}

func SetClusterAuthPubKey(ctx context.Context, cli core.CoreServiceClient, baseReq *base.BaseReq) (interface{}, error) {
	//tenantID := &TenantID
	req := &core.SetClusterAuthPubKeyReq{
		ClusterId: ClusterID,
		Jwks:      jwks,
	}
	return cli.SetClusterAuthPubKey(ctx, req)
}

func GetDBUsers(ctx context.Context, cli account.AccountAPIServiceClient, baseReq *base.BaseReq) (interface{}, error) {
	return cli.GetDBUsers(ctx, &account.GetDBUsersReq{
		OrgId:     30060,
		ProjectId: 74069,
	})
}

func QueryCloudProviders(ctx context.Context, cli core.CoreServiceClient, baseReq *base.BaseReq) (interface{}, error) {
	req := &core.QueryCloudProvidersReq{
		Filter: &core.SimplifiedCloudProviderFilter{
			Ids: []uint64{1},
		},
		BaseReq: baseReq,
	}
	return cli.QueryCloudProviders(ctx, req)
}

func DeletePrivateLinkService(ctx context.Context, cli core.CoreServiceClient, baseReq *base.BaseReq) (interface{}, error) {
	req := &core.DeletePrivateLinkServiceReq{
		OrgId:     TenantID,
		ProjectId: ProjectID,
		ClusterId: ClusterID,
	}
	return cli.DeletePrivateLinkService(ctx, req)
}

func CreatePrivateLinkEndpoint(ctx context.Context, cli core.CoreServiceClient, baseReq *base.BaseReq) (interface{}, error) {
	req := &core.CreatePrivateLinkEndpointReq{
		OrgId:     TenantID,
		ProjectId: ProjectID,
		ClusterId: ClusterID,
		PrivatelinkEndpoint: &core.PrivateLinkEndpoint{
			EndpointId: "vpce-040f0bfb4d21b8222",
			Type:       core.PrivateLinkEndpoint_TYPE_DBAAS,
		},
	}
	return cli.CreatePrivateLinkEndpoint(ctx, req)
}

func DeletePrivateLinkEndpoint(ctx context.Context, cli core.CoreServiceClient, baseReq *base.BaseReq) (interface{}, error) {
	req := &core.DeletePrivateLinkEndpointReq{
		OrgId:      TenantID,
		ProjectId:  ProjectID,
		ClusterId:  ClusterID,
		EndpointId: "vpce-040f0bfb4d21b8224",
	}
	return cli.DeletePrivateLinkEndpoint(ctx, req)
}

func ListPrivateLinkEndpoints(ctx context.Context, cli core.CoreServiceClient, baseReq *base.BaseReq) (interface{}, error) {
	req := &core.ListPrivateLinkEndpointsReq{
		OrgId:     TenantID,
		ProjectId: ProjectID,
	}
	return cli.ListPrivateLinkEndpoints(ctx, req)
}

func DeleteCluster(ctx context.Context, cli core.CoreServiceClient, baseReq *base.BaseReq) (interface{}, error) {
	apiKey := "APIKEY_xxx"
	ctx = grpcMetadata.AppendToOutgoingContext(ctx, "api-key", apiKey)
	req := &core.DeleteClusterReq{
		ClusterId: 3448949,
		BaseReq:   baseReq,
	}
	return cli.DeleteCluster(ctx, req)
}

func GetAwsCmek(ctx context.Context, cli core.CoreServiceClient, baseReq *base.BaseReq) (interface{}, error) {
	req := &core.GetAwsCmekReq{
		ProjectId:  43562,
		RegionName: pointer.ToString(AwsRegionName),
		BaseReq:    baseReq,
	}
	return cli.GetAwsCmek(ctx, req)
}

func CreateAwsCmek(ctx context.Context, cli core.CoreServiceClient, baseReq *base.BaseReq) (interface{}, error) {
	req := &core.CreateAwsCmekReq{
		ProjectId: 43562,
		Specs: []*core.AwsCmekSpec{
			{
				RegionName: "us-west-2",
				KmsArn:     "arn-xxx",
			},
			{
				RegionName: "us-east-1",
				KmsArn:     "arn-xxx2",
			},
		},
		BaseReq: baseReq,
	}
	return cli.CreateAwsCmek(ctx, req)
}

func ListClusterJobs(ctx context.Context, cli core.CoreServiceClient, baseReq *base.BaseReq) (interface{}, error) {
	req := &core.ListClusterJobsReq{
		Filter: &core.ClusterJobFilter{
			JobType: core.ClusterJobType_CLUSTER_JOB_TYPE_CDC,
		},
		BaseReq: baseReq,
	}
	return cli.ListClusterJobs(ctx, req)
}

func GetMaintenanceWindowByProjectID(ctx context.Context, cli core.CoreServiceClient, baseReq *base.BaseReq) (interface{}, error) {
	req := &core.GetMaintenanceWindowByProjectIDReq{
		ProjectId: 43562,
		BaseReq:   baseReq,
	}
	return cli.GetMaintenanceWindowByProjectID(ctx, req)
}

func UpdateMaintenanceWindow(ctx context.Context, cli core.CoreServiceClient, baseReq *base.BaseReq) (interface{}, error) {
	req := &core.UpdateMaintenanceWindowReq{
		MaintenanceWindow: &core.MaintenanceWindow{
			ProjectId:    43562,
			DayOfWeek:    3,
			HourOfDay:    6,
			MinuteOfHour: 0,
		},
		BaseReq: baseReq,
	}
	return cli.UpdateMaintenanceWindow(ctx, req)
}

func CreateMaintenanceTask(ctx context.Context, cli core.CoreServiceClient, baseReq *base.BaseReq) (interface{}, error) {
	var deadline int64 = 1687474800
	req := &core.CreateMaintenanceTaskReq{
		ProjectId:   43562,
		Description: "AWS Instance retirement 2",
		Deadline:    &deadline,
		ClusterIds:  []uint64{3538941},
		BaseReq:     baseReq,
	}
	return cli.CreateMaintenanceTask(ctx, req)
}

func QueryMaintenanceTasks(ctx context.Context, cli core.CoreServiceClient, baseReq *base.BaseReq) (interface{}, error) {
	req := &core.QueryMaintenanceTasksReq{
		Filter: &core.MaintenanceTaskFilter{
			ProjectIds: []uint64{43562},
			Statuses:   []core.MaintenanceTask_Status{core.MaintenanceTask_STATUS_PENDING},
		},
		BaseReq: baseReq,
	}
	return cli.QueryMaintenanceTasks(ctx, req)
}

func DeferMaintenanceTask(ctx context.Context, cli core.CoreServiceClient, baseReq *base.BaseReq) (interface{}, error) {
	req := &core.DeferMaintenanceTaskReq{
		Id:      1,
		BaseReq: nil,
	}
	return cli.DeferMaintenanceTask(ctx, req)
}

func ListUsersByFilter(ctx context.Context, cli account.AccountAPIServiceClient, baseReq *base.BaseReq) (interface{}, error) {
	return cli.ListUsersByFilter(ctx, &account.ListUsersByFilterRequest{
		Filter: &account.ListUsersFilter{
			ScopeTypes:  []account.ScopeType{account.ScopeType_SCOPE_TYPE_PROJECT},
			ScopeIds:    []uint64{2353477},
			TargetTypes: []account.TargetType{account.TargetType_TARGET_TYPE_USER},
			TargetIds:   nil,
			Roles:       nil,
			RoleIds:     nil,
		},
	})
}

func SendEmail(ctx context.Context, cli account.AccountAPIServiceClient, baseReq *base.BaseReq) (interface{}, error) {
	req := &account.SendEmailReq{
		OrgId:        0, // leave it empty
		Scene:        "maintenance_window_reminder",
		Identifier:   "23",
		Subject:      "TiDB Cloud Maintenance Window Completed Notification",
		Emails:       []string{"liuzhi@pingcap.com"},
		CcEmails:     nil, // leave it empty
		TemplateId:   "d-4fca9aecf6264b32ad214273758d3cb6",
		TemplateVars: nil, // fill later
	}
	templateVars := map[string]string{
		"userName":                "Louis",
		"clusterList":             "Cluster0, Cluster1, Cluster2",
		"clusterCount":            "3",
		"opsCanceledClusterList":  "Cluster3, Cluster4",
		"opsCanceledClusterCount": "2",
		"projectName":             "default project",
		"dateTime":                "Apr 21, 2023 18:00 UTC+08:00",
		"taskList":                "Upgrading the TiDB version, Optimizing the storage configuration",
	}
	req.TemplateVars = templateVars

	return cli.SendEmail(ctx, req)
}

func ClearEmailUniqueID(ctx context.Context, cli account.AccountAPIServiceClient, baseReq *base.BaseReq) (interface{}, error) {
	req := &account.ClearEmailUniqueIDReq{
		OrgId:      0, // leave it empty
		Scene:      "maintenance_window.completed",
		Identifier: "43562-1686088800-69984",
	}
	return cli.ClearEmailUniqueID(ctx, req)
}

func SyncMaintenanceWindow(ctx context.Context, cli core.CoreServiceClient, baseReq *base.BaseReq) (interface{}, error) {
	req := &core.SyncMaintenanceWindowReq{
		BaseReq: baseReq,
	}
	return cli.SyncMaintenanceWindow(ctx, req)
}

func QueryMaintenanceTaskExecutions(ctx context.Context, cli core.CoreServiceClient, baseReq *base.BaseReq) (interface{}, error) {
	req := &core.QueryMaintenanceTaskExecutionsReq{
		Filter: &core.MaintenanceTaskExecutionFilter{
			ClusterIds:         nil,
			Statuses:           []core.MaintenanceTaskExecution_Status{core.MaintenanceTaskExecution_STATUS_PENDING},
			MaintenanceTaskIds: []uint64{210003},
		},
		BaseReq: baseReq,
	}
	return cli.QueryMaintenanceTaskExecutions(ctx, req)
}

func UpdateMaintenanceTaskExecutionStatus(ctx context.Context, cli core.CoreServiceClient, baseReq *base.BaseReq) (interface{}, error) {
	req := &core.UpdateMaintenanceTaskExecutionStatusReq{
		Id:      150004,
		Status:  core.MaintenanceTaskExecution_STATUS_CANCELED,
		BaseReq: nil,
	}
	return cli.UpdateMaintenanceTaskExecutionStatus(ctx, req)
}

func UpdateMaintenanceTaskStatus(ctx context.Context, cli core.CoreServiceClient, baseReq *base.BaseReq) (interface{}, error) {
	req := &core.UpdateMaintenanceTaskStatusReq{
		Id:      210004,
		Status:  core.MaintenanceTask_STATUS_DONE,
		BaseReq: nil,
	}
	return cli.UpdateMaintenanceTaskStatus(ctx, req)
}

func ExecuteCtlCommand(ctx context.Context, cli core.CoreServiceClient, baseReq *base.BaseReq) (interface{}, error) {
	req := &core.ExecuteCtlCommandReq{
		ClusterId: 3839136,
		//Command:   "pd-ctl -u https://db-pd.tidb3839136.svc:2379 config show replication",
		//Command: "pd-ctl -u https://db-pd-0.db-pd-peer.tidb3839136.svc:2379 config show replication",
		Command: "pd-ctl -V",
		//Command: "tikv-ctl --host db-tikv-0.db-tikv-peer.tidb3839136.svc:20160 store",
		//Command: "tikv-ctl --host db-tikv-0.db-tikv-peer.tidb3839136.svc:20160 region-properties -r 2",
		BaseReq: baseReq,
	}
	return cli.ExecuteCtlCommand(ctx, req)
}

func GetClusterTopology(ctx context.Context, cli core.CoreServiceClient, baseReq *base.BaseReq) (interface{}, error) {
	req := &core.GetClusterTopologyReq{
		ClusterId: 3839136,
		BaseReq:   baseReq,
	}
	return cli.GetClusterTopology(ctx, req)
}

func CreateAccessPoint(ctx context.Context, cli core.CoreServiceClient, baseReq *base.BaseReq) (interface{}, error) {
	req := &core.CreateAccessPointReq{
		ClusterId:      3840540,
		DisplayName:    "ap-4",
		PublicEndpoint: nil,
		BaseReq:        baseReq,
	}
	return cli.CreateAccessPoint(ctx, req)
}

func UpdateAccessPoint(ctx context.Context, cli core.CoreServiceClient, baseReq *base.BaseReq) (interface{}, error) {
	newName := "ap-2"
	req := &core.UpdateAccessPointReq{
		Id:             2,
		DisplayName:    &newName,
		PublicEndpoint: nil,
		BaseReq:        baseReq,
	}
	return cli.UpdateAccessPoint(ctx, req)
}

func DeleteAccessPoint(ctx context.Context, cli core.CoreServiceClient, baseReq *base.BaseReq) (interface{}, error) {
	req := &core.DeleteAccessPointReq{
		Id:      1,
		BaseReq: baseReq,
	}
	return cli.DeleteAccessPoint(ctx, req)
}

func GetDefaultCidr(ctx context.Context, cli core.CoreServiceClient, baseReq *base.BaseReq) (interface{}, error) {
	req := &core.GetDefaultCidrRequest{
		CloudProviderName: "gcp",
		RegionName:        "us-west1",
		BaseReq:           baseReq,
	}
	return cli.GetDefaultCidr(ctx, req)
}

func GetBillableClustersCount(ctx context.Context, cli globaldedicatedv1.ClusterServiceClient) (interface{}, error) {
	startTime, _ := time.Parse(time.RFC3339, "2024-04-14T00:00:00Z")
	endTime, _ := time.Parse(time.RFC3339, "2024-04-15T00:00:00Z")

	req := &globaldedicatedv1.GetBillableClustersCountRequest{
		ProjectId: 3199748,
		StartTime: timestamppb.New(startTime),
		EndTime:   timestamppb.New(endTime),
	}
	return cli.GetBillableClustersCount(ctx, req)
}
