package util

import (
	"context"
	"fmt"

	"sigs.k8s.io/controller-runtime/pkg/client"
	"sigs.k8s.io/controller-runtime/pkg/predicate"

	cloudv1 "github.com/tidbcloud/infra-api/api/v1"
)

const (
	regionalKey = "cloud.pingcap.com/region"
)

// CheckNetworkRegion returns true if the VPC belongs to the given region.
func CheckNetworkRegion(region string, network *cloudv1.Network) (bool, error) {
	if network.Spec.Region == "" {
		return false, fmt.Errorf("network region is empty")
	}
	if network.Spec.Region == region {
		return true, nil
	}
	return false, nil
}

// EnsureRegion checks whether object contains regional label.
// If the label doesn't exist, it will annotate the object and return false.
// Otherwise it will return true.
func EnsureRegion(obj client.Object, region string) bool {
	if GetLabel(obj, regionalKey) != "" {
		return true
	}
	SetLabel(obj, regionalKey, region)
	return false
}

// ContainsRegionLabel returns true if the object contains the region label.
func ContainsRegionLabel(obj client.Object) bool {
	return GetLabel(obj, regionalKey) != ""
}

// CheckRegionLabel returns true if the object has the region label and the val matches region
func CheckRegionLabel(obj client.Object, region string) bool {
	return GetLabel(obj, regionalKey) != region
}

// RegionalPredicate ignores objects from other regions.
func RegionalPredicate(region string) predicate.Predicate {
	return predicate.NewPredicateFuncs(func(obj client.Object) bool {
		labels := obj.GetLabels()
		// return true if the object doesn't have regional label or it is in the specified region
		if labels == nil || labels[regionalKey] == "" || labels[regionalKey] == region {
			return true
		}
		return false
	})
}

// CheckClusterRegion returns true if the cluster belongs the region
func CheckClusterRegion(ctx context.Context, cli client.Client, cluster *cloudv1.Cluster, region string) (bool, error) {
	network := &cloudv1.Network{}
	err := cli.Get(ctx, cluster.GetNetworkRef(), network)
	if err != nil {
		return false, err
	}
	return CheckNetworkRegion(region, network)
}
