// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package schema

import (
	"bytes"
	"fmt"
	"reflect"
	"testing"

	"github.com/hashicorp/terraform/internal/configs/hcl2shim"
	"github.com/hashicorp/terraform/internal/legacy/helper/hashcode"
	"github.com/hashicorp/terraform/internal/legacy/terraform"
)

func TestConfigFieldReader_impl(t *testing.T) {
	var _ FieldReader = new(ConfigFieldReader)
}

func TestConfigFieldReader(t *testing.T) {
	testFieldReader(t, func(s map[string]*Schema) FieldReader {
		return &ConfigFieldReader{
			Schema: s,

			Config: testConfig(t, map[string]interface{}{
				"bool":   true,
				"float":  3.1415,
				"int":    42,
				"string": "string",

				"list": []interface{}{"foo", "bar"},

				"listInt": []interface{}{21, 42},

				"map": map[string]interface{}{
					"foo": "bar",
					"bar": "baz",
				},
				"mapInt": map[string]interface{}{
					"one": "1",
					"two": "2",
				},
				"mapIntNestedSchema": map[string]interface{}{
					"one": "1",
					"two": "2",
				},
				"mapFloat": map[string]interface{}{
					"oneDotTwo": "1.2",
				},
				"mapBool": map[string]interface{}{
					"True":  "true",
					"False": "false",
				},

				"set": []interface{}{10, 50},
				"setDeep": []interface{}{
					map[string]interface{}{
						"index": 10,
						"value": "foo",
					},
					map[string]interface{}{
						"index": 50,
						"value": "bar",
					},
				},
			}),
		}
	})
}

// This contains custom table tests for our ConfigFieldReader
func TestConfigFieldReader_custom(t *testing.T) {
	schema := map[string]*Schema{
		"bool": &Schema{
			Type: TypeBool,
		},
	}

	cases := map[string]struct {
		Addr   []string
		Result FieldReadResult
		Config *terraform.ResourceConfig
		Err    bool
	}{
		"basic": {
			[]string{"bool"},
			FieldReadResult{
				Value:  true,
				Exists: true,
			},
			testConfig(t, map[string]interface{}{
				"bool": true,
			}),
			false,
		},

		"computed": {
			[]string{"bool"},
			FieldReadResult{
				Exists:   true,
				Computed: true,
			},
			testConfig(t, map[string]interface{}{
				"bool": hcl2shim.UnknownVariableValue,
			}),
			false,
		},
	}

	for name, tc := range cases {
		t.Run(name, func(t *testing.T) {
			r := &ConfigFieldReader{
				Schema: schema,
				Config: tc.Config,
			}
			out, err := r.ReadField(tc.Addr)
			if err != nil != tc.Err {
				t.Fatalf("%s: err: %s", name, err)
			}
			if s, ok := out.Value.(*Set); ok {
				// If it is a set, convert to a list so its more easily checked.
				out.Value = s.List()
			}
			if !reflect.DeepEqual(tc.Result, out) {
				t.Fatalf("%s: bad: %#v", name, out)
			}
		})
	}
}

func TestConfigFieldReader_DefaultHandling(t *testing.T) {
	schema := map[string]*Schema{
		"strWithDefault": &Schema{
			Type:    TypeString,
			Default: "ImADefault",
		},
		"strWithDefaultFunc": &Schema{
			Type: TypeString,
			DefaultFunc: func() (interface{}, error) {
				return "FuncDefault", nil
			},
		},
	}

	cases := map[string]struct {
		Addr   []string
		Result FieldReadResult
		Config *terraform.ResourceConfig
		Err    bool
	}{
		"gets default value when no config set": {
			[]string{"strWithDefault"},
			FieldReadResult{
				Value:    "ImADefault",
				Exists:   true,
				Computed: false,
			},
			testConfig(t, map[string]interface{}{}),
			false,
		},
		"config overrides default value": {
			[]string{"strWithDefault"},
			FieldReadResult{
				Value:    "fromConfig",
				Exists:   true,
				Computed: false,
			},
			testConfig(t, map[string]interface{}{
				"strWithDefault": "fromConfig",
			}),
			false,
		},
		"gets default from function when no config set": {
			[]string{"strWithDefaultFunc"},
			FieldReadResult{
				Value:    "FuncDefault",
				Exists:   true,
				Computed: false,
			},
			testConfig(t, map[string]interface{}{}),
			false,
		},
		"config overrides default function": {
			[]string{"strWithDefaultFunc"},
			FieldReadResult{
				Value:    "fromConfig",
				Exists:   true,
				Computed: false,
			},
			testConfig(t, map[string]interface{}{
				"strWithDefaultFunc": "fromConfig",
			}),
			false,
		},
	}

	for name, tc := range cases {
		r := &ConfigFieldReader{
			Schema: schema,
			Config: tc.Config,
		}
		out, err := r.ReadField(tc.Addr)
		if err != nil != tc.Err {
			t.Fatalf("%s: err: %s", name, err)
		}
		if s, ok := out.Value.(*Set); ok {
			// If it is a set, convert to a list so its more easily checked.
			out.Value = s.List()
		}
		if !reflect.DeepEqual(tc.Result, out) {
			t.Fatalf("%s: bad: %#v", name, out)
		}
	}
}

