package utils

import (
	"fmt"
	"reflect"
	"testing"
)

func TestSetPathValue_SingleKey(t *testing.T) {
	input := map[string]any{}
	got := SetPathValue("name", "Max", input)

	want := map[string]any{"name": "Max"}

	if !reflect.DeepEqual(got, want) {
		t.Fatalf("unexpected map.\n got: %#v\nwant: %#v", got, want)
	}
}

func TestSetPathValue_DotSyntax(t *testing.T) {
	input := map[string]any{}
	meta := map[string]any{
		"name": "Max",
	}
	got := SetPathValue(".", meta, input)

	want := map[string]any{"name": "Max"}

	fmt.Printf("%+v\n", got)

	if !reflect.DeepEqual(got, want) {
		t.Fatalf("unexpected map.\n got: %#v\nwant: %#v", got, want)
	}
}

func TestSetPathValue_DotSyntaxString(t *testing.T) {
	var input any
	meta := "flour"

	got := SetPathValue(".", meta, input)

	want := "flour"

	fmt.Printf("%+v\n", got)

	if !reflect.DeepEqual(got, want) {
		t.Fatalf("unexpected map.\n got: %#v\nwant: %#v", got, want)
	}
}

func TestSetPathValue_NestedKeys_CreateMissingMaps(t *testing.T) {
	input := map[string]any{}
	got := SetPathValue("user.profile.name", "Max", input)

	// Desired behavior: create nested maps and set the value.
	// NOTE: If this test fails, your implementation likely isn't descending into nested maps.
	want := map[string]any{
		"user": map[string]any{
			"profile": map[string]any{
				"name": "Max",
			},
		},
	}

	if !reflect.DeepEqual(got, want) {
		t.Fatalf("unexpected map for nested keys.\n got: %#v\nwant: %#v", got, want)
	}
}

func TestSetPathValue_OverwriteExistingValue(t *testing.T) {
	input := map[string]any{"foo": "old"}
	got := SetPathValue("foo", "new", input)

	want := map[string]any{"foo": "new"}

	if !reflect.DeepEqual(got, want) {
		t.Fatalf("unexpected map after overwrite.\n got: %#v\nwant: %#v", got, want)
	}
}

func TestSetPathValue_PartiallyExistingPath(t *testing.T) {
	input := map[string]any{
		"user": map[string]any{
			"profile": map[string]any{},
		},
	}
	got := SetPathValue("user.profile.age", 28, input)

	want := map[string]any{
		"user": map[string]any{
			"profile": map[string]any{
				"age": 28,
			},
		},
	}

	if !reflect.DeepEqual(got, want) {
		t.Fatalf("unexpected map with partially existing path.\n got: %#v\nwant: %#v", got, want)
	}
}

func TestSetPathValue_EmptySegmentsAreIgnored(t *testing.T) {
	input := map[string]any{}
	got := SetPathValue("a..b", 1, input)

	// Expected behavior (common-sense): treat empty segments as no-op and still set a.b = 1
	want := map[string]any{
		"a": map[string]any{
			"b": 1,
		},
	}

	if !reflect.DeepEqual(got, want) {
		t.Fatalf("unexpected map with empty segments.\n got: %#v\nwant: %#v", got, want)
	}
}

func TestSetPathValue_ComplexValueTypes(t *testing.T) {
	input := map[string]any{}
	val := []int{1, 2, 3}
	got := SetPathValue("nums.list", val, input)

	want := map[string]any{
		"nums": map[string]any{
			"list": []int{1, 2, 3},
		},
	}

	if !reflect.DeepEqual(got, want) {
		t.Fatalf("unexpected map with complex value types.\n got: %#v\nwant: %#v", got, want)
	}
}
