// Copyright 2023 Princess B33f Heavy Industries / Dave Shanley
// SPDX-License-Identifier: MIT

package high

import (
	"github.com/pb33f/libopenapi/datamodel/low"
	"github.com/pb33f/libopenapi/utils"
	"github.com/stretchr/testify/assert"
	"gopkg.in/yaml.v3"
	"reflect"
	"strings"
	"testing"
)

type key struct {
	Name             string `yaml:"name,omitempty"`
	ref              bool
	refStr           string
	ln               int
	nilval           bool
	v                any
	kn               *yaml.Node
	low.IsReferenced `yaml:"-"`
}

func (k key) GetKeyNode() *yaml.Node {
	if k.kn != nil {
		return k.kn
	}
	kn := utils.CreateStringNode("meddy")
	kn.Line = k.ln
	return kn
}

func (k key) GetValueUntyped() any {
	return k.v
}

func (k key) GetValueNode() *yaml.Node {
	return k.GetValueNodeUntyped()
}

func (k key) GetValueNodeUntyped() *yaml.Node {
	if k.nilval {
		return nil
	}
	kn := utils.CreateStringNode("maddy")
	kn.Line = k.ln
	return kn
}

func (k key) IsReference() bool {
	return k.ref
}

func (k key) GetReference() string {
	return k.refStr
}

func (k key) SetReference(ref string) {
	k.refStr = ref
}

func (k key) GoLowUntyped() any {
	return &k
}

func (k key) MarshalYAML() (interface{}, error) {
	return utils.CreateStringNode("pizza"), nil
}

func (k key) MarshalYAMLInline() (interface{}, error) {
	return utils.CreateStringNode("pizza-inline!"), nil
}

type plug struct {
	Name []string `yaml:"name,omitempty"`
}

type test1 struct {
	Thrig      map[string]*plug      `yaml:"thrig,omitempty"`
	Thing      string                `yaml:"thing,omitempty"`
	Thong      int                   `yaml:"thong,omitempty"`
	Thrum      int64                 `yaml:"thrum,omitempty"`
	Thang      float32               `yaml:"thang,omitempty"`
	Thung      float64               `yaml:"thung,omitempty"`
	Thyme      bool                  `yaml:"thyme,omitempty"`
	Thurm      any                   `yaml:"thurm,omitempty"`
	Thugg      *bool                 `yaml:"thugg,renderZero"`
	Thurr      *int64                `yaml:"thurr,omitempty"`
	Thral      *float64              `yaml:"thral,omitempty"`
	Tharg      []string              `yaml:"tharg,omitempty"`
	Type       []string              `yaml:"type,omitempty"`
	Throg      []*key                `yaml:"throg,omitempty"`
	Thrat      []interface{}         `yaml:"thrat,omitempty"`
	Thrag      []map[string][]string `yaml:"thrag,omitempty"`
	Thrug      map[string]string     `yaml:"thrug,omitempty"`
	Thoom      []map[string]string   `yaml:"thoom,omitempty"`
	Thomp      map[key]string        `yaml:"thomp,omitempty"`
	Thump      key                   `yaml:"thump,omitempty"`
	Thane      key                   `yaml:"thane,omitempty"`
	Thunk      key                   `yaml:"thunk,omitempty"`
	Thrim      *key                  `yaml:"thrim,omitempty"`
	Thril      map[string]*key       `yaml:"thril,omitempty"`
	Extensions map[string]any        `yaml:"-"`
	ignoreMe   string                `yaml:"-"`
	IgnoreMe   string                `yaml:"-"`
}

func (te *test1) GetExtensions() map[low.KeyReference[string]]low.ValueReference[any] {

	g := make(map[low.KeyReference[string]]low.ValueReference[any])

	for i := range te.Extensions {

		f := reflect.TypeOf(te.Extensions[i])
		switch f.Kind() {
		case reflect.String:
			vn := utils.CreateStringNode(te.Extensions[i].(string))
			vn.Line = 999999 // weighted to the bottom.
			g[low.KeyReference[string]{
				Value:   i,
				KeyNode: vn,
			}] = low.ValueReference[any]{
				ValueNode: vn,
				Value:     te.Extensions[i].(string),
			}
		case reflect.Map:
			kn := utils.CreateStringNode(i)
			var vn yaml.Node
			_ = vn.Decode(te.Extensions[i])

			kn.Line = 999999 // weighted to the bottom.
			g[low.KeyReference[string]{
				Value:   i,
				KeyNode: kn,
			}] = low.ValueReference[any]{
				ValueNode: &vn,
				Value:     te.Extensions[i],
			}
		}

	}
	return g
}

