package mgmt

import (
	"context"
	"testing"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
	"github.com/tidbcloud/metering/pkg/common/models"
	dedicatedv1 "github.com/tidbcloud/tidb-management-service/api/spec/global/dedicated/v1"
	tidb_mgmt_servicev1 "github.com/tidbcloud/tidb-management-service/api/spec/tidb_mgmt_service/v1"
	"google.golang.org/grpc"
	"google.golang.org/protobuf/types/known/emptypb"
)

func parseSKUJson(t *testing.T, skuStr string) []*models.SKUJson {
	t.Helper()
	skus, err := models.StringToSKUJson(skuStr)
	require.NoError(t, err)
	return skus
}

func findComponentByNodeSKU(t *testing.T, components []*models.ComponentMeta, componentName, skuName string) *models.ComponentMeta {
	t.Helper()
	for _, comp := range components {
		if componentName != "" && comp.Component != componentName {
			continue
		}
		skus := parseSKUJson(t, comp.NodeSKU)
		for _, sku := range skus {
			if sku.SKUName == skuName {
				return comp
			}
		}
	}
	t.Fatalf("component %s with sku %s not found", componentName, skuName)
	return nil
}

func mustFindSKU(t *testing.T, skus []*models.SKUJson, skuName, skuValue string) *models.SKUJson {
	t.Helper()
	for _, sku := range skus {
		if sku.SKUName == skuName && sku.SKUValue == skuValue {
			return sku
		}
	}
	t.Fatalf("sku %s with value %s not found", skuName, skuValue)
	return nil
}

func TestListClusters(t *testing.T) {
	result, err := svc.List(context.TODO(), 1111)
	require.NoError(t, err)
	require.Len(t, result, 5)
	assert.Equal(t, "20001", result[0].ClusterID)
	assert.Equal(t, int32(5), result[2].State)

	clusterinfo := result[0]
	tikvComponent := findComponentByNodeSKU(t, clusterinfo.Components, "tikv", "node:aws:us-west-2:DEPLOY_TYPE_DEDICATED:t4g.medium")
	assert.Equal(t, uint32(3), tikvComponent.Count)
	tikvNodeSkus := parseSKUJson(t, tikvComponent.NodeSKU)
	require.Len(t, tikvNodeSkus, 1)
	assert.Equal(t, "node:aws:us-west-2:DEPLOY_TYPE_DEDICATED:t4g.medium", tikvNodeSkus[0].SKUName)
	assert.Equal(t, "1", tikvNodeSkus[0].SKUValue)
	assert.Equal(t, uint32(3), tikvNodeSkus[0].Count)

	tiproxyComponent := findComponentByNodeSKU(t, clusterinfo.Components, "tiproxy", "tiproxy:aws:us-west-2:DEPLOY_TYPE_DEDICATED:t4g.medium")
	tiproxySkus := parseSKUJson(t, tiproxyComponent.NodeSKU)
	require.Len(t, tiproxySkus, 1)
	assert.Equal(t, "tiproxy:aws:us-west-2:DEPLOY_TYPE_DEDICATED:t4g.medium", tiproxySkus[0].SKUName)

	storageskus := parseSKUJson(t, tikvComponent.StoragesSKU)
	require.Len(t, storageskus, 8)
	assert.Equal(t, uint32(3), mustFindSKU(t, storageskus, "disk-storage:aws:us-west-2:basicV2:data-disk", "10").Count)
	assert.Equal(t, uint32(3), mustFindSKU(t, storageskus, "disk-iops:aws:us-west-2:basicV2:data-disk", "4000").Count)
	assert.Equal(t, uint32(3), mustFindSKU(t, storageskus, "disk-throughput:aws:us-west-2:basicV2:data-disk", "400").Count)
	assert.Equal(t, uint32(3), mustFindSKU(t, storageskus, "disk-additionaliops:aws:us-west-2:basicV2:data-disk", "1000").Count)
	assert.Equal(t, uint32(3), mustFindSKU(t, storageskus, "disk-storage:aws:us-west-2:basicV2:log-disk", "10").Count)
	assert.Equal(t, uint32(3), mustFindSKU(t, storageskus, "disk-iops:aws:us-west-2:basicV2:log-disk", "4000").Count)
	assert.Equal(t, uint32(3), mustFindSKU(t, storageskus, "disk-throughput:aws:us-west-2:basicV2:log-disk", "400").Count)
	assert.Equal(t, uint32(3), mustFindSKU(t, storageskus, "disk-additionaliops:aws:us-west-2:basicV2:log-disk", "1000").Count)
}

