package namespace

import (
	"testing"

	"github.com/stretchr/testify/assert"
	cloudv1 "github.com/tidbcloud/infra-api/api/v1"
	"github.com/tidbcloud/shared-provider/pkg/utils/labels"
	corev1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

func TestNewOwnedNamespace(t *testing.T) {
	cases := []struct {
		net             *cloudv1.Network
		namespace       *corev1.Namespace
		resultNamespace *corev1.Namespace
	}{
		{
			net: &cloudv1.Network{
				ObjectMeta: metav1.ObjectMeta{
					Annotations: map[string]string{
						NamespaceKey: "test",
					},
				},
			},
			namespace: nil,
			resultNamespace: &corev1.Namespace{
				ObjectMeta: metav1.ObjectMeta{
					Name: "test",
					Labels: map[string]string{
						labels.LabelKeyOwnedBy:   "",
						labels.LabelKeyNamespace: "",
						labels.LabelKeyName:      "",
						labels.LabelKeyUID:       "",
					},
				},
			},
		},
		{
			net: &cloudv1.Network{
				ObjectMeta: metav1.ObjectMeta{
					Annotations: nil,
					Namespace:   NamespacePrefix + "test",
					Labels: map[string]string{
						labels.LabelKeyOwnedBy:   "",
						labels.LabelKeyNamespace: "",
						labels.LabelKeyName:      "",
						labels.LabelKeyUID:       "",
					},
				},
			},
			namespace: nil,
			resultNamespace: &corev1.Namespace{
				ObjectMeta: metav1.ObjectMeta{
					Name: NamespacePrefix + NamespacePrefix + "test",
					Labels: map[string]string{
						labels.LabelKeyOwnedBy:   "",
						labels.LabelKeyNamespace: "",
						labels.LabelKeyName:      "",
						labels.LabelKeyUID:       "",
					},
				},
			},
		},
		{
			net: &cloudv1.Network{
				ObjectMeta: metav1.ObjectMeta{
					Annotations: map[string]string{
						NamespaceKey: "test",
					},
					Namespace: "testNs",
					Name:      "testName",
				},
			},
			namespace: &corev1.Namespace{
				ObjectMeta: metav1.ObjectMeta{
					Name: NamespacePrefix + "test",
					Labels: map[string]string{
						"test": "1",
					},
				},
			},
			resultNamespace: &corev1.Namespace{
				ObjectMeta: metav1.ObjectMeta{
					Name: NamespacePrefix + "test",
					Labels: map[string]string{
						labels.LabelKeyOwnedBy:   ".",
						labels.LabelKeyNamespace: "testNs",
						labels.LabelKeyName:      "testName",
						labels.LabelKeyUID:       "",
						"test":                   "1",
					},
				},
			},
		},
	}

	for _, c := range cases {
		resultNs := NewOwnedNamespace(c.net, c.namespace)

		assert.Equal(t, resultNs.Name, c.resultNamespace.Name)

		if c.namespace != nil {
			println(resultNs.Labels)
			for k, v := range c.resultNamespace.Labels {
				assert.Equal(t, v, resultNs.Labels[k])
			}
		}
	}
}

func TestSetOwnedNamespaceNameInNetwork(t *testing.T) {
	cases := []struct {
		net             *cloudv1.Network
		namespace       string
		resultNamespace string
	}{
		{
			net: &cloudv1.Network{
				ObjectMeta: metav1.ObjectMeta{
					Annotations: nil,
				},
			},
			namespace:       "test",
			resultNamespace: "test",
		},
		{
			net: &cloudv1.Network{
				ObjectMeta: metav1.ObjectMeta{
					Annotations: map[string]string{
						NamespaceKey: "oldNs",
					},
				},
			},
			namespace:       "newNs",
			resultNamespace: "newNs",
		},
	}

	for _, c := range cases {
		SetOwnedNamespaceNameInNetwork(c.net, c.namespace)

		assert.Equal(t, c.net.Annotations[NamespaceKey], c.resultNamespace)
	}
}

func TestGetOwnedNamespaceNameFromNetwork(t *testing.T) {
	cases := []struct {
		net       *cloudv1.Network
		namespace string
	}{
		{
			net: &cloudv1.Network{
				ObjectMeta: metav1.ObjectMeta{
					Namespace: "test",
					Annotations: map[string]string{
						NamespaceKey: "shared-tier-test",
					},
				},
			},
			namespace: "shared-tier-test",
		},
		{
			net: &cloudv1.Network{
				ObjectMeta: metav1.ObjectMeta{
					Namespace:   "test",
					Annotations: map[string]string{},
				},
			},
			namespace: NamespacePrefix + "test",
		},
		{
			net: &cloudv1.Network{
				ObjectMeta: metav1.ObjectMeta{
					Namespace: "test",
					Annotations: map[string]string{
						NamespaceKey: "test",
					},
				},
			},
			namespace: "test",
		},
	}

	for _, c := range cases {
		ns := GetOwnedNamespaceNameFromNetwork(c.net)
		assert.Equal(t, c.namespace, ns)
	}
}
