package hclparse_test

import (
	"errors"
	"testing"

	"github.com/gruntwork-io/terragrunt/internal/hclparse"
	"github.com/stretchr/testify/assert"
)

func TestTypedErrors_Messages(t *testing.T) {
	t.Parallel()

	baseErr := errors.New("base error")

	tests := []struct {
		name     string
		err      error
		contains string
	}{
		{name: "UnexpectedBodyTypeError", err: hclparse.UnexpectedBodyTypeError{FilePath: "test.hcl"}, contains: "test.hcl"},
		{name: "DuplicateUnitNameError", err: hclparse.DuplicateUnitNameError{Name: "vpc"}, contains: "vpc"},
		{name: "DuplicateStackNameError", err: hclparse.DuplicateStackNameError{Name: "infra"}, contains: "infra"},
		{name: "IncludeValidationError", err: hclparse.IncludeValidationError{IncludeName: "shared", Reason: "has locals"}, contains: "shared"},
		{name: "FileReadError", err: hclparse.FileReadError{FilePath: "missing.hcl", Err: baseErr}, contains: "missing.hcl"},
		{name: "FileParseError", err: hclparse.FileParseError{FilePath: "bad.hcl", Err: baseErr}, contains: "bad.hcl"},
		{name: "FileDecodeError", err: hclparse.FileDecodeError{Name: "inc", Err: baseErr}, contains: "inc"},
		{name: "FileWriteError", err: hclparse.FileWriteError{FilePath: "out.hcl", Err: baseErr}, contains: "out.hcl"},
		{name: "DirCreateError", err: hclparse.DirCreateError{DirPath: "/tmp/dir", Err: baseErr}, contains: "/tmp/dir"},
		{name: "LocalEvalError", err: hclparse.LocalEvalError{Name: "env", Err: baseErr}, contains: "env"},
		{name: "LocalsCycleError", err: hclparse.LocalsCycleError{Names: []string{"a", "b"}}, contains: "[a b]"},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			t.Parallel()

			msg := tt.err.Error()
			assert.Contains(t, msg, tt.contains)
			assert.NotEmpty(t, msg)
		})
	}
}

func TestTypedErrors_Unwrap(t *testing.T) {
	t.Parallel()

	baseErr := errors.New("root cause")

	t.Run("FileReadError", func(t *testing.T) {
		t.Parallel()

		err := hclparse.FileReadError{FilePath: "f.hcl", Err: baseErr}
		assert.ErrorIs(t, err, baseErr)
	})

	t.Run("FileWriteError", func(t *testing.T) {
		t.Parallel()

		err := hclparse.FileWriteError{FilePath: "f.hcl", Err: baseErr}
		assert.ErrorIs(t, err, baseErr)
	})

	t.Run("DirCreateError", func(t *testing.T) {
		t.Parallel()

		err := hclparse.DirCreateError{DirPath: "/d", Err: baseErr}
		assert.ErrorIs(t, err, baseErr)
	})
}