func TestDetail(t *testing.T) {
	result, err := svc.Detail(context.TODO(), 1243431, 123423)
	require.NoError(t, err)
	require.Len(t, result, 6)

	tidbMedium := findComponentByNodeSKU(t, result, "tidb", "node:aws:us-west-2:DEPLOY_TYPE_DEDICATED:t4g.medium")
	assert.Equal(t, uint32(0x3), tidbMedium.Count)
	assert.Empty(t, tidbMedium.StoragesSKU)
	tidbMediumSkus := parseSKUJson(t, tidbMedium.NodeSKU)
	require.Len(t, tidbMediumSkus, 1)
	assert.Equal(t, uint32(3), tidbMediumSkus[0].Count)

	tidbLarge := findComponentByNodeSKU(t, result, "tidb", "node:aws:us-west-2:DEPLOY_TYPE_DEDICATED:t4g.large")
	assert.Equal(t, int32(0), tidbLarge.State)
	tidbLargeSkus := parseSKUJson(t, tidbLarge.NodeSKU)
	require.Len(t, tidbLargeSkus, 1)
	assert.Equal(t, uint32(1), tidbLargeSkus[0].Count)

	tikvNode := findComponentByNodeSKU(t, result, "tikv", "node:aws:us-west-2:DEPLOY_TYPE_DEDICATED:t4g.medium")
	tikvNodeSkus := parseSKUJson(t, tikvNode.NodeSKU)
	require.Len(t, tikvNodeSkus, 1)
	assert.Equal(t, uint32(3), tikvNodeSkus[0].Count)
	assert.Equal(t, "GP3", tikvNode.VolumeType)

	tikvPending := findComponentByNodeSKU(t, result, "tikv", "node:aws:us-west-2:DEPLOY_TYPE_DEDICATED:PENDING")
	tikvPendingSkus := parseSKUJson(t, tikvPending.NodeSKU)
	require.Len(t, tikvPendingSkus, 1)
	assert.Equal(t, uint32(1), tikvPendingSkus[0].Count)

	tiflashNode := findComponentByNodeSKU(t, result, "tiflash", "node:aws:us-west-2:DEPLOY_TYPE_DEDICATED:t4g.medium")
	assert.Equal(t, uint32(0xa), tiflashNode.StorageSizeGi)

	storageskus := parseSKUJson(t, tikvNode.StoragesSKU)
	require.Len(t, storageskus, 6)
	assert.Equal(t, uint32(1), mustFindSKU(t, storageskus, "disk-storage:aws:us-west-2:basicV2:data-disk", "10").Count)
	assert.Equal(t, uint32(1), mustFindSKU(t, storageskus, "disk-storage:aws:us-west-2:basicV2:data-disk", "20").Count)
	assert.Equal(t, uint32(1), mustFindSKU(t, storageskus, "disk-iops:aws:us-west-2:basicV2:data-disk", "4000").Count)
	assert.Equal(t, uint32(1), mustFindSKU(t, storageskus, "disk-iops:aws:us-west-2:basicV2:data-disk", "5000").Count)
	assert.Equal(t, uint32(2), mustFindSKU(t, storageskus, "disk-throughput:aws:us-west-2:basicV2:data-disk", "400").Count)
	assert.Equal(t, uint32(2), mustFindSKU(t, storageskus, "disk-additionaliops:aws:us-west-2:basicV2:data-disk", "1000").Count)

	tiproxyNode := findComponentByNodeSKU(t, result, "tiproxy", "tiproxy:aws:us-west-2:DEPLOY_TYPE_DEDICATED:t4g.medium")
	assert.Equal(t, "tiproxy", tiproxyNode.Component)
	tiproxySkus := parseSKUJson(t, tiproxyNode.NodeSKU)
	require.Len(t, tiproxySkus, 1)
	assert.Equal(t, "tiproxy:aws:us-west-2:DEPLOY_TYPE_DEDICATED:t4g.medium", tiproxySkus[0].SKUName)
	assert.Equal(t, uint32(1), tiproxySkus[0].Count)
}

// LocalGrpcService mock tidb-mgmt-service response
// only need to implement ListClusters and ShowComponentNodeInfo
type LocalGrpcService struct {
}

func (l LocalGrpcService) ListClusters(ctx context.Context, in *tidb_mgmt_servicev1.ListClustersRequest, opts ...grpc.CallOption) (*tidb_mgmt_servicev1.ListClustersResponse, error) {
	resp := &tidb_mgmt_servicev1.ListClustersResponse{}
	resp.Clusters = append(resp.Clusters, buildClusters()...)
	return resp, nil
}

