package tidbmanager

import (
	"context"
	"sync"
	"testing"

	"github.com/go-logr/logr"
	. "github.com/onsi/gomega"
	"github.com/tidbcloud/aws-shared-provider/pkg/scheme"
	corev1 "k8s.io/api/core/v1"
	apierrors "k8s.io/apimachinery/pkg/api/errors"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"sigs.k8s.io/controller-runtime/pkg/client"
	"sigs.k8s.io/controller-runtime/pkg/client/fake"
	"sigs.k8s.io/controller-runtime/pkg/log"
)

func Test_tidbManager_removePod(t1 *testing.T) {
	tests := []struct {
		name      string
		queueSize int
		pod       *corev1.Pod
		removePod removePod
		want      bool
	}{
		{
			name:      "remove a pod",
			queueSize: 1,
			pod:       &corev1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "po1", Namespace: "tidb-pool"}},
			removePod: removePod{name: "po1"},
			want:      true,
		},
		{
			name:      "force remove a pod",
			queueSize: 1,
			pod:       &corev1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "po1", Namespace: "tidb-pool"}},
			removePod: removePod{name: "po1", force: true},
			want:      true,
		},
		{
			name:      "remove a not exist pod",
			queueSize: 1,
			pod:       &corev1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "po1", Namespace: "tidb-pool"}},
			removePod: removePod{name: "not_exist_po"},
			want:      true,
		},
		{
			name:      "remove a pod, but queue if full",
			queueSize: 0,
			pod:       &corev1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "po1", Namespace: "tidb-pool"}},
			removePod: removePod{name: "po1"},
			want:      false,
		},
	}
	for _, tt := range tests {
		t1.Run(tt.name, func(t1 *testing.T) {
			g := NewGomegaWithT(t1)
			wg := sync.WaitGroup{}
			t := &tidbManager{
				Logger:            logr.New(log.NullLogSink{}),
				ctx:               context.Background(),
				client:            fake.NewClientBuilder().WithScheme(scheme.Scheme).WithRuntimeObjects(tt.pod).Build(),
				tidbPoolNamespace: tt.pod.Namespace,
				removePodQueue:    make(chan removePod, tt.queueSize),
			}
			if tt.queueSize > 0 {
				t.processRemovePod(2)
			}
			if tt.want {
				wg.Add(1)
				tt.removePod.f = func() { wg.Done() }
			}
			g.Expect(t.removePod(tt.removePod)).To(Equal(tt.want))
			if tt.want {
				wg.Wait()
				g.Expect(apierrors.IsNotFound(t.client.Get(context.Background(), client.ObjectKey{
					Name:      tt.removePod.name,
					Namespace: tt.pod.Namespace,
				}, &corev1.Pod{}))).To(BeTrue())
			}
		})
	}
}
