package v1alpha1

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

// the VPCPeering struct is borrowed from infra-api/api/networkpeer_types.go
type VPCPeeringPhase string

const (
	VPCPeeringPhasePending  VPCPeeringPhase = "Pending"
	VPCPeeringPhaseCreating VPCPeeringPhase = "Creating"
	VPCPeeringPhaseActive   VPCPeeringPhase = "Active"
	VPCPeeringPhaseFailed   VPCPeeringPhase = "Failed"
	VPCPeeringPhaseDeleting VPCPeeringPhase = "Deleting"

	ProviderAWS = "aws"
	ProviderGCP = "gcp"
)

const (
	// same value as corssplane's external name
	LabelKeyExternalName = "cloud.pingcap.com/externalName"
	// store the if given by tidb-mgmt global service
	LabelKeyBizID = "cloud.pingcap.com/bizId"
)

const (
	AnnotationKeySourceVPCID     = "cloud.pingcap.com/sourceVpcId"
	AnnotationKeySourceVPCCIDR   = "cloud.pingcap.com/sourceVpcCIDR"
	AnnotationKeySourceAccountID = "cloud.pingcap.com/sourceAccountId"

	AnnotationKeyRouteTableEnsured        = "cloud.pingcap.com/routeTableEnsured"
	AnnotationKeyVPCPeeringApproved       = "cloud.pingcap.com/vpcPeeringApproved"
	AnnotationKeyVPCPeeringAllowRemoteDNS = "cloud.pingcap.com/vpcPeeringAllowRemoteDNS"

	// the prefix of the annotation key for the peering that has ensured the route table.
	// eg. AnnotationKeyRouteTableEnsuredPeeringPrefix + "vpcpeering-name" = "true"
	AnnotationKeyRouteTableEnsuredPeeringPrefix = "cloud.pingcap.com/routetableEnsuredPeering-"

	// the prefix of the annotation key for the acceptor peering that has ensured the route table.
	// eg. AnnotationKeyRouteTableEnsuredAcceptorPeeringPrefix + "vpcpeering-name" = "true"
	AnnotationKeyRouteTableEnsuredAcceptorPeeringPrefix = "cloud.pingcap.com/routetableEnsuredAcceptorPeering-"
)

const (
	FinalizerVPCPeering = "vpcpeering.dedicated.regionalserver.tidbcloud.com/finalizer"
)

// parameters for AWS
type AWS struct {
	// TODO(shenjun): the name PeerCIDR and PeerRegion doesn't look good.
	// +optional
	AccountID string `json:"accountId,omitempty"`
	// +optional
	VpcID string `json:"vpcId,omitempty"`
	// +optional
	PeerCIDR string `json:"peerCIDR,omitempty"` // just to store cidr for biz, not used by crossplane provider-aws.
	// +optional
	PeerRegion string `json:"peerRegion,omitempty"`
}

// parameters for GCP
type GCP struct {
	// TODO(shenjun): the name PeerNetwork and PeerCIDR doesn't look good.
	ProjectID   string `json:"projectId"`
	PeerNetwork string `json:"peerNetwork"`
	PeerCIDR    string `json:"peerCIDR,omitempty"` // just to store cidr for biz, not used by crossplane provider-gcp.
}

type TargetVPC struct {
	Name string `json:"name"`
}

type Target struct {
	AWS       *AWS       `json:"aws,omitempty"`
	GCP       *GCP       `json:"gcp,omitempty"`
	TargetVPC *TargetVPC `json:"targetVPC,omitempty"` // this filed is used only if the target is also a VPC CR in our kube-apiserver.
}

type VPCPeeringSpec struct {
	// since regional-server support logic region, we need to define `Porvider` and `Region` in Spec.
	Provider string            `json:"provider"` // value can be `eks/gke`
	Region   string            `json:"region"`   // indicates which physical region this cr live
	Tags     map[string]string `json:"tags,omitempty"`
	// Source porints to the dedicated.regionalserver.tidbcloud.com/vpc CR's name
	// for requester, source is the requester's vpc
	// for accepter, source is the accepter's vpc
	SourceVPCRef *Reference `json:"sourceVPCRef"`
	// +optional
	AccountRef *AccountReference `json:"accountRef,omitempty"`
	// for requester, target is the accepter's vpc
	// for accepter, target is the requester's vpc
	// +optional
	Target Target `json:"target"`
	// supported values are `requester` and `accepter`.
	// If this field is exmpty, represent the peering role is requester
	// +optional
	PeeringRole string `json:"peeringRole"`
	// +optional
	VPCPeeringConnectionID string `json:"vpcPeeringConnectionId"`
}

const (
	// PeeringRoleRequester is the requester of the peering
	PeeringRoleRequester = "requester"
	// PeeringRoleAccepter is the accepter of the peering
	PeeringRoleAccepter = "accepter"
)

type PeeringRequesterInfo struct {
	// +optional
	VPCID string `json:"vpcId"`
	// +optional
	CIDR string `json:"cidr"`
}

// +kubebuilder:object:root=true
// +kubebuilder:resource:categories=regionserver
// +kubebuilder:subresource:status
// +kubebuilder:printcolumn:name="TENANT",type="string",JSONPath=".metadata.labels.cloud\\.pingcap\\.com/tenantId"
// +kubebuilder:printcolumn:name="SOURCE-VPC-REF",type="string",JSONPath=".spec.sourceVPCRef.name"
// +kubebuilder:printcolumn:name="EXTERNAL-NAME",type="string",JSONPath=".status.externalName"
// +kubebuilder:printcolumn:name="PAUSED",type="string",JSONPath=".metadata.annotations.dedicated\\.regionalserver\\.tidbcloud\\.com/paused"
// +kubebuilder:printcolumn:name="PHASE",type="string",JSONPath=".status.phase"
// +kubebuilder:printcolumn:name="AGE",type="date",JSONPath=".metadata.creationTimestamp"
// VPC is the Schema for the VPCPeering API
type VPCPeering struct {
	metav1.TypeMeta   `json:",inline"`
	metav1.ObjectMeta `json:"metadata,omitempty"`

	Spec   VPCPeeringSpec   `json:"spec,omitempty"`
	Status VPCPeeringStatus `json:"status,omitempty"`
}

type VPCPeeringStatus struct {
	// +optional
	Phase VPCPeeringPhase `json:"phase,omitempty"`
	// +optional
	Reason string `json:"reason,omitempty"`
	// the resource name in provider, same as corssplane external name
	// +optional
	ExternalName string `json:"externalName,omitempty"`
	// +optional
	CrossplaneResourceName string `json:"crossplaneResourceName,omitempty"`
	// +optional
	HostedZoneID string `json:"hostedZoneId,omitempty"` // useless, HostedZoneID is no more needed
}

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

func init() {
	SchemeBuilder.Register(&VPCPeering{}, &VPCPeeringList{})
}
