package v1alpha1

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

// 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="AGE",type="date",JSONPath=".metadata.creationTimestamp"
// LoadBalancer is the Schema for the loadbalancer API
type LoadBalancer struct {
	metav1.TypeMeta   `json:",inline"`
	metav1.ObjectMeta `json:"metadata,omitempty"`

	Spec   LoadBalancerSpec   `json:"spec,omitempty"`
	Status LoadBalancerStatus `json:"status,omitempty"`
}

type LoadBalancerType string

const (
	PublicLoadBalancerType  LoadBalancerType = "public"
	PrivateLoadBalancerType LoadBalancerType = "private"
)

// LoadBalancerSpec defines the desired state of LoadBalancer
// +kubebuilder:validation:XValidation:rule="has(self.ownership) == has(oldSelf.ownership) && (!has(self.ownership) || self.ownership == oldSelf.ownership)",message="ownership is immutable"
type LoadBalancerSpec struct {
	DataPlane   Reference        `json:"dataPlane,omitempty"`
	Identity    string           `json:"identity"`
	SubIdentity string           `json:"subIdentity,omitempty"`
	Namespace   string           `json:"namespace"`
	Type        LoadBalancerType `json:"type"`
	// Deprecated: prefer Ports for multi-port LBs. Kept for backward
	// compatibility with existing (single-port) CRs such as tiproxy and
	// per-TiDBGroup private/public LBs.
	// +optional
	Port     int32             `json:"port,omitempty"`
	Selector map[string]string `json:"selectors"`
	// +optional
	Tags map[string]string `json:"tags"`
	// +optional
	IpWhiteList []string `json:"ipWhiteList"`
	// Ports overrides Port when non-empty. Each entry produces one listener
	// on the cloud LB and one Kubernetes ServicePort.
	// +optional
	Ports []LoadBalancerPort `json:"ports,omitempty"`
	// Annotations are merged onto the generated K8s Service annotations
	// after the controller's provider-specific defaults. Caller values win
	// on key collision, which lets callers set provider-specific tuning
	// knobs (e.g. aws-load-balancer-target-group-attributes,
	// aws-load-balancer-healthcheck-path) without typed API fields.
	// +optional
	Annotations map[string]string `json:"annotations,omitempty"`
	// PreserveClientIP controls whether the generated load balancer keeps
	// the original client IP. When unset, providers default PRIVATE to
	// false and PUBLIC to true. Currently only supported by AWS and
	// AliCloud load balancers.
	// +optional
	PreserveClientIP *bool `json:"preserveClientIP,omitempty"`

	// GracefulUnhealthyEnabled is a transitional TiProxy legacy graceful rollout switch.
	// When enabled, dataplane-manager applies provider-specific best-effort behavior
	// so unhealthy old TiProxy backends can keep serving existing connections while
	// new connections are steered away as much as the provider allows.
	// +optional
	GracefulUnhealthyEnabled bool `json:"gracefulUnhealthyEnabled,omitempty"`
	// +optional
	Ownership *ResourceOwnership `json:"ownership,omitempty"`
}

// LoadBalancerPort defines a single LB listener.
type LoadBalancerPort struct {
	// Name is the K8s ServicePort name, e.g. "cassandra", "cassandra-ssl".
	Name string `json:"name"`
	// Port is the LB listener port.
	Port int32 `json:"port"`
	// TargetPort is the pod-facing port. Defaults to Port when zero.
	// +optional
	TargetPort int32 `json:"targetPort,omitempty"`
	// Protocol is "TCP" / "UDP" / "TLS". Empty string defaults to TCP.
	// +optional
	Protocol string `json:"protocol,omitempty"`
}

type LoadBalancerPhase string

const (
	LoadBalancerPhaseActive   LoadBalancerPhase = "Active"
	LoadBalancerPhaseCreating LoadBalancerPhase = "Creating"
	LoadBalancerPhaseDeleting LoadBalancerPhase = "Deleting"
	LoadBalancerPhaseFailed   LoadBalancerPhase = "Failed"
)

// LoadBalancerStatus defines the observed state of LoadBalancer
type LoadBalancerStatus struct {
	// +optional
	DNS string `json:"dns,omitempty"`
	// +optional
	Phase LoadBalancerPhase `json:"phase,omitempty"`
	// +optional
	CloudResourceId string `json:"cloudResourceId"`
	// +optional
	PrivateIPs []string `json:"privateIPs,omitempty"`
}

// +kubebuilder:object:root=true

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

func init() {
	SchemeBuilder.Register(&LoadBalancer{}, &LoadBalancerList{})
}

func DefaultPreserveClientIP(lbType LoadBalancerType) bool {
	return lbType == PublicLoadBalancerType
}

func ResolvePreserveClientIP(lbType LoadBalancerType, v *bool) bool {
	if v != nil {
		return *v
	}
	return DefaultPreserveClientIP(lbType)
}
