package network

import (
	"context"
	"testing"

	cciamv1beta1 "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/clients/generated/apis/iam/v1beta1"
	"github.com/stretchr/testify/assert"
	cloudv1 "github.com/tidbcloud/infra-api/api/v1"
	corev1 "k8s.io/api/core/v1"
	apierrors "k8s.io/apimachinery/pkg/api/errors"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	k8sruntime "k8s.io/apimachinery/pkg/runtime"
	"sigs.k8s.io/controller-runtime/pkg/client"

	"github.com/tidbcloud/shared-provider/pkg/types"
	nameutil "github.com/tidbcloud/shared-provider/pkg/utils/name"
	"github.com/tidbcloud/shared-provider/pkg/utils/namespace"
)

func TestGCPImportResource(t *testing.T) {
	var (
		env        = "ut"
		project    = "123456"
		gcpProject = "gcp-ut"
		name       = nameutil.GetImportGCPServiceAccountName(env, project)
		net        = cloudv1.Network{
			ObjectMeta: metav1.ObjectMeta{
				Namespace: "network-ns",
				Name:      "ns-network",
				UID:       "net-uid",
				Labels: map[string]string{
					"tags.tidbcloud.com/kubernetes": kubeClusterName,
					"tags.tidbcloud.com/project":    project,
				},
			},
			Spec: cloudv1.NetworkSpec{
				Provider: types.ProviderTypeGCPSharedTier,
				Region:   region,
				CIDR:     cidr,
			},
		}
		ns = corev1.Namespace{
			ObjectMeta: metav1.ObjectMeta{
				Name: namespace.GetOwnedNamespaceNameFromNetwork(&net),
			},
		}
		objKey = client.ObjectKey{Namespace: ns.Name, Name: name}
		secret = corev1.Secret{
			ObjectMeta: metav1.ObjectMeta{
				Namespace: ns.Name,
				Name:      name,
			},
		}
		objs      = []k8sruntime.Object{&ns, &secret}
		infraObjs = []k8sruntime.Object{&net}
	)

	r := newFakeReconciler(objs, infraObjs)
	r.Env = env
	r.GCPProjectID = gcpProject

	err := r.ensureGCPImportResource(context.Background(), &net)
	assert.NoError(t, err)
	var gsa cciamv1beta1.IAMServiceAccount
	var gsak cciamv1beta1.IAMServiceAccountKey
	assert.NoError(t, r.Client.Get(context.Background(), objKey, &gsa))
	assert.NoError(t, r.Client.Get(context.Background(), objKey, &gsak))

	// network status updated
	assert.NoError(t, r.InfraClient.Get(context.Background(), client.ObjectKeyFromObject(&net), &net))
	assert.Equal(t, net.Status.IAM.ServiceAccountEmail, getGCPServiceAccountEmail(name, gcpProject))

	// call again without error
	err = r.ensureGCPImportResource(context.Background(), &net)
	assert.NoError(t, err)

	err = r.cleanUpGCPImportResource(context.Background(), &net)
	assert.NoError(t, err)
	assert.True(t, apierrors.IsNotFound(r.Client.Get(context.Background(), objKey, &gsa)))
	assert.True(t, apierrors.IsNotFound(r.Client.Get(context.Background(), objKey, &gsak)))

	// call again without error
	err = r.cleanUpGCPImportResource(context.Background(), &net)
	assert.NoError(t, err)
}
