package message

import (
	"errors"
	"testing"

	"github.com/stretchr/testify/assert"
	regionalapiv1 "github.com/tidbcloud/infra-provider/api/tidbcloud/regional-server/v1"
)

func TestCreatePrivateLinkServiceReqValidatable_Validate(t *testing.T) {
	tests := []struct {
		name     string
		request  CreatePrivateLinkServiceReqValidatable
		expected error
	}{
		{
			name: "empty conns",
			request: CreatePrivateLinkServiceReqValidatable{
				CreatePrivateLinkServiceRequest: &regionalapiv1.CreatePrivateLinkServiceRequest{
					PrivateLinkService: &regionalapiv1.PrivateLinkService{
						Id:          "id",
						ClusterId:   "clusterId",
						TidbGroupId: "tidbGroupId",
					},
				},
			},
		},
		{
			name: "azure: ip address is empty",
			request: CreatePrivateLinkServiceReqValidatable{
				CreatePrivateLinkServiceRequest: &regionalapiv1.CreatePrivateLinkServiceRequest{
					PrivateLinkService: &regionalapiv1.PrivateLinkService{
						Id:          "id",
						ClusterId:   "clusterId",
						TidbGroupId: "tidbGroupId",
						Connections: []*regionalapiv1.PrivateLinkService_Connection{
							{
								Info: &regionalapiv1.PrivateLinkService_Connection_Azure_{
									Azure: &regionalapiv1.PrivateLinkService_Connection_Azure{
										PrivateEndpointResourceId: "privateEndpointResourceId",
									},
								},
							},
						},
					},
				},
			},
			expected: errors.New("PrivateLinkService.connections.Azure.PrivateIpAddress is empty"),
		},
		{
			name: "request is successfully validated",
			request: CreatePrivateLinkServiceReqValidatable{
				CreatePrivateLinkServiceRequest: &regionalapiv1.CreatePrivateLinkServiceRequest{
					PrivateLinkService: &regionalapiv1.PrivateLinkService{
						Id:          "id",
						ClusterId:   "clusterId",
						TidbGroupId: "tidbGroupId",
						Connections: []*regionalapiv1.PrivateLinkService_Connection{
							{
								Info: &regionalapiv1.PrivateLinkService_Connection_Azure_{
									Azure: &regionalapiv1.PrivateLinkService_Connection_Azure{
										PrivateEndpointResourceId: "privateEndpointResourceId",
										PrivateIpAddress:          "1.2.3.4",
									},
								},
							},
						},
					},
				},
			},
		},
	}
	for _, test := range tests {
		t.Run(test.name, func(t *testing.T) {
			err := test.request.Validate()
			assert.Equal(t, test.expected, err)
		})
	}
}

func TestUpdatePrivateLinkServiceReqValidatable_Valid(t *testing.T) {
	tests := []struct {
		name     string
		request  UpdatePrivateLinkServiceReqValidatable
		expected error
	}{
		{
			name: "empty conns",
			request: UpdatePrivateLinkServiceReqValidatable{
				UpdatePrivateLinkServiceRequest: &regionalapiv1.UpdatePrivateLinkServiceRequest{
					ClusterId:              "clusterId",
					PrivateLinkServiceId:   "id",
					PrivateLinkConnections: []*regionalapiv1.PrivateLinkService_Connection{},
				},
			},
		},
		{
			name: "azure: ip address is empty",
			request: UpdatePrivateLinkServiceReqValidatable{
				UpdatePrivateLinkServiceRequest: &regionalapiv1.UpdatePrivateLinkServiceRequest{
					ClusterId:            "clusterId",
					PrivateLinkServiceId: "id",
					PrivateLinkConnections: []*regionalapiv1.PrivateLinkService_Connection{
						{
							Info: &regionalapiv1.PrivateLinkService_Connection_Azure_{
								Azure: &regionalapiv1.PrivateLinkService_Connection_Azure{
									PrivateEndpointResourceId: "privateEndpointResourceId",
								},
							},
						},
					},
				},
			},
			expected: errors.New("PrivateLinkService.connections.Azure.PrivateIpAddress is empty"),
		},
		{
			name: "request is successfully validated",
			request: UpdatePrivateLinkServiceReqValidatable{
				UpdatePrivateLinkServiceRequest: &regionalapiv1.UpdatePrivateLinkServiceRequest{
					ClusterId:            "clusterId",
					PrivateLinkServiceId: "id",
					PrivateLinkConnections: []*regionalapiv1.PrivateLinkService_Connection{
						{
							Info: &regionalapiv1.PrivateLinkService_Connection_Azure_{
								Azure: &regionalapiv1.PrivateLinkService_Connection_Azure{
									PrivateEndpointResourceId: "privateEndpointResourceId",
									PrivateIpAddress:          "1.2.3.4",
								},
							},
						},
					},
				},
			},
		},
		{
			name: "azure: ip address is invalid",
			request: UpdatePrivateLinkServiceReqValidatable{
				UpdatePrivateLinkServiceRequest: &regionalapiv1.UpdatePrivateLinkServiceRequest{
					ClusterId:            "clusterId",
					PrivateLinkServiceId: "id",
					PrivateLinkConnections: []*regionalapiv1.PrivateLinkService_Connection{
						{
							Info: &regionalapiv1.PrivateLinkService_Connection_Azure_{
								Azure: &regionalapiv1.PrivateLinkService_Connection_Azure{
									PrivateEndpointResourceId: "privateEndpointResourceId",
									PrivateIpAddress:          "1.2.3",
								},
							},
						},
					},
				},
			},
			expected: errors.New("PrivateLinkService.connections.Azure.PrivateIpAddress is invalid"),
		},
	}
	for _, test := range tests {
		t.Run(test.name, func(t *testing.T) {
			err := test.request.Validate()
			assert.Equal(t, test.expected, err)
		})
	}
}

