package extragroup

import (
	"strings"

	"gomodules.xyz/jsonpatch/v2"
	"k8s.io/apimachinery/pkg/labels"
	"k8s.io/apimachinery/pkg/selection"
	"sigs.k8s.io/controller-runtime/pkg/client"

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

const (
	// This anno is set to avoid call AWS API multiple times
	// This anno is set in FullService task and maybe used in PrivateLink task
	annoKeyLoadBalancerARN = "load-balancer.aws.cloud.pingcap.com/arn"

	// These labels are defined to list resources of specified extra group
	labelKeyExtraGroup = "cloud.pingcap.com/extra-group"
	labelKeyNamespace  = "cloud.pingcap.com/namespace"
	labelKeyCluster    = "cloud.pingcap.com/cluster"
	labelKeyOwnedBy    = "cloud.pingcap.com/owned-by"

	// It means the resource is owned by private link task
	labelValOwnedByPrivateLink = "private-link"
)

func childrenLabels(c *cloudv1.Cluster, typ, groupName string) map[string]string {
	ls := map[string]string{
		labelKeyNamespace: c.Namespace,
		labelKeyCluster:   c.Name,
		labelKeyOwnedBy:   typ,
	}
	// groupName is empty means all groups
	if groupName != "" {
		ls[labelKeyExtraGroup] = groupName
	}
	return ls
}

func childrenSelector(c *cloudv1.Cluster, typ, groupName string) labels.Selector {
	selector := labels.SelectorFromSet(labels.Set(childrenLabels(c, typ, groupName)))
	if groupName != "" {
		return selector
	}

	req, err := labels.NewRequirement(labelKeyExtraGroup, selection.Exists, nil)
	if err != nil {
		panic("unreachable")
	}

	selector.Add(*req)
	return selector
}

func groupIsContained(group string, allGroups ...string) bool {
	for _, g := range allGroups {
		if g == group {
			return true
		}
	}

	return false
}

func newAnnoPatch(k, v string) k8s.ObjectPatch {
	return func(obj client.Object) *jsonpatch.Operation {
		anno, op := obj.GetAnnotations(), "replace"
		if anno == nil || anno[k] == "" {
			op = "add"
		}
		return &jsonpatch.Operation{
			Operation: op,
			Path:      `/metadata/annotations/` + strings.ReplaceAll(k, "/", "~1"),
			Value:     v,
		}
	}

}
