package utils

import "testing"

func TestParseMemoryToMB(t *testing.T) {
	tests := []struct {
		name     string
		input    string
		expected int
	}{
		// GiB format (case-insensitive)
		{"4Gi", "4Gi", 4 * 1024},
		{"4GI", "4GI", 4 * 1024},
		{"4gi", "4gi", 4 * 1024},
		{"4G", "4G", 4 * 1024},
		{"4g", "4g", 4 * 1024},
		{"8.5Gi", "8.5Gi", int(8.5 * 1024)},
		{"0.5Gi", "0.5Gi", int(0.5 * 1024)},

		// MiB format (case-insensitive)
		{"4096Mi", "4096Mi", 4096},
		{"4096MI", "4096MI", 4096},
		{"4096mi", "4096mi", 4096},
		{"4096M", "4096M", 4096},
		{"4096m", "4096m", 4096},
		{"512Mi", "512Mi", 512},

		// KiB format (case-insensitive)
		{"1024Ki", "1024Ki", 1},
		{"1024KI", "1024KI", 1},
		{"1024ki", "1024ki", 1},
		{"1024K", "1024K", 1},
		{"1024k", "1024k", 1},
		{"512Ki", "512Ki", 0}, // Rounds down

		// Plain numbers (assumed MB)
		{"4096", "4096", 4096},
		{"8192", "8192", 8192},
		{"0", "0", 0},

		// Empty string (default)
		{"empty", "", 4096},

		// Whitespace handling
		{"with spaces", "  4096  ", 4096},
		{"with tabs", "\t8192\t", 8192},

		// Edge cases
		{"large value", "1024Gi", 1024 * 1024},
		{"small value", "1Mi", 1},
		{"fractional MiB", "1.5Mi", 1}, // Truncates
		{"fractional KiB", "1536Ki", 1}, // 1536/1024 = 1.5, rounds down to 1
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			result := ParseMemoryToMB(tt.input)
			if result != tt.expected {
				t.Errorf("ParseMemoryToMB(%q) = %d, want %d", tt.input, result, tt.expected)
			}
		})
	}
}

func TestParseMemoryToGB(t *testing.T) {
	tests := []struct {
		name     string
		input    string
		expected int
	}{
		{"4Gi to GB", "4Gi", 4},
		{"8Gi to GB", "8Gi", 8},
		{"4096Mi to GB", "4096Mi", 4},
		{"8192Mi to GB", "8192Mi", 8},
		{"1024MB to GB", "1024M", 1},
		{"plain number GB", "8", 0}, // 8 MB = 0 GB (truncates)
		{"plain number 8192MB", "8192", 8}, // 8192 MB = 8 GB
		{"empty default", "", 4}, // 4096 MB default = 4 GB
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			result := ParseMemoryToGB(tt.input)
			if result != tt.expected {
				t.Errorf("ParseMemoryToGB(%q) = %d, want %d", tt.input, result, tt.expected)
			}
		})
	}
}

func TestParseDiskToGB(t *testing.T) {
	tests := []struct {
		name     string
		input    string
		expected int
	}{
		// TiB format (case-insensitive)
		{"1Ti", "1Ti", 1 * 1024},
		{"1TI", "1TI", 1 * 1024},
		{"1ti", "1ti", 1024},
		{"1T", "1T", 1024},
		{"1t", "1t", 1024},
		{"2.5Ti", "2.5Ti", int(2.5 * 1024)},

		// GiB format (case-insensitive)
		{"50Gi", "50Gi", 50},
		{"50GI", "50GI", 50},
		{"50gi", "50gi", 50},
		{"50G", "50G", 50},
		{"50g", "50g", 50},
		{"100Gi", "100Gi", 100},
		{"8.5Gi", "8.5Gi", 8}, // Truncates

		// MiB format (case-insensitive)
		{"51200Mi", "51200Mi", 50}, // 51200 MiB = 50 GB
		{"51200MI", "51200MI", 50},
		{"51200mi", "51200mi", 50},
		{"51200M", "51200M", 50},
		{"51200m", "51200m", 50},
		{"1024Mi", "1024Mi", 1},

		// Plain numbers (assumed GB)
		{"50", "50", 50},
		{"100", "100", 100},
		{"0", "0", 0},

		// Empty string (default)
		{"empty", "", 50},

		// Whitespace handling
		{"with spaces", "  100  ", 100},
		{"with tabs", "\t50\t", 50},

		// Edge cases
		{"large value", "10Ti", 10 * 1024},
		{"small value", "1Gi", 1},
		{"fractional GiB", "1.5Gi", 1}, // Truncates
		{"fractional MiB", "1536Mi", 1}, // 1536/1024 = 1.5, rounds down to 1
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			result := ParseDiskToGB(tt.input)
			if result != tt.expected {
				t.Errorf("ParseDiskToGB(%q) = %d, want %d", tt.input, result, tt.expected)
			}
		})
	}
}

func TestParseMemoryToMB_InvalidInput(t *testing.T) {
	// Invalid inputs should return default (4096 MB)
	invalidInputs := []string{
		"invalid",
		"abc123",
		"10.5.5Gi", // Invalid number format
		"10XX",     // Invalid unit
	}

	for _, input := range invalidInputs {
		result := ParseMemoryToMB(input)
		if result != 4096 {
			t.Errorf("ParseMemoryToMB(%q) with invalid input should return default 4096, got %d", input, result)
		}
	}
}

func TestParseDiskToGB_InvalidInput(t *testing.T) {
	// Invalid inputs should return default (50 GB)
	invalidInputs := []string{
		"invalid",
		"abc123",
		"10.5.5Gi", // Invalid number format
		"10XX",     // Invalid unit
	}

	for _, input := range invalidInputs {
		result := ParseDiskToGB(input)
		if result != 50 {
			t.Errorf("ParseDiskToGB(%q) with invalid input should return default 50, got %d", input, result)
		}
	}
}