func (te *test1) MarshalYAML() (interface{}, error) {
	nb := NewNodeBuilder(te, te)
	return nb.Render(), nil
}

func (te *test1) GetKeyNode() *yaml.Node {
	kn := utils.CreateStringNode("meddy")
	kn.Line = 20
	return kn
}

func (te *test1) GoesLowUntyped() any {
	return te
}

func TestNewNodeBuilder(t *testing.T) {

	b := true
	c := int64(12345)
	d := 1234.1234

	t1 := test1{
		ignoreMe: "I should never be seen!",
		Thing:    "ding",
		Thong:    1,
		Thurm:    nil,
		Thrum:    1234567,
		Thang:    2.2,
		Thung:    3.33333,
		Thyme:    true,
		Thugg:    &b,
		Thurr:    &c,
		Thral:    &d,
		Tharg:    []string{"chicken", "nuggets"},
		Type:     []string{"chicken"},
		Thoom: []map[string]string{
			{
				"maddy": "champion",
			},
			{
				"ember": "naughty",
			},
		},
		Thomp: map[key]string{
			{ln: 1}: "princess",
		},
		Thane: key{ // this is going to be ignored, needs to be a ValueReference
			ln:     2,
			ref:    true,
			refStr: "ripples",
		},
		Thrug: map[string]string{
			"chicken": "nuggets",
		},
		Thump: key{Name: "I will be ignored", ln: 3},
		Thunk: key{ln: 4, nilval: true},
		Extensions: map[string]any{
			"x-pizza": "time",
		},
	}

	nb := NewNodeBuilder(&t1, nil)
	node := nb.Render()

	data, _ := yaml.Marshal(node)

	desired := `thing: ding
thong: 1
thrum: 1234567
thang: 2.2
thung: 3.33
thyme: true
thugg: true
thurr: 12345
thral: 1234.1234
tharg:
    - chicken
    - nuggets
type: chicken
thrug:
    chicken: nuggets
thoom:
    - maddy: champion
    - ember: naughty
thomp:
    meddy: princess
x-pizza: time`

	assert.Equal(t, desired, strings.TrimSpace(string(data)))

}

func TestNewNodeBuilder_Type(t *testing.T) {

	t1 := test1{
		Type: []string{"chicken", "soup"},
	}

	nb := NewNodeBuilder(&t1, &t1)
	node := nb.Render()

	data, _ := yaml.Marshal(node)

	desired := `type:
    - chicken
    - soup`

	assert.Equal(t, desired, strings.TrimSpace(string(data)))
}

func TestNewNodeBuilder_IsReferenced(t *testing.T) {

	t1 := key{
		Name:   "cotton",
		ref:    true,
		refStr: "#/my/heart",
		ln:     2,
	}

	nb := NewNodeBuilder(&t1, &t1)
	node := nb.Render()

	data, _ := yaml.Marshal(node)

	desired := `$ref: '#/my/heart'`

	assert.Equal(t, desired, strings.TrimSpace(string(data)))
}

func TestNewNodeBuilder_Extensions(t *testing.T) {

	t1 := test1{
		Thing: "ding",
		Extensions: map[string]any{
			"x-pizza": "time",
			"x-money": "time",
		},
		Thong: 1,
	}

	nb := NewNodeBuilder(&t1, &t1)
	node := nb.Render()

	data, _ := yaml.Marshal(node)
	assert.Len(t, data, 49)
}

func TestNewNodeBuilder_LowValueNode(t *testing.T) {

	t1 := test1{
		Thing: "ding",
		Extensions: map[string]any{
			"x-pizza": "time",
			"x-money": "time",
		},
		Thong: 1,
	}

	nb := NewNodeBuilder(&t1, &t1)
	node := nb.Render()

	data, _ := yaml.Marshal(node)

	assert.Len(t, data, 49)
}

func TestNewNodeBuilder_NoValue(t *testing.T) {

	t1 := test1{
		Thing: "",
	}

	nodeEnty := NodeEntry{}
	nb := NewNodeBuilder(&t1, &t1)
	node := nb.AddYAMLNode(nil, &nodeEnty)
	assert.Nil(t, node)
}

