package main

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

	"github.com/tidbcloud/idl/pbgen/proto/base"
	"github.com/tidbcloud/idl/pbgen/proto/core"
	"github.com/tidbcloud/pkgv2/logid"
	"google.golang.org/grpc"
)

var (
	AwsRegionName           = "us-west-2"
	GcpRegionName           = "us-east1"
	TenantID         uint64 = 1      // management
	ProjectID        uint64 = 100021 // louis2(ccc)
	ClusterID        uint64 = 390171
	DevTierClusterID uint64 = 390012
	OperatorUserID   uint64 = 330001 // fei.chen
	BackupID         uint64 = 330015
	DeployType              = core.DeployType_DEPLOY_TYPE_DEDICATED
)

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

	connectTo := "127.0.0.1:20000"
	conn, err := grpc.Dial(connectTo, grpc.WithBlock(), grpc.WithInsecure())
	if err != nil {
		panic(err)
	}
	fmt.Println("Connected to", connectTo)
	cli := core.NewCoreServiceClient(conn)
	BaseReq := &base.BaseReq{
		Tags: map[string]string{
			logid.GRPCHeaderKey: requestid,
		},
	}

	var resp interface{}
	_ = resp
	_ = cli
	_ = BaseReq
	//resp, err = CreateCluster(ctx, cli, BaseReq)
	//resp, err = CreateDevTierCluster(ctx, cli, BaseReq)
	//resp,err = ScaleOutCluster(ctx, cli, BaseReq)
	//resp,err = ScaleInCluster(ctx, cli, BaseReq)
	//resp,err = ScaleOutClusterWithTiFlash(ctx, cli, BaseReq)
	//resp,err = RestoreCluster(ctx, cli, BaseReq)

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

	//resp, err = ListProfile4Tenant(ctx, cli, BaseReq)
	resp, err = ListCloudProviders(ctx, cli, BaseReq)
	//resp, err = CalcClusterFee(ctx, cli, BaseReq)

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

func CreateCluster(ctx context.Context, cli core.CoreServiceClient, baseReq *base.BaseReq) (interface{}, error) {
	req := &core.CreateClusterReq{
		BaseReq:          baseReq,
		TenantId:         TenantID,
		ProjectId:        ProjectID,
		Name:             "sct-1",
		RootPassword:     "12345678",
		CloudProvider:    "aws",
		Region:           AwsRegionName,
		DeployType:       core.DeployType_DEPLOY_TYPE_DEDICATED,
		IsDevTier:        false,
		PrimaryClusterId: 0,
		Components: []*core.ClusterComponent{
			{
				ComponentType: core.ComponentType_COMPONENT_TYPE_TIDB,
				NodeProfileId: 550, // t3.medium
				Replicas:      1,
				StorageSizeGi: 20,
			},
			{
				ComponentType: core.ComponentType_COMPONENT_TYPE_TIKV,
				NodeProfileId: 551, // t3.medium
				Replicas:      3,
				StorageSizeGi: 20,
			},
		},
		CreateById: OperatorUserID, // fei.chen
	}

	return cli.CreateCluster(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,
				NodeProfileId: 554, // s1.dev
				Replicas:      1,
				StorageSizeGi: 20,
			},
			{
				ComponentType: core.ComponentType_COMPONENT_TYPE_TIKV,
				NodeProfileId: 553, // 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,
				NodeProfileId: 550, // t3.medium
				Replicas:      2,
				StorageSizeGi: 20,
			},
			{
				ComponentType: core.ComponentType_COMPONENT_TYPE_TIKV,
				NodeProfileId: 551, // 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,
				NodeProfileId: 554, // s1.dev
				Replicas:      1,
				StorageSizeGi: 20,
			},
			{
				ComponentType: core.ComponentType_COMPONENT_TYPE_TIKV,
				NodeProfileId: 553, // s1.dev
				Replicas:      3,
				StorageSizeGi: 20,
			},
			{
				ComponentType: core.ComponentType_COMPONENT_TYPE_TIFLASH,
				NodeProfileId: 555, // 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,
				NodeProfileId: 550, // t3.medium
				Replicas:      1,
				StorageSizeGi: 20,
			},
			{
				ComponentType: core.ComponentType_COMPONENT_TYPE_TIKV,
				NodeProfileId: 551, // t3.medium
				Replicas:      3,
				StorageSizeGi: 20,
			},
		},
	}

	return cli.ScaleCluster(ctx, req)
}

func RestoreCluster(ctx context.Context, cli core.CoreServiceClient, baseReq *base.BaseReq) (interface{}, error) {
	req := &core.RestoreClusterReq{
		BackupId:           BackupID,
		OperatorUserId:     OperatorUserID, // fei.chen
		ClusterName:        "restore-sct1",
		ClusterDescription: "restore",
		ClusterPassword:    "12345678",
		BaseReq:            baseReq,
	}

	return cli.RestoreCluster(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 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,
				NodeProfileId: 550,
				Replicas:      1,
				StorageSizeGi: 0,
			}, {
				ComponentType: core.ComponentType_COMPONENT_TYPE_TIKV,
				NodeProfileId: 551,
				Replicas:      3,
				StorageSizeGi: 20,
			},
		},
		BaseReq: baseReq,
	}
	return cli.CalcClusterFee(ctx, req)
}

func Measure(ctx context.Context, cli core.CoreServiceClient, baseReq *base.BaseReq) (interface{}, error) {
	req := &core.MeasureReq{
		TenantIds:      []uint64{1},
		EndTime:        time.Now().Unix(),
		MeasureProject: false,
		MeasureCluster: false,
		BaseReq:        baseReq,
	}
	return cli.Measure(ctx, req)
}

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