package privatelink

import (
	"testing"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"

	globalcommonv1 "github.com/tidbcloud/tidb-management-service/api/spec/global/common/v1"
	globalngv1 "github.com/tidbcloud/tidb-management-service/api/spec/global/nextgen/v1"
	"github.com/tidbcloud/tidb-management-service/nextgen-global-service/pkg/config"
)

func newTestService() *service {
	return &service{
		cfg: &config.Config{
			BizConfig: config.BizConfig{
				AwsPrivateLinkEndpointLimitPerGroup: 15,
			},
		},
	}
}

func TestShouldImportPrivateLinkConnections(t *testing.T) {
	awsConn := []*globalngv1.PrivateLinkConnection{{EndpointId: "vpce-0123456789abcdef0"}}

	cases := []struct {
		name     string
		provider globalcommonv1.CloudProvider_Name
		req      *globalngv1.CreatePrivateLinkServiceRequest
		want     bool
	}{
		{
			name:     "aws with service_name and connections",
			provider: globalcommonv1.CloudProvider_AWS,
			req: &globalngv1.CreatePrivateLinkServiceRequest{
				PrivateLinkService:     &globalngv1.PrivateLinkService{ServiceName: "com.amazonaws.vpce.us-east-1.vpce-svc-0123"},
				PrivateLinkConnections: awsConn,
			},
			want: true,
		},
		{
			name:     "aws without service_name",
			provider: globalcommonv1.CloudProvider_AWS,
			req: &globalngv1.CreatePrivateLinkServiceRequest{
				PrivateLinkService:     &globalngv1.PrivateLinkService{},
				PrivateLinkConnections: awsConn,
			},
			want: false,
		},
		{
			name:     "aws with service_name but no connections",
			provider: globalcommonv1.CloudProvider_AWS,
			req: &globalngv1.CreatePrivateLinkServiceRequest{
				PrivateLinkService: &globalngv1.PrivateLinkService{ServiceName: "x"},
			},
			want: false,
		},
		{
			name:     "non-aws ignored",
			provider: globalcommonv1.CloudProvider_AZURE,
			req: &globalngv1.CreatePrivateLinkServiceRequest{
				PrivateLinkService:     &globalngv1.PrivateLinkService{ServiceName: "x"},
				PrivateLinkConnections: awsConn,
			},
			want: false,
		},
	}

	for _, tc := range cases {
		t.Run(tc.name, func(t *testing.T) {
			assert.Equal(t, tc.want, shouldImportPrivateLinkConnections(tc.provider, tc.req))
		})
	}
}

func TestValidateImportPrivateLinkConnections(t *testing.T) {
	svc := newTestService()
	const tidbGroupID uint64 = 100
	awsProvider := globalcommonv1.CloudProvider_AWS

	t.Run("ok", func(t *testing.T) {
		err := svc.validateImportPrivateLinkConnections(awsProvider, tidbGroupID, []*globalngv1.PrivateLinkConnection{
			{
				EndpointId:   "vpce-0123456789abcdef0",
				EndpointType: globalngv1.PrivateLinkConnection_CUSTOMER,
			},
			{
				EndpointId:   "vpce-fedcba9876543210f",
				EndpointType: globalngv1.PrivateLinkConnection_CUSTOMER,
			},
		})
		require.NoError(t, err)
	})

	t.Run("invalid endpoint id", func(t *testing.T) {
		err := svc.validateImportPrivateLinkConnections(awsProvider, tidbGroupID, []*globalngv1.PrivateLinkConnection{
			{
				EndpointId:   "not-a-vpce",
				EndpointType: globalngv1.PrivateLinkConnection_CUSTOMER,
			},
		})
		require.Error(t, err)
		assert.Contains(t, err.Error(), "invalid endpoint id")
	})

	t.Run("duplicate endpoint id", func(t *testing.T) {
		err := svc.validateImportPrivateLinkConnections(awsProvider, tidbGroupID, []*globalngv1.PrivateLinkConnection{
			{
				EndpointId:   "vpce-0123456789abcdef0",
				EndpointType: globalngv1.PrivateLinkConnection_CUSTOMER,
			},
			{
				EndpointId:   "vpce-0123456789abcdef0",
				EndpointType: globalngv1.PrivateLinkConnection_CUSTOMER,
			},
		})
		require.Error(t, err)
		assert.Contains(t, err.Error(), "duplicated endpoint id")
	})

	t.Run("empty list", func(t *testing.T) {
		require.NoError(t, svc.validateImportPrivateLinkConnections(awsProvider, tidbGroupID, nil))
	})

	t.Run("exceeds per-group limit", func(t *testing.T) {
		small := &service{cfg: &config.Config{BizConfig: config.BizConfig{AwsPrivateLinkEndpointLimitPerGroup: 1}}}
		err := small.validateImportPrivateLinkConnections(awsProvider, tidbGroupID, []*globalngv1.PrivateLinkConnection{
			{
				EndpointId:   "vpce-0123456789abcdef0",
				EndpointType: globalngv1.PrivateLinkConnection_CUSTOMER,
			},
			{
				EndpointId:   "vpce-fedcba9876543210f",
				EndpointType: globalngv1.PrivateLinkConnection_CUSTOMER,
			},
		})
		require.Error(t, err)
		assert.Contains(t, err.Error(), "too many endpoints")
	})
}