func TestConfigFieldReader_ComputedMap(t *testing.T) {
	schema := map[string]*Schema{
		"map": &Schema{
			Type:     TypeMap,
			Computed: true,
		},
		"listmap": &Schema{
			Type:     TypeMap,
			Computed: true,
			Elem:     TypeList,
		},
		"maplist": &Schema{
			Type:     TypeList,
			Computed: true,
			Elem:     TypeMap,
		},
	}

	cases := []struct {
		Name   string
		Addr   []string
		Result FieldReadResult
		Config *terraform.ResourceConfig
		Err    bool
	}{
		{
			"set, normal",
			[]string{"map"},
			FieldReadResult{
				Value: map[string]interface{}{
					"foo": "bar",
				},
				Exists:   true,
				Computed: false,
			},
			testConfig(t, map[string]interface{}{
				"map": map[string]interface{}{
					"foo": "bar",
				},
			}),
			false,
		},

		{
			"computed element",
			[]string{"map"},
			FieldReadResult{
				Exists:   true,
				Computed: true,
			},
			testConfig(t, map[string]interface{}{
				"map": map[string]interface{}{
					"foo": hcl2shim.UnknownVariableValue,
				},
			}),
			false,
		},

		{
			"native map",
			[]string{"map"},
			FieldReadResult{
				Value: map[string]interface{}{
					"bar": "baz",
					"baz": "bar",
				},
				Exists:   true,
				Computed: false,
			},
			testConfig(t, map[string]interface{}{
				"map": map[string]interface{}{
					"bar": "baz",
					"baz": "bar",
				},
			}),
			false,
		},

		{
			"map-from-list-of-maps",
			[]string{"maplist", "0"},
			FieldReadResult{
				Value: map[string]interface{}{
					"key": "bar",
				},
				Exists:   true,
				Computed: false,
			},
			testConfig(t, map[string]interface{}{
				"maplist": []interface{}{
					map[string]interface{}{
						"key": "bar",
					},
				},
			}),
			false,
		},

		{
			"value-from-list-of-maps",
			[]string{"maplist", "0", "key"},
			FieldReadResult{
				Value:    "bar",
				Exists:   true,
				Computed: false,
			},
			testConfig(t, map[string]interface{}{
				"maplist": []interface{}{
					map[string]interface{}{
						"key": "bar",
					},
				},
			}),
			false,
		},

		{
			"list-from-map-of-lists",
			[]string{"listmap", "key"},
			FieldReadResult{
				Value:    []interface{}{"bar"},
				Exists:   true,
				Computed: false,
			},
			testConfig(t, map[string]interface{}{
				"listmap": map[string]interface{}{
					"key": []interface{}{
						"bar",
					},
				},
			}),
			false,
		},

		{
			"value-from-map-of-lists",
			[]string{"listmap", "key", "0"},
			FieldReadResult{
				Value:    "bar",
				Exists:   true,
				Computed: false,
			},
			testConfig(t, map[string]interface{}{
				"listmap": map[string]interface{}{
					"key": []interface{}{
						"bar",
					},
				},
			}),
			false,
		},
	}

	for i, tc := range cases {
		t.Run(fmt.Sprintf("%d-%s", i, tc.Name), func(t *testing.T) {
			r := &ConfigFieldReader{
				Schema: schema,
				Config: tc.Config,
			}
			out, err := r.ReadField(tc.Addr)
			if err != nil != tc.Err {
				t.Fatal(err)
			}
			if s, ok := out.Value.(*Set); ok {
				// If it is a set, convert to the raw map
				out.Value = s.m
				if len(s.m) == 0 {
					out.Value = nil
				}
			}
			if !reflect.DeepEqual(tc.Result, out) {
				t.Fatalf("\nexpected: %#v\ngot:      %#v", tc.Result, out)
			}
		})
	}
}

