package utils

import (
	"testing"

	infra "github.com/tidbcloud/tidb-management-service/api/serverless_infra"
)

func TestValidAuthorizedNetworks(t *testing.T) {
	tests := []struct {
		name     string
		networks []infra.AuthorizedNetwork
		clientIP string
		want     bool
	}{
		{
			name:     "Empty networks",
			networks: nil,
			clientIP: "192.168.1.1",
			want:     true,
		},
		{
			name:     "zero networks",
			networks: make([]infra.AuthorizedNetwork, 0),
			clientIP: "192.168.1.1",
			want:     false,
		},
		{
			name:     "Client IP not in any network",
			networks: []infra.AuthorizedNetwork{{StartIpAddress: "192.168.0.1", EndIpAddress: "192.168.0.10"}},
			clientIP: "192.168.1.1",
			want:     false,
		},
		{
			name:     "empty Client IP",
			networks: []infra.AuthorizedNetwork{{StartIpAddress: "192.168.0.1", EndIpAddress: "192.168.0.10"}},
			clientIP: "",
			want:     true,
		},
		{
			name:     "invalid Client IP",
			networks: []infra.AuthorizedNetwork{{StartIpAddress: "192.168.0.1", EndIpAddress: "192.168.0.10"}},
			clientIP: "1192.168.1.1a",
			want:     true,
		},
		{
			name:     "Client IP in the range",
			networks: []infra.AuthorizedNetwork{{StartIpAddress: "192.168.1.1", EndIpAddress: "192.168.1.10"}},
			clientIP: "192.168.1.5",
			want:     true,
		},
		{
			name:     "Client IP at the start of the range",
			networks: []infra.AuthorizedNetwork{{StartIpAddress: "192.168.1.1", EndIpAddress: "192.168.1.10"}},
			clientIP: "192.168.1.1",
			want:     true,
		},
		{
			name:     "Client IP at the end of the range",
			networks: []infra.AuthorizedNetwork{{StartIpAddress: "192.168.1.1", EndIpAddress: "192.168.1.10"}},
			clientIP: "192.168.1.10",
			want:     true,
		},
		{
			name:     "Invalid IP format",
			networks: []infra.AuthorizedNetwork{{StartIpAddress: "256.1.1.1", EndIpAddress: "192.168.1.10"}},
			clientIP: "192.168.1.5",
			want:     false,
		},
		{
			name:     "Invalid network range",
			networks: []infra.AuthorizedNetwork{{StartIpAddress: "192.168.1.10", EndIpAddress: "192.168.1.1"}},
			clientIP: "192.168.1.5",
			want:     false,
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			if got := ValidAuthorizedNetworks(tt.networks, tt.clientIP); got != tt.want {
				t.Errorf("ValidAuthorizedNetworks() = %v, want %v", got, tt.want)
			}
		})
	}
}

func TestValidPrivatelinkAuthorizedNetworks(t *testing.T) {
	tests := []struct {
		name          string
		networks      []infra.PrivatelinkAuthorizedNetwork
		vpcEndpointID string
		want          bool
	}{
		{
			name:          "nil endpoint ids",
			networks:      nil,
			vpcEndpointID: "vpce-123",
			want:          true,
		},
		{
			name:          "empty endpoint ids",
			networks:      []infra.PrivatelinkAuthorizedNetwork{},
			vpcEndpointID: "vpce-123",
			want:          true,
		},
		{
			name:          "missing vpc endpoint id",
			networks:      []infra.PrivatelinkAuthorizedNetwork{{VpcEndpointId: "vpce-123"}},
			vpcEndpointID: "",
			want:          true,
		},
		{
			name:          "exact match",
			networks:      []infra.PrivatelinkAuthorizedNetwork{{VpcEndpointId: "vpce-123"}, {VpcEndpointId: "vpce-456"}},
			vpcEndpointID: "vpce-456",
			want:          true,
		},
		{
			name:          "wildcard match",
			networks:      []infra.PrivatelinkAuthorizedNetwork{{VpcEndpointId: "*"}},
			vpcEndpointID: "vpce-456",
			want:          true,
		},
		{
			name:          "no match",
			networks:      []infra.PrivatelinkAuthorizedNetwork{{VpcEndpointId: "vpce-123"}},
			vpcEndpointID: "vpce-456",
			want:          false,
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			if got := ValidPrivatelinkAuthorizedNetworks(tt.networks, tt.vpcEndpointID); got != tt.want {
				t.Errorf("ValidPrivatelinkAuthorizedNetworks() = %v, want %v", got, tt.want)
			}
		})
	}
}
