package config

import (
	"testing"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
	"k8s.io/utils/ptr"
)

func TestGetO11yNodePools(t *testing.T) {
	defaultMinSize := 0
	defaultMaxSize := 10
	defaultSystemVolumeSize := int64(20)

	tests := []struct {
		name        string
		cfg         O11yNodeConfig
		expected    []O11yNodePoolConfigValues
		expectError string
	}{
		{
			name:     "disabled returns nil",
			cfg:      O11yNodeConfig{Enabled: false, Pools: []O11yNodePoolConfig{{InstanceType: "m6i.large", CPU: 2, MemoryGi: 8}}},
			expected: nil,
		},
		{
			name:     "enabled with empty pools returns empty slice",
			cfg:      O11yNodeConfig{Enabled: true},
			expected: []O11yNodePoolConfigValues{},
		},
		{
			name: "all from config file",
			cfg: O11yNodeConfig{
				Enabled: true,
				Pools: []O11yNodePoolConfig{{
					AMIType:          "AL2_x86_64",
					InstanceType:     "config-instance-type",
					MinSize:          ptr.To(int32(1)),
					MaxSize:          ptr.To(int32(15)),
					SystemVolumeSize: ptr.To(int64(80)),
					CPU:              4,
					MemoryGi:         16,
				}},
			},
			expected: []O11yNodePoolConfigValues{{
				AMIType:          "AL2_x86_64",
				InstanceType:     "config-instance-type",
				MinSize:          1,
				MaxSize:          15,
				SystemVolumeSize: 80,
				CPU:              4,
				MemoryGi:         16,
			}},
		},
		{
			name: "partial override keeps provider defaults for sizes",
			cfg: O11yNodeConfig{
				Enabled: true,
				Pools: []O11yNodePoolConfig{{
					InstanceType: "m6i.2xlarge",
					CPU:          8,
					MemoryGi:     32,
				}},
			},
			expected: []O11yNodePoolConfigValues{{
				InstanceType:     "m6i.2xlarge",
				MinSize:          defaultMinSize,
				MaxSize:          defaultMaxSize,
				SystemVolumeSize: defaultSystemVolumeSize,
				CPU:              8,
				MemoryGi:         32,
			}},
		},
		{
			name: "duplicate instanceType keeps first",
			cfg: O11yNodeConfig{
				Enabled: true,
				Pools: []O11yNodePoolConfig{
					{InstanceType: "t3.medium", CPU: 2, MemoryGi: 4, MaxSize: ptr.To(int32(5))},
					{InstanceType: "t3.medium", CPU: 2, MemoryGi: 4, MaxSize: ptr.To(int32(20))},
					{InstanceType: "m6i.large", CPU: 2, MemoryGi: 8},
				},
			},
			expected: []O11yNodePoolConfigValues{
				{
					InstanceType:     "t3.medium",
					MinSize:          defaultMinSize,
					MaxSize:          5,
					SystemVolumeSize: defaultSystemVolumeSize,
					CPU:              2,
					MemoryGi:         4,
				},
				{
					InstanceType:     "m6i.large",
					MinSize:          defaultMinSize,
					MaxSize:          defaultMaxSize,
					SystemVolumeSize: defaultSystemVolumeSize,
					CPU:              2,
					MemoryGi:         8,
				},
			},
		},
		{
			name: "empty instanceType returns error",
			cfg: O11yNodeConfig{
				Enabled: true,
				Pools:   []O11yNodePoolConfig{{CPU: 2, MemoryGi: 4}},
			},
			expectError: "instanceType is required",
		},
		{
			name: "missing cpu returns error",
			cfg: O11yNodeConfig{
				Enabled: true,
				Pools:   []O11yNodePoolConfig{{InstanceType: "t3.medium", MemoryGi: 4}},
			},
			expectError: "cpu and memoryGi must be positive",
		},
		{
			name: "missing memoryGi returns error",
			cfg: O11yNodeConfig{
				Enabled: true,
				Pools:   []O11yNodePoolConfig{{InstanceType: "t3.medium", CPU: 2}},
			},
			expectError: "cpu and memoryGi must be positive",
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			got, err := GetO11yNodePools(tt.cfg, defaultMinSize, defaultMaxSize, defaultSystemVolumeSize)
			if tt.expectError != "" {
				require.Error(t, err)
				assert.Contains(t, err.Error(), tt.expectError)
				return
			}
			require.NoError(t, err)
			assert.Equal(t, tt.expected, got)
		})
	}
}
