/*
Package utils provides common utility functions used across all modules.
This file contains tests for safe slice operations.
*/
package utils

import (
	"reflect"
	"testing"
)

// TestRemoveAtIndex_ValidIndex tests removing elements at valid indices.
// Validates: Requirement 6.3 - Safe slice removal
func TestRemoveAtIndex_ValidIndex(t *testing.T) {
	tests := []struct {
		name     string
		slice    []string
		index    int
		expected []string
	}{
		{
			name:     "remove first element",
			slice:    []string{"a", "b", "c", "d"},
			index:    0,
			expected: []string{"b", "c", "d"},
		},
		{
			name:     "remove middle element",
			slice:    []string{"a", "b", "c", "d"},
			index:    1,
			expected: []string{"a", "c", "d"},
		},
		{
			name:     "remove last element",
			slice:    []string{"a", "b", "c", "d"},
			index:    3,
			expected: []string{"a", "b", "c"},
		},
		{
			name:     "remove only element",
			slice:    []string{"a"},
			index:    0,
			expected: []string{},
		},
		{
			name:     "remove from two element slice - first",
			slice:    []string{"a", "b"},
			index:    0,
			expected: []string{"b"},
		},
		{
			name:     "remove from two element slice - second",
			slice:    []string{"a", "b"},
			index:    1,
			expected: []string{"a"},
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			result := RemoveAtIndex(tt.slice, tt.index)
			if !reflect.DeepEqual(result, tt.expected) {
				t.Errorf("RemoveAtIndex(%v, %d) = %v, expected %v",
					tt.slice, tt.index, result, tt.expected)
			}
		})
	}
}

// TestRemoveAtIndex_InvalidIndex tests that invalid indices don't cause panics.
// Validates: Requirement 6.3 - Safe slice removal to avoid index out of bounds
func TestRemoveAtIndex_InvalidIndex(t *testing.T) {
	tests := []struct {
		name     string
		slice    []string
		index    int
		expected []string
	}{
		{
			name:     "negative index",
			slice:    []string{"a", "b", "c"},
			index:    -1,
			expected: []string{"a", "b", "c"},
		},
		{
			name:     "index equals length",
			slice:    []string{"a", "b", "c"},
			index:    3,
			expected: []string{"a", "b", "c"},
		},
		{
			name:     "index greater than length",
			slice:    []string{"a", "b", "c"},
			index:    10,
			expected: []string{"a", "b", "c"},
		},
		{
			name:     "very large negative index",
			slice:    []string{"a", "b", "c"},
			index:    -1000,
			expected: []string{"a", "b", "c"},
		},
		{
			name:     "very large positive index",
			slice:    []string{"a", "b", "c"},
			index:    1000000,
			expected: []string{"a", "b", "c"},
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			// This should not panic
			result := RemoveAtIndex(tt.slice, tt.index)
			if !reflect.DeepEqual(result, tt.expected) {
				t.Errorf("RemoveAtIndex(%v, %d) = %v, expected %v",
					tt.slice, tt.index, result, tt.expected)
			}
		})
	}
}

// TestRemoveAtIndex_EdgeCases tests edge cases like nil and empty slices.
// Validates: Requirement 6.3 - Safe slice removal
func TestRemoveAtIndex_EdgeCases(t *testing.T) {
	t.Run("nil slice", func(t *testing.T) {
		var slice []string = nil
		result := RemoveAtIndex(slice, 0)
		if result != nil {
			t.Errorf("RemoveAtIndex(nil, 0) = %v, expected nil", result)
		}
	})

	t.Run("empty slice", func(t *testing.T) {
		slice := []string{}
		result := RemoveAtIndex(slice, 0)
		if len(result) != 0 {
			t.Errorf("RemoveAtIndex([], 0) = %v, expected empty slice", result)
		}
	})

	t.Run("empty slice with negative index", func(t *testing.T) {
		slice := []string{}
		result := RemoveAtIndex(slice, -1)
		if len(result) != 0 {
			t.Errorf("RemoveAtIndex([], -1) = %v, expected empty slice", result)
		}
	})
}

// TestRemoveAtIndex_DoesNotModifyOriginal tests that the original slice is not modified.
// Validates: Requirement 6.3 - Safe slice removal
func TestRemoveAtIndex_DoesNotModifyOriginal(t *testing.T) {
	original := []string{"a", "b", "c", "d"}
	originalCopy := make([]string, len(original))
	copy(originalCopy, original)

	_ = RemoveAtIndex(original, 1)

	if !reflect.DeepEqual(original, originalCopy) {
		t.Errorf("Original slice was modified: got %v, expected %v", original, originalCopy)
	}
}

