package v1alpha1

import (
	corev1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

const (
	AnnotationKeyOwnImageTagDataflowAgent  = "cloud.pingcap.com/own-image-tag-dataflow-agent"
	AnnotationKeyOwnImageTagTiFlowOperator = "cloud.pingcap.com/own-image-tag-tiflow-operator"
	AnnotationKeyOwnImageTagClusterProxy   = "cloud.pingcap.com/own-image-tag-cluster-proxy"
	AnnotationKeyOwnImageTagSLIReporter    = "cloud.pingcap.com/own-image-tag-sli-reporter"
	AnnotationKeyOwnSpecMaxPodsPerNode     = "cloud.pingcap.com/own-spec-maxpodspernode"
	// aws-ebs-csi-driver is a special case, we cannot use addon directly, so just skip the status checking
	// see the AnnotaionK

	// for migrate on aws and gcp, this anno is only used to overwrite the providerconfig value in eks and gke cr.
	AnnotationKeyOwnCrossplaneNameProvidreConfig = "cloud.pingcap.com/own-crossplane-name-providerconfig"
	// for migrate on aws
	AnnotationKeyOwnCrossplaneNameEKS             = "cloud.pingcap.com/own-crossplane-name-eks"
	AnnotationKeyOwnCrossplaneNameIAMRole         = "cloud.pingcap.com/own-crossplane-name-iamrole"
	AnnotationKeyOwnCrossplaneNameInstanceProfile = "cloud.pingcap.com/own-crossplane-name-instanceprofile"
	AnnotationKeyOwnCrossplaneNameNodeGroup       = "cloud.pingcap.com/own-crossplane-name-nodegroup"
	// for migrate on gcp
	AnnotationKeyOwnCrossplaneNameServiceAccount       = "cloud.pingcap.com/own-crossplane-name-serviceaccount"
	AnnotationKeyOwnCrossplaneNameServiceAccountKey    = "cloud.pingcap.com/own-crossplane-name-serviceaccountkey"
	AnnotationKeyOwnCrossplaneNameServiceAccountPolicy = "cloud.pingcap.com/own-crossplane-name-serviceaccountpolicy"
	AnnotationKeyOwnCrossplaneNameGKE                  = "cloud.pingcap.com/own-crossplane-name-gke"
	AnnotationKeyOwnCrossplaneNameNodePool             = "cloud.pingcap.com/own-crossplane-name-nodepool"
	AnnotationKeyOwnCrossplaneNameOIDCProvider         = "cloud.pingcap.com/own-crossplane-name-oidcprovider"
	AnnotationKeyOwnCrossplaneNameIAMRolePCAIssuer     = "cloud.pingcap.com/own-crossplane-name-iamrole-pcaissuer"
	AnnotationKeyOwnCrossplaneNameIAMRoleSLIReporter   = "cloud.pingcap.com/own-crossplane-name-iamrole-slireporter"
)

const (
	// value is "ture" or "false"
	AnnotationKeyLegacyAPPBoxSkipEKSTask              = "cloud.pingcap.com/legacy-appbox-skip-eks-task"
	AnnotationKeyLegacyAPPBoxSkipGKETask              = "cloud.pingcap.com/legacy-appbox-skip-gke-task"
	AnnotationKeyLegacyAPPBoxSkipAddonAWSEBSCSIDriver = "cloud.pingcap.com/legacy-appbox-skip-addon-csi"        // to control addon aws-ebs-csi-driver
	AnnotationKeyLegacyAPPBoxSkipAddonCoreDNS         = "cloud.pingcap.com/legacy-appbox-skip-addon-coredns"    // to control addon aws-ebs-csi-driver
	AnnotationKeyLegacyAPPBoxSkipAddonKubeProxy       = "cloud.pingcap.com/legacy-appbox-skip-addon-kube-proxy" // to control addon aws-ebs-csi-driver
	AnnotationKeyLegacyAPPBoxSkipAddonVPCCNI          = "cloud.pingcap.com/legacy-appbox-skip-addon-vpc-cni"    // to control addon aws-ebs-csi-driver
)

const (
	// used to disable tiflow operator, default is false.
	// If set to true, the tiflow operator will not be installed.
	AnnotationKeyDisableTiflowOperator = "cloud.pingcap.com/disable-tiflow-operator"
)

const (
	// AnnotationKeyEnableGoldpinger controls whether goldpinger is deployed on this APPBox.
	// Goldpinger is only deployed when this annotation is set to "true" (opt-in).
	AnnotationKeyEnableGoldpinger      = "cloud.pingcap.com/enable-goldpinger"
	AnnotationKeyEnableNodePinger      = "cloud.pingcap.com/enable-node-pinger"
	AnnotationKeyEnableCapacityPlanner = "cloud.pingcap.com/enable-capacity-planner"
	// AnnotationKeyEnableAKSAPIServerVNetIntegration opts existing non-BYOC AKS APPBoxes into API server VNet integration.
	AnnotationKeyEnableAKSAPIServerVNetIntegration = "cloud.pingcap.com/enable-aks-apiserver-vnet-integration"
	// AnnotationKeyAKSAPIServerVNetIntegrationRequested marks AKS clusters where the controller has requested API server VNet integration.
	AnnotationKeyAKSAPIServerVNetIntegrationRequested = "cloud.pingcap.com/aks-apiserver-vnet-integration-requested"
)

const (
	// AnnotationKeyUpgradeTrigger is used to trigger a reconciliation of the APPBox.
	// This forces the controller to re-evaluate and potentially upgrade the APPBox.
	// Value is the trigger time.
	AnnotationKeyUpgradeTrigger = "cloud.pingcap.com/upgrade-trigger-"

	// AnnotationKeyUpgradeAddonsFixed indicates whether the addons have been successfully
	// upgraded and fixed. When set to "true", the upgrade process will skip addon fixes
	// since they have already been completed.
	AnnotationKeyUpgradeAddonsFixed = "cloud.pingcap.com/upgrade-addons-fixed"

	// AnnotationKeyUpgradeRebuildAddon tracks the progress of rebuilding individual addons
	// during an upgrade. The full annotation key includes the addon name, e.g:
	// "cloud.pingcap.com/upgrade-rebuild-aws-ebs-csi-driver"
	AnnotationKeyUpgradeRebuildAddon = "cloud.pingcap.com/upgrade-rebuild-"

	// AnnotationValueUpgradeStepRemoveResource indicates that an addon resource has been
	// removed as part of the upgrade process and is ready for rebuilding.
	AnnotationValueUpgradeStepRemoveResource = "remove-resource"

	// AnnotationValueUpgradeStepRebuildResource indicates that an addon resource has been
	// successfully rebuilt with the updated configuration.
	AnnotationValueUpgradeStepRebuildResource = "rebuild-resource"
)

// EDIT THIS FILE!  THIS IS SCAFFOLDING FOR YOU TO OWN!
// NOTE: json tags are required.  Any new fields you add must have json tags for the fields to be serialized.

// +kubebuilder:object:root=true
// +kubebuilder:resource:categories=regionserver
// +kubebuilder:subresource:status
// +kubebuilder:printcolumn:name="PHASE",type="string",JSONPath=".status.phase"
// +kubebuilder:printcolumn:name="K8SVERSION",type="string",JSONPath=".spec.kubernetesConfig.version"
// +kubebuilder:printcolumn:name="AGE",type="date",JSONPath=".metadata.creationTimestamp"
// APPBox is the Schema for the appboxes API
type APPBox struct {
	metav1.TypeMeta   `json:",inline"`
	metav1.ObjectMeta `json:"metadata,omitempty"`

	Spec   APPBoxSpec   `json:"spec,omitempty"`
	Status APPBoxStatus `json:"status,omitempty"`
}

// APPBoxSpec defines the desired state of APPBox
type APPBoxSpec struct {
	Region string `json:"region"`

	Provider string `json:"provider"`

	KubernetesConfig KubernetesConfig `json:"kubernetesConfig"`

	PCA *PCAConfig `json:"pca,omitempty"`

	VPCRef *Reference `json:"vpcRef"`
}

type KubernetesConfig struct {
	// The Kubernetes version of the cluster.
	Version     string `json:"version"`
	ServiceCidr string `json:"serviceCidr"`
	// +optional
	AddonTemplateID string `json:"addonTemplateId"`
	// +optional
	InfraTemplateID string `json:"infraTemplateId"`
	// +optional
	DedicatedTemplateID string `json:"dedicatedTemplateId"`
	// +optional
	DPTemplateID string `json:"dpTemplateId"`
	// +optional
	AdminNodeConfig NodeConfig `json:"adminNodeConfig"`
}

type NodeConfig struct {
	// +optional
	InstanceType string `json:"instanceType"`
	// +optional
	MaxSize *int32 `json:"maxSize"`
	// +optional
	MinSize *int32 `json:"minSize"`
	// +optional
	SystemVolumeSize *int64 `json:"systemVolumeSize"`
	// +optional
	AdditionalInstanceTypes []string `json:"additionalInstanceTypes,omitempty"`
}

// APPBoxStatus defines the observed state of APPBox
type APPBoxStatus struct {
	// +optional
	Phase APPBoxPhase `json:"phase,omitempty"`
	// +optional
	Reason string `json:"reason,omitempty"`
	// +optional
	KubernetesClusterName string `json:"kubernetesClusterName,omitempty"`
	// +optional
	KubernetesClusterID string `json:"kubernetesClusterID,omitempty"`
	// +optional
	ProxyBaseUrl string `json:"proxyBaseUrl,omitempty"`
	// +optional
	DataflowAgentUrl string `json:"dataflowAgentUrl,omitempty"`
	// +optional
	GatewayBaseUrl string `json:"gatewayBaseUrl,omitempty"`
	// +optional
	Addons []AddonStatus `json:"addons,omitempty"`
	// +patchMergeKey=type
	// +patchStrategy=merge
	// +optional
	Conditions Conditions `json:"conditions,omitempty"`
	// +optional
	IAM IAMStatus `json:"iam,omitempty"`
	// Azure only
	// +optional
	NodeRoleAssignments []RoleAssignmentStatus `json:"nodeRoleAssignments,omitempty"`
	// Azure only
	// deprecated, use NodeRoleAssignments
	// +optional
	ACRRoleAssignments []RoleAssignmentStatus `json:"acrRoleAssignments,omitempty"`
	// Azure only
	// deprecated, use NodeRoleAssignments
	// +optional
	VNetRoleAssignments []RoleAssignmentStatus `json:"vnetRoleAssignments,omitempty"`
	// KubeConfigSecretRef is the reference to the secret that contains the kubeconfig of the cluster.
	// Currently, it is only used for AKS.
	// +optional
	KubeConfigSecretRef *corev1.SecretReference `json:"kubeConfigSecretRef,omitempty"`
}

type RoleAssignmentStatus struct {
	// +optional
	Name string `json:"name,omitempty"`
	// +optional
	ID string `json:"id,omitempty"`
	// +optional
	PrincipalID string `json:"principalID,omitempty"`
	// +optional
	RoleDefinitionName string `json:"roleDefinitionName,omitempty"`
	// +optional
	Scope string `json:"scope,omitempty"`
}

type IAMStatus struct {
	// +optional
	// NodeRoleARN is the ARN of the instance profile that is associated with the EKS admin nodes.
	NodeRoleARN string `json:"nodeRoleARN,omitempty"`

	// +optional
	// NodeRoleName is the name of the instance profile that is associated with the ACK admin nodes.
	NodeRoleName string `json:"nodeRoleName,omitempty"`

	// +optional
	// WorkerNodeRoleARN is the ARN of the instance profile that is associated with the EKS worker nodes.
	WorkerNodeRoleARN string `json:"workerNodeRoleARN,omitempty"`

	// +optional
	// ServiceAccountEmail is the key of the service account that is associated with the GKE admin nodes.
	ServiceAccountEmail string `json:"serviceAccountEmail,omitempty"`

	// +optional
	// KubeletIdentityClientID is the client ID of the kubelet identity that is associated with the AKS admin nodes.
	KubeletIdentityClientID string `json:"kubeletIdentityClientID,omitempty"`

	// +optional
	// KubeletIdentityObjectID is the object ID of the kubelet identity that is associated with the AKS admin nodes.
	KubeletIdentityObjectID string `json:"kubeletIdentityObjectID,omitempty"`
}

type AddonStatus struct {
	// +optional
	Version string `json:"version,omitempty"`

	// +optional
	Name string `json:"name,omitempty"`
}

type APPBoxPhase string

const (
	APPBoxPhasePending        APPBoxPhase = "Pending"
	APPBoxPhaseCreating       APPBoxPhase = "Creating"
	APPBoxPhaseFailed         APPBoxPhase = "Failed"
	APPBoxPhaseActive         APPBoxPhase = "Active"
	APPBoxPhaseReadyForDelete APPBoxPhase = "ReadyForDelete"
	APPBoxPhaseDeleting       APPBoxPhase = "Deleting"
)

const (
	APPBoxConditionK8SReady             string = "K8sReady"
	APPBoxConditionNodeGroupReady       string = "NodeGroupReady"
	APPBoxConditionWorkerNodeGroupReady string = "WorkerNodeGroupReady"
	APPBoxConditionSharedNodeGroupReady string = "SharedNodeGroupReady"
)

// +kubebuilder:object:root=true

// APPBoxList contains a list of APPBox
type APPBoxList struct {
	metav1.TypeMeta `json:",inline"`
	metav1.ListMeta `json:"metadata,omitempty"`
	Items           []APPBox `json:"items"`
}

func init() {
	SchemeBuilder.Register(&APPBox{}, &APPBoxList{})
}
