package cvt

import (
	"fmt"

	"github.com/tidbcloud/core-svc/idl/pbgen/proto/central"
	"github.com/tidbcloud/core-svc/idl/pbgen/proto/core"
	"github.com/tidbcloud/core-svc/idl/pbgen/proto/dataflow"
	entity "github.com/tidbcloud/core-svc/model"
)

// TODO(Loius): merge them into one definition
func ComponentTypeCore2Central(componentType core.ComponentType) central.ComponentType {
	switch componentType {
	case core.ComponentType_COMPONENT_TYPE_PD:
		return central.ComponentType_COMPONENT_TYPE_PD
	case core.ComponentType_COMPONENT_TYPE_TIDB:
		return central.ComponentType_COMPONENT_TYPE_TIDB
	case core.ComponentType_COMPONENT_TYPE_TIKV:
		return central.ComponentType_COMPONENT_TYPE_TIKV
	case core.ComponentType_COMPONENT_TYPE_TIFLASH:
		return central.ComponentType_COMPONENT_TYPE_TIFLASH
	case core.ComponentType_COMPONENT_TYPE_TICDC:
		return central.ComponentType_COMPONENT_TYPE_TICDC
	}
	panic("unknown componentType")
}

func ComponentTypeCentral2Core(componentType central.ComponentType) core.ComponentType {
	switch componentType {
	case central.ComponentType_COMPONENT_TYPE_PD:
		return core.ComponentType_COMPONENT_TYPE_PD
	case central.ComponentType_COMPONENT_TYPE_TIDB:
		return core.ComponentType_COMPONENT_TYPE_TIDB
	case central.ComponentType_COMPONENT_TYPE_TIKV:
		return core.ComponentType_COMPONENT_TYPE_TIKV
	case central.ComponentType_COMPONENT_TYPE_TIFLASH:
		return core.ComponentType_COMPONENT_TYPE_TIFLASH
	case central.ComponentType_COMPONENT_TYPE_TICDC:
		return core.ComponentType_COMPONENT_TYPE_TICDC
	}
	panic("unknown componentType")
}

func ComponentTypeCentral2Dataflow(componentType central.ComponentType) dataflow.ComponentType {
	switch componentType {
	case central.ComponentType_COMPONENT_TYPE_PD:
		return dataflow.ComponentType_COMPONENT_TYPE_PD
	case central.ComponentType_COMPONENT_TYPE_TIDB:
		return dataflow.ComponentType_COMPONENT_TYPE_TIDB
	case central.ComponentType_COMPONENT_TYPE_TIKV:
		return dataflow.ComponentType_COMPONENT_TYPE_TIKV
	case central.ComponentType_COMPONENT_TYPE_TIFLASH:
		return dataflow.ComponentType_COMPONENT_TYPE_TIFLASH
	case central.ComponentType_COMPONENT_TYPE_TICDC:
		return dataflow.ComponentType_COMPONENT_TYPE_TICDC
	}
	panic(fmt.Sprintf("unknown componentType: %d-%s", componentType, componentType))
}

func ComponentTypeModel2Core(componentName entity.ComponentName) core.ComponentType {
	switch componentName {
	case entity.PD:
		return core.ComponentType_COMPONENT_TYPE_PD
	case entity.TiDB:
		return core.ComponentType_COMPONENT_TYPE_TIDB
	case entity.TiKV:
		return core.ComponentType_COMPONENT_TYPE_TIKV
	case entity.TiFlash:
		return core.ComponentType_COMPONENT_TYPE_TIFLASH
	case entity.TiCDC:
		return core.ComponentType_COMPONENT_TYPE_TICDC
	}
	panic("unknown componentType")
}

func NodeProfileCore2Central(nodeProfile *core.NodeProfile4Tenant) *central.ClusterNodeProfile {
	return &central.ClusterNodeProfile{
		Id:               nodeProfile.Id,
		Name:             nodeProfile.Name,
		DisplayName:      nodeProfile.DisplayName,
		DefaultNodeNum:   nodeProfile.DefaultNodeNum,
		MinStorageSizeGi: nodeProfile.MinStorageSizeGi,
		MaxStorageSizeGi: nodeProfile.MaxStorageSizeGi,
		CpuNum:           nodeProfile.CpuNum,
		MemoryGi:         nodeProfile.MemoryGi,
	}
}

func ClusterComponentsCentral2Core(c []*central.ClusterComponent) []*core.ClusterComponent {
	out := make([]*core.ClusterComponent, 0, len(c))
	for _, each := range c {
		out = append(out, &core.ClusterComponent{
			ComponentType: ComponentTypeCentral2Core(each.ComponentType),
			NodeProfileId: each.NodeProfileId,
			Replicas:      each.Replicas,
			StorageSizeGi: int64(each.StorageSizeGi),
		})
	}
	return out
}

func ClusterComponentsCentral2Dataflow(c []*central.ClusterComponent) []*dataflow.FlatClusterComponent {
	out := make([]*dataflow.FlatClusterComponent, 0, len(c))
	for _, each := range c {
		out = append(out, &dataflow.FlatClusterComponent{
			ComponentType: ComponentTypeCentral2Dataflow(each.ComponentType),
			NodeProfileId: each.NodeProfileId,
			Replicas:      each.Replicas,
			StorageSizeGi: int64(each.StorageSizeGi),
		})
	}
	return out
}

const (
	IamRoleUsageCrossAccount = "Cross-Account Deployment"
)

func CoreIamRoleUsageServiceName2Central(tp core.IamRoleUsage_ServiceName) string {
	switch tp {
	case core.IamRoleUsage_SERVICE_NAME_CROSS_ACCOUNT:
		return IamRoleUsageCrossAccount
	}
	panic(fmt.Sprintf("invalid iam role usage service name, %s", tp))
}