func (l LocalGrpcService) ShowComponentNodeInfo(ctx context.Context, in *tidb_mgmt_servicev1.ShowComponentNodeInfoRequest, opts ...grpc.CallOption) (*tidb_mgmt_servicev1.ShowComponentNodeInfoResponse, error) {
	resp := &tidb_mgmt_servicev1.ShowComponentNodeInfoResponse{}
	resp.ComponentNodeInfo = buildScalingComponentInfo()
	return resp, nil
}

// Subsequent methods do not need to be implemented

func (l LocalGrpcService) CountClusters(ctx context.Context, in *tidb_mgmt_servicev1.CountClustersRequest, opts ...grpc.CallOption) (*tidb_mgmt_servicev1.CountClustersResponse, error) {
	//TODO implement me
	panic("implement me")
}

func (l LocalGrpcService) CleanClusters(ctx context.Context, in *tidb_mgmt_servicev1.CleanClustersRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) {
	//TODO implement me
	panic("implement me")
}

func (l LocalGrpcService) CleanProjectResource(ctx context.Context, in *tidb_mgmt_servicev1.CleanProjectResourceRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) {
	//TODO implement me
	panic("implement me")
}

func (l LocalGrpcService) CleanOrganizationResource(ctx context.Context, in *tidb_mgmt_servicev1.CleanOrganizationResourceRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) {
	//TODO implement me
	panic("implement me")
}

func (l LocalGrpcService) ApplyCluster(ctx context.Context, in *tidb_mgmt_servicev1.ApplyClusterRequest, opts ...grpc.CallOption) (*tidb_mgmt_servicev1.Cluster, error) {
	//TODO implement me
	panic("implement me")
}

func (l LocalGrpcService) RestoreDedicatedCluster(ctx context.Context, in *tidb_mgmt_servicev1.RestoreDedicatedClusterRequest, opts ...grpc.CallOption) (*tidb_mgmt_servicev1.Cluster, error) {
	//TODO implement me
	panic("implement me")
}

func (l LocalGrpcService) RestoreServerlessCluster(ctx context.Context, in *tidb_mgmt_servicev1.RestoreServerlessClusterRequest, opts ...grpc.CallOption) (*tidb_mgmt_servicev1.Cluster, error) {
	//TODO implement me
	panic("implement me")
}

func (l LocalGrpcService) DeleteCluster(ctx context.Context, in *tidb_mgmt_servicev1.DeleteClusterRequest, opts ...grpc.CallOption) (*tidb_mgmt_servicev1.Cluster, error) {
	//TODO implement me
	panic("implement me")
}

func (l LocalGrpcService) ModifyClusterVolume(ctx context.Context, in *tidb_mgmt_servicev1.ModifyClusterVolumeRequest, opts ...grpc.CallOption) (*tidb_mgmt_servicev1.Cluster, error) {
	//TODO implement me
	panic("implement me")
}

func (l LocalGrpcService) ScaleClusterPdComponent(ctx context.Context, in *tidb_mgmt_servicev1.ScaleClusterPdComponentRequest, opts ...grpc.CallOption) (*tidb_mgmt_servicev1.Cluster, error) {
	//TODO implement me
	panic("implement me")
}

func (l LocalGrpcService) ScaleClusterTiProxyComponent(ctx context.Context, in *tidb_mgmt_servicev1.ScaleClusterTiProxyComponentRequest, opts ...grpc.CallOption) (*tidb_mgmt_servicev1.Cluster, error) {
	//TODO implement me
	panic("implement me")
}

func (l LocalGrpcService) ScaleClusterComponents(ctx context.Context, in *tidb_mgmt_servicev1.ScaleClusterComponentsRequest, opts ...grpc.CallOption) (*tidb_mgmt_servicev1.Cluster, error) {
	//TODO implement me
	panic("implement me")
}

func (l LocalGrpcService) CreateClusterWithClusterConfiguration(ctx context.Context, in *tidb_mgmt_servicev1.CreateClusterWithClusterConfigurationRequest, opts ...grpc.CallOption) (*tidb_mgmt_servicev1.Cluster, error) {
	//TODO implement me
	panic("implement me")
}

func (l LocalGrpcService) CountBillableClusters(ctx context.Context, in *tidb_mgmt_servicev1.CountBillableClustersRequest, opts ...grpc.CallOption) (*tidb_mgmt_servicev1.CountBillableClustersResponse, error) {
	//TODO implement me
	panic("implement me")
}

