package network

import (
	"context"
	"testing"

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

	cloudv1 "github.com/tidbcloud/infra-api/api/v1"
	awsfake "github.com/tidbcloud/infra-api/pkg/providers/aws/fake"
	"github.com/tidbcloud/shared-provider/pkg/types"
)

func TestSyncFinalizer(t *testing.T) {
	var (
		net = cloudv1.Network{
			ObjectMeta: metav1.ObjectMeta{
				Namespace: "network-ns1",
				Name:      "finalizer-network",
				Labels: map[string]string{
					"tags.tidbcloud.com/kubernetes": kubeClusterName,
				},
			},
			Spec: cloudv1.NetworkSpec{
				Provider: types.ProviderTypeAWSSharedTier,
				Region:   region,
				CIDR:     cidr,
			},
		}
		netNotExist = net

		objs          []k8sruntime.Object
		infraObjs     = []k8sruntime.Object{&net}
		fakeAwsClient = awsfake.NewMockClient(t)
		r             = newFakeReconciler(objs, infraObjs)
	)

	mockAWSClient(fakeAwsClient)
	r.AwsClient = fakeAwsClient

	// ensureFinalizer
	assert.NoError(t, r.ensureFinalizer(context.Background(), &net))
	assert.True(t, controllerutil.ContainsFinalizer(&net, networkFinalizer))

	// ensureFinalizer again
	assert.NoError(t, r.ensureFinalizer(context.Background(), &net))
	assert.True(t, controllerutil.ContainsFinalizer(&net, networkFinalizer))

	// ensureFinalizer with not exist network in the infra API server
	assert.Error(t, r.ensureFinalizer(context.Background(), &netNotExist))

	// tryToFinalize for the non-deleting network
	assert.NoError(t, r.tryToFinalize(context.Background(), &net))
	assert.True(t, controllerutil.ContainsFinalizer(&net, networkFinalizer))

	// tryToFinalize for the deleting network
	net.Status.Phase = cloudv1.NetworkPhaseDeleting
	assert.NoError(t, r.tryToFinalize(context.Background(), &net))
	assert.False(t, controllerutil.ContainsFinalizer(&net, networkFinalizer))

	// tryToFinalize again
	assert.NoError(t, r.tryToFinalize(context.Background(), &net))
	assert.False(t, controllerutil.ContainsFinalizer(&net, networkFinalizer))
}
