package target

import (
	"context"
	"fmt"
	"sort"

	corev1 "k8s.io/api/core/v1"
	"sigs.k8s.io/controller-runtime/pkg/client"
)

// ListPods resolves zero or more Targets to a deduplicated Pod snapshot.
func ListPods(ctx context.Context, reader client.Reader, targets ...Target) ([]*corev1.Pod, error) {
	byKey := make(map[client.ObjectKey]*corev1.Pod)
	for _, target := range targets {
		labels := target.Labels()
		var pods corev1.PodList
		if err := reader.List(ctx, &pods,
			client.InNamespace(target.Namespace()),
			client.MatchingLabels(PodSelectorLabels(target)),
		); err != nil {
			return nil, fmt.Errorf("list Pods for target namespace %q labels %v: %w", target.Namespace(), labels, err)
		}
		for i := range pods.Items {
			pod := &pods.Items[i]
			if !pod.DeletionTimestamp.IsZero() {
				continue
			}
			byKey[client.ObjectKeyFromObject(pod)] = pod.DeepCopy()
		}
	}

	keys := make([]client.ObjectKey, 0, len(byKey))
	for key := range byKey {
		keys = append(keys, key)
	}
	sort.Slice(keys, func(i, j int) bool {
		if keys[i].Namespace != keys[j].Namespace {
			return keys[i].Namespace < keys[j].Namespace
		}
		return keys[i].Name < keys[j].Name
	})
	pods := make([]*corev1.Pod, 0, len(keys))
	for _, key := range keys {
		pods = append(pods, byKey[key])
	}
	return pods, nil
}

// PodSelectorLabels converts canonical target labels to Kubernetes Pod labels.
func PodSelectorLabels(target Target) map[string]string {
	labels := target.Labels()
	return map[string]string{
		PodLabelGroup:     labels[LabelGroup],
		PodLabelComponent: labels[LabelComponent],
	}
}