func TestPausePrivateLinkServiceReqValidatable_Validate(t *testing.T) {
	tests := []struct {
		name     string
		request  PausePrivateLinkServiceReqValidatable
		expected error
	}{
		{
			name: "valid request",
			request: PausePrivateLinkServiceReqValidatable{
				PausePrivateLinkServiceRequest: &regionalapiv1.PausePrivateLinkServiceRequest{
					ClusterId:            "clusterId",
					PrivateLinkServiceId: "id",
				},
			},
		},
		{
			name: "empty clusterId",
			request: PausePrivateLinkServiceReqValidatable{
				PausePrivateLinkServiceRequest: &regionalapiv1.PausePrivateLinkServiceRequest{
					PrivateLinkServiceId: "id",
				},
			},
			expected: errors.New("clusterId is empty"),
		},
		{
			name: "empty privateLinkServiceId",
			request: PausePrivateLinkServiceReqValidatable{
				PausePrivateLinkServiceRequest: &regionalapiv1.PausePrivateLinkServiceRequest{
					ClusterId: "clusterId",
				},
			},
			expected: errors.New("privateLinkServiceId is empty"),
		},
	}
	for _, test := range tests {
		t.Run(test.name, func(t *testing.T) {
			err := test.request.Validate()
			assert.Equal(t, test.expected, err)
		})
	}
}

func TestPurgePrivateLinkMetadataReqValidatable_Validate(t *testing.T) {
	tests := []struct {
		name     string
		request  PurgePrivateLinkMetadataReqValidatable
		expected error
	}{
		{
			name: "valid request",
			request: PurgePrivateLinkMetadataReqValidatable{
				PurgePrivateLinkMetadataRequest: &regionalapiv1.PurgePrivateLinkMetadataRequest{
					ClusterId:            "clusterId",
					PrivateLinkServiceId: "id",
				},
			},
		},
		{
			name: "empty clusterId",
			request: PurgePrivateLinkMetadataReqValidatable{
				PurgePrivateLinkMetadataRequest: &regionalapiv1.PurgePrivateLinkMetadataRequest{
					PrivateLinkServiceId: "id",
				},
			},
			expected: errors.New("clusterId is empty"),
		},
		{
			name: "empty privateLinkServiceId",
			request: PurgePrivateLinkMetadataReqValidatable{
				PurgePrivateLinkMetadataRequest: &regionalapiv1.PurgePrivateLinkMetadataRequest{
					ClusterId: "clusterId",
				},
			},
			expected: errors.New("privateLinkServiceId is empty"),
		},
	}
	for _, test := range tests {
		t.Run(test.name, func(t *testing.T) {
			err := test.request.Validate()
			assert.Equal(t, test.expected, err)
		})
	}
}
