//go:build unit || all
// +build unit all

package controllers

import (
	"context"
	"testing"

	. "github.com/onsi/gomega"
	cloudv1 "github.com/tidbcloud/infra-api/api/v1"
	"github.com/tidbcloud/infra-provider/pkg/util"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/runtime"
	"sigs.k8s.io/controller-runtime/pkg/client"
	"sigs.k8s.io/controller-runtime/pkg/client/fake"
)

func TestCheckRegionalLabel(t *testing.T) {
	const (
		fakeName  = "fakeName"
		fakeNS    = "fakeNS"
		fooRegion = "foo"
	)
	network := &cloudv1.Network{
		ObjectMeta: metav1.ObjectMeta{
			Name:      fakeName,
			Namespace: fakeNS,
		},
		Spec: cloudv1.NetworkSpec{
			Region: fooRegion,
		},
	}
	cluster := &cloudv1.Cluster{
		ObjectMeta: metav1.ObjectMeta{
			Name:      fakeName,
			Namespace: fakeNS,
		},
		Spec: cloudv1.ClusterSpec{
			NetworkName: fakeName,
		},
	}
	impt := &cloudv1.Import{
		ObjectMeta: metav1.ObjectMeta{
			Name:      fakeName,
			Namespace: fakeNS,
		},
		Spec: cloudv1.ImportSpec{
			ClusterName: fakeName,
		},
	}
	cases := []struct {
		name      string
		region    string
		objs      []client.Object
		obj       client.Object
		expectErr bool
	}{
		{
			name: "obj region label is empty",
			objs: []client.Object{
				network,
				cluster,
			},
			obj:       impt.DeepCopy(),
			region:    fooRegion,
			expectErr: false,
		},
		{
			name: "obj region label doesn't match",
			objs: []client.Object{
				network,
				cluster,
			},
			obj:       impt.DeepCopy(),
			region:    "bar",
			expectErr: true,
		},
		{
			name: "obj region label matches",
			objs: []client.Object{
				network,
				cluster,
			},
			obj: func() client.Object {
				obj := impt.DeepCopy()
				util.EnsureRegion(obj, fooRegion)
				return obj
			}(),
			region:    fooRegion,
			expectErr: false,
		},
	}

	for _, tc := range cases {
		t.Run(tc.name, func(t *testing.T) {
			g := NewGomegaWithT(t)
			s := runtime.NewScheme()
			g.Expect(cloudv1.SchemeBuilder.AddToScheme(s)).To(Succeed())
			cli := fake.NewClientBuilder().WithScheme(s).WithObjects(append(tc.objs, tc.obj)...).Build()

			err := CheckRegionalLabel(context.TODO(), cluster, tc.obj, cli, tc.region)
			if tc.expectErr {
				g.Expect(err).To(HaveOccurred())
			} else {
				g.Expect(err).NotTo(HaveOccurred())
				g.Expect(cli.Get(context.TODO(), client.ObjectKey{Name: fakeName, Namespace: fakeNS}, tc.obj)).To(Succeed())
				g.Expect(util.ContainsRegionLabel(tc.obj)).To(BeTrue())
			}
		})
	}
}
