package v1alpha1

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

type PrivateLinkServicePhase string

const (
	PrivateLinkServicePhasePending        PrivateLinkServicePhase = "Pending"
	PrivateLinkServicePhaseReadyForCreate PrivateLinkServicePhase = "ReadyForCreate"
	PrivateLinkServicePhaseCreating       PrivateLinkServicePhase = "Creating"
	PrivateLinkServicePhaseFailed         PrivateLinkServicePhase = "Failed"
	PrivateLinkServicePhaseActive         PrivateLinkServicePhase = "Active"
	PrivateLinkServicePhaseReadyForDelete PrivateLinkServicePhase = "ReadyForDelete"
	PrivateLinkServicePhaseDeleting       PrivateLinkServicePhase = "Deleting"
	PrivateLinkServicePhaseDeleted        PrivateLinkServicePhase = "Deleted"
)

const (
	LabelKeyOwnedBy            = "cloud.pingcap.com/owned-by"
	LabelValOwnedByPrivateLink = "private-link"

	DefaultPrivateSQLEndpointPort = int32(4000)
)

const (
	// for aws
	// for vpcendpointserviceconfiguration
	AnnotationKeyOwnCrossplaneNameVPCEService       = "cloud.pingcap.com/own-crossplane-name-vpcesvc"
	AnnotationKeyOwnCrossplaneNameResourceRecordSet = "cloud.pingcap.com/own-crossplane-name-rrset"
	// for gcp
	// there is no xp resource for the follwong name, they are created by gcp client
	AnnotationKeyOwnCrossplaneNamePSCNATSubenet        = "cloud.pingcap.com/own-crossplane-name-pscnatsubnet"
	AnnotationKeyOwnCrossplaneNamePSCServiceAttachment = "cloud.pingcap.com/own-crossplane-name-pscserviceattchment"
	AnnotationKeyOwnCrossplaneNamePSCDomain            = "cloud.pingcap.com/own-crossplane-name-pscdomain"
)

// 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"
// PrivateLinkService is the Schema for the PrivateLinkService API
type PrivateLinkService struct {
	metav1.TypeMeta   `json:",inline"`
	metav1.ObjectMeta `json:"metadata,omitempty"`

	Spec   PrivateLinkServiceSpec   `json:"spec,omitempty"`
	Status PrivateLinkServiceStatus `json:"status,omitempty"`
}

type PrivateLinkServiceSpec struct {
	Provider      string         `json:"provider"`
	Region        string         `json:"region"`
	VPCRef        Reference      `json:"vpcRef"`
	LoadBalancers []LoadBalancer `json:"loadBalancers"`
	// +optional
	Connections []Connection `json:"Connections,omitempty"`
}

type LoadBalancer struct {
	ID string `json:"id"`
	// Is it necessary to add this field?
	ClusterID string `json:"clusterId"`
}

type Connection struct {
	Endpoint string `json:"endpoint"`
	// +optional
	// IPs is the ips of the endpoint, it is used to create dns record.
	// Used in Azure.
	IPs []string `json:"ips,omitempty"`
}

type PrivateLinkServiceStatus struct {
	// +optional
	Phase PrivateLinkServicePhase `json:"phase,omitempty"`
	// +optional
	Message string `json:"message,omitempty"`
	// +optional
	VPCID string `json:"vpcId,omitempty"`
	// +optional
	EndpointService EndpointServiceStatus `json:"endpointServices,omitempty"`
	// +optional
	AllowedPrincipals []string `json:"allowedPrincipals,omitempty"`
	// +optional
	DNSIdentify string `json:"dnsIdentify,omitempty"`
	// +optional
	LoadBalancers []LoadBalancerStatus `json:"loadBalancerStatuses,omitempty"`
	// +optional
	Connections []ConnectionStatus `json:"connectionStatuses,omitempty"`
	// +optional
	DNSRecord DNSRecordStatus `json:"dnsStatus,omitempty"`
	// +optional
	DNSOwnership string `json:"verifyDnsOwnership,omitempty"`
	// +optional
	NATSubnet NATSubnetStatus `json:"natSubnetStatus,omitempty"`
	// +optional
	ServiceAttachment ServiceAttachmentStatus `json:"serviceAttachmentStatus,omitempty"`
	// +optional
	AzurePrivateLinkService AzurePrivateLinkServiceStatus `json:"azurePrivateLinkServiceStatus,omitempty"`
}

type AzurePrivateLinkServiceStatus struct {
	// +optional
	Name string `json:"name,omitempty"`
	// A globally unique DNS Name for your Private Link Service. You can use this alias to request a connection to your Private Link Service.
	// +optional
	Alias string `json:"alias,omitempty"`
	// +optional
	ID string `json:"id,omitempty"`
	// +optional
	ServiceDNSName string `json:"serviceDnsName,omitempty"`
}

type ServiceAttachmentStatus struct {
	// +optional
	Name string `json:"name,omitempty"`
	// +optional
	ServiceAttachment string `json:"serviceAttachment,omitempty"`
	// +optional
	ConnectDomain string `json:"connectDomain,omitempty"`
	// +optional
	Port int32 `json:"port,omitempty"`
}

type NATSubnetStatus struct {
	// +optional
	Name string `json:"name,omitempty"`
	// +optional
	IPCidrRange string `json:"ipCidrRange,omitempty"`
}

type EndpointServiceStatus struct {
	// +optional
	Name string `json:"name,omitempty"`
	// +optional
	PrivateDNSName string `json:"privateDnsName,omitempty"`
	// +optional
	Port int32 `json:"port,omitempty"`
	// +optional
	ServiceName string `json:"serviceName,omitempty"`
	// +optional
	ServiceID string `json:"serviceId,omitempty"`
	// +optional
	AvailabilityZones []string `json:"availabilityZones,omitempty"`
}

type DNSRecordStatus struct {
	// +optional
	Name string `json:"name,omitempty"`
	// +optional
	Status string `json:"status,omitempty"`
	// +optional
	Type string `json:"type,omitempty"`
	// +optional
	Value string `json:"value,omitempty"`
}

type LoadBalancerPhase string

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

type LoadBalancerStatus struct {
	// +optional
	ID string `json:"id,omitempty"`
	// +optional
	CloudResourceId string `json:"cloudResourceId,omitempty"`
	// +optional
	Port int32 `json:"port,omitempty"`
	// +optional
	Host string `json:"host,omitempty"`
	// +optional
	Phase LoadBalancerPhase `json:"phase,omitempty"`
	// +optional
	Type string `json:"type,omitempty"`
}

type ConnectionStatus struct {
	Endpoint string          `json:"endpoint"`
	Phase    ConnectionPhase `json:"phase"`
	// +optional
	Message string `json:"message,omitempty"`
	// +optional
	// DNSName is the dns name of the endpoint.
	// Used in GCP and Azure.
	DNSName string `json:"dnsName,omitempty"`
	// +optional
	// IPs is the ips of the endpoint, it is used to create dns record.
	// Used in Azure.
	IPs []string `json:"ips,omitempty"`
}

type ConnectionPhase string

const (
	ConnectionPhasePending  ConnectionPhase = "Pending"
	ConnectionPhaseActive   ConnectionPhase = "Active"
	ConnectionPhaseDeleting ConnectionPhase = "Deleting"
	ConnectionPhaseFailed   ConnectionPhase = "Failed"
)

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

func init() {
	SchemeBuilder.Register(&PrivateLinkService{}, &PrivateLinkServiceList{})
}