// TestRemoveAtIndex_IntSlice tests RemoveAtIndex with integer slices.
// Validates: Requirement 6.3 - Safe slice removal
func TestRemoveAtIndex_IntSlice(t *testing.T) {
	tests := []struct {
		name     string
		slice    []int
		index    int
		expected []int
	}{
		{
			name:     "remove from int slice",
			slice:    []int{1, 2, 3, 4, 5},
			index:    2,
			expected: []int{1, 2, 4, 5},
		},
		{
			name:     "remove first from int slice",
			slice:    []int{10, 20, 30},
			index:    0,
			expected: []int{20, 30},
		},
		{
			name:     "invalid index on int slice",
			slice:    []int{1, 2, 3},
			index:    5,
			expected: []int{1, 2, 3},
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			result := RemoveAtIndex(tt.slice, tt.index)
			if !reflect.DeepEqual(result, tt.expected) {
				t.Errorf("RemoveAtIndex(%v, %d) = %v, expected %v",
					tt.slice, tt.index, result, tt.expected)
			}
		})
	}
}

// TestRemoveAtIndexInPlace_ValidIndex tests in-place removal at valid indices.
// Validates: Requirement 6.3 - Safe slice removal
func TestRemoveAtIndexInPlace_ValidIndex(t *testing.T) {
	tests := []struct {
		name     string
		slice    []string
		index    int
		expected []string
	}{
		{
			name:     "remove first element",
			slice:    []string{"a", "b", "c", "d"},
			index:    0,
			expected: []string{"b", "c", "d"},
		},
		{
			name:     "remove middle element",
			slice:    []string{"a", "b", "c", "d"},
			index:    1,
			expected: []string{"a", "c", "d"},
		},
		{
			name:     "remove last element",
			slice:    []string{"a", "b", "c", "d"},
			index:    3,
			expected: []string{"a", "b", "c"},
		},
		{
			name:     "remove only element",
			slice:    []string{"a"},
			index:    0,
			expected: []string{},
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			// Make a copy since in-place modifies the original
			slice := make([]string, len(tt.slice))
			copy(slice, tt.slice)

			result := RemoveAtIndexInPlace(slice, tt.index)
			if !reflect.DeepEqual(result, tt.expected) {
				t.Errorf("RemoveAtIndexInPlace(%v, %d) = %v, expected %v",
					tt.slice, tt.index, result, tt.expected)
			}
		})
	}
}

// TestRemoveAtIndexInPlace_InvalidIndex tests that invalid indices don't cause panics.
// Validates: Requirement 6.3 - Safe slice removal to avoid index out of bounds
func TestRemoveAtIndexInPlace_InvalidIndex(t *testing.T) {
	tests := []struct {
		name     string
		slice    []string
		index    int
		expected []string
	}{
		{
			name:     "negative index",
			slice:    []string{"a", "b", "c"},
			index:    -1,
			expected: []string{"a", "b", "c"},
		},
		{
			name:     "index equals length",
			slice:    []string{"a", "b", "c"},
			index:    3,
			expected: []string{"a", "b", "c"},
		},
		{
			name:     "index greater than length",
			slice:    []string{"a", "b", "c"},
			index:    10,
			expected: []string{"a", "b", "c"},
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			// Make a copy since in-place modifies the original
			slice := make([]string, len(tt.slice))
			copy(slice, tt.slice)

			// This should not panic
			result := RemoveAtIndexInPlace(slice, tt.index)
			if !reflect.DeepEqual(result, tt.expected) {
				t.Errorf("RemoveAtIndexInPlace(%v, %d) = %v, expected %v",
					tt.slice, tt.index, result, tt.expected)
			}
		})
	}
}

// TestRemoveAtIndexInPlace_EdgeCases tests edge cases like nil and empty slices.
// Validates: Requirement 6.3 - Safe slice removal
func TestRemoveAtIndexInPlace_EdgeCases(t *testing.T) {
	t.Run("nil slice", func(t *testing.T) {
		var slice []string = nil
		result := RemoveAtIndexInPlace(slice, 0)
		if result != nil {
			t.Errorf("RemoveAtIndexInPlace(nil, 0) = %v, expected nil", result)
		}
	})

	t.Run("empty slice", func(t *testing.T) {
		slice := []string{}
		result := RemoveAtIndexInPlace(slice, 0)
		if len(result) != 0 {
			t.Errorf("RemoveAtIndexInPlace([], 0) = %v, expected empty slice", result)
		}
	})
}

