package cloud

import (
	"testing"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
	ec2v1beta1 "github.com/upbound/provider-aws/apis/ec2/v1beta1"
)

func TestParsePLEDNSEntries(t *testing.T) {
	tests := []struct {
		name                     string
		entries                  []ec2v1beta1.DNSEntryObservation
		logicalToPhysicalZoneMap map[string]string
		expectedRegionalAddress  string
		expectedZonalAddresses   map[string]string
		expectedError            string
	}{
		{
			name: "normal case with 3 AZs and private DNS",
			entries: []ec2v1beta1.DNSEntryObservation{
				{
					DNSName:      strPtr("vpce-023af6250979c0365-j9m3ti32.vpce-svc-0e427c5d93acce18f.us-west-2.vpce.amazonaws.com"),
					HostedZoneID: strPtr("Z1YSA3EXCYUU9Z"),
				},
				{
					DNSName:      strPtr("vpce-023af6250979c0365-j9m3ti32-us-west-2a.vpce-svc-0e427c5d93acce18f.us-west-2.vpce.amazonaws.com"),
					HostedZoneID: strPtr("Z1YSA3EXCYUU9Z"),
				},
				{
					DNSName:      strPtr("vpce-023af6250979c0365-j9m3ti32-us-west-2b.vpce-svc-0e427c5d93acce18f.us-west-2.vpce.amazonaws.com"),
					HostedZoneID: strPtr("Z1YSA3EXCYUU9Z"),
				},
				{
					DNSName:      strPtr("vpce-023af6250979c0365-j9m3ti32-us-west-2c.vpce-svc-0e427c5d93acce18f.us-west-2.vpce.amazonaws.com"),
					HostedZoneID: strPtr("Z1YSA3EXCYUU9Z"),
				},
				{
					DNSName:      strPtr("privatelink-19964668.vwiyyv21q7co.clusters.tidb-cloud.com"),
					HostedZoneID: strPtr("Z09814683NRQ8JG4GH6UE"),
				},
			},
			logicalToPhysicalZoneMap: map[string]string{
				"us-west-2a": "usw2-az1",
				"us-west-2b": "usw2-az2",
				"us-west-2c": "usw2-az3",
			},
			expectedRegionalAddress: "vpce-023af6250979c0365-j9m3ti32.vpce-svc-0e427c5d93acce18f.us-west-2.vpce.amazonaws.com",
			expectedZonalAddresses: map[string]string{
				"usw2-az1": "vpce-023af6250979c0365-j9m3ti32-us-west-2a.vpce-svc-0e427c5d93acce18f.us-west-2.vpce.amazonaws.com",
				"usw2-az2": "vpce-023af6250979c0365-j9m3ti32-us-west-2b.vpce-svc-0e427c5d93acce18f.us-west-2.vpce.amazonaws.com",
				"usw2-az3": "vpce-023af6250979c0365-j9m3ti32-us-west-2c.vpce-svc-0e427c5d93acce18f.us-west-2.vpce.amazonaws.com",
			},
			expectedError: "",
		},
		{
			name: "only private DNS name, no AWS DNS",
			entries: []ec2v1beta1.DNSEntryObservation{
				{
					DNSName:      strPtr("privatelink-19964668.vwiyyv21q7co.clusters.tidb-cloud.com"),
					HostedZoneID: strPtr("Z09814683NRQ8JG4GH6UE"),
				},
			},
			logicalToPhysicalZoneMap: map[string]string{},
			expectedRegionalAddress:  "",
			expectedZonalAddresses:   nil,
			expectedError:            "dns entries of private link should have at least 2",
		},
		{
			name: "only regional DNS without zonal DNS",
			entries: []ec2v1beta1.DNSEntryObservation{
				{
					DNSName:      strPtr("vpce-023af6250979c0365-j9m3ti32.vpce-svc-0e427c5d93acce18f.us-west-2.vpce.amazonaws.com"),
					HostedZoneID: strPtr("Z1YSA3EXCYUU9Z"),
				},
				{
					DNSName:      strPtr("privatelink-19964668.vwiyyv21q7co.clusters.tidb-cloud.com"),
					HostedZoneID: strPtr("Z09814683NRQ8JG4GH6UE"),
				},
			},
			logicalToPhysicalZoneMap: map[string]string{},
			expectedRegionalAddress:  "vpce-023af6250979c0365-j9m3ti32.vpce-svc-0e427c5d93acce18f.us-west-2.vpce.amazonaws.com",
			expectedZonalAddresses:   map[string]string{},
			expectedError:            "",
		},
		{
			name: "DNS with wrong level count (5 levels)",
			entries: []ec2v1beta1.DNSEntryObservation{
				{
					DNSName:      strPtr("vpce-023af6250979c0365-j9m3ti32.vpce-svc-0e427c5d93acce18f.us-west-2.vpce.amazonaws.com"),
					HostedZoneID: strPtr("Z1YSA3EXCYUU9Z"),
				},
				{
					DNSName:      strPtr("vpce-023af6250979c0365.us-west-2.vpce.amazonaws.com"),
					HostedZoneID: strPtr("Z1YSA3EXCYUU9Z"),
				},
			},
			logicalToPhysicalZoneMap: map[string]string{},
			expectedRegionalAddress:  "",
			expectedZonalAddresses:   nil,
			expectedError:            "zonal dns name should have 6 level, but 5",
		},
		{
			name: "DNS with wrong level count (7 levels)",
			entries: []ec2v1beta1.DNSEntryObservation{
				{
					DNSName:      strPtr("vpce-023af6250979c0365-j9m3ti32.vpce-svc-0e427c5d93acce18f.us-west-2.vpce.amazonaws.com"),
					HostedZoneID: strPtr("Z1YSA3EXCYUU9Z"),
				},
				{
					DNSName:      strPtr("vpce-023af6250979c0365-j9m3ti32.extra.vpce-svc-0e427c5d93acce18f.us-west-2.vpce.amazonaws.com"),
					HostedZoneID: strPtr("Z1YSA3EXCYUU9Z"),
				},
			},
			logicalToPhysicalZoneMap: map[string]string{},
			expectedRegionalAddress:  "",
			expectedZonalAddresses:   nil,
			expectedError:            "zonal dns name should have 6 level, but 7",
		},
		{
			name: "zonal DNS with wrong parts count in first level",
			entries: []ec2v1beta1.DNSEntryObservation{
				{
					DNSName:      strPtr("vpce-023af6250979c0365-j9m3ti32.vpce-svc-0e427c5d93acce18f.us-west-2.vpce.amazonaws.com"),
					HostedZoneID: strPtr("Z1YSA3EXCYUU9Z"),
				},
				{
					DNSName:      strPtr("vpce-023af6250979c0365-j9m3ti32-us-west.vpce-svc-0e427c5d93acce18f.us-west-2.vpce.amazonaws.com"),
					HostedZoneID: strPtr("Z1YSA3EXCYUU9Z"),
				},
			},
			logicalToPhysicalZoneMap: map[string]string{},
			expectedRegionalAddress:  "",
			expectedZonalAddresses:   nil,
			expectedError:            "the sixth level of zonal dns name should have 6 parts, but 5",
		},
		{
			name: "multiple private DNS names",
			entries: []ec2v1beta1.DNSEntryObservation{
				{
					DNSName:      strPtr("vpce-023af6250979c0365-j9m3ti32.vpce-svc-0e427c5d93acce18f.us-west-2.vpce.amazonaws.com"),
					HostedZoneID: strPtr("Z1YSA3EXCYUU9Z"),
				},
				{
					DNSName:      strPtr("vpce-023af6250979c0365-j9m3ti32-us-west-2a.vpce-svc-0e427c5d93acce18f.us-west-2.vpce.amazonaws.com"),
					HostedZoneID: strPtr("Z1YSA3EXCYUU9Z"),
				},
				{
					DNSName:      strPtr("privatelink-19964668.vwiyyv21q7co.clusters.tidb-cloud.com"),
					HostedZoneID: strPtr("Z09814683NRQ8JG4GH6UE"),
				},
				{
					DNSName:      strPtr("another-custom.domain.com"),
					HostedZoneID: strPtr("Z09814683NRQ8JG4GH6UE"),
				},
			},
			logicalToPhysicalZoneMap: map[string]string{
				"us-west-2a": "usw2-az1",
			},
			expectedRegionalAddress: "vpce-023af6250979c0365-j9m3ti32.vpce-svc-0e427c5d93acce18f.us-west-2.vpce.amazonaws.com",
			expectedZonalAddresses: map[string]string{
				"usw2-az1": "vpce-023af6250979c0365-j9m3ti32-us-west-2a.vpce-svc-0e427c5d93acce18f.us-west-2.vpce.amazonaws.com",
			},
			expectedError: "",
		},
		{
			name: "single AZ deployment",
			entries: []ec2v1beta1.DNSEntryObservation{
				{
					DNSName:      strPtr("vpce-023af6250979c0365-j9m3ti32.vpce-svc-0e427c5d93acce18f.us-east-1.vpce.amazonaws.com"),
					HostedZoneID: strPtr("Z7HUB22UULQXV"),
				},
				{
					DNSName:      strPtr("vpce-023af6250979c0365-j9m3ti32-us-east-1a.vpce-svc-0e427c5d93acce18f.us-east-1.vpce.amazonaws.com"),
					HostedZoneID: strPtr("Z7HUB22UULQXV"),
				},
			},
			logicalToPhysicalZoneMap: map[string]string{
				"us-east-1a": "use1-az1",
			},
			expectedRegionalAddress: "vpce-023af6250979c0365-j9m3ti32.vpce-svc-0e427c5d93acce18f.us-east-1.vpce.amazonaws.com",
			expectedZonalAddresses: map[string]string{
				"use1-az1": "vpce-023af6250979c0365-j9m3ti32-us-east-1a.vpce-svc-0e427c5d93acce18f.us-east-1.vpce.amazonaws.com",
			},
			expectedError: "",
		},
		{
			name:                     "empty entries",
			entries:                  []ec2v1beta1.DNSEntryObservation{},
			logicalToPhysicalZoneMap: map[string]string{},
			expectedRegionalAddress:  "",
			expectedZonalAddresses:   nil,
			expectedError:            "dns entries of private link should have at least 2",
		},
		{
			name: "missing logical zone in map",
			entries: []ec2v1beta1.DNSEntryObservation{
				{
					DNSName:      strPtr("vpce-023af6250979c0365-j9m3ti32.vpce-svc-0e427c5d93acce18f.us-west-2.vpce.amazonaws.com"),
					HostedZoneID: strPtr("Z1YSA3EXCYUU9Z"),
				},
				{
					DNSName:      strPtr("vpce-023af6250979c0365-j9m3ti32-us-west-2a.vpce-svc-0e427c5d93acce18f.us-west-2.vpce.amazonaws.com"),
					HostedZoneID: strPtr("Z1YSA3EXCYUU9Z"),
				},
			},
			logicalToPhysicalZoneMap: map[string]string{
				"us-west-2b": "usw2-az2", // 不包含 us-west-2a
			},
			expectedRegionalAddress: "vpce-023af6250979c0365-j9m3ti32.vpce-svc-0e427c5d93acce18f.us-west-2.vpce.amazonaws.com",
			expectedZonalAddresses: map[string]string{
				"": "vpce-023af6250979c0365-j9m3ti32-us-west-2a.vpce-svc-0e427c5d93acce18f.us-west-2.vpce.amazonaws.com",
			},
			expectedError: "",
		},
		{
			name: "mixed region zonal DNS",
			entries: []ec2v1beta1.DNSEntryObservation{
				{
					DNSName:      strPtr("vpce-023af6250979c0365-j9m3ti32.vpce-svc-0e427c5d93acce18f.us-west-2.vpce.amazonaws.com"),
					HostedZoneID: strPtr("Z1YSA3EXCYUU9Z"),
				},
				{
					DNSName:      strPtr("vpce-023af6250979c0365-j9m3ti32-us-west-2a.vpce-svc-0e427c5d93acce18f.us-west-2.vpce.amazonaws.com"),
					HostedZoneID: strPtr("Z1YSA3EXCYUU9Z"),
				},
				{
					DNSName:      strPtr("vpce-023af6250979c0365-j9m3ti32-eu-west-1a.vpce-svc-0e427c5d93acce18f.eu-west-1.vpce.amazonaws.com"),
					HostedZoneID: strPtr("Z1YSA3EXCYUU9Z"),
				},
			},
			logicalToPhysicalZoneMap: map[string]string{
				"us-west-2a": "usw2-az1",
				"eu-west-1a": "euw1-az1",
			},
			expectedRegionalAddress: "vpce-023af6250979c0365-j9m3ti32.vpce-svc-0e427c5d93acce18f.us-west-2.vpce.amazonaws.com",
			expectedZonalAddresses: map[string]string{
				"usw2-az1": "vpce-023af6250979c0365-j9m3ti32-us-west-2a.vpce-svc-0e427c5d93acce18f.us-west-2.vpce.amazonaws.com",
				"euw1-az1": "vpce-023af6250979c0365-j9m3ti32-eu-west-1a.vpce-svc-0e427c5d93acce18f.eu-west-1.vpce.amazonaws.com",
			},
			expectedError: "",
		},
		{
			name: "only zonal DNS without regional",
			entries: []ec2v1beta1.DNSEntryObservation{
				{
					DNSName:      strPtr("vpce-023af6250979c0365-j9m3ti32-us-west-2a.vpce-svc-0e427c5d93acce18f.us-west-2.vpce.amazonaws.com"),
					HostedZoneID: strPtr("Z1YSA3EXCYUU9Z"),
				},
				{
					DNSName:      strPtr("vpce-023af6250979c0365-j9m3ti32-us-west-2b.vpce-svc-0e427c5d93acce18f.us-west-2.vpce.amazonaws.com"),
					HostedZoneID: strPtr("Z1YSA3EXCYUU9Z"),
				},
			},
			logicalToPhysicalZoneMap: map[string]string{
				"us-west-2a": "usw2-az1",
				"us-west-2b": "usw2-az2",
			},
			expectedRegionalAddress: "",
			expectedZonalAddresses: map[string]string{
				"usw2-az1": "vpce-023af6250979c0365-j9m3ti32-us-west-2a.vpce-svc-0e427c5d93acce18f.us-west-2.vpce.amazonaws.com",
				"usw2-az2": "vpce-023af6250979c0365-j9m3ti32-us-west-2b.vpce-svc-0e427c5d93acce18f.us-west-2.vpce.amazonaws.com",
			},
			expectedError: "",
		},
		{
			name: "special characters in VPC endpoint ID",
			entries: []ec2v1beta1.DNSEntryObservation{
				{
					DNSName:      strPtr("vpce-0a1b2c3d4e5f6g7h8-abc123xyz.vpce-svc-9i8h7g6f5e4d3c2b1a.ap-south-1.vpce.amazonaws.com"),
					HostedZoneID: strPtr("Z1YSA3EXCYUU9Z"),
				},
				{
					DNSName:      strPtr("vpce-0a1b2c3d4e5f6g7h8-abc123xyz-ap-south-1a.vpce-svc-9i8h7g6f5e4d3c2b1a.ap-south-1.vpce.amazonaws.com"),
					HostedZoneID: strPtr("Z1YSA3EXCYUU9Z"),
				},
			},
			logicalToPhysicalZoneMap: map[string]string{
				"ap-south-1a": "aps1-az1",
			},
			expectedRegionalAddress: "vpce-0a1b2c3d4e5f6g7h8-abc123xyz.vpce-svc-9i8h7g6f5e4d3c2b1a.ap-south-1.vpce.amazonaws.com",
			expectedZonalAddresses: map[string]string{
				"aps1-az1": "vpce-0a1b2c3d4e5f6g7h8-abc123xyz-ap-south-1a.vpce-svc-9i8h7g6f5e4d3c2b1a.ap-south-1.vpce.amazonaws.com",
			},
			expectedError: "",
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			regionalAddress, zonalAddresses, err := parsePLEDNSEntries(tt.entries, tt.logicalToPhysicalZoneMap)

			if tt.expectedError != "" {
				require.Error(t, err)
				assert.Contains(t, err.Error(), tt.expectedError)
			} else {
				require.NoError(t, err)
				assert.Equal(t, tt.expectedRegionalAddress, regionalAddress)
				assert.Equal(t, tt.expectedZonalAddresses, zonalAddresses)
			}
		})
	}
}

func strPtr(s string) *string {
	return &s
}
