package v1alpha1

import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

type NodePoolPhase string

const (
	NodePoolPhaseCreating NodePoolPhase = "Creating"
	NodePoolPhaseActive   NodePoolPhase = "Active"
	// Now no actually Failed phase of nodepool.
	// It's hard to ensure an error is unrecoverable.
	// It should be set only if nodepool spec is invalid.
	NodePoolPhaseFailed   NodePoolPhase = "Failed"
	NodePoolPhaseDeleting NodePoolPhase = "Deleting"
)

// +kubebuilder:object:root=true
// +kubebuilder:resource:categories=regionserver
// +kubebuilder:subresource:status
// +kubebuilder:printcolumn:name="INSTANCETYPE",type="string",JSONPath=".spec.instanceType"
// +kubebuilder:printcolumn:name="K8SVERSION",type="string",JSONPath=".spec.kubernetesVersion"
// +kubebuilder:printcolumn:name="DATAPLANE",type="string",JSONPath=".spec.dataPlane.name"
// +kubebuilder:printcolumn:name="PHASE",type="string",JSONPath=".status.phase"
// +kubebuilder:printcolumn:name="AGE",type="date",JSONPath=".metadata.creationTimestamp"
// NodePool is the Schema for the NodePools API
type NodePool struct {
	metav1.TypeMeta   `json:",inline"`
	metav1.ObjectMeta `json:"metadata,omitempty"`

	Spec   NodePoolSpec   `json:"spec,omitempty"`
	Status NodePoolStatus `json:"status,omitempty"`
}

type NodePoolSpec struct {
	ResourceNamePrefix    string    `json:"resourceNamePrefix,omitempty"`
	DataPlane             Reference `json:"dataPlane,omitempty"`
	InstanceType          string    `json:"instanceType,omitempty"`
	KubernetesVersion     string    `json:"kubernetesVersion,omitempty"`
	CpuCore               uint32    `json:"cpuCore,omitempty"`
	AvailableCpuMilliCore uint32    `json:"availableCpuMilliCore,omitempty"`
	// MaxCpuMilli is the CPU resource limit in millicores.
	MaxCpuMilli       uint32 `json:"maxCpuMilli,omitempty"`
	MemoryGi          uint32 `json:"memoryGi,omitempty"`
	AvailableMemoryMi uint32 `json:"availableMemoryMi,omitempty"`
	// MaxMemoryMi is the memory resource limit in MiB.
	MaxMemoryMi     uint32 `json:"maxMemoryMi,omitempty"`
	NodeType        string `json:"nodeType,omitempty"`
	WithLocalDisk   bool   `json:"withLocalDisk,omitempty"`
	LocalDiskSizeGi uint32 `json:"localDiskSizeGi,omitempty"`
	// PlacementGroupEnabled is the durable per-NodePool gate set at
	// NodePool creation and read by the EKS controllers (placementgroup.go,
	// nodegroup.go partition branch) on every reconcile.
	//
	// Source-of-truth chain on the CSNG side (see
	// domain/workflow/action/create_node_instance_group.go):
	//   1. Sibling inheritance: if a non-builtin workload NodePool exists
	//      in the dataplane, the value is inherited from
	//      Spec.PlacementGroupEnabled of the first such sibling.
	//   2. SharedPool gate fallback: otherwise, the value is read from
	//      SharedPool.Provider.PlacementGroupEnabled, which
	//      domain/server/create_sharedpool.go sets from the canonical
	//      "AWS + single-AZ?" check at CreateSharedPool time.
	//
	// DPM CreateNodePool honours this wire value with a topology sanity
	// check — when true, the dataplane must be single-AZ EKS; false is
	// always accepted. The field is set once and never re-derived by the
	// controllers, so legacy single-AZ, PG-disabled pools keep their
	// original false record across reconciles.
	PlacementGroupEnabled bool              `json:"placementGroupEnabled,omitempty"`
	Labels                map[string]string `json:"labels,omitempty"`
	Taints                []NodePoolTaint   `json:"taints,omitempty"`
}

type NodePoolTaint struct {
	Key    string `json:"key,omitempty"`
	Value  string `json:"value,omitempty"`
	Effect string `json:"effect,omitempty"`
}

type NodePoolStatus struct {
	Phase              NodePoolPhase      `json:"phase,omitempty"`
	Reason             string             `json:"reason,omitempty"`
	KubernetesName     string             `json:"kubernetesName,omitempty"`
	Zones              []string           `json:"zones,omitempty"`
	NodeRole           string             `json:"nodeRole,omitempty"`
	CurrentReplicas    uint32             `json:"currentReplicas,omitempty"`
	ObservedGeneration int64              `json:"observedGeneration,omitempty"`
	Conditions         []metav1.Condition `json:"conditions,omitempty"`
}

// +kubebuilder:object:root=true
type NodePoolList struct {
	metav1.TypeMeta `json:",inline"`
	metav1.ListMeta `json:"metadata,omitempty"`
	Items           []NodePool `json:"items"`
}

func init() {
	SchemeBuilder.Register(&NodePool{}, &NodePoolList{})
}
