package controller

import (
	"context"
	"fmt"
	"os"
	"path/filepath"
	"testing"

	cephv1 "git.unkin.net/unkin/cephrgw-operator/api/v1alpha1"
	k8upv1 "github.com/k8up-io/k8up/v2/api/v1"
	corev1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	utilruntime "k8s.io/apimachinery/pkg/util/runtime"
	clientgoscheme "k8s.io/client-go/kubernetes/scheme"
	"sigs.k8s.io/controller-runtime/pkg/client"
	"sigs.k8s.io/controller-runtime/pkg/envtest"
)

var (
	testEnv      *envtest.Environment
	k8sClient    client.Client
	envtestReady bool
)

func TestMain(m *testing.M) {
	utilruntime.Must(cephv1.AddToScheme(clientgoscheme.Scheme))
	utilruntime.Must(k8upv1.AddToScheme(clientgoscheme.Scheme))

	testEnv = &envtest.Environment{
		CRDDirectoryPaths:     []string{filepath.Join("..", "..", "test", "crds")},
		ErrorIfCRDPathMissing: true,
	}
	cfg, err := testEnv.Start()
	if err != nil {
		// envtest binaries (KUBEBUILDER_ASSETS) may be unavailable; run the
		// pure-unit tests and skip the controller tests.
		fmt.Fprintf(os.Stderr, "envtest unavailable, skipping controller tests: %v\n", err)
		os.Exit(m.Run())
	}
	k8sClient, err = client.New(cfg, client.Options{Scheme: clientgoscheme.Scheme})
	if err != nil {
		fmt.Fprintf(os.Stderr, "failed to build client: %v\n", err)
		os.Exit(1)
	}
	envtestReady = true
	code := m.Run()
	_ = testEnv.Stop()
	os.Exit(code)
}

func requireEnvtest(t *testing.T) {
	t.Helper()
	if !envtestReady {
		t.Skip("envtest not available (KUBEBUILDER_ASSETS unset)")
	}
}

func newNamespace(t *testing.T, ctx context.Context) string {
	t.Helper()
	name := fmt.Sprintf("test-%s", randSuffix())
	ns := &corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: name}}
	if err := k8sClient.Create(ctx, ns); err != nil {
		t.Fatalf("create namespace: %v", err)
	}
	return name
}

func createDestinations(t *testing.T, ctx context.Context, ns string) {
	t.Helper()
	cm := &corev1.ConfigMap{
		ObjectMeta: metav1.ObjectMeta{Name: "autobackup-destinations", Namespace: ns},
		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",
		},
	}
	if err := k8sClient.Create(ctx, cm); err != nil {
		t.Fatalf("create destinations configmap: %v", err)
	}
}

var suffixCounter int

func randSuffix() string {
	suffixCounter++
	return fmt.Sprintf("%d", suffixCounter)
}