func TestNewNodeBuilder_EmptyString(t *testing.T) {
	t1 := new(test1)
	nodeEnty := NodeEntry{}
	nb := NewNodeBuilder(t1, t1)
	node := nb.AddYAMLNode(nil, &nodeEnty)
	assert.Nil(t, node)
}

func TestNewNodeBuilder_EmptyStringRenderZero(t *testing.T) {
	t1 := new(test1)
	nodeEnty := NodeEntry{RenderZero: true, Value: ""}
	nb := NewNodeBuilder(t1, t1)
	m := utils.CreateEmptyMapNode()
	node := nb.AddYAMLNode(m, &nodeEnty)
	assert.NotNil(t, node)
}

func TestNewNodeBuilder_Bool(t *testing.T) {
	t1 := new(test1)
	nb := NewNodeBuilder(t1, t1)
	nodeEnty := NodeEntry{}
	node := nb.AddYAMLNode(nil, &nodeEnty)
	assert.Nil(t, node)
}

func TestNewNodeBuilder_BoolRenderZero(t *testing.T) {
	type yui struct {
		Thrit bool `yaml:"thrit,renderZero"`
	}
	t1 := new(yui)
	t1.Thrit = false
	nb := NewNodeBuilder(t1, t1)
	r := nb.Render()
	assert.NotNil(t, r)
}

func TestNewNodeBuilder_Int(t *testing.T) {
	t1 := new(test1)
	nb := NewNodeBuilder(t1, t1)
	p := utils.CreateEmptyMapNode()
	nodeEnty := NodeEntry{Tag: "p", Value: 12, Key: "p"}
	node := nb.AddYAMLNode(p, &nodeEnty)
	assert.NotNil(t, node)
	assert.Len(t, node.Content, 2)
	assert.Equal(t, "12", node.Content[1].Value)
}

func TestNewNodeBuilder_Int64(t *testing.T) {
	t1 := new(test1)
	nb := NewNodeBuilder(t1, t1)
	p := utils.CreateEmptyMapNode()
	nodeEnty := NodeEntry{Tag: "p", Value: int64(234556), Key: "p"}
	node := nb.AddYAMLNode(p, &nodeEnty)
	assert.NotNil(t, node)
	assert.Len(t, node.Content, 2)
	assert.Equal(t, "234556", node.Content[1].Value)
}

func TestNewNodeBuilder_Float32(t *testing.T) {
	t1 := new(test1)
	nb := NewNodeBuilder(t1, t1)
	p := utils.CreateEmptyMapNode()
	nodeEnty := NodeEntry{Tag: "p", Value: float32(1234.23), Key: "p"}
	node := nb.AddYAMLNode(p, &nodeEnty)
	assert.NotNil(t, node)
	assert.Len(t, node.Content, 2)
	assert.Equal(t, "1234.23", node.Content[1].Value)
}

func TestNewNodeBuilder_Float64(t *testing.T) {
	t1 := new(test1)
	nb := NewNodeBuilder(t1, t1)
	p := utils.CreateEmptyMapNode()
	nodeEnty := NodeEntry{Tag: "p", Value: 1234.232323, Key: "p", StringValue: "1234.232323"}
	node := nb.AddYAMLNode(p, &nodeEnty)
	assert.NotNil(t, node)
	assert.Len(t, node.Content, 2)
	assert.Equal(t, "1234.232323", node.Content[1].Value)
}

func TestNewNodeBuilder_EmptyNode(t *testing.T) {
	t1 := new(test1)
	nb := NewNodeBuilder(t1, t1)
	nb.Nodes = nil
	m := nb.Render()
	assert.Len(t, m.Content, 0)

}

func TestNewNodeBuilder_MapKeyHasValue(t *testing.T) {

	t1 := test1{
		Thrug: map[string]string{
			"dump": "trump",
		},
	}

	type test1low struct {
		Thrug key   `yaml:"thrug"`
		Thugg *bool `yaml:"thugg"`
	}

	t2 := test1low{
		Thrug: key{
			v: map[string]string{
				"dump": "trump",
			},
			ln: 2,
		},
	}

	nb := NewNodeBuilder(&t1, &t2)
	node := nb.Render()

	data, _ := yaml.Marshal(node)

	desired := `thrug:
    dump: trump`

	assert.Equal(t, desired, strings.TrimSpace(string(data)))
}

