package utils

import (
	"testing"
)

func TestGetConfigString(t *testing.T) {
	tests := []struct {
		name     string
		config   map[string]interface{}
		key      string
		expected string
	}{
		{"existing string key", map[string]interface{}{"name": "hello"}, "name", "hello"},
		{"missing key", map[string]interface{}{"name": "hello"}, "other", ""},
		{"nil value", map[string]interface{}{"name": nil}, "name", ""},
		{"non-string value int", map[string]interface{}{"count": 42}, "count", ""},
		{"non-string value bool", map[string]interface{}{"flag": true}, "flag", ""},
		{"empty string value", map[string]interface{}{"name": ""}, "name", ""},
		{"empty map", map[string]interface{}{}, "name", ""},
		{"nil map", nil, "name", ""},
		{"nested map value", map[string]interface{}{"sub": map[string]interface{}{"k": "v"}}, "sub", ""},
	}

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

func TestGetConfigStringRequired(t *testing.T) {
	t.Run("existing key returns value", func(t *testing.T) {
		config := map[string]interface{}{"name": "hello"}
		val, err := GetConfigStringRequired(config, "name")
		if err != nil {
			t.Errorf("unexpected error: %v", err)
		}
		if val != "hello" {
			t.Errorf("got %q, want %q", val, "hello")
		}
	})

	t.Run("missing key returns error", func(t *testing.T) {
		config := map[string]interface{}{"other": "value"}
		val, err := GetConfigStringRequired(config, "name")
		if err == nil {
			t.Error("expected error for missing key, got nil")
		}
		if val != "" {
			t.Errorf("expected empty string, got %q", val)
		}
	})

	t.Run("empty string value returns error", func(t *testing.T) {
		config := map[string]interface{}{"name": ""}
		val, err := GetConfigStringRequired(config, "name")
		if err == nil {
			t.Error("expected error for empty value, got nil")
		}
		if val != "" {
			t.Errorf("expected empty string, got %q", val)
		}
	})

	t.Run("non-string value returns error", func(t *testing.T) {
		config := map[string]interface{}{"count": 42}
		val, err := GetConfigStringRequired(config, "count")
		if err == nil {
			t.Error("expected error for non-string value, got nil")
		}
		if val != "" {
			t.Errorf("expected empty string, got %q", val)
		}
	})

	t.Run("nil map returns error", func(t *testing.T) {
		_, err := GetConfigStringRequired(nil, "name")
		if err == nil {
			t.Error("expected error for nil map, got nil")
		}
	})
}

func TestGetConfigMap(t *testing.T) {
	tests := []struct {
		name      string
		config    map[string]interface{}
		key       string
		wantOk    bool
		wantNil   bool
	}{
		{
			"existing nested map",
			map[string]interface{}{"sub": map[string]interface{}{"k": "v"}},
			"sub",
			true,
			false,
		},
		{
			"missing key",
			map[string]interface{}{"other": "value"},
			"sub",
			false,
			true,
		},
		{
			"non-map value string",
			map[string]interface{}{"name": "hello"},
			"name",
			false,
			true,
		},
		{
			"non-map value int",
			map[string]interface{}{"count": 42},
			"count",
			false,
			true,
		},
		{
			"nil value",
			map[string]interface{}{"sub": nil},
			"sub",
			false,
			true,
		},
		{
			"empty nested map",
			map[string]interface{}{"sub": map[string]interface{}{}},
			"sub",
			true,
			false,
		},
		{
			"nil config map",
			nil,
			"sub",
			false,
			true,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			result, ok := GetConfigMap(tt.config, tt.key)
			if ok != tt.wantOk {
				t.Errorf("GetConfigMap(%v, %q) ok = %v, want %v", tt.config, tt.key, ok, tt.wantOk)
			}
			if tt.wantNil && result != nil {
				t.Errorf("expected nil result, got %v", result)
			}
			if !tt.wantNil && result == nil {
				t.Error("expected non-nil result, got nil")
			}
		})
	}

	// Verify contents of returned map
	t.Run("returned map has correct contents", func(t *testing.T) {
		inner := map[string]interface{}{"key1": "val1", "key2": 123}
		config := map[string]interface{}{"sub": inner}
		result, ok := GetConfigMap(config, "sub")
		if !ok {
			t.Fatal("expected ok=true")
		}
		if result["key1"] != "val1" {
			t.Errorf("result[key1] = %v, want val1", result["key1"])
		}
		if result["key2"] != 123 {
			t.Errorf("result[key2] = %v, want 123", result["key2"])
		}
	})
}
