package network

import (
	"context"
	"testing"

	"github.com/stretchr/testify/assert"
	corev1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	k8sruntime "k8s.io/apimachinery/pkg/runtime"
	"sigs.k8s.io/controller-runtime/pkg/client"

	cloudv1 "github.com/tidbcloud/infra-api/api/v1"
	"github.com/tidbcloud/shared-provider/pkg/types"
	"github.com/tidbcloud/shared-provider/pkg/utils/namespace"
)

func TestSyncDefaultSa(t *testing.T) {
	var (
		net = cloudv1.Network{
			ObjectMeta: metav1.ObjectMeta{
				Namespace: "network-ns",
				Name:      "ns-network",
				UID:       "net-uid",
				Labels: map[string]string{
					"tags.tidbcloud.com/kubernetes": kubeClusterName,
				},
			},
			Spec: cloudv1.NetworkSpec{
				Provider: types.ProviderTypeAWSSharedTier,
				Region:   region,
				CIDR:     cidr,
			},
		}
		ns = corev1.Namespace{
			ObjectMeta: metav1.ObjectMeta{
				Name: namespace.GetOwnedNamespaceNameFromNetwork(&net),
			},
		}
		trueVal  = true
		falseVal = false
	)

	cases := []struct {
		name     string
		sa       *corev1.ServiceAccount
		hasError bool
	}{
		{
			name:     "sa does not exist",
			hasError: true,
		},
		{
			name: "sa without AutomountServiceAccountToken set",
			sa: &corev1.ServiceAccount{
				ObjectMeta: metav1.ObjectMeta{
					Namespace: ns.Name,
					Name:      "default",
				},
			},
		},
		{
			name: "sa with AutomountServiceAccountToken set to true",
			sa: &corev1.ServiceAccount{
				ObjectMeta: metav1.ObjectMeta{
					Namespace: ns.Name,
					Name:      "default",
				},
				AutomountServiceAccountToken: &trueVal,
			},
		},
		{
			name: "sa with AutomountServiceAccountToken set to false",
			sa: &corev1.ServiceAccount{
				ObjectMeta: metav1.ObjectMeta{
					Namespace: ns.Name,
					Name:      "default",
				},
				AutomountServiceAccountToken: &falseVal,
			},
		},
	}

	for _, cs := range cases {
		t.Run(cs.name, func(t *testing.T) {
			t.Log("running case", cs.name)
			var (
				objs      = []k8sruntime.Object{&ns}
				infraObjs = []k8sruntime.Object{&net}
			)
			if cs.sa != nil {
				objs = append(objs, cs.sa)
			}
			r := newFakeReconciler(objs, infraObjs)
			err := r.syncDefaultSA(context.Background(), &net)
			if cs.hasError {
				assert.Error(t, err)
			} else {
				assert.NoError(t, err)
				sa := &corev1.ServiceAccount{}
				assert.NoError(t, r.Client.Get(context.Background(), client.ObjectKey{Namespace: ns.Name, Name: "default"}, sa))
				assert.False(t, *sa.AutomountServiceAccountToken)
			}
		})
	}
}