func TestNewNodeBuilder_MapKeyHasValueThatHasValue(t *testing.T) {

	t1 := test1{
		Thomp: map[key]string{
			{v: "who"}: "princess",
		},
	}

	type test1low struct {
		Thomp key   `yaml:"thomp"`
		Thugg *bool `yaml:"thugg"`
	}

	t2 := test1low{
		Thomp: key{
			v: map[key]string{
				{
					v: key{
						v:  "ice",
						kn: utils.CreateStringNode("limes"),
					},
					kn: utils.CreateStringNode("chimes"),
					ln: 6}: "princess",
			},
			ln: 2,
		},
	}

	nb := NewNodeBuilder(&t1, &t2)
	node := nb.Render()

	data, _ := yaml.Marshal(node)

	desired := `thomp:
    meddy: princess`

	assert.Equal(t, desired, strings.TrimSpace(string(data)))
}

func TestNewNodeBuilder_MapKeyHasValueThatHasValueMatch(t *testing.T) {

	t1 := test1{
		Thomp: map[key]string{
			{v: "who"}: "princess",
		},
	}

	type test1low struct {
		Thomp low.NodeReference[map[key]string] `yaml:"thomp"`
		Thugg *bool                             `yaml:"thugg"`
	}

	g := low.NodeReference[map[key]string]{
		Value: map[key]string{
			{v: "my", kn: utils.CreateStringNode("limes")}: "princess",
		},
	}

	t2 := test1low{
		Thomp: g,
	}

	nb := NewNodeBuilder(&t1, &t2)
	node := nb.Render()

	data, _ := yaml.Marshal(node)

	desired := `thomp:
    meddy: princess`

	assert.Equal(t, desired, strings.TrimSpace(string(data)))
}

func TestNewNodeBuilder_MapKeyHasValueThatHasValueMatchKeyNode(t *testing.T) {

	t1 := test1{
		Thomp: map[key]string{
			{v: "who"}: "princess",
		},
	}

	type test1low struct {
		Thomp low.NodeReference[map[key]string] `yaml:"thomp"`
		Thugg *bool                             `yaml:"thugg"`
	}

	g := low.NodeReference[map[key]string]{
		Value: map[key]string{
			{v: "my", kn: utils.CreateStringNode("limes")}: "princess",
		},
	}

	t2 := test1low{
		Thomp: g,
	}

	nb := NewNodeBuilder(&t1, &t2)
	node := nb.Render()

	data, _ := yaml.Marshal(node)

	desired := `thomp:
    meddy: princess`

	assert.Equal(t, desired, strings.TrimSpace(string(data)))
}

func TestNewNodeBuilder_MapKeyHasValueThatHasValueMatch_NoWrap(t *testing.T) {

	t1 := test1{
		Thomp: map[key]string{
			{v: "who"}: "princess",
		},
	}

	type test1low struct {
		Thomp map[key]string `yaml:"thomp"`
		Thugg *bool          `yaml:"thugg"`
	}

	t2 := test1low{
		Thomp: map[key]string{
			{v: "my", kn: utils.CreateStringNode("meddy")}: "princess",
		},
	}

	nb := NewNodeBuilder(&t1, &t2)
	node := nb.Render()

	data, _ := yaml.Marshal(node)

	desired := `thomp:
    meddy: princess`

	assert.Equal(t, desired, strings.TrimSpace(string(data)))
}

func TestNewNodeBuilder_MissingLabel(t *testing.T) {

	t1 := new(test1)
	nb := NewNodeBuilder(t1, t1)
	p := utils.CreateEmptyMapNode()
	nodeEnty := NodeEntry{Value: 1234.232323, Key: "p"}
	node := nb.AddYAMLNode(p, &nodeEnty)
	assert.NotNil(t, node)
	assert.Len(t, node.Content, 0)
}

func TestNewNodeBuilder_ExtensionMap(t *testing.T) {

	t1 := test1{
		Thing: "ding",
		Extensions: map[string]any{
			"x-pizza": map[string]string{
				"dump": "trump",
			},
			"x-money": "time",
		},
		Thong: 1,
	}

	nb := NewNodeBuilder(&t1, &t1)
	node := nb.Render()

	data, _ := yaml.Marshal(node)

	assert.Len(t, data, 60)
}

func TestNewNodeBuilder_MapKeyHasValueThatHasValueMismatch(t *testing.T) {

	t1 := test1{
		Extensions: map[string]any{
			"x-pizza": map[string]string{
				"dump": "trump",
			},
			"x-cake": map[string]string{
				"maga": "nomore",
			},
		},
		Thril: map[string]*key{
			"princess": {v: "who", Name: "beef", ln: 2},
			"heavy":    {v: "who", Name: "industries", ln: 3},
		},
	}

	nb := NewNodeBuilder(&t1, nil)
	node := nb.Render()

	data, _ := yaml.Marshal(node)

	assert.Len(t, data, 94)
}

