package aws

import (
	"testing"

	awssdk "github.com/aws/aws-sdk-go-v2/aws"
	"github.com/aws/aws-sdk-go-v2/service/ec2/types"

	"security-center-backend/internal/modules/caasm/collector"
)

func TestAppendNetworkInterfaceIPAssetsEmitsPrivatePublicAndIPv6(t *testing.T) {
	result := &collector.AssetResult{}

	appendNetworkInterfaceIPAssets(result, "eni-123", types.NetworkInterface{
		PrivateIpAddress: awssdk.String("10.0.1.10"),
		Association: &types.NetworkInterfaceAssociation{
			PublicIp: awssdk.String("198.51.100.10"),
		},
		PrivateIpAddresses: []types.NetworkInterfacePrivateIpAddress{
			{
				PrivateIpAddress: awssdk.String("10.0.1.11"),
				Association: &types.NetworkInterfaceAssociation{
					PublicIp: awssdk.String("198.51.100.11"),
				},
			},
		},
		Ipv6Addresses: []types.NetworkInterfaceIpv6Address{
			{Ipv6Address: awssdk.String("2001:db8::10")},
		},
	}, "vpce.example.test")

	requireIPAsset(t, result, "eni-123", "10.0.1.10", false)
	requireIPAsset(t, result, "eni-123", "10.0.1.11", false)
	requireIPAsset(t, result, "eni-123", "198.51.100.10", true)
	requireIPAsset(t, result, "eni-123", "198.51.100.11", true)
	requireIPAsset(t, result, "eni-123", "2001:db8::10", true)
}

func TestAppendNATGatewayIPAssetsEmitsGatewayAndENIAddresses(t *testing.T) {
	result := &collector.AssetResult{}

	appendNATGatewayIPAssets(result, "nat-123", types.NatGateway{
		NatGatewayAddresses: []types.NatGatewayAddress{
			{
				PrivateIp:          awssdk.String("10.0.2.10"),
				PublicIp:           awssdk.String("203.0.113.10"),
				NetworkInterfaceId: awssdk.String("eni-nat"),
			},
		},
	})

	requireIPAsset(t, result, "nat-123", "10.0.2.10", false)
	requireIPAsset(t, result, "nat-123", "203.0.113.10", true)
	requireIPAsset(t, result, "eni-nat", "10.0.2.10", false)
	requireIPAsset(t, result, "eni-nat", "203.0.113.10", true)
}

func TestAppendAWSIPAssetSkipsNonLiteralAddresses(t *testing.T) {
	result := &collector.AssetResult{}

	appendAWSIPAsset(result, "asset-1", "service.example.com", "", true)
	appendAWSIPAsset(result, "asset-1", "10.0.0.0/24", "", false)
	appendAWSIPAsset(result, "asset-1", "10.0.0.10", "", false)

	if got := len(result.IPAssets); got != 1 {
		t.Fatalf("IPAssets len = %d, want 1", got)
	}
	requireIPAsset(t, result, "asset-1", "10.0.0.10", false)
}

func requireIPAsset(t *testing.T, result *collector.AssetResult, nativeID, ip string, public bool) {
	t.Helper()
	for _, asset := range result.IPAssets {
		if asset.Asset.NativeID == nativeID && asset.IPAddress == ip && asset.IsPublic == public {
			return
		}
	}
	t.Fatalf("IPAsset %s %s public=%v not found in %#v", nativeID, ip, public, result.IPAssets)
}
