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

package configs

import (
	"github.com/hashicorp/hcl/v2"
	"github.com/hashicorp/hcl/v2/hclsyntax"
	hcljson "github.com/hashicorp/hcl/v2/json"
	"github.com/hashicorp/terraform/internal/addrs"
	"github.com/hashicorp/terraform/internal/tfdiags"
	"github.com/zclconf/go-cty/cty"
)

type Import struct {
	ID hcl.Expression

	Identity hcl.Expression

	To hcl.Expression
	// The To address may not be resolvable immediately if it contains dynamic
	// index expressions, so we will extract the ConfigResource address and
	// store it here for reference.
	ToResource addrs.ConfigResource

	ForEach hcl.Expression

	ProviderConfigRef *ProviderConfigRef
	Provider          addrs.Provider

	DeclRange         hcl.Range
	ProviderDeclRange hcl.Range
}

func decodeImportBlock(block *hcl.Block) (*Import, hcl.Diagnostics) {
	var diags hcl.Diagnostics
	imp := &Import{
		DeclRange: block.DefRange,
	}

	content, moreDiags := block.Body.Content(importBlockSchema)
	diags = append(diags, moreDiags...)

	if attr, exists := content.Attributes["id"]; exists {
		imp.ID = attr.Expr
	}

	if attr, exists := content.Attributes["identity"]; exists {
		imp.Identity = attr.Expr
	}

	if attr, exists := content.Attributes["to"]; exists {
		toExpr, jsDiags := unwrapJSONRefExpr(attr.Expr)
		diags = diags.Extend(jsDiags)
		if diags.HasErrors() {
			return imp, diags
		}

		imp.To = toExpr

		addr, toDiags := parseConfigResourceFromExpression(imp.To)
		diags = diags.Extend(toDiags.ToHCL())

		if addr.Resource.Mode != addrs.ManagedResourceMode {
			diags = append(diags, &hcl.Diagnostic{
				Severity: hcl.DiagError,
				Summary:  "Invalid import address",
				Detail:   "Only managed resources can be imported.",
				Subject:  attr.Range.Ptr(),
			})
		}

		imp.ToResource = addr
	}

	if attr, exists := content.Attributes["for_each"]; exists {
		imp.ForEach = attr.Expr
	}

	if attr, exists := content.Attributes["provider"]; exists {
		if len(imp.ToResource.Module) > 0 {
			diags = append(diags, &hcl.Diagnostic{
				Severity: hcl.DiagError,
				Summary:  "Invalid import provider argument",
				Detail:   "The provider argument can only be specified in import blocks that will generate configuration.\n\nUse the providers argument within the module block to configure providers for all resources within a module, including imported resources.",
				Subject:  attr.Range.Ptr(),
			})
		}

		var providerDiags hcl.Diagnostics
		imp.ProviderConfigRef, providerDiags = decodeProviderConfigRef(attr.Expr, "provider")
		imp.ProviderDeclRange = attr.Range
		diags = append(diags, providerDiags...)
	}

	if imp.ID == nil && imp.Identity == nil {
		diags = append(diags, &hcl.Diagnostic{
			Severity: hcl.DiagError,
			Summary:  "Invalid import block",
			Detail:   "At least one of 'id' or 'identity' must be specified.",
			Subject:  block.DefRange.Ptr(),
		})
	}

	if imp.ID != nil && imp.Identity != nil {
		diags = append(diags, &hcl.Diagnostic{
			Severity: hcl.DiagError,
			Summary:  "Invalid import block",
			Detail:   "Only one of 'id' or 'identity' can be specified.",
			Subject:  block.DefRange.Ptr(),
		})
	}

	return imp, diags
}

var importBlockSchema = &hcl.BodySchema{
	Attributes: []hcl.AttributeSchema{
		{
			Name: "provider",
		},
		{
			Name: "for_each",
		},
		{
			Name: "id",
		},
		{
			Name:     "to",
			Required: true,
		},
		{
			Name: "identity",
		},
	},
}