func TestNewNodeBuilder_SliceRef(t *testing.T) {

	c := key{ref: true, refStr: "#/red/robin/yummmmm", Name: "milky"}
	ty := []*key{&c}
	t1 := test1{
		Throg: ty,
	}

	nb := NewNodeBuilder(&t1, &t1)
	node := nb.Render()

	data, _ := yaml.Marshal(node)

	desired := `throg:
    - $ref: '#/red/robin/yummmmm'`

	assert.Equal(t, desired, strings.TrimSpace(string(data)))
}

func TestNewNodeBuilder_SliceRef_Inline(t *testing.T) {

	c := key{ref: true, refStr: "#/red/robin/yummmmm", Name: "milky"}
	ty := []*key{&c}
	t1 := test1{
		Throg: ty,
	}

	nb := NewNodeBuilder(&t1, &t1)
	nb.Resolve = true
	node := nb.Render()

	data, _ := yaml.Marshal(node)

	desired := `throg:
    - pizza-inline!`

	assert.Equal(t, desired, strings.TrimSpace(string(data)))
}

type testRender struct {
}

func (t testRender) MarshalYAML() (interface{}, error) {
	return utils.CreateStringNode("testy!"), nil
}

type testRenderRawNode struct {
}

func (t testRenderRawNode) MarshalYAML() (interface{}, error) {
	return yaml.Node{Kind: yaml.ScalarNode, Value: "zesty!"}, nil
}

func TestNewNodeBuilder_SliceRef_Inline_NotCompatible(t *testing.T) {

	ty := []interface{}{testRender{}}
	t1 := test1{
		Thrat: ty,
	}

	nb := NewNodeBuilder(&t1, &t1)
	nb.Resolve = true
	node := nb.Render()

	data, _ := yaml.Marshal(node)

	desired := `thrat:
    - testy!`

	assert.Equal(t, desired, strings.TrimSpace(string(data)))
}

func TestNewNodeBuilder_SliceRef_Inline_NotCompatible_NotPointer(t *testing.T) {

	ty := []interface{}{testRenderRawNode{}}
	t1 := test1{
		Thrat: ty,
	}

	nb := NewNodeBuilder(&t1, &t1)
	nb.Resolve = true
	node := nb.Render()

	data, _ := yaml.Marshal(node)

	desired := `thrat:
    - zesty!`

	assert.Equal(t, desired, strings.TrimSpace(string(data)))
}

func TestNewNodeBuilder_PointerRef_Inline_NotCompatible_RawNode(t *testing.T) {

	ty := testRenderRawNode{}
	t1 := test1{
		Thurm: &ty,
	}

	nb := NewNodeBuilder(&t1, &t1)
	nb.Resolve = true
	node := nb.Render()

	data, _ := yaml.Marshal(node)

	desired := `thurm: zesty!`

	assert.Equal(t, desired, strings.TrimSpace(string(data)))
}

func TestNewNodeBuilder_PointerRef_Inline_NotCompatible(t *testing.T) {

	ty := key{}
	t1 := test1{
		Thurm: &ty,
	}

	nb := NewNodeBuilder(&t1, &t1)
	nb.Resolve = true
	node := nb.Render()

	data, _ := yaml.Marshal(node)

	desired := `thurm: pizza-inline!`

	assert.Equal(t, desired, strings.TrimSpace(string(data)))
}

func TestNewNodeBuilder_SliceNoRef(t *testing.T) {

	c := key{ref: false, Name: "milky"}
	ty := []*key{&c}
	t1 := test1{
		Throg: ty,
	}

	nb := NewNodeBuilder(&t1, &t1)
	node := nb.Render()

	data, _ := yaml.Marshal(node)

	desired := `throg:
    - pizza`

	assert.Equal(t, desired, strings.TrimSpace(string(data)))
}

func TestNewNodeBuilder_TestStructAny(t *testing.T) {

	t1 := test1{
		Thurm: low.ValueReference[any]{
			ValueNode: utils.CreateStringNode("beer"),
		},
	}

	nb := NewNodeBuilder(&t1, &t1)
	node := nb.Render()

	data, _ := yaml.Marshal(node)

	desired := `thurm: beer`

	assert.Equal(t, desired, strings.TrimSpace(string(data)))
}
func TestNewNodeBuilder_TestStructString(t *testing.T) {

	t1 := test1{
		Thurm: low.ValueReference[string]{
			ValueNode: utils.CreateStringNode("beer"),
		},
	}

	nb := NewNodeBuilder(&t1, &t1)
	node := nb.Render()

	data, _ := yaml.Marshal(node)

	desired := `thurm: beer`

	assert.Equal(t, desired, strings.TrimSpace(string(data)))
}

