package utils

import (
	"testing"

	"github.com/BurntSushi/toml"
	"github.com/stretchr/testify/assert"
)

func TestMergeConfig(t *testing.T) {
	assert := assert.New(t)

	base := make(map[string]interface{})
	overlay := make(map[string]interface{})
	base["layer1.key1"] = "value1"
	base["layer1.key2"] = "value2"
	base["layer2.key1"] = "value3"
	overlay["layer1.key1"] = "value4"
	overlay["layer2.key1"] = "value5"
	overlay["layer3.key1"] = "value6"

	result := MergeConfig(base, overlay)

	// result of function MergeConfig is multi-layered map
	assert.Nil(result["layer2.key1"])

	// test if the original map is not changed
	assert.Equal("value1", base["layer1.key1"])
	assert.Equal("value2", base["layer1.key2"])
	assert.Equal("value3", base["layer2.key1"])
	assert.Equal(3, len(base))

	assert.Equal(3, len(result))
	assert.Equal("value4", result["layer1"].(map[string]interface{})["key1"])
	assert.Equal("value2", result["layer1"].(map[string]interface{})["key2"])
	assert.Equal("value5", result["layer2"].(map[string]interface{})["key1"])
	assert.Equal("value6", result["layer3"].(map[string]interface{})["key1"])
}

func TestMergeRawConfig(t *testing.T) {
	assert := assert.New(t)
	baseText := `layer1.key1 = "value1"
layer1.key2 = "value2"
layer2.key1 = "value3"`
	overlayText := `layer1.key1 = "value4"
layer2.key1 = "value5"
layer3.key1 = "value6"`

	var base, overlay map[string]interface{}
	err := toml.Unmarshal([]byte(baseText), &base)
	assert.Nil(err)
	err = toml.Unmarshal([]byte(overlayText), &overlay)
	assert.Nil(err)
	result := MergeRawConfig(base, overlay)
	assert.Equal(3, len(result))

	// result of function MergeConfig is multi-layered map
	assert.Nil(result["layer2.key1"])

	// test if the original map is not changed
	assert.Equal("value1", base["layer1"].(map[string]interface{})["key1"])
	assert.Equal("value2", base["layer1"].(map[string]interface{})["key2"])
	assert.Equal("value3", base["layer2"].(map[string]interface{})["key1"])
	assert.Nil(base["layer3"])

	assert.Equal("value4", result["layer1"].(map[string]interface{})["key1"])
	assert.Equal("value2", result["layer1"].(map[string]interface{})["key2"])
	assert.Equal("value5", result["layer2"].(map[string]interface{})["key1"])
	assert.Equal("value6", result["layer3"].(map[string]interface{})["key1"])
}

func TestConvert2IntConvertsNumbersInArrayItems(t *testing.T) {
	assert := assert.New(t)
	config := map[string]any{
		"kvengine": map[string]any{
			"per-keyspace-configs": []any{
				map[string]any{
					"keyspace":    float64(2),
					"enable-blob": true,
					"ratio":       float64(2.5),
				},
			},
		},
	}

	Convert2Int(config)

	item := config["kvengine"].(map[string]any)["per-keyspace-configs"].([]any)[0].(map[string]any)
	assert.Equal(int64(2), item["keyspace"])
	assert.Equal(float64(2.5), item["ratio"])

	tomlBytes, err := MarshalTOML(config)
	assert.NoError(err)
	assert.Contains(string(tomlBytes), "keyspace = 2")
	assert.NotContains(string(tomlBytes), "keyspace = 2.0")
}
