package domain

import (
	"fmt"

	"github.com/tidbcloud/core-svc/idl/pbgen/proto/core"
	"github.com/tidbcloud/dataflow-service/app/repo/entity"
	"google.golang.org/protobuf/types/known/structpb"
	corev1 "k8s.io/api/core/v1"
)

type TiCDCClusterBizType string

const (
	TiCDCClusterBizTypeRecoveryGroup TiCDCClusterBizType = "recovery_group"
	TiCDCClusterBizTypeChangefeed    TiCDCClusterBizType = "changefeed"
)

type Taint struct {
	Effect TaintEffectType
	Key    string
	Value  string
}

type TaintEffectType string

const (
	TaintEffectNoSchedule       TaintEffectType = "NoSchedule"
	TaintEffectPreferNoSchedule TaintEffectType = "PreferNoSchedule"
	TaintEffectNoExecute        TaintEffectType = "NoExecute"
)

func ConvertTaintEffectToK8s(effectType TaintEffectType) corev1.TaintEffect {
	switch effectType {
	case TaintEffectNoSchedule:
		return corev1.TaintEffectNoSchedule
	case TaintEffectPreferNoSchedule:
		return corev1.TaintEffectPreferNoSchedule
	case TaintEffectNoExecute:
		return corev1.TaintEffectNoExecute
	default:
		return corev1.TaintEffectNoSchedule
	}
}

type CreateTiCDCClusterReq struct {
	// used by ticdc cluster migration tool
	UseNewCdcKernel bool

	InfraProviderType string
	CloudAccountID    string

	ProjectID  uint64
	TenantID   uint64
	ClusterID  uint64
	BizType    TiCDCClusterBizType
	Region     string
	Name       string
	DeployType entity.TiCDCClusterDeployType

	SpecificationCode string
	Version           string
}

type CreateTiCDCClusterResp struct {
	ID         uint64
	WorkflowID string
}

type QueryTiCDCClusterReq struct {
	ID   uint64
	Name string
}

type QueryTiCDCClusterResp struct {
	TiCDCClusterEntity *entity.TiCDCCluster
}

type DeleteTiCDCClusterReq struct {
	ID uint64
}

type DeleteTiCDCClusterResp struct {
	WorkflowID string
}

type ScaleTiCDCClusterReq struct {
	ID uint64

	SpecificationCode string
}

type ScaleTiCDCClusterResp struct {
	WorkflowID string
}

type ApplyTiCDCClusterConfigReq struct {
	TiCDCClusterID uint64
}

type ListTiCDCClustersReq struct {
	TiDBClusterID uint64
}

type ListTiCDCClustersResp struct {
	Items []entity.TiCDCCluster
}

type RestartTiCDCClusterReq struct {
	TiCDCClusterID uint64
}

type GetTiCDCClusterRoleReq struct {
	TenantID      uint64
	ProjectID     uint64
	TiDBClusterID uint64
	Region        string
	CloudProvider CloudProviderType
}

type GetTiCDCClusterRoleResp struct {
	CloudIAMIdentity string
	CloudAccountID   string
	AWSExternalID    string
}

type GetExistingTiCDCClusterVersionReq struct {
	TiCDCClusterID uint64
}

type GetExistingTiCDCClusterVersionResp struct {
	Version string
	NewArch bool
}

type GetNewTiCDCClusterVersionReq struct {
	TenantID           uint64
	ProjectID          uint64
	TiDBClusterID      uint64
	TiDBClusterVersion string
}

type GetNewTiCDCClusterVersionResp struct {
	Version string
	NewArch bool
}

type QuerySpecificationReq struct {
	Code string
}

type QuerySpecificationResp struct {
	Specification *TiCDCClusterSpecification
}

type ListSpecificationsReq struct {
	InfraProviderType *string
}

type ListSpecificationsResp struct {
	Specifications []*TiCDCClusterSpecification
}

type CreateChangefeedReq struct {
	TiCDCClusterID     uint64
	KernelChangefeedID string

	DownStreamType entity.TiCDCChangefeedDownStreamType
	Config         *TiCDCChangefeedConfig
	BizType        TiCDCClusterBizType
	BusinessID     uint64
}

type CreateChangefeedResp struct {
	TiCDCClusterID uint64
	ChangefeedID   uint64
}

type DeleteChangefeedReq struct {
	ChangefeedID uint64
}

type DeleteChangefeedResp struct{}

type MarkChangefeedDeletedReq struct {
	ChangefeedID uint64
}

type MarkChangefeedDeletedResp struct{}

type ListChangefeedsReq struct {
	Filter *ListChangefeedFilter
	Pager  *Pager
}

type ListChangefeedFilter struct {
	TiCDCClusterIDs []uint64
	ChangefeedIDs   []uint64
	Deleted         bool
	BizType         *TiCDCClusterBizType
	BusinessIDs     []uint64
}

type ListChangefeedsResp struct {
	Items []ListChangefeedItem
	Total int64
}

type ListChangefeedItem struct {
	ChangefeedEntity entity.TiCDCChangefeed
}

type PauseChangefeedReq struct {
	ChangefeedID uint64
}

type PauseChangefeedResp struct{}

type ResumeChangefeedReq struct {
	ChangefeedID uint64
}

type ResumeChangefeedResp struct{}

type ModifyChangefeedConfigReq struct {
	ChangefeedID uint64

	Config *TiCDCChangefeedConfig
}

type ModifyChangefeedConfigResp struct{}

type QueryChangefeedReq struct {
	Filter *ListChangefeedFilter
}

type QueryChangefeedResp struct {
	ChangefeedEntity entity.TiCDCChangefeed
	Config           *TiCDCChangefeedConfig
}

type TiCDCChangefeedConfig struct {
	URIConfig TiCDCChangefeedURIConfig
	Config    *TiCDCChangefeedConfigData
}

type MeterChangefeedTrafficReq struct {
	ChangefeedId               uint64
	ChangefeedKernelId         string
	BizType                    entity.KernelTrafficBizType
	PrimaryCluster             *core.Cluster
	InfoMap                    entity.ChangefeedTrafficExtension
	CloudProviderType          entity.CloudProviderType
	SecondaryCloudProviderType entity.CloudProviderType
	SecondaryRegion            string
}

type MeterChangefeedTrafficResp struct {
	MeterRecord *entity.KernelChangefeedTrafficRecord
}

type GetChangefeedDetailReq struct {
	ChangefeedID entity.ID
}

type GetChangefeedDetailResp struct {
	Changefeed *structpb.Struct
}

type GetChangefeedClusterReq struct {
	ChangefeedID entity.ID
}

type GetChangefeedClusterResp struct {
	TiCDCCluster *structpb.Struct
}

type UpdateTiCDCClusterStorageReq struct {
	TiCDCClusterID uint64
	SizeGi         uint32
	ThroughputMbs  uint32
	Iops           uint32
}
type TiCDCClusterSpecification struct {
	Code     string
	Replicas uint32
	RPSLimit uint32
	RCUNum   uint32
}

func (s *TiCDCClusterSpecification) GetRCUNumber() uint32 {
	if s.RCUNum == 0 {
		panic(fmt.Sprintf("TiCDCClusterSpecification %s has invalid RCUNum 0, please check the data", s.Code))
	}

	return s.RCUNum
}