func TestNewNodeBuilder_TestStructPointer(t *testing.T) {

	t1 := test1{
		Thrim: &key{
			ref:    true,
			refStr: "#/cash/money",
			Name:   "pizza",
		},
	}

	nb := NewNodeBuilder(&t1, &t1)
	node := nb.Render()

	data, _ := yaml.Marshal(node)

	desired := `thrim:
    $ref: '#/cash/money'`

	assert.Equal(t, desired, strings.TrimSpace(string(data)))
}

func TestNewNodeBuilder_TestStructRef(t *testing.T) {

	fkn := utils.CreateStringNode("pizzaBurgers")
	fkn.Line = 22

	t1 := test1{
		Thurm: low.NodeReference[string]{
			Reference:     "#/cash/money",
			ReferenceNode: true,
			KeyNode:       fkn,
			ValueNode:     fkn,
		},
	}

	nb := NewNodeBuilder(&t1, &t1)
	node := nb.Render()

	data, _ := yaml.Marshal(node)

	desired := `thurm: pizzaBurgers`

	assert.Equal(t, desired, strings.TrimSpace(string(data)))
}

func TestNewNodeBuilder_TestStructDefaultEncode(t *testing.T) {

	f := 1
	t1 := test1{
		Thurm: &f,
	}

	nb := NewNodeBuilder(&t1, &t1)
	node := nb.Render()

	data, _ := yaml.Marshal(node)

	desired := `thurm: 1`

	assert.Equal(t, desired, strings.TrimSpace(string(data)))
}

func TestNewNodeBuilder_TestSliceMapSliceStruct(t *testing.T) {

	a := []map[string][]string{
		{"pizza": {"beer", "wine"}},
	}

	t1 := test1{
		Thrag: a,
	}

	nb := NewNodeBuilder(&t1, &t1)
	node := nb.Render()

	data, _ := yaml.Marshal(node)

	desired := `thrag:
    - pizza:
        - beer
        - wine`

	assert.Equal(t, desired, strings.TrimSpace(string(data)))
}

func TestNewNodeBuilder_TestRenderZero(t *testing.T) {

	f := false
	t1 := test1{
		Thugg: &f,
	}

	nb := NewNodeBuilder(&t1, &t1)
	node := nb.Render()

	data, _ := yaml.Marshal(node)

	desired := `thugg: false`

	assert.Equal(t, desired, strings.TrimSpace(string(data)))
}

func TestNewNodeBuilder_TestRenderServerVariableSimulation(t *testing.T) {

	t1 := test1{
		Thrig: map[string]*plug{
			"pork": {Name: []string{"gammon", "bacon"}},
		},
	}

	nb := NewNodeBuilder(&t1, &t1)
	node := nb.Render()

	data, _ := yaml.Marshal(node)

	desired := `thrig:
    pork:
        name:
            - gammon
            - bacon`

	assert.Equal(t, desired, strings.TrimSpace(string(data)))
}

func TestNewNodeBuilder_ShouldHaveNotDoneTestsLikeThisOhWell(t *testing.T) {

	m := make(map[low.KeyReference[string]]low.ValueReference[*key])

	m[low.KeyReference[string]{
		KeyNode: utils.CreateStringNode("pizza"),
		Value:   "pizza",
	}] = low.ValueReference[*key]{
		ValueNode: utils.CreateStringNode("beer"),
		Value:     &key{},
	}

	d := make(map[string]*key)
	d["pizza"] = &key{}

	type t1low struct {
		Thril low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*key]]
		Thugg *bool `yaml:"thugg"`
	}

	t1 := test1{
		Thril: d,
	}

	t2 := t1low{
		Thril: low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*key]]{
			Value:     m,
			ValueNode: utils.CreateStringNode("beer"),
		},
	}

	nb := NewNodeBuilder(&t1, &t2)
	node := nb.Render()

	data, _ := yaml.Marshal(node)

	desired := `thril:
    pizza: pizza`

	assert.Equal(t, desired, strings.TrimSpace(string(data)))
}
