package cvt

import (
	"fmt"

	"github.com/pingcap/dbaas/central/db/entity"
	"github.com/tidbcloud/idl/pbgen/proto/central"
	"github.com/tidbcloud/idl/pbgen/proto/core"
)

// 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 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,
		DefaultNodeNum:   nodeProfile.DefaultNodeNum,
		MinStorageSizeGi: nodeProfile.MinStorageSizeGi,
		MaxStorageSizeGi: nodeProfile.MaxStorageSizeGi,
		CpuNum:           nodeProfile.CpuNum,
	}
}

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 ClusterComponentModel2Core(c *entity.ClusterComponent) *core.ClusterComponent {
	return &core.ClusterComponent{
		ComponentType: ComponentTypeModel2Core(c.ComponentType),
		NodeProfileId: c.LabelProfileID.Uint64(),
		Replicas:      int32(c.Replicas),
		StorageSizeGi: int64(c.StorageSizeGi),
	}
}

func ClusterComponentState2Core(c []entity.ComponentState) []*core.ClusterComponent {
	out := make([]*core.ClusterComponent, 0, len(c))
	for _, each := range c {
		out = append(out, &core.ClusterComponent{
			ComponentType: ComponentTypeModel2Core(each.ComponentType),
			NodeProfileId: each.LabelProfileID.Uint64(),
			Replicas:      int32(each.Replicas),
			StorageSizeGi: int64(each.StorageSizeGi),
		})
	}
	return out
}

func CoreBackupStatus2Central(backupStatus core.BackupStatus) central.Backup_Status {
	switch backupStatus {
	case core.BackupStatus_BACKUP_STATUS_PENDING:
		return central.Backup_PENDING
	case core.BackupStatus_BACKUP_STATUS_RUNNING:
		return central.Backup_RUNNING
	case core.BackupStatus_BACKUP_STATUS_SUCCESS:
		return central.Backup_SUCCESS
	case core.BackupStatus_BACKUP_STATUS_FAILED:
		return central.Backup_FAILED
	}
	panic(fmt.Sprintf("invalid backup status, %s", backupStatus))
}

func CoreBackupType2Central(tp core.Backup_Type) central.BackupType {
	switch tp {
	case core.Backup_TYPE_AUTO:
		return central.BackupType_AUTO
	case core.Backup_TYPE_MANUAL:
		return central.BackupType_MANUAL
	}
	panic(fmt.Sprintf("invalid backup tp, %s", tp))
}

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))
}