// TestSafeGet_ValidIndex tests SafeGet with valid indices.
// Validates: Requirement 6.3 - Safe slice operations
func TestSafeGet_ValidIndex(t *testing.T) {
	slice := []string{"a", "b", "c", "d"}

	tests := []struct {
		name          string
		index         int
		expectedValue string
		expectedOk    bool
	}{
		{"first element", 0, "a", true},
		{"middle element", 1, "b", true},
		{"last element", 3, "d", true},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			val, ok := SafeGet(slice, tt.index)
			if val != tt.expectedValue || ok != tt.expectedOk {
				t.Errorf("SafeGet(%v, %d) = (%v, %v), expected (%v, %v)",
					slice, tt.index, val, ok, tt.expectedValue, tt.expectedOk)
			}
		})
	}
}

// TestSafeGet_InvalidIndex tests SafeGet with invalid indices.
// Validates: Requirement 6.3 - Safe slice operations to avoid index out of bounds
func TestSafeGet_InvalidIndex(t *testing.T) {
	slice := []string{"a", "b", "c"}

	tests := []struct {
		name  string
		index int
	}{
		{"negative index", -1},
		{"index equals length", 3},
		{"index greater than length", 10},
		{"very large negative", -1000},
		{"very large positive", 1000000},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			val, ok := SafeGet(slice, tt.index)
			if ok {
				t.Errorf("SafeGet(%v, %d) returned ok=true, expected ok=false", slice, tt.index)
			}
			if val != "" {
				t.Errorf("SafeGet(%v, %d) returned value=%v, expected empty string", slice, tt.index, val)
			}
		})
	}
}

// TestSafeGet_EdgeCases tests SafeGet with edge cases.
// Validates: Requirement 6.3 - Safe slice operations
func TestSafeGet_EdgeCases(t *testing.T) {
	t.Run("nil slice", func(t *testing.T) {
		var slice []string = nil
		val, ok := SafeGet(slice, 0)
		if ok {
			t.Error("SafeGet(nil, 0) returned ok=true, expected ok=false")
		}
		if val != "" {
			t.Errorf("SafeGet(nil, 0) returned value=%v, expected empty string", val)
		}
	})

	t.Run("empty slice", func(t *testing.T) {
		slice := []string{}
		val, ok := SafeGet(slice, 0)
		if ok {
			t.Error("SafeGet([], 0) returned ok=true, expected ok=false")
		}
		if val != "" {
			t.Errorf("SafeGet([], 0) returned value=%v, expected empty string", val)
		}
	})

	t.Run("single element slice - valid", func(t *testing.T) {
		slice := []string{"only"}
		val, ok := SafeGet(slice, 0)
		if !ok {
			t.Error("SafeGet([\"only\"], 0) returned ok=false, expected ok=true")
		}
		if val != "only" {
			t.Errorf("SafeGet([\"only\"], 0) returned value=%v, expected \"only\"", val)
		}
	})

	t.Run("single element slice - invalid", func(t *testing.T) {
		slice := []string{"only"}
		val, ok := SafeGet(slice, 1)
		if ok {
			t.Error("SafeGet([\"only\"], 1) returned ok=true, expected ok=false")
		}
		if val != "" {
			t.Errorf("SafeGet([\"only\"], 1) returned value=%v, expected empty string", val)
		}
	})
}

// TestSafeGet_IntSlice tests SafeGet with integer slices.
// Validates: Requirement 6.3 - Safe slice operations
func TestSafeGet_IntSlice(t *testing.T) {
	slice := []int{10, 20, 30, 40, 50}

	t.Run("valid index", func(t *testing.T) {
		val, ok := SafeGet(slice, 2)
		if !ok {
			t.Error("SafeGet returned ok=false, expected ok=true")
		}
		if val != 30 {
			t.Errorf("SafeGet returned value=%v, expected 30", val)
		}
	})

	t.Run("invalid index", func(t *testing.T) {
		val, ok := SafeGet(slice, 10)
		if ok {
			t.Error("SafeGet returned ok=true, expected ok=false")
		}
		if val != 0 {
			t.Errorf("SafeGet returned value=%v, expected 0 (zero value)", val)
		}
	})
}

// TestRemoveAtIndex_StructSlice tests RemoveAtIndex with struct slices.
// Validates: Requirement 6.3 - Safe slice removal
func TestRemoveAtIndex_StructSlice(t *testing.T) {
	type Person struct {
		Name string
		Age  int
	}

	slice := []Person{
		{Name: "Alice", Age: 30},
		{Name: "Bob", Age: 25},
		{Name: "Charlie", Age: 35},
	}

	result := RemoveAtIndex(slice, 1)

	expected := []Person{
		{Name: "Alice", Age: 30},
		{Name: "Charlie", Age: 35},
	}

	if !reflect.DeepEqual(result, expected) {
		t.Errorf("RemoveAtIndex with struct slice failed: got %v, expected %v", result, expected)
	}
}
