// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1

package addrs

import (
	"fmt"
	"testing"
)

func TestModuleInstanceEqual_true(t *testing.T) {
	addrs := []string{
		"module.foo",
		"module.foo.module.bar",
		"module.foo[1].module.bar",
		`module.foo["a"].module.bar["b"]`,
		`module.foo["a"].module.bar.module.baz[3]`,
	}
	for _, m := range addrs {
		t.Run(m, func(t *testing.T) {
			addr, diags := ParseModuleInstanceStr(m)
			if len(diags) > 0 {
				t.Fatalf("unexpected diags: %s", diags.Err())
			}
			if !addr.Equal(addr) {
				t.Fatalf("expected %#v to be equal to itself", addr)
			}
		})
	}
}

func TestModuleInstanceEqual_false(t *testing.T) {
	testCases := []struct {
		left  string
		right string
	}{
		{
			"module.foo",
			"module.bar",
		},
		{
			"module.foo",
			"module.foo.module.bar",
		},
		{
			"module.foo[1]",
			"module.bar[1]",
		},
		{
			`module.foo[1]`,
			`module.foo["1"]`,
		},
		{
			"module.foo.module.bar",
			"module.foo[1].module.bar",
		},
		{
			`module.foo.module.bar`,
			`module.foo["a"].module.bar`,
		},
	}
	for _, tc := range testCases {
		t.Run(fmt.Sprintf("%s = %s", tc.left, tc.right), func(t *testing.T) {
			left, diags := ParseModuleInstanceStr(tc.left)
			if len(diags) > 0 {
				t.Fatalf("unexpected diags parsing %s: %s", tc.left, diags.Err())
			}
			right, diags := ParseModuleInstanceStr(tc.right)
			if len(diags) > 0 {
				t.Fatalf("unexpected diags parsing %s: %s", tc.right, diags.Err())
			}

			if left.Equal(right) {
				t.Fatalf("expected %#v not to be equal to %#v", left, right)
			}

			if right.Equal(left) {
				t.Fatalf("expected %#v not to be equal to %#v", right, left)
			}
		})
	}
}

func BenchmarkStringShort(b *testing.B) {
	addr, _ := ParseModuleInstanceStr(`module.foo`)
	for n := 0; n < b.N; n++ {
		_ = addr.String()
	}
}

func BenchmarkStringLong(b *testing.B) {
	addr, _ := ParseModuleInstanceStr(`module.southamerica-brazil-region.module.user-regional-desktops.module.user-name`)
	for n := 0; n < b.N; n++ {
		_ = addr.String()
	}
}

func TestModuleInstance_IsDeclaredByCall(t *testing.T) {
	tests := []struct {
		instance ModuleInstance
		call     AbsModuleCall
		want     bool
	}{
		{
			ModuleInstance{},
			AbsModuleCall{},
			false,
		},
		{
			mustParseModuleInstanceStr("module.child"),
			AbsModuleCall{},
			false,
		},
		{
			ModuleInstance{},
			AbsModuleCall{
				RootModuleInstance,
				ModuleCall{Name: "child"},
			},
			false,
		},
		{
			mustParseModuleInstanceStr("module.child"),
			AbsModuleCall{ // module.child
				RootModuleInstance,
				ModuleCall{Name: "child"},
			},
			true,
		},
		{
			mustParseModuleInstanceStr(`module.child`),
			AbsModuleCall{ // module.kinder.module.child
				mustParseModuleInstanceStr("module.kinder"),
				ModuleCall{Name: "child"},
			},
			false,
		},
		{
			mustParseModuleInstanceStr("module.kinder"),
			// module.kinder.module.child contains module.kinder, but is not itself an instance of module.kinder
			AbsModuleCall{
				mustParseModuleInstanceStr("module.kinder"),
				ModuleCall{Name: "child"},
			},
			false,
		},
		{
			mustParseModuleInstanceStr("module.child"),
			AbsModuleCall{
				mustParseModuleInstanceStr(`module.kinder["a"]`),
				ModuleCall{Name: "kinder"},
			},
			false,
		},
	}

	for _, test := range tests {
		t.Run(fmt.Sprintf("%q.IsCallInstance(%q)", test.instance, test.call.String()), func(t *testing.T) {
			got := test.instance.IsDeclaredByCall(test.call)
			if got != test.want {
				t.Fatal("wrong result")
			}
		})
	}
}

func TestModuleInstance_ContainingModule(t *testing.T) {
	tcs := map[string]struct {
		module   string
		expected string
	}{
		"no_instances": {
			module:   "module.parent.module.child",
			expected: "module.parent.module.child",
		},
		"last_instance": {
			module:   "module.parent.module.child[0]",
			expected: "module.parent.module.child",
		},
		"middle_instance": {
			module:   "module.parent[0].module.child",
			expected: "module.parent[0].module.child",
		},
		"all_instances": {
			module:   "module.parent[0].module.child[0]",
			expected: "module.parent[0].module.child",
		},
		"single_no_instance": {
			module:   "module.parent",
			expected: "module.parent",
		},
		"single_instance": {
			module:   "module.parent[0]",
			expected: "module.parent",
		},
	}
	for name, tc := range tcs {
		t.Run(name, func(t *testing.T) {
			module := mustParseModuleInstanceStr(tc.module)
			actual, expected := module.ContainingModule().String(), tc.expected
			if actual != expected {
				t.Errorf("expected: %s\nactual:  %s", expected, actual)
			}
		})
	}
}

func mustParseModuleInstanceStr(str string) ModuleInstance {
	mi, diags := ParseModuleInstanceStr(str)
	if diags.HasErrors() {
		panic(diags.ErrWithWarnings())
	}
	return mi
}
