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

package eks

import (
	"context"
	"testing"

	"github.com/crossplane-contrib/provider-aws/apis/v1beta1"
	. "github.com/onsi/gomega"

	"github.com/tidbcloud/eks-provider/controllers/network/task"
	cloudv1 "github.com/tidbcloud/infra-api/api/v1"
	"github.com/tidbcloud/infra-provider/pkg/config"
	"github.com/tidbcloud/infra-provider/pkg/consts"
	"github.com/tidbcloud/infra-provider/pkg/namer"

	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/client-go/kubernetes/scheme"
	"sigs.k8s.io/controller-runtime/pkg/client"
	"sigs.k8s.io/controller-runtime/pkg/client/fake"
)

var (
	fakeNetwork cloudv1.Network
	fakePCName  string
	fakeNamer   = namer.NewNamer()
)

func init() {
	fakeNetwork.Name = "fake-eks-cluster"
	fakePCName = namer.UniqueIdentifier(fakeNetwork.ObjectMeta)
}

func TestProviderConfigDelete(t *testing.T) {
	cases := []struct {
		name    string
		pc      *ProviderConfig
		usages  []client.Object
		done    bool
		deleted bool
	}{
		{
			"no-dependent-usages",
			NewProviderConfig(
				&task.Context{
					Namer:   namer.NewNamer(),
					Network: &fakeNetwork,
				},
			),
			[]client.Object{
				&v1beta1.ProviderConfig{
					ObjectMeta: metav1.ObjectMeta{
						Name: "test-pc",
					},
				},
			},
			true,
			true,
		},
		{
			"exist-dependent-usages",
			NewProviderConfig(
				&task.Context{
					Namer: fakeNamer,
					Config: config.RootConfig{
						ControllerConfig: config.ControllerConfig{
							Network: config.NetworkConfig{
								IgnoreDelete: []string{
									"Bucket",
								},
							},
						},
					},
					Network: &fakeNetwork,
				},
			),
			[]client.Object{
				&v1beta1.ProviderConfig{
					ObjectMeta: metav1.ObjectMeta{
						Name: "test-pc",
					},
				},
				&v1beta1.ProviderConfigUsage{
					ObjectMeta: metav1.ObjectMeta{
						Name: "test-pcu",
						Labels: map[string]string{
							consts.CrossplaneProviderConfigLabel: fakePCName,
						},
					},
				},
			},
			true,
			false,
		},
		{
			"ignore-bucket",
			NewProviderConfig(
				&task.Context{
					Namer: namer.NewNamer(),
					Config: config.RootConfig{
						ControllerConfig: config.ControllerConfig{
							Network: config.NetworkConfig{
								IgnoreDelete: []string{
									"Bucket",
								},
							},
						},
					},
					Network: &fakeNetwork,
				},
			),
			[]client.Object{
				&v1beta1.ProviderConfig{
					ObjectMeta: metav1.ObjectMeta{
						Name: "test-pc",
					},
				},
			},
			true,
			true,
		},
	}

	for _, tc := range cases {
		tc := tc
		t.Run(
			tc.name,
			func(t *testing.T) {
				t.Parallel()
				g := NewGomegaWithT(t)
				s := runtime.NewScheme()
				g.Expect(scheme.AddToScheme(s)).To(Succeed())
				g.Expect(v1beta1.SchemeBuilder.AddToScheme(s)).To(Succeed())
				cli := fake.
					NewClientBuilder().
					WithScheme(s).
					WithObjects(tc.usages...).
					Build()
				tc.pc.Context.Local = cli
				res := tc.pc.Delete(context.TODO())
				if tc.done {
					g.Expect(res.Error()).To(Succeed())
				} else {
					g.Expect(res.Error()).NotTo(Succeed())
					return
				}
				postRes := tc.pc.PostDelete(context.TODO())
				if tc.deleted {
					g.Expect(postRes.Error()).To(Succeed())
				} else {
					g.Expect(postRes.Error()).NotTo(Succeed())
					return
				}
			},
		)
	}
}
