package cache

import (
	"encoding/json"
	"testing"

	"github.com/stretchr/testify/require"
)

func TestDecodeRedisValue(t *testing.T) {
	tests := []struct {
		name    string
		input   string
		want    interface{}
		wantErr bool
	}{
		{"string", "\"hello\"", "hello", false},
		{"number_int", "42", int64(42), false},
		{"number_float", "3.14", 3.14, false},
		{"bool_true", "true", true, false},
		{"bool_false", "false", false, false},
		{"null", "null", nil, false},
		{"array", "[1, 2, 3]", []interface{}{int64(1), int64(2), int64(3)}, false},
		{"object", "{\"a\":1,\"b\":2}", map[string]interface{}{"a": int64(1), "b": int64(2)}, false},
		{"invalid_returns_raw", "not-json", "not-json", false},
		{"empty", "", "", false},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			got, err := decodeRedisValue(tt.input)
			if tt.wantErr {
				require.Error(t, err)
				return
			}
			require.NoError(t, err)
			require.Equal(t, tt.want, got)
		})
	}
}

func TestNormalizeRedisValue(t *testing.T) {
	tests := []struct {
		name  string
		input interface{}
		want  interface{}
	}{
		{"number_to_int", json.Number("42"), int64(42)},
		{"number_to_float", json.Number("3.14"), 3.14},
		{"number_string", json.Number("abc"), "abc"},
		{"string_unchanged", "hello", "hello"},
		{"int_unchanged", int64(42), int64(42)},
		{"bool_unchanged", true, true},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			got := normalizeRedisValue(tt.input)
			require.Equal(t, tt.want, got)
		})
	}
}

func TestNormalizeRedisValue_Array(t *testing.T) {
	input := []interface{}{json.Number("1"), json.Number("2"), "text"}
	want := []interface{}{int64(1), int64(2), "text"}
	got := normalizeRedisValue(input)
	require.Equal(t, want, got)
}

func TestNormalizeRedisValue_Map(t *testing.T) {
	input := map[string]interface{}{"num": json.Number("42"), "str": "text"}
	want := map[string]interface{}{"num": int64(42), "str": "text"}
	got := normalizeRedisValue(input)
	require.Equal(t, want, got)
}
