package config

import "github.com/tidbcloud/infra-provider/pkg/consts"

const (
	// DefaultConnectionDrainingTimeout is the default connection draining timeout for GCP load balancer.
	defaultConnectionDrainingTimeoutForGCP int64 = 15

	// DefaultPreStopSleepSeconds is the default sleep seconds for preStop hook.
	// Note: this value should be at least twice than LB's connection draining timeout.
	DefaultPreStopSleepSeconds int64 = 30
)

type ClusterControllerConfig struct {
	Provider string `json:"provider"`
	Region   string `json:"region"`

	// Reconciler is the value for cloud.pingcap.com/reconciler label
	// It's used during testing to make Cluster CR reconciled by a specific controller
	Reconciler string `json:"reconciler"`

	// Concurrency is the controller concurrency
	Concurrency int `json:"concurrency"`

	// Some storageclasses will not be used by tidb-mgmt, but will be used by cluster component, such as tidb `index-acceleration`
	// We don't want to hardcode it
	// In the future these might be all passed by tidb-mgmt to support billing, so at the moment we config it here
	// To avoid restarting the cluster-controller when adding a new storageclass, this config file is re-read everytime we need to sync storageclass
	// This is a poor-man's version of hot-reload implementation and might be a performance issue when there are lots of clusters to be created, but should work well for our current scale
	StorageClassConfigFile string `json:"storageClassConfigFile"`

	// InstanceTypeConfigFile is the config file that declares the available cpu and memory of instance types
	InstanceTypeConfigFile string `json:"instanceTypeConfigFile"`

	// ControlplaneProviderConfig is the name of crossplane ProviderConfig CR
	// This ProviderConfig is used to provision controlplane resources.
	// For example, we need to use this ProviderConfig to grant dataplane node to access container registry in controlplane account
	ControlplaneProviderConfig string `json:"controlplaneProviderConfig"`

	// DataplaneKubeconfig is the path of dataplane kubeconfig
	// It's used for local testing, such as KinD environment
	DataplaneKubeconfig string `json:"dataplaneKubeconfig"`

	// HostedZoneDomain is the suffix domain name for tidb cluster external endpoints
	HostedZoneDomain string `json:"hostedZoneDomain"`
	// HostedZoneID is the id of AWS Route53 hosted zone for the DNS
	HostedZoneID string `json:"hostedZoneID"`

	// ConfigChange is the ConfigChange controller configurations
	ConfigChange ConfigChangeConfig `json:"configChange"`

	// AWS is the AWS specific configurations
	AWS AWSConfig `json:"aws,omitempty"`
	// GCP is the GCP specific configurations
	GCP GCPConfig `json:"gcp,omitempty"`
	// Azure is the Azure specific configurations
	Azure AzureConfig `json:"azure,omitempty"`

	// Audit is the audit log sidecar configuration
	Audit AuditConfig `json:"audit"`
	// ClusterAgent is the cluster agent deployment configuration
	ClusterAgent ClusterAgentConfig `json:"clusterAgent"`

	// TiKVPreStopImage is the image used for TiKV pre-stop hook.
	// It's only used in TiDB Operator v2.
	TiKVPreStopImage string `json:"tikvPreStopImage"`

	// TiDBPreStopHookSleepSeconds is the sleep seconds for TiDB pre-stop hook.
	// Normally, it should be at least twice than LB's connection draining timeout.
	TiDBPreStopHookSleepSeconds *int64 `json:"tidbPreStopHookSleepSeconds,omitempty"`
}

func (ccf ClusterControllerConfig) GetTiDBPreStopHookSleepSeconds() int64 {
	if ccf.TiDBPreStopHookSleepSeconds != nil {
		return *ccf.TiDBPreStopHookSleepSeconds
	}
	return DefaultPreStopSleepSeconds
}

func (ccf ClusterControllerConfig) GetLBConnectionDrainingTimeout(provider string) int64 {
	switch provider {
	case consts.ProviderTypeGKE:
		if ccf.GCP.LoadBalancerConnectionDrainingTimeout != nil {
			return *ccf.GCP.LoadBalancerConnectionDrainingTimeout
		}
		return defaultConnectionDrainingTimeoutForGCP
	}
	return 0
}

type AWSConfig struct {
	// AccountID is the controlplane AWS account ID
	// We can use this to retrieve the resource name or ARN in controlplane AWS account
	AccountID string `json:"accountID"`

	// NodeRolePolicyFile is the file name of the permission policy attached to node role
	NodeRolePolicyFile string `json:"nodeRolePolicyFile"`
	// NodeRoleManagedPolicies are the extra AWS Managed policies that need to attach to node role
	NodeRoleManagedPolicies []string `json:"nodeRoleManagedPolicies"`

	// NodeUserdataSystemConfigurationFile is the file name of the node operating system configuration userdata
	NodeUserdataSystemConfigurationFile string `json:"nodeUserdataSystemConfigurationFile"`

	// NodeCapacityType specifies whether to use SPOT or ON_DEMAND instance type for worker nodegroup
	// Note: SPOT MUST only be used in testing environment
	NodeCapacityType string `json:"nodeCapacityType"`

	// PreferSubnetIndex is the index of the subnet to prefer for the nodegroup
	// If the index is out of range, the default subnet will be used
	// Default is 0
	PreferSubnetIndex int `json:"preferSubnetIndex"`

	// TODO: CJL remove me after release finish
	// EnableBatchOpsExport Create Batchops role based on config
	EnableBatchOpsExport bool `json:"enableBatchOpsExport"`
}

type GCPConfig struct {
	// ProjectID is the controlplane GCP Project ID
	// We can use this to retrieve the resource name in controlplane GCP project
	ProjectID string `json:"projectID"`

	// GlobalCrossplaneProviderConfig is the name of crossplane ProviderConfig CR
	// This ProviderConfig is used to provision global resources on AWS such as Route53, PCA
	GlobalCrossplaneProviderConfig string `json:"globalCrossplaneProviderConfig"`

	// LoadBalancerConnectionDrainingTimeout is the connection draining timeout for GCP load balancer.
	// The number of seconds a draining instance will wait for in-flight connections to complete. Instances do not accept new requests during a connection drain.
	LoadBalancerConnectionDrainingTimeout *int64 `json:"loadBalancerConnectionDrainingTimeout,omitempty"`
}

type AzureConfig struct {
	// Crossplane Managed Identity Configurations for crossplane providerconfig construction
	CrossplaneAzureProviderSubscriptionID          string `json:"crossplaneAzureProviderSubscriptionID"`
	CrossplaneAzureProviderDataPlaneSubscriptionID string `json:"crossplaneAzureProviderDataPlaneSubscriptionID"`
	CrossplaneAzureProviderTenantID                string `json:"crossplaneAzureProviderTenantID"`
	CrossplaneAzureProviderClientID                string `json:"crossplaneAzureProviderClientID"`
	Zone                                           string `json:"zone"`
	ControlPlaneResourceGroup                      string `json:"controlPlaneResourceGroup"`
}