func TestConfigFieldReader_ComputedSet(t *testing.T) {
	schema := map[string]*Schema{
		"strSet": &Schema{
			Type: TypeSet,
			Elem: &Schema{Type: TypeString},
			Set:  HashString,
		},
	}

	cases := map[string]struct {
		Addr   []string
		Result FieldReadResult
		Config *terraform.ResourceConfig
		Err    bool
	}{
		"set, normal": {
			[]string{"strSet"},
			FieldReadResult{
				Value: map[string]interface{}{
					"2356372769": "foo",
				},
				Exists:   true,
				Computed: false,
			},
			testConfig(t, map[string]interface{}{
				"strSet": []interface{}{"foo"},
			}),
			false,
		},

		"set, computed element": {
			[]string{"strSet"},
			FieldReadResult{
				Value:    nil,
				Exists:   true,
				Computed: true,
			},
			testConfig(t, map[string]interface{}{
				"strSet": []interface{}{hcl2shim.UnknownVariableValue},
			}),
			false,
		},
	}

	for name, tc := range cases {
		r := &ConfigFieldReader{
			Schema: schema,
			Config: tc.Config,
		}
		out, err := r.ReadField(tc.Addr)
		if err != nil != tc.Err {
			t.Fatalf("%s: err: %s", name, err)
		}
		if s, ok := out.Value.(*Set); ok {
			// If it is a set, convert to the raw map
			out.Value = s.m
			if len(s.m) == 0 {
				out.Value = nil
			}
		}
		if !reflect.DeepEqual(tc.Result, out) {
			t.Fatalf("%s: bad: %#v", name, out)
		}
	}
}

func TestConfigFieldReader_computedComplexSet(t *testing.T) {
	hashfunc := func(v interface{}) int {
		var buf bytes.Buffer
		m := v.(map[string]interface{})
		buf.WriteString(fmt.Sprintf("%s-", m["name"].(string)))
		buf.WriteString(fmt.Sprintf("%s-", m["vhd_uri"].(string)))
		return hashcode.String(buf.String())
	}

	schema := map[string]*Schema{
		"set": &Schema{
			Type: TypeSet,
			Elem: &Resource{
				Schema: map[string]*Schema{
					"name": {
						Type:     TypeString,
						Required: true,
					},

					"vhd_uri": {
						Type:     TypeString,
						Required: true,
					},
				},
			},
			Set: hashfunc,
		},
	}

	cases := map[string]struct {
		Addr   []string
		Result FieldReadResult
		Config *terraform.ResourceConfig
		Err    bool
	}{
		"set, normal": {
			[]string{"set"},
			FieldReadResult{
				Value: map[string]interface{}{
					"532860136": map[string]interface{}{
						"name":    "myosdisk1",
						"vhd_uri": "bar",
					},
				},
				Exists:   true,
				Computed: false,
			},
			testConfig(t, map[string]interface{}{
				"set": []interface{}{
					map[string]interface{}{
						"name":    "myosdisk1",
						"vhd_uri": "bar",
					},
				},
			}),
			false,
		},
	}

	for name, tc := range cases {
		r := &ConfigFieldReader{
			Schema: schema,
			Config: tc.Config,
		}
		out, err := r.ReadField(tc.Addr)
		if err != nil != tc.Err {
			t.Fatalf("%s: err: %s", name, err)
		}
		if s, ok := out.Value.(*Set); ok {
			// If it is a set, convert to the raw map
			out.Value = s.m
			if len(s.m) == 0 {
				out.Value = nil
			}
		}
		if !reflect.DeepEqual(tc.Result, out) {
			t.Fatalf("%s: bad: %#v", name, out)
		}
	}
}

func testConfig(t *testing.T, raw map[string]interface{}) *terraform.ResourceConfig {
	return terraform.NewResourceConfigRaw(raw)
}
