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

package backend

import (
	"strings"
	"testing"

	"github.com/google/go-cmp/cmp"
	"github.com/hashicorp/hcl/v2"
	"github.com/zclconf/go-cty/cty"

	"github.com/hashicorp/terraform/internal/configs"
	"github.com/hashicorp/terraform/internal/terraform"
	"github.com/hashicorp/terraform/internal/tfdiags"
)

func TestUnparsedValue(t *testing.T) {
	vv := map[string]UnparsedVariableValue{
		"undeclared0": testUnparsedVariableValue("0"),
		"undeclared1": testUnparsedVariableValue("1"),
		"undeclared2": testUnparsedVariableValue("2"),
		"undeclared3": testUnparsedVariableValue("3"),
		"undeclared4": testUnparsedVariableValue("4"),
		"declared1":   testUnparsedVariableValue("5"),
	}
	decls := map[string]*configs.Variable{
		"declared1": {
			Name:           "declared1",
			Type:           cty.String,
			ConstraintType: cty.String,
			ParsingMode:    configs.VariableParseLiteral,
			DeclRange: hcl.Range{
				Filename: "fake.tf",
				Start:    hcl.Pos{Line: 2, Column: 1, Byte: 0},
				End:      hcl.Pos{Line: 2, Column: 1, Byte: 0},
			},
		},
		"missing1": {
			Name:           "missing1",
			Type:           cty.String,
			ConstraintType: cty.String,
			ParsingMode:    configs.VariableParseLiteral,
			DeclRange: hcl.Range{
				Filename: "fake.tf",
				Start:    hcl.Pos{Line: 3, Column: 1, Byte: 0},
				End:      hcl.Pos{Line: 3, Column: 1, Byte: 0},
			},
		},
		"missing2": {
			Name:           "missing1",
			Type:           cty.String,
			ConstraintType: cty.String,
			ParsingMode:    configs.VariableParseLiteral,
			Default:        cty.StringVal("default for missing2"),
			DeclRange: hcl.Range{
				Filename: "fake.tf",
				Start:    hcl.Pos{Line: 4, Column: 1, Byte: 0},
				End:      hcl.Pos{Line: 4, Column: 1, Byte: 0},
			},
		},
	}

	const undeclSingular = `Value for undeclared variable`
	const undeclPlural = `Values for undeclared variables`

	t.Run("ParseDeclaredVariableValues", func(t *testing.T) {
		gotVals, diags := ParseDeclaredVariableValues(vv, decls)

		if got, want := len(diags), 0; got != want {
			t.Fatalf("wrong number of diagnostics %d; want %d", got, want)
		}

		wantVals := terraform.InputValues{
			"declared1": {
				Value:      cty.StringVal("5"),
				SourceType: terraform.ValueFromNamedFile,
				SourceRange: tfdiags.SourceRange{
					Filename: "fake.tfvars",
					Start:    tfdiags.SourcePos{Line: 1, Column: 1, Byte: 0},
					End:      tfdiags.SourcePos{Line: 1, Column: 1, Byte: 0},
				},
			},
		}

		if diff := cmp.Diff(wantVals, gotVals, cmp.Comparer(cty.Value.RawEquals)); diff != "" {
			t.Errorf("wrong result\n%s", diff)
		}
	})

	t.Run("ParseUndeclaredVariableValues", func(t *testing.T) {
		gotVals, diags := ParseUndeclaredVariableValues(vv, decls)

		if got, want := len(diags), 3; got != want {
			t.Fatalf("wrong number of diagnostics %d; want %d", got, want)
		}

		if got, want := diags[0].Description().Summary, undeclSingular; got != want {
			t.Errorf("wrong summary for diagnostic 0\ngot:  %s\nwant: %s", got, want)
		}

		if got, want := diags[1].Description().Summary, undeclSingular; got != want {
			t.Errorf("wrong summary for diagnostic 1\ngot:  %s\nwant: %s", got, want)
		}

		if got, want := diags[2].Description().Summary, undeclPlural; got != want {
			t.Errorf("wrong summary for diagnostic 2\ngot:  %s\nwant: %s", got, want)
		}

		wantVals := terraform.InputValues{
			"undeclared0": {
				Value:      cty.StringVal("0"),
				SourceType: terraform.ValueFromNamedFile,
				SourceRange: tfdiags.SourceRange{
					Filename: "fake.tfvars",
					Start:    tfdiags.SourcePos{Line: 1, Column: 1},
					End:      tfdiags.SourcePos{Line: 1, Column: 1},
				},
			},
			"undeclared1": {
				Value:      cty.StringVal("1"),
				SourceType: terraform.ValueFromNamedFile,
				SourceRange: tfdiags.SourceRange{
					Filename: "fake.tfvars",
					Start:    tfdiags.SourcePos{Line: 1, Column: 1},
					End:      tfdiags.SourcePos{Line: 1, Column: 1},
				},
			},
			"undeclared2": {
				Value:      cty.StringVal("2"),
				SourceType: terraform.ValueFromNamedFile,
				SourceRange: tfdiags.SourceRange{
					Filename: "fake.tfvars",
					Start:    tfdiags.SourcePos{Line: 1, Column: 1},
					End:      tfdiags.SourcePos{Line: 1, Column: 1},
				},
			},
			"undeclared3": {
				Value:      cty.StringVal("3"),
				SourceType: terraform.ValueFromNamedFile,
				SourceRange: tfdiags.SourceRange{
					Filename: "fake.tfvars",
					Start:    tfdiags.SourcePos{Line: 1, Column: 1},
					End:      tfdiags.SourcePos{Line: 1, Column: 1},
				},
			},
			"undeclared4": {
				Value:      cty.StringVal("4"),
				SourceType: terraform.ValueFromNamedFile,
				SourceRange: tfdiags.SourceRange{
					Filename: "fake.tfvars",
					Start:    tfdiags.SourcePos{Line: 1, Column: 1},
					End:      tfdiags.SourcePos{Line: 1, Column: 1},
				},
			},
		}
		if diff := cmp.Diff(wantVals, gotVals, cmp.Comparer(cty.Value.RawEquals)); diff != "" {
			t.Errorf("wrong result\n%s", diff)
		}
	})

	t.Run("ParseVariableValues", func(t *testing.T) {
		gotVals, diags := ParseVariableValues(vv, decls)
		for _, diag := range diags {
			t.Logf("%s: %s", diag.Description().Summary, diag.Description().Detail)
		}
		if got, want := len(diags), 4; got != want {
			t.Fatalf("wrong number of diagnostics %d; want %d", got, want)
		}

		const missingRequired = `No value for required variable`

		if got, want := diags[0].Description().Summary, undeclSingular; got != want {
			t.Errorf("wrong summary for diagnostic 0\ngot:  %s\nwant: %s", got, want)
		}
		if got, want := diags[1].Description().Summary, undeclSingular; got != want {
			t.Errorf("wrong summary for diagnostic 1\ngot:  %s\nwant: %s", got, want)
		}
		if got, want := diags[2].Description().Summary, undeclPlural; got != want {
			t.Errorf("wrong summary for diagnostic 2\ngot:  %s\nwant: %s", got, want)
		}
		if got, want := diags[2].Description().Detail, "3 other variable(s)"; !strings.Contains(got, want) {
			t.Errorf("wrong detail for diagnostic 2\ngot:  %s\nmust contain: %s", got, want)
		}
		if got, want := diags[3].Description().Summary, missingRequired; got != want {
			t.Errorf("wrong summary for diagnostic 3\ngot:  %s\nwant: %s", got, want)
		}

		wantVals := terraform.InputValues{
			"declared1": {
				Value:      cty.StringVal("5"),
				SourceType: terraform.ValueFromNamedFile,
				SourceRange: tfdiags.SourceRange{
					Filename: "fake.tfvars",
					Start:    tfdiags.SourcePos{Line: 1, Column: 1, Byte: 0},
					End:      tfdiags.SourcePos{Line: 1, Column: 1, Byte: 0},
				},
			},
			"missing1": {
				Value:      cty.DynamicVal,
				SourceType: terraform.ValueFromConfig,
				SourceRange: tfdiags.SourceRange{
					Filename: "fake.tf",
					Start:    tfdiags.SourcePos{Line: 3, Column: 1, Byte: 0},
					End:      tfdiags.SourcePos{Line: 3, Column: 1, Byte: 0},
				},
			},
			"missing2": {
				Value:      cty.NilVal, // Terraform Core handles substituting the default
				SourceType: terraform.ValueFromConfig,
				SourceRange: tfdiags.SourceRange{
					Filename: "fake.tf",
					Start:    tfdiags.SourcePos{Line: 4, Column: 1, Byte: 0},
					End:      tfdiags.SourcePos{Line: 4, Column: 1, Byte: 0},
				},
			},
		}
		if diff := cmp.Diff(wantVals, gotVals, cmp.Comparer(cty.Value.RawEquals)); diff != "" {
			t.Errorf("wrong result\n%s", diff)
		}
	})
}

type testUnparsedVariableValue string

func (v testUnparsedVariableValue) ParseVariableValue(mode configs.VariableParsingMode) (*terraform.InputValue, tfdiags.Diagnostics) {
	return &terraform.InputValue{
		Value:      cty.StringVal(string(v)),
		SourceType: terraform.ValueFromNamedFile,
		SourceRange: tfdiags.SourceRange{
			Filename: "fake.tfvars",
			Start:    tfdiags.SourcePos{Line: 1, Column: 1, Byte: 0},
			End:      tfdiags.SourcePos{Line: 1, Column: 1, Byte: 0},
		},
	}, nil
}
