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

package configs

import (
	"fmt"
	"os"
	"path"
	"path/filepath"
	"reflect"
	"testing"

	"github.com/davecgh/go-spew/spew"

	version "github.com/hashicorp/go-version"
	"github.com/hashicorp/hcl/v2"
	"github.com/spf13/afero"
)

// testParser returns a parser that reads files from the given map, which
// is from paths to file contents.
//
// Since this function uses only in-memory objects, it should never fail.
// If any errors are encountered in practice, this function will panic.
func testParser(files map[string]string) *Parser {
	fs := afero.Afero{Fs: afero.NewMemMapFs()}

	for filePath, contents := range files {
		dirPath := path.Dir(filePath)
		err := fs.MkdirAll(dirPath, os.ModePerm)
		if err != nil {
			panic(err)
		}
		err = fs.WriteFile(filePath, []byte(contents), os.ModePerm)
		if err != nil {
			panic(err)
		}
	}

	return NewParser(fs)
}

// testModuleConfigFrom File reads a single file from the given path as a
// module and returns its configuration. This is a helper for use in unit tests.
func testModuleConfigFromFile(filename string) (*Config, hcl.Diagnostics) {
	parser := NewParser(nil)
	f, diags := parser.LoadConfigFile(filename)
	mod, modDiags := NewModule([]*File{f}, nil)
	diags = append(diags, modDiags...)
	cfg, moreDiags := BuildConfig(mod, nil)
	return cfg, append(diags, moreDiags...)
}

// testModuleFromDir reads configuration from the given directory path as
// a module and returns it. This is a helper for use in unit tests.
func testModuleFromDir(path string) (*Module, hcl.Diagnostics) {
	parser := NewParser(nil)
	return parser.LoadConfigDir(path)
}

// testModuleFromDir reads configuration from the given directory path as a
// module and returns its configuration. This is a helper for use in unit tests.
func testModuleConfigFromDir(path string) (*Config, hcl.Diagnostics) {
	parser := NewParser(nil)
	mod, diags := parser.LoadConfigDir(path)
	cfg, moreDiags := BuildConfig(mod, nil)
	return cfg, append(diags, moreDiags...)
}

// testNestedModuleConfigFromDir reads configuration from the given directory path as
// a module with (optional) submodules and returns its configuration. This is a
// helper for use in unit tests.
func testNestedModuleConfigFromDir(t *testing.T, path string) (*Config, hcl.Diagnostics) {
	t.Helper()

	parser := NewParser(nil)
	mod, diags := parser.LoadConfigDir(path)
	if mod == nil {
		t.Fatal("got nil root module; want non-nil")
	}

	versionI := 0
	cfg, nestedDiags := BuildConfig(mod, ModuleWalkerFunc(
		func(req *ModuleRequest) (*Module, *version.Version, hcl.Diagnostics) {
			// For the sake of this test we're going to just treat our
			// SourceAddr as a path relative to the calling module.
			// A "real" implementation of ModuleWalker should accept the
			// various different source address syntaxes Terraform supports.

			// Build a full path by walking up the module tree, prepending each
			// source address path until we hit the root
			paths := []string{req.SourceAddr.String()}
			for config := req.Parent; config != nil && config.Parent != nil; config = config.Parent {
				paths = append([]string{config.SourceAddr.String()}, paths...)
			}
			paths = append([]string{path}, paths...)
			sourcePath := filepath.Join(paths...)

			mod, diags := parser.LoadConfigDir(sourcePath)
			version, _ := version.NewVersion(fmt.Sprintf("1.0.%d", versionI))
			versionI++
			return mod, version, diags
		},
	))

	diags = append(diags, nestedDiags...)
	return cfg, diags
}

func assertNoDiagnostics(t *testing.T, diags hcl.Diagnostics) bool {
	t.Helper()
	return assertDiagnosticCount(t, diags, 0)
}

func assertDiagnosticCount(t *testing.T, diags hcl.Diagnostics, want int) bool {
	t.Helper()
	if len(diags) != want {
		t.Errorf("wrong number of diagnostics %d; want %d", len(diags), want)
		for _, diag := range diags {
			t.Logf("- %s", diag)
		}
		return true
	}
	return false
}

func assertDiagnosticSummary(t *testing.T, diags hcl.Diagnostics, want string) bool {
	t.Helper()

	for _, diag := range diags {
		if diag.Summary == want {
			return false
		}
	}

	t.Errorf("missing diagnostic summary %q", want)
	for _, diag := range diags {
		t.Logf("- %s", diag)
	}
	return true
}

func assertExactDiagnostics(t *testing.T, diags hcl.Diagnostics, want []string) bool {
	t.Helper()

	gotDiags := map[string]bool{}
	wantDiags := map[string]bool{}

	for _, diag := range diags {
		gotDiags[diag.Error()] = true
	}
	for _, msg := range want {
		wantDiags[msg] = true
	}

	bad := false
	for got := range gotDiags {
		if _, exists := wantDiags[got]; !exists {
			t.Errorf("unexpected diagnostic: %s", got)
			bad = true
		}
	}
	for want := range wantDiags {
		if _, exists := gotDiags[want]; !exists {
			t.Errorf("missing expected diagnostic: %s", want)
			bad = true
		}
	}

	return bad
}

func assertResultDeepEqual(t *testing.T, got, want interface{}) bool {
	t.Helper()
	if !reflect.DeepEqual(got, want) {
		t.Errorf("wrong result\ngot: %swant: %s", spew.Sdump(got), spew.Sdump(want))
		return true
	}
	return false
}

func stringPtr(s string) *string {
	return &s
}