func (l LocalGrpcService) UpdateServerlessRegionalClusterAnnotations(ctx context.Context, in *tidb_mgmt_servicev1.UpdateServerlessRegionalClusterAnnotationsRequest, opts ...grpc.CallOption) (*tidb_mgmt_servicev1.Cluster, error) {
	//TODO implement me
	panic("implement me")
}

var tikvCount = uint32(3)
var tidbCount = uint32(2)
var tiflashCount = uint32(1)
var pdCount = uint32(3)
var tiproxyCount = uint32(2)

var throuput = uint32(400)
var iops = uint32(4000)
var sizeGi = uint32(10)
var additionalIops = uint32(1000)

func buildClusters() []*tidb_mgmt_servicev1.Cluster {
	return []*tidb_mgmt_servicev1.Cluster{
		buildCluster("test-creating", uint64(10001), uint64(10002), uint64(10003), dedicatedv1.Cluster_CREATING),
		buildCluster("test-available", uint64(20001), uint64(20002), uint64(20003), dedicatedv1.Cluster_AVAILABLE),
		buildCluster("test-paused", uint64(40001), uint64(40002), uint64(40003), dedicatedv1.Cluster_PAUSED),
		buildCluster("test-resuming", uint64(50001), uint64(50002), uint64(50003), dedicatedv1.Cluster_RESUMING),
		buildCluster("test-unavailable", uint64(60001), uint64(60002), uint64(60003), dedicatedv1.Cluster_UNAVAILABLE),
		buildCluster("test-pausing", uint64(70001), uint64(70002), uint64(70003), dedicatedv1.Cluster_PAUSING),
		buildCluster("test-scaling", uint64(80001), uint64(80002), uint64(80003), dedicatedv1.Cluster_SCALING),
		buildCluster("test-deleted", uint64(90001), uint64(90002), uint64(90003), dedicatedv1.Cluster_DELETED),
	}
}

func volumeType2ptrVolumeType(s dedicatedv1.StorageMu_VolumeType) *dedicatedv1.StorageMu_VolumeType {
	return &s
}

