package ack

import (
	"testing"

	"github.com/tidbcloud/infra-provider/regional-server/api/v1alpha1"
	"github.com/tidbcloud/infra-provider/regional-server/pkg/controllers/loadbalancer/task"
)

func TestSecurityGroup_allowedPorts(t *testing.T) {
	t.Parallel()

	cases := []struct {
		name string
		spec v1alpha1.LoadBalancerSpec
		want []allowedPort
	}{
		{
			name: "legacy single Port defaults to tcp",
			spec: v1alpha1.LoadBalancerSpec{Port: 4000},
			want: []allowedPort{{Port: 4000, Protocol: "tcp"}},
		},
		{
			name: "Ports propagate UDP and TCP literals to IPProtocol",
			spec: v1alpha1.LoadBalancerSpec{
				Ports: []v1alpha1.LoadBalancerPort{
					{Name: "tcp-listener", Port: 9042, Protocol: "TCP"},
					{Name: "udp-listener", Port: 5353, Protocol: "UDP"},
				},
			},
			want: []allowedPort{
				{Port: 9042, Protocol: "tcp"},
				{Port: 5353, Protocol: "udp"},
			},
		},
		{
			name: "empty and TLS protocol both fall back to tcp",
			spec: v1alpha1.LoadBalancerSpec{
				Ports: []v1alpha1.LoadBalancerPort{
					{Name: "default", Port: 9042},
					{Name: "tls", Port: 9142, Protocol: "TLS"},
				},
			},
			want: []allowedPort{
				{Port: 9042, Protocol: "tcp"},
				{Port: 9142, Protocol: "tcp"},
			},
		},
		{
			name: "duplicate Port deduped on first protocol seen",
			spec: v1alpha1.LoadBalancerSpec{
				Ports: []v1alpha1.LoadBalancerPort{
					{Name: "first", Port: 9042, Protocol: "UDP"},
					{Name: "second", Port: 9042, Protocol: "TCP"},
				},
			},
			want: []allowedPort{{Port: 9042, Protocol: "udp"}},
		},
	}

	for _, tc := range cases {
		t.Run(tc.name, func(t *testing.T) {
			t.Parallel()

			sg := &securityGroup{BaseTask: &task.BaseTask{Context: &task.Context{
				LoadBalancer: &v1alpha1.LoadBalancer{Spec: tc.spec},
			}}}
			got := sg.allowedPorts()
			if len(got) != len(tc.want) {
				t.Fatalf("len(allowedPorts()) = %d, want %d (got %+v)", len(got), len(tc.want), got)
			}
			for i := range tc.want {
				if got[i] != tc.want[i] {
					t.Fatalf("allowedPorts()[%d] = %+v, want %+v", i, got[i], tc.want[i])
				}
			}
		})
	}
}