// parseResourceInstanceFromExpression takes an arbitrary expression
// representing a resource instance, and parses out the static ConfigResource
// skipping an variable index expressions. This is used to connect an import
// block's "to" to the configuration address before the full instance
// expressions are evaluated.
func parseConfigResourceFromExpression(expr hcl.Expression) (addrs.ConfigResource, tfdiags.Diagnostics) {
	traversal, hcdiags := exprToResourceTraversal(expr)
	if hcdiags.HasErrors() {
		return addrs.ConfigResource{}, tfdiags.Diagnostics(nil).Append(hcdiags)
	}

	addr, diags := addrs.ParseAbsResourceInstance(traversal)
	if diags.HasErrors() {
		return addrs.ConfigResource{}, diags
	}

	return addr.ConfigResource(), diags
}

// unwrapJSONRefExpr takes a string expression from a JSON configuration,
// and re-evaluates the string as HCL. If the expression is not JSON, the
// original expression is returned directly.
func unwrapJSONRefExpr(expr hcl.Expression) (hcl.Expression, hcl.Diagnostics) {
	if !hcljson.IsJSONExpression(expr) {
		return expr, nil
	}

	// We can abuse the hcl json api and rely on the fact that calling
	// Value on a json expression with no EvalContext will return the
	// raw string. We can then parse that as normal hcl syntax, and
	// continue with the decoding.
	v, diags := expr.Value(nil)
	if diags.HasErrors() {
		return nil, diags
	}

	// the JSON representation can only be a string
	if v.Type() != cty.String {
		diags = diags.Append(&hcl.Diagnostic{
			Severity: hcl.DiagError,
			Summary:  "Invalid reference expression",
			Detail:   "A single reference string is required.",
			Subject:  expr.Range().Ptr(),
		})

		return nil, diags
	}

	rng := expr.Range()
	expr, ds := hclsyntax.ParseExpression([]byte(v.AsString()), rng.Filename, rng.Start)
	diags = diags.Extend(ds)
	return expr, diags
}

// exprToResourceTraversal is used to parse the import block's to expression,
// which must be a resource instance, but may contain limited variables with
// index expressions. Since we only need the ConfigResource to connect the
// import to the configuration, we skip any index expressions.
func exprToResourceTraversal(expr hcl.Expression) (hcl.Traversal, hcl.Diagnostics) {
	var trav hcl.Traversal
	var diags hcl.Diagnostics

	switch e := expr.(type) {
	case *hclsyntax.RelativeTraversalExpr:
		t, d := exprToResourceTraversal(e.Source)
		diags = diags.Extend(d)
		trav = append(trav, t...)
		trav = append(trav, e.Traversal...)

	case *hclsyntax.ScopeTraversalExpr:
		// a static reference, we can just append the traversal
		trav = append(trav, e.Traversal...)

	case *hclsyntax.IndexExpr:
		// Get the collection from the index expression, we don't need the
		// index for a ConfigResource
		t, d := exprToResourceTraversal(e.Collection)
		diags = diags.Extend(d)
		if diags.HasErrors() {
			return nil, diags
		}
		trav = append(trav, t...)

	default:
		// if we don't recognise the expression type (which means we are likely
		// dealing with a test mock), try and interpret this as an absolute
		// traversal
		t, d := hcl.AbsTraversalForExpr(e)
		diags = diags.Extend(d)
		trav = append(trav, t...)
	}

	return trav, diags
}

// parseImportToStatic attempts to parse the To address of an import block
// statically to get the resource address. This returns false when the address
// cannot be parsed, which is usually a result of dynamic index expressions
// using for_each.
func parseImportToStatic(expr hcl.Expression) (addrs.AbsResourceInstance, bool) {
	// we may have a nil expression in some error cases, which we can just
	// false to avoid the parsing
	if expr == nil {
		return addrs.AbsResourceInstance{}, false
	}

	var toDiags tfdiags.Diagnostics
	traversal, hd := hcl.AbsTraversalForExpr(expr)
	toDiags = toDiags.Append(hd)
	to, td := addrs.ParseAbsResourceInstance(traversal)
	toDiags = toDiags.Append(td)
	return to, !toDiags.HasErrors()
}
