package zoneredundantevicter

import (
	"context"
	"testing"

	. "github.com/onsi/gomega"
	"github.com/tidbcloud/aws-shared-provider/pkg/types"
	"github.com/tidbcloud/aws-shared-provider/pkg/utils/labels"
	corev1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"sigs.k8s.io/controller-runtime/pkg/client"
)

func TestReconciler_evictPodPVC(t *testing.T) {
	tests := []struct {
		name         string
		objs         []client.Object
		pod          *corev1.Pod
		wantExistPVC bool
	}{
		{
			name: "pvc not exist",
			pod: &corev1.Pod{
				ObjectMeta: metav1.ObjectMeta{
					Name:   "pod-pvc-not-exist",
					Labels: map[string]string{labels.ZREvicterPVCEvictableKey: "true"},
				},
				Spec: corev1.PodSpec{
					Volumes: []corev1.Volume{{
						VolumeSource: corev1.VolumeSource{PersistentVolumeClaim: &corev1.PersistentVolumeClaimVolumeSource{
							ClaimName: "pvc-not-exist",
						}},
					}},
				},
			},
		},
		{
			name: "empty pvc AnnoVolumeSelectedNode",
			objs: []client.Object{
				&corev1.PersistentVolumeClaim{ObjectMeta: metav1.ObjectMeta{
					Name: "pvc-empty-volume-selected-node",
				}},
			},
			pod: &corev1.Pod{
				ObjectMeta: metav1.ObjectMeta{
					Name:   "pod-empty-volume-selected-node",
					Labels: map[string]string{labels.ZREvicterPVCEvictableKey: "true"},
				},
				Spec: corev1.PodSpec{
					Volumes: []corev1.Volume{{
						VolumeSource: corev1.VolumeSource{PersistentVolumeClaim: &corev1.PersistentVolumeClaimVolumeSource{
							ClaimName: "pvc-empty-volume-selected-node",
						}},
					}},
				},
			},
			wantExistPVC: true,
		},
		{
			name: "evict pvc",
			objs: []client.Object{
				&corev1.PersistentVolumeClaim{ObjectMeta: metav1.ObjectMeta{
					Name:        "pvc-evict",
					Annotations: map[string]string{types.AnnoVolumeSelectedNode: "node1"},
				}},
			},
			pod: &corev1.Pod{
				ObjectMeta: metav1.ObjectMeta{
					Name:   "pod-evict-pvc",
					Labels: map[string]string{labels.ZREvicterPVCEvictableKey: "true"},
				},
				Spec: corev1.PodSpec{
					Volumes: []corev1.Volume{{
						VolumeSource: corev1.VolumeSource{PersistentVolumeClaim: &corev1.PersistentVolumeClaimVolumeSource{
							ClaimName: "pvc-evict",
						}},
					}},
				},
			},
			wantExistPVC: false,
		},
		{
			name: "unevictable pvc",
			objs: []client.Object{
				&corev1.PersistentVolumeClaim{ObjectMeta: metav1.ObjectMeta{
					Name:        "pvc-not-evict",
					Annotations: map[string]string{types.AnnoVolumeSelectedNode: "node1"},
				}},
			},
			pod: &corev1.Pod{
				ObjectMeta: metav1.ObjectMeta{Name: "pod-not-evict-pvc"},
				Spec: corev1.PodSpec{
					Volumes: []corev1.Volume{{
						VolumeSource: corev1.VolumeSource{PersistentVolumeClaim: &corev1.PersistentVolumeClaimVolumeSource{
							ClaimName: "pvc-not-evict",
						}},
					}},
				},
			},
			wantExistPVC: true,
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			g := NewGomegaWithT(t)
			r := newFakeReconciler(tt.objs, nil, nil, nil)
			g.Expect(r.evictPodPVC(context.Background(), tt.pod)).To(Succeed())

			pvcList := &corev1.PersistentVolumeClaimList{}
			g.Expect(r.Client.List(context.Background(), pvcList)).To(Succeed())
			if tt.wantExistPVC {
				g.Expect(pvcList.Items).To(HaveLen(1))
			} else {
				g.Expect(pvcList.Items).To(HaveLen(0))
			}
		})
	}
}
