package config

type FeatureGateName string

type ExpFeatureGate struct {
	Name              string `json:"name"`
	MinSupportVersion string `json:"minSupportVersion"`
	Command           string `json:"command"`
	FeatureGate       `json:"featureGate"`
}

// controller related feature gates
const (
	// EnableDPCompatibilityMode specifies whether to enable compatibility mode for data plane.
	EnableDPCompatibilityMode = "enable_dp_compatibility_mode"
)

// cluster related feature gates
const (
	// UseProxyGatewayIngress specifies whether to use proxy gateway ingress url as proxy base url.
	UseProxyGatewayIngress = "use_proxy_gateway_ingress"

	// SetPriorityClass specifies whether to set a priority class for tidb clusters.
	SetPriorityClass = "set_priority_class"

	// UseTiDBOperatorV2 specifies whether to use TiDB Operator v2 to manager tidb clusters.
	UseTiDBOperatorV2 = "use_tidb_operator_v2"

	// UseVolumeAttributesClass specifies whether to use VAC to modify volumes in tidb operator v2.
	UseVolumeAttributesClass = "use_volume_attributes_class"

	// EnableGracefulShutdownForExisting specifies whether to enable graceful shutdown for existing tidb clusters.
	EnableGracefulShutdownForExisting = "enable_graceful_shutdown_for_existing_clusters"

	// RemoveNEGAnnotationForExisting specifies whether to remove NEG annotation for GCP LB loadbalancer type services.
	RemoveNEGAnnotationForExisting = "remove_neg_annotation_for_existing_clusters"

	// NormalizeLastAppliedConfiguration specifies whether to omit dynamic fields from last-applied configurations.
	NormalizeLastAppliedConfiguration = "normalize_last_applied_configuration"
)

// network related feature gates
const (
	NetworkHibernation FeatureGateName = "network_hibernation"

	// Extend GKE CIDR per node in gke to 16
	// It will increase the number of pods per node in GKE, but reduce the size of the cluster
	ExtendGKECIDRPerNodeTo16 = "extend_gke_cidr_per_node_to_16"

	// Set the placeholder bit to 1 to avoid CIDR overlap
	// Only used for GCP migration
	// For more information: https://pingcap.feishu.cn/wiki/wikcnPjWiguDcqMxDbFVMBSmNMc
	SetGKECIDRPlaceholder = "set_gke_cidr_placeholder"

	// SplitCSIDaemonSet specifies whether to split ebs csi daemonset into two daemonsets.
	SplitCSIDaemonSet = "split_csi_daemonset"

	// DisableGKELogging specifies whether to disable GKE logging service for newly created GKE clusters.
	DisableGKELogging = "disable_gke_logging"

	// DisableGKEMonitoring specifies whether to disable GKE monitoring service for newly created GKE clusters.
	DisableGKEMonitoring = "disable_gke_monitoring"

	// EnableEthtoolCollecter specifies whether to enable ethtool collector in node exporter.
	EnableEthtoolCollecter = "enable_ethtool_collecter"

	// AllocateSharedBucket specifies whether to allocate shared bucket for clusters.
	AllocateSharedBucket = "allocate_shared_bucket"

	// Allocate more CIDRs for psc nat subnets
	// For more information: https://pingcap.feishu.cn/wiki/HSF4woLAViypk3kCOFfcaOZOnue?from=from_copylink
	AllocateMoreNATs = "allocate_more_nats"
)

// regional-server related feature gates
const (
	// Whether to deploy TiDB Operator v2 (CRD & deployment).
	// In the first phase, we will only deploy TiDB Operator v2 in the new K8s clusters.
	// Later when we migrate TiDB Operator v1 to v2, we will deploy TiDB Operator v2 in existing clusters.
	DeployTiDBOperatorV2 FeatureGateName = "deploy_tidb_operator_v2"

	// UpdateLegacyNodeRolePolicy specifies whether to update the legacy node role policy.
	UpdateLegacyNodeRolePolicy = "update_legacy_node_role_policy"

	// O11yNewAgentController specifies whether to use the new O11y agent controller.
	O11yNewAgentController = "o11y_new_agent_controller"
)

type FeatureGate struct {
	// If `All` is true, this feature gate will be enabled for all except DisabledTenants and DisabledProjects.
	// If `All` is false, this feature gate will be disabled for all except EnabledTenants and EnabledProjects.
	All bool `json:"all"`
	// Enable the feature for the specified tenants.
	EnabledTenants []UintOrString `json:"enabledTenants"`
	// Enable the feature for the specified projects.
	EnabledProjects []UintOrString `json:"enabledProjects"`
	// Disable the feature for the specified tenants.
	DisabledTenants []UintOrString `json:"disabledTenants"`
	// Disable the feature for the specified projects.
	DisabledProjects []UintOrString `json:"disabledProjects"`
}

func FeatureEnabled(featureGates map[FeatureGateName]FeatureGate, featureName FeatureGateName, tenant, project string) bool {
	gates, ok := featureGates[featureName]
	if !ok {
		return false
	}
	return IsFeatureEnabled(gates, tenant, project)
}

func IsFeatureEnabled(gates FeatureGate, tenant, project string) bool {
	// Check if it's enabled for all.
	if gates.All {
		// Check if it's disabled for the tenant.
		for _, tid := range gates.DisabledTenants {
			if tenant == string(tid) {
				return false
			}
		}
		// Check if it's disabled for the project.
		for _, pid := range gates.DisabledProjects {
			if project == string(pid) {
				return false
			}
		}
		return true
	} else {
		// Check if it's enabled for the tenant.
		for _, tid := range gates.EnabledTenants {
			if tenant == string(tid) {
				return true
			}
		}
		// Check if it's enabled for the project.
		for _, pid := range gates.EnabledProjects {
			if project == string(pid) {
				return true
			}
		}
		return false
	}
}