func buildCluster(clusterName string, clusterID, projectID, orgID uint64, state dedicatedv1.Cluster_State) *tidb_mgmt_servicev1.Cluster {
	cluster := &tidb_mgmt_servicev1.Cluster{
		OrganizationId: orgID,
		ClusterId:      clusterID,
		ProjectId:      projectID,
		ClusterName:    clusterName,
		CloudProvider:  "aws",
		DeployType:     1,
		Region:         "us-west-2",
		ClusterInfo: &tidb_mgmt_servicev1.Cluster_DedicatedCluster{
			DedicatedCluster: &dedicatedv1.Cluster{
				OrganizationId: orgID,
				ClusterId:      clusterID,
				ProjectId:      projectID,
				State:          state,
				ClusterComponents: []*dedicatedv1.Cluster_ClusterComponent{
					{
						ComponentType: dedicatedv1.ComponentType_TIKV,
						Count:         &tikvCount,
						CpuNum:        uint32(2),
						MemorySizeGi:  uint32(4),
						InstanceType:  "t4g.medium",
						Storages: map[string]*dedicatedv1.Cluster_ClusterComponent_Storage{
							"data": {
								VolumeType:      volumeType2ptrVolumeType(dedicatedv1.StorageMu_GP3),
								SizeGi:          sizeGi,
								Iops:            iops,
								ThroughputMibps: throuput,
								MeteringSkuKeys: map[string]uint32{
									"disk-storage:aws:us-west-2:basicV2:data-disk":        sizeGi,
									"disk-iops:aws:us-west-2:basicV2:data-disk":           iops,
									"disk-throughput:aws:us-west-2:basicV2:data-disk":     throuput,
									"disk-additionaliops:aws:us-west-2:basicV2:data-disk": additionalIops,
								},
							},
							"log": {
								VolumeType:      volumeType2ptrVolumeType(dedicatedv1.StorageMu_GP3),
								SizeGi:          sizeGi,
								Iops:            iops,
								ThroughputMibps: throuput,
								MeteringSkuKeys: map[string]uint32{
									"disk-storage:aws:us-west-2:basicV2:log-disk":        sizeGi,
									"disk-iops:aws:us-west-2:basicV2:log-disk":           iops,
									"disk-throughput:aws:us-west-2:basicV2:log-disk":     throuput,
									"disk-additionaliops:aws:us-west-2:basicV2:log-disk": additionalIops,
								},
							},
						},
						MeteringSkuKeys: map[string]uint32{
							"node:aws:us-west-2:DEPLOY_TYPE_DEDICATED:t4g.medium": 1,
						},
					},
					{
						ComponentType: dedicatedv1.ComponentType_PD,
						Count:         &pdCount,
						CpuNum:        uint32(2),
						MemorySizeGi:  uint32(4),
						InstanceType:  "t4g.medium",
						Storages: map[string]*dedicatedv1.Cluster_ClusterComponent_Storage{
							"data": {
								VolumeType:      volumeType2ptrVolumeType(dedicatedv1.StorageMu_GP3),
								SizeGi:          sizeGi,
								Iops:            iops,
								ThroughputMibps: throuput,
								MeteringSkuKeys: map[string]uint32{
									"disk-storage:aws:us-west-2:basicV2:data-disk":        sizeGi,
									"disk-iops:aws:us-west-2:basicV2:data-disk":           iops,
									"disk-throughput:aws:us-west-2:basicV2:data-disk":     throuput,
									"disk-additionaliops:aws:us-west-2:basicV2:data-disk": additionalIops,
								},
							},
						},
						MeteringSkuKeys: map[string]uint32{
							"node:aws:us-west-2:DEPLOY_TYPE_DEDICATED:t4g.medium": 1,
						},
					},
					{
						ComponentType:        dedicatedv1.ComponentType_TIDB,
						Count:                &tidbCount,
						CpuNum:               uint32(2),
						MemorySizeGi:         uint32(4),
						InstanceType:         "t4g.medium",
						TidbGroupDisplayName: "1795007861923794944",
						MeteringSkuKeys: map[string]uint32{
							"node:aws:us-west-2:DEPLOY_TYPE_DEDICATED:t4g.medium": 1,
						},
						Storages: map[string]*dedicatedv1.Cluster_ClusterComponent_Storage{
							"data": {
								VolumeType:      volumeType2ptrVolumeType(dedicatedv1.StorageMu_GP3),
								SizeGi:          sizeGi,
								Iops:            iops,
								ThroughputMibps: throuput,
								MeteringSkuKeys: map[string]uint32{
									"disk-storage:aws:us-west-2:basicV2:data-disk":        sizeGi,
									"disk-iops:aws:us-west-2:basicV2:data-disk":           iops,
									"disk-throughput:aws:us-west-2:basicV2:data-disk":     throuput,
									"disk-additionaliops:aws:us-west-2:basicV2:data-disk": additionalIops,
								},
							},
						},
					},
					{
						ComponentType: dedicatedv1.ComponentType_TIFLASH,
						Count:         &tiflashCount,
						CpuNum:        uint32(2),
						MemorySizeGi:  uint32(4),
						InstanceType:  "t4g.medium",
						Storages: map[string]*dedicatedv1.Cluster_ClusterComponent_Storage{
							"data": {
								VolumeType:      volumeType2ptrVolumeType(dedicatedv1.StorageMu_GP3),
								SizeGi:          sizeGi,
								Iops:            iops,
								ThroughputMibps: throuput,
								MeteringSkuKeys: map[string]uint32{
									"disk-storage:aws:us-west-2:basicV2:data-disk":        sizeGi,
									"disk-iops:aws:us-west-2:basicV2:data-disk":           iops,
									"disk-throughput:aws:us-west-2:basicV2:data-disk":     throuput,
									"disk-additionaliops:aws:us-west-2:basicV2:data-disk": additionalIops,
								},
							},
						},
						MeteringSkuKeys: map[string]uint32{
							"node:aws:us-west-2:DEPLOY_TYPE_DEDICATED:t4g.medium": 1,
						},
					},
					{
						ComponentType:        dedicatedv1.ComponentType_TIPROXY,
						Count:                &tiproxyCount,
						CpuNum:               uint32(2),
						MemorySizeGi:         uint32(4),
						InstanceType:         "t4g.medium",
						TidbGroupDisplayName: "1795007861923794944",
						MeteringSkuKeys: map[string]uint32{
							"tiproxy:aws:us-west-2:DEPLOY_TYPE_DEDICATED:t4g.medium": 1,
						},
						Storages: map[string]*dedicatedv1.Cluster_ClusterComponent_Storage{
							"data": {
								VolumeType:      volumeType2ptrVolumeType(dedicatedv1.StorageMu_GP3),
								SizeGi:          sizeGi,
								Iops:            iops,
								ThroughputMibps: throuput,
								MeteringSkuKeys: map[string]uint32{
									"disk-storage:aws:us-west-2:basicV2:data-disk":        sizeGi,
									"disk-iops:aws:us-west-2:basicV2:data-disk":           iops,
									"disk-throughput:aws:us-west-2:basicV2:data-disk":     throuput,
									"disk-additionaliops:aws:us-west-2:basicV2:data-disk": additionalIops,
								},
							},
						},
					},
				},
			},
		},
	}
	return cluster
}

