package eks

import (
	"testing"

	"github.com/stretchr/testify/assert"
	"github.com/tidbcloud/infra-provider/regional-server/api/v1alpha1"
	"github.com/tidbcloud/infra-provider/regional-server/pkg/util"
	s3v1beta1 "github.com/upbound/provider-aws/apis/s3/v1beta1"
)

func TestMakeRuleParams(t *testing.T) {
	tests := []struct {
		name     string
		rules    []v1alpha1.BucketLifecycleRule
		expected []s3v1beta1.BucketLifecycleConfigurationRuleParameters
	}{
		{
			name: "single rule with all fields",
			rules: []v1alpha1.BucketLifecycleRule{
				{
					Id:                             "test-rule",
					Enabled:                        true,
					ExpirationDays:                 30,
					IncompleteUploadExpirationDays: 7,
					PrefixFilter:                   "logs/",
					TagsFilter: []v1alpha1.BucketTagFilter{
						{Key: "env", Value: "test"},
					},
				},
			},
			expected: []s3v1beta1.BucketLifecycleConfigurationRuleParameters{
				{
					ID:     util.Pointer("test-rule"),
					Status: util.Pointer("Enabled"),
					Filter: []s3v1beta1.RuleFilterParameters{
						{
							And: []s3v1beta1.AndParameters{
								{
									Prefix: util.Pointer("logs/"),
									Tags: map[string]*string{
										"env": util.Pointer("test"),
									},
								},
							},
						},
					},
					Expiration: []s3v1beta1.RuleExpirationParameters{
						{Days: util.Pointer(float64(30))},
					},
					AbortIncompleteMultipartUpload: []s3v1beta1.AbortIncompleteMultipartUploadParameters{
						{DaysAfterInitiation: util.Pointer(float64(7))},
					},
				},
			},
		},
		{
			name: "disabled rule with only expiration",
			rules: []v1alpha1.BucketLifecycleRule{
				{
					Id:             "disabled-rule",
					Enabled:        false,
					ExpirationDays: 90,
				},
			},
			expected: []s3v1beta1.BucketLifecycleConfigurationRuleParameters{
				{
					ID:     util.Pointer("disabled-rule"),
					Status: util.Pointer("Disabled"),
					Expiration: []s3v1beta1.RuleExpirationParameters{
						{Days: util.Pointer(float64(90))},
					},
				},
			},
		},
		{
			name: "rule with only prefix filter",
			rules: []v1alpha1.BucketLifecycleRule{
				{
					Id:           "prefix-only",
					Enabled:      true,
					PrefixFilter: "documents/",
				},
			},
			expected: []s3v1beta1.BucketLifecycleConfigurationRuleParameters{
				{
					ID:     util.Pointer("prefix-only"),
					Status: util.Pointer("Enabled"),
					Filter: []s3v1beta1.RuleFilterParameters{
						{
							Prefix: util.Pointer("documents/"),
						},
					},
				},
			},
		},
		{
			name: "rule with only tags filter",
			rules: []v1alpha1.BucketLifecycleRule{
				{
					Id:      "tags-only",
					Enabled: true,
					TagsFilter: []v1alpha1.BucketTagFilter{
						{Key: "type", Value: "backup"},
						{Key: "retention", Value: "short"},
					},
				},
			},
			expected: []s3v1beta1.BucketLifecycleConfigurationRuleParameters{
				{
					ID:     util.Pointer("tags-only"),
					Status: util.Pointer("Enabled"),
					Filter: []s3v1beta1.RuleFilterParameters{
						{
							Tag: []s3v1beta1.TagParameters{
								{Key: util.Pointer("type"), Value: util.Pointer("backup")},
								{Key: util.Pointer("retention"), Value: util.Pointer("short")},
							},
						},
					},
				},
			},
		},
		{
			name: "multiple rules",
			rules: []v1alpha1.BucketLifecycleRule{
				{
					Id:             "rule1",
					Enabled:        true,
					ExpirationDays: 30,
				},
				{
					Id:                             "rule2",
					Enabled:                        false,
					IncompleteUploadExpirationDays: 14,
				},
			},
			expected: []s3v1beta1.BucketLifecycleConfigurationRuleParameters{
				{
					ID:     util.Pointer("rule1"),
					Status: util.Pointer("Enabled"),
					Expiration: []s3v1beta1.RuleExpirationParameters{
						{Days: util.Pointer(float64(30))},
					},
				},
				{
					ID:     util.Pointer("rule2"),
					Status: util.Pointer("Disabled"),
					AbortIncompleteMultipartUpload: []s3v1beta1.AbortIncompleteMultipartUploadParameters{
						{DaysAfterInitiation: util.Pointer(float64(14))},
					},
				},
			},
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			result := makeRuleParams(tt.rules)
			assert.Equal(t, tt.expected, result)
		})
	}
}

func TestMakeRuleFilterParameters(t *testing.T) {
	tests := []struct {
		name     string
		rule     v1alpha1.BucketLifecycleRule
		expected s3v1beta1.RuleFilterParameters
	}{
		{
			name: "prefix and tags filter",
			rule: v1alpha1.BucketLifecycleRule{
				PrefixFilter: "logs/",
				TagsFilter: []v1alpha1.BucketTagFilter{
					{Key: "env", Value: "production"},
					{Key: "team", Value: "backend"},
				},
			},
			expected: s3v1beta1.RuleFilterParameters{
				And: []s3v1beta1.AndParameters{
					{
						Prefix: util.Pointer("logs/"),
						Tags: map[string]*string{
							"env":  util.Pointer("production"),
							"team": util.Pointer("backend"),
						},
					},
				},
			},
		},
		{
			name: "prefix only filter",
			rule: v1alpha1.BucketLifecycleRule{
				PrefixFilter: "documents/",
				TagsFilter:   []v1alpha1.BucketTagFilter{},
			},
			expected: s3v1beta1.RuleFilterParameters{
				Prefix: util.Pointer("documents/"),
			},
		},
		{
			name: "tags only filter",
			rule: v1alpha1.BucketLifecycleRule{
				PrefixFilter: "",
				TagsFilter: []v1alpha1.BucketTagFilter{
					{Key: "type", Value: "temporary"},
					{Key: "importance", Value: "low"},
				},
			},
			expected: s3v1beta1.RuleFilterParameters{
				Tag: []s3v1beta1.TagParameters{
					{Key: util.Pointer("type"), Value: util.Pointer("temporary")},
					{Key: util.Pointer("importance"), Value: util.Pointer("low")},
				},
			},
		},
		{
			name: "single tag filter",
			rule: v1alpha1.BucketLifecycleRule{
				PrefixFilter: "",
				TagsFilter: []v1alpha1.BucketTagFilter{
					{Key: "category", Value: "archive"},
				},
			},
			expected: s3v1beta1.RuleFilterParameters{
				Tag: []s3v1beta1.TagParameters{
					{Key: util.Pointer("category"), Value: util.Pointer("archive")},
				},
			},
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			result := makeRuleFilterParameters(tt.rule)
			assert.Equal(t, tt.expected, result)
		})
	}
}
