package controller

import (
	"context"
	"errors"
	"testing"

	corev1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/runtime"
	clientgoscheme "k8s.io/client-go/kubernetes/scheme"
	"sigs.k8s.io/controller-runtime/pkg/client/fake"
)

func destClient(t *testing.T, objs ...runtime.Object) *fake.ClientBuilder {
	t.Helper()
	return fake.NewClientBuilder().WithScheme(clientgoscheme.Scheme).WithRuntimeObjects(objs...)
}

func TestResolveDestinationHit(t *testing.T) {
	cm := &corev1.ConfigMap{
		ObjectMeta: metav1.ObjectMeta{Name: "autobackup-destinations", Namespace: "autobackup-operator"},
		Data: map[string]string{
			"cephs3_ec4_1": "placementTarget: cephs3_ec4_1\nzonegroup: au\nendpoint: https://s3.ceph.unkin.net\nendpointCASecret: vault-ca-cert\nendpointCAKey: ca.crt\n",
		},
	}
	c := destClient(t, cm).Build()
	d, err := resolveDestination(context.Background(), c, "autobackup-operator", "autobackup-destinations", "cephs3_ec4_1")
	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
	if d.PlacementTarget != "cephs3_ec4_1" || d.Zonegroup != "au" || d.Endpoint != "https://s3.ceph.unkin.net" {
		t.Errorf("unexpected destination: %+v", d)
	}
	if d.EndpointCASecret != "vault-ca-cert" || d.EndpointCAKey != "ca.crt" {
		t.Errorf("unexpected CA fields: %+v", d)
	}
}

func TestResolveDestinationMissEntry(t *testing.T) {
	cm := &corev1.ConfigMap{
		ObjectMeta: metav1.ObjectMeta{Name: "autobackup-destinations", Namespace: "autobackup-operator"},
		Data:       map[string]string{"other": "endpoint: https://x\n"},
	}
	c := destClient(t, cm).Build()
	_, err := resolveDestination(context.Background(), c, "autobackup-operator", "autobackup-destinations", "cephs3_ec4_1")
	if !errors.Is(err, errDestinationNotFound) {
		t.Errorf("expected errDestinationNotFound, got %v", err)
	}
}

func TestResolveDestinationMissConfigMap(t *testing.T) {
	c := destClient(t).Build()
	_, err := resolveDestination(context.Background(), c, "autobackup-operator", "autobackup-destinations", "cephs3_ec4_1")
	if !errors.Is(err, errDestinationNotFound) {
		t.Errorf("expected errDestinationNotFound, got %v", err)
	}
}

func TestResolveDestinationMissingEndpoint(t *testing.T) {
	cm := &corev1.ConfigMap{
		ObjectMeta: metav1.ObjectMeta{Name: "autobackup-destinations", Namespace: "autobackup-operator"},
		Data:       map[string]string{"noendpoint": "placementTarget: x\n"},
	}
	c := destClient(t, cm).Build()
	_, err := resolveDestination(context.Background(), c, "autobackup-operator", "autobackup-destinations", "noendpoint")
	if err == nil {
		t.Errorf("expected error for missing endpoint")
	}
}