func buildScalingComponentInfo() *dedicatedv1.ComponentNodeInfo {
	componentInfo := &dedicatedv1.ComponentNodeInfo{
		Tidb: []*dedicatedv1.ComponentNodeInfo_Component{
			{
				Nodes: []*dedicatedv1.ComponentNodeInfo_Component_Node{
					{
						State:                  dedicatedv1.ComponentNodeInfo_Component_Node_AVAILABLE,
						Cpu:                    uint32(2),
						MemorySizeGi:           uint32(4),
						StorageSizeGi:          sizeGi,
						StorageIops:            iops,
						StorageThroughputMibps: throuput,
						InstanceType:           "t4g.medium",
						VolumeType:             dedicatedv1.StorageMu_GP3,
						MeteringSkuKeys: map[string]uint32{
							"node:aws:us-west-2:DEPLOY_TYPE_DEDICATED:t4g.medium": 1,
						},
						// tidb should not metering storage
						Storages: map[string]*dedicatedv1.ComponentNodeInfo_Component_Storage{
							"data": {
								VolumeType:             dedicatedv1.StorageMu_GP3,
								StorageSizeGi:          sizeGi,
								StorageIops:            iops,
								StorageThroughputMibps: throuput,
								MeteringSkuKeys: map[string]uint32{
									"disk-storage:aws:us-west-2:basicV2:data-disk":        sizeGi,
									"disk-iops:aws:us-west-2:basicV2:data-disk":           iops,
									"disk-throughput:aws:us-west-2:basicV2:data-disk":     throuput,
									"disk-additionaliops:aws:us-west-2:basicV2:data-disk": additionalIops,
								},
							},
						},
					},
					{
						State:                  dedicatedv1.ComponentNodeInfo_Component_Node_DELETING,
						Cpu:                    uint32(2),
						MemorySizeGi:           uint32(4),
						StorageSizeGi:          sizeGi,
						StorageIops:            iops,
						StorageThroughputMibps: throuput,
						InstanceType:           "t4g.medium",
						VolumeType:             dedicatedv1.StorageMu_GP3,
						MeteringSkuKeys: map[string]uint32{
							"node:aws:us-west-2:DEPLOY_TYPE_DEDICATED:t4g.medium": 1,
						},
						// tidb should not metering storage
						Storages: map[string]*dedicatedv1.ComponentNodeInfo_Component_Storage{
							"data": {
								VolumeType:             dedicatedv1.StorageMu_GP3,
								StorageSizeGi:          sizeGi,
								StorageIops:            iops,
								StorageThroughputMibps: throuput,
								MeteringSkuKeys: map[string]uint32{
									"disk-storage:aws:us-west-2:basicV2:data-disk":        sizeGi,
									"disk-iops:aws:us-west-2:basicV2:data-disk":           iops,
									"disk-throughput:aws:us-west-2:basicV2:data-disk":     throuput,
									"disk-additionaliops:aws:us-west-2:basicV2:data-disk": additionalIops,
								},
							},
						},
					},
					{
						State:                  dedicatedv1.ComponentNodeInfo_Component_Node_UNAVAILABLE,
						Cpu:                    uint32(2),
						MemorySizeGi:           uint32(4),
						StorageSizeGi:          sizeGi,
						StorageIops:            iops,
						StorageThroughputMibps: throuput,
						InstanceType:           "t4g.medium",
						VolumeType:             dedicatedv1.StorageMu_GP3,
						MeteringSkuKeys: map[string]uint32{
							"node:aws:us-west-2:DEPLOY_TYPE_DEDICATED:t4g.medium": 1,
						},
						// tidb should not metering storage
						Storages: map[string]*dedicatedv1.ComponentNodeInfo_Component_Storage{
							"data": {
								VolumeType:             dedicatedv1.StorageMu_GP3,
								StorageSizeGi:          sizeGi,
								StorageIops:            iops,
								StorageThroughputMibps: throuput,
								MeteringSkuKeys: map[string]uint32{
									"disk-storage:aws:us-west-2:basicV2:data-disk":        sizeGi,
									"disk-iops:aws:us-west-2:basicV2:data-disk":           iops,
									"disk-throughput:aws:us-west-2:basicV2:data-disk":     throuput,
									"disk-additionaliops:aws:us-west-2:basicV2:data-disk": additionalIops,
								},
							},
						},
					},
					{
						State:                  dedicatedv1.ComponentNodeInfo_Component_Node_CREATING,
						Cpu:                    uint32(2),
						MemorySizeGi:           uint32(4),
						StorageSizeGi:          sizeGi,
						StorageIops:            iops,
						StorageThroughputMibps: throuput,
						InstanceType:           "t4g.medium",
						VolumeType:             dedicatedv1.StorageMu_GP3,
						MeteringSkuKeys: map[string]uint32{
							"node:aws:us-west-2:DEPLOY_TYPE_DEDICATED:t4g.medium": 1,
						},
						// tidb should not metering storage
						Storages: map[string]*dedicatedv1.ComponentNodeInfo_Component_Storage{
							"data": {
								VolumeType:             dedicatedv1.StorageMu_GP3,
								StorageSizeGi:          sizeGi,
								StorageIops:            iops,
								StorageThroughputMibps: throuput,
								MeteringSkuKeys: map[string]uint32{
									"disk-storage:aws:us-west-2:basicV2:data-disk":        sizeGi,
									"disk-iops:aws:us-west-2:basicV2:data-disk":           iops,
									"disk-throughput:aws:us-west-2:basicV2:data-disk":     throuput,
									"disk-additionaliops:aws:us-west-2:basicV2:data-disk": additionalIops,
								},
							},
						},
					},
				},
				TidbGroupId:          uint64(1213344),
				TidbGroupDisplayName: "aaa",
				IsDefaultTidbGroup:   true,
			},
			{
				Nodes: []*dedicatedv1.ComponentNodeInfo_Component_Node{
					{
						State:                  dedicatedv1.ComponentNodeInfo_Component_Node_AVAILABLE,
						Cpu:                    uint32(4),
						MemorySizeGi:           uint32(8),
						StorageSizeGi:          sizeGi,
						StorageIops:            iops,
						StorageThroughputMibps: throuput,
						InstanceType:           "t4g.large",
						VolumeType:             dedicatedv1.StorageMu_GP3,
						MeteringSkuKeys: map[string]uint32{
							"node:aws:us-west-2:DEPLOY_TYPE_DEDICATED:t4g.large": 1,
						},
						// tidb should not metering storage
						Storages: map[string]*dedicatedv1.ComponentNodeInfo_Component_Storage{
							"data": {
								VolumeType:             dedicatedv1.StorageMu_GP3,
								StorageSizeGi:          sizeGi,
								StorageIops:            iops,
								StorageThroughputMibps: throuput,
								MeteringSkuKeys: map[string]uint32{
									"disk-storage:aws:us-west-2:basicV2:data-disk":        sizeGi,
									"disk-iops:aws:us-west-2:basicV2:data-disk":           iops,
									"disk-throughput:aws:us-west-2:basicV2:data-disk":     throuput,
									"disk-additionaliops:aws:us-west-2:basicV2:data-disk": additionalIops,
								},
							},
						},
					},
				},
				TidbGroupId:          uint64(23432342),
				TidbGroupDisplayName: "bbb",
				IsDefaultTidbGroup:   false,
			},
		},
		Tikv: &dedicatedv1.ComponentNodeInfo_Component{
			Nodes: []*dedicatedv1.ComponentNodeInfo_Component_Node{
				{
					State:                  dedicatedv1.ComponentNodeInfo_Component_Node_AVAILABLE,
					Cpu:                    uint32(2),
					MemorySizeGi:           uint32(4),
					StorageSizeGi:          sizeGi,
					StorageIops:            iops,
					StorageThroughputMibps: throuput,
					InstanceType:           "t4g.medium",
					VolumeType:             dedicatedv1.StorageMu_GP3,
					MeteringSkuKeys: map[string]uint32{
						"node:aws:us-west-2:DEPLOY_TYPE_DEDICATED:t4g.medium": 1,
					},
					Storages: map[string]*dedicatedv1.ComponentNodeInfo_Component_Storage{
						"data": {
							VolumeType:             dedicatedv1.StorageMu_GP3,
							StorageSizeGi:          sizeGi,
							StorageIops:            iops,
							StorageThroughputMibps: throuput,
							MeteringSkuKeys: map[string]uint32{
								"disk-storage:aws:us-west-2:basicV2:data-disk":        sizeGi,
								"disk-iops:aws:us-west-2:basicV2:data-disk":           iops,
								"disk-throughput:aws:us-west-2:basicV2:data-disk":     throuput,
								"disk-additionaliops:aws:us-west-2:basicV2:data-disk": additionalIops,
							},
						},
					},
				},
				{
					State:                  dedicatedv1.ComponentNodeInfo_Component_Node_DELETING,
					Cpu:                    uint32(2),
					MemorySizeGi:           uint32(4),
					StorageSizeGi:          sizeGi,
					StorageIops:            iops,
					StorageThroughputMibps: throuput,
					InstanceType:           "t4g.medium",
					VolumeType:             dedicatedv1.StorageMu_GP3,
					MeteringSkuKeys: map[string]uint32{
						"node:aws:us-west-2:DEPLOY_TYPE_DEDICATED:t4g.medium": 1,
					},
					//for node may only scaling storage
					Storages: map[string]*dedicatedv1.ComponentNodeInfo_Component_Storage{
						"data": {
							VolumeType:             dedicatedv1.StorageMu_GP3,
							StorageSizeGi:          sizeGi + 10,
							StorageIops:            iops + 1000,
							StorageThroughputMibps: throuput,
							MeteringSkuKeys: map[string]uint32{
								"disk-storage:aws:us-west-2:basicV2:data-disk":        sizeGi + 10,
								"disk-iops:aws:us-west-2:basicV2:data-disk":           iops + 1000,
								"disk-throughput:aws:us-west-2:basicV2:data-disk":     throuput,
								"disk-additionaliops:aws:us-west-2:basicV2:data-disk": additionalIops,
							},
						},
					},
				},
				{
					State:                  dedicatedv1.ComponentNodeInfo_Component_Node_UNAVAILABLE,
					Cpu:                    uint32(2),
					MemorySizeGi:           uint32(4),
					StorageSizeGi:          sizeGi,
					StorageIops:            iops,
					StorageThroughputMibps: throuput,
					InstanceType:           "t4g.medium",
					VolumeType:             dedicatedv1.StorageMu_GP3,
					MeteringSkuKeys: map[string]uint32{
						"node:aws:us-west-2:DEPLOY_TYPE_DEDICATED:t4g.medium": 1,
					},
				},
				{
					State:                  dedicatedv1.ComponentNodeInfo_Component_Node_UNAVAILABLE,
					Cpu:                    uint32(0),
					MemorySizeGi:           uint32(0),
					StorageSizeGi:          sizeGi,
					StorageIops:            iops,
					StorageThroughputMibps: throuput,
					InstanceType:           "",
					VolumeType:             dedicatedv1.StorageMu_GP3,
					MeteringSkuKeys: map[string]uint32{
						"node:aws:us-west-2:DEPLOY_TYPE_DEDICATED:PENDING": 1,
					},
				},
				{
					State:                  dedicatedv1.ComponentNodeInfo_Component_Node_CREATING,
					Cpu:                    uint32(2),
					MemorySizeGi:           uint32(4),
					StorageSizeGi:          sizeGi,
					StorageIops:            iops,
					StorageThroughputMibps: throuput,
					InstanceType:           "t4g.medium",
					VolumeType:             dedicatedv1.StorageMu_GP3,
					MeteringSkuKeys: map[string]uint32{
						"node:aws:us-west-2:DEPLOY_TYPE_DEDICATED:t4g.medium": 1,
					},
				},
			},
		},
		Tiflash: &dedicatedv1.ComponentNodeInfo_Component{
			Nodes: []*dedicatedv1.ComponentNodeInfo_Component_Node{
				{
					State:                  dedicatedv1.ComponentNodeInfo_Component_Node_AVAILABLE,
					Cpu:                    uint32(2),
					MemorySizeGi:           uint32(4),
					StorageSizeGi:          sizeGi,
					StorageIops:            iops,
					StorageThroughputMibps: throuput,
					InstanceType:           "t4g.medium",
					VolumeType:             dedicatedv1.StorageMu_GP3,
					MeteringSkuKeys: map[string]uint32{
						"node:aws:us-west-2:DEPLOY_TYPE_DEDICATED:t4g.medium": 1,
					},
				},
			},
		},
		Tiproxy: []*dedicatedv1.ComponentNodeInfo_Component{
			{
				Nodes: []*dedicatedv1.ComponentNodeInfo_Component_Node{
					{
						State:                  dedicatedv1.ComponentNodeInfo_Component_Node_AVAILABLE,
						Cpu:                    uint32(2),
						MemorySizeGi:           uint32(4),
						StorageSizeGi:          sizeGi,
						StorageIops:            iops,
						StorageThroughputMibps: throuput,
						InstanceType:           "t4g.medium",
						VolumeType:             dedicatedv1.StorageMu_GP3,
						MeteringSkuKeys: map[string]uint32{
							"tiproxy:aws:us-west-2:DEPLOY_TYPE_DEDICATED:t4g.medium": 1,
						},
					},
				},
			},
		},
	}

	return componentInfo
}
