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

package stackconfig

import (
	"github.com/apparentlymart/go-versions/versions/constraints"
	"github.com/hashicorp/go-slug/sourceaddrs"
	"github.com/hashicorp/hcl/v2"
	"github.com/hashicorp/hcl/v2/gohcl"

	"github.com/hashicorp/terraform/internal/addrs"
	"github.com/hashicorp/terraform/internal/stacks/stackaddrs"
	"github.com/hashicorp/terraform/internal/tfdiags"
)

// Removed represents a component that was removed from the configuration.
//
// Removed blocks don't have labels associated with them, instead they have
// a "from" attribute that points directly to the old component that was
// removed. Removed blocks can also point to component instances specifically,
// using an index expression. The "for_each" attribute also means that the
// "from" attribute can't always be evaluated statically.
//
// Removed blocks are, therefore, represented by the FromComponent and FromIndex
// fields, which together represent the address of the removed component. The
// FromComponent field is the address of the component itself, and the FromIndex
// field is the index expression that will be evaluated to determine the
// specific instance of the component that was removed.
//
// FromIndex can be null if either the removed block is pointing to a component
// that was not instanced, or is pointing to all the instances of a removed
// component.
//
// For this reason, multiple Removed blocks can be associated with the same
// FromComponent, but with different FromIndex values. When the FromIndex values
// are evaluated, during the planning stage, we will validate that the FromIndex
// values are unique.
type Removed struct {
	FromComponent stackaddrs.Component
	FromIndex     hcl.Expression

	SourceAddr                               sourceaddrs.Source
	VersionConstraints                       constraints.IntersectionSpec
	SourceAddrRange, VersionConstraintsRange tfdiags.SourceRange

	// FinalSourceAddr is populated only when a configuration is loaded
	// through [LoadConfigDir], and in that case contains the finalized
	// address produced by resolving the SourceAddr field relative to
	// the address of the file where the component was declared. This
	// is the address to use if you intend to load the component's
	// root module from a source bundle.
	FinalSourceAddr sourceaddrs.FinalSource

	ForEach hcl.Expression

	// ProviderConfigs describes the mapping between the static provider
	// configuration slots declared in the component's root module and the
	// dynamic provider configuration objects in scope in the calling
	// stack configuration.
	//
	// This map deals with the slight schism between the stacks language's
	// treatment of provider configurations as regular values of a special
	// data type vs. the main Terraform language's treatment of provider
	// configurations as something special passed out of band from the
	// input variables. The overall structure and the map keys are fixed
	// statically during decoding, but the final provider configuration objects
	// are determined only at runtime by normal expression evaluation.
	//
	// The keys of this map refer to provider configuration slots inside
	// the module being called, but use the local names defined in the
	// calling stack configuration. The stacks language runtime will
	// translate the caller's local names into the callee's declared provider
	// configurations by using the stack configuration's table of local
	// provider names.
	ProviderConfigs map[addrs.LocalProviderConfig]hcl.Expression

	// Destroy controls whether this removed block will actually destroy all
	// instances of resources within this component, or just removed them from
	// the state. Defaults to true.
	Destroy bool

	DeclRange tfdiags.SourceRange
}

func decodeRemovedBlock(block *hcl.Block) (*Removed, tfdiags.Diagnostics) {
	var diags tfdiags.Diagnostics
	ret := &Removed{
		DeclRange: tfdiags.SourceRangeFromHCL(block.DefRange),
	}

	content, hclDiags := block.Body.Content(removedBlockSchema)
	diags = diags.Append(hclDiags)
	if hclDiags.HasErrors() {
		return nil, diags
	}

	// We're splitting out the component and the index now, as we can decode and
	// analyse the component now. The index might be referencing the for_each
	// variable, which we can't decode yet.
	component, index, moreDiags := stackaddrs.ParseRemovedFrom(content.Attributes["from"].Expr)
	diags = diags.Append(moreDiags)
	if moreDiags.HasErrors() {
		return nil, diags
	}
	ret.FromComponent = component
	ret.FromIndex = index

	sourceAddr, versionConstraints, moreDiags := decodeSourceAddrArguments(
		content.Attributes["source"],
		content.Attributes["version"],
	)
	diags = diags.Append(moreDiags)
	if moreDiags.HasErrors() {
		return nil, diags
	}

	ret.SourceAddr = sourceAddr
	ret.VersionConstraints = versionConstraints
	ret.SourceAddrRange = tfdiags.SourceRangeFromHCL(content.Attributes["source"].Range)
	if content.Attributes["version"] != nil {
		ret.VersionConstraintsRange = tfdiags.SourceRangeFromHCL(content.Attributes["version"].Range)
	}
	// Now that we've populated the mandatory source location fields we can
	// safely return a partial ret if we encounter any further errors, as
	// long as we leave the other fields either unset or in some other
	// reasonable state for careful partial analysis.

	if attr, ok := content.Attributes["for_each"]; ok {
		if ret.FromIndex == nil {
			// if we have a for_each expression, then we must have an index
			// otherwise we'll try and remove the same thing multiple times.
			diags = diags.Append(&hcl.Diagnostic{
				Severity: hcl.DiagError,
				Summary:  "Invalid for_each expression",
				Detail:   "A removed block with a for_each expression must reference that expression within the `from` attribute.",
				Subject:  attr.NameRange.Ptr(),
			})
		} else {
			matches := false
			for _, variable := range ret.FromIndex.Variables() {
				if root, ok := variable[0].(hcl.TraverseRoot); ok {
					if root.Name == "each" {
						matches = true
						break
					}
				}
			}
			if !matches {
				// You have to refer to the for_each attribute somewhere in the
				// from attribute.
				diags = diags.Append(&hcl.Diagnostic{
					Severity: hcl.DiagError,
					Summary:  "Invalid for_each expression",
					Detail:   "A removed block with a for_each expression must reference that expression within the `from` attribute.",
					Subject:  attr.NameRange.Ptr(),
				})
			}
		}

		ret.ForEach = attr.Expr
	}
	if attr, ok := content.Attributes["providers"]; ok {
		var providerDiags tfdiags.Diagnostics
		ret.ProviderConfigs, providerDiags = decodeProvidersAttribute(attr)
		diags = diags.Append(providerDiags)
	}

	ret.Destroy = true // default to true
	for _, block := range content.Blocks {
		switch block.Type {
		case "lifecycle":
			lcContent, lcDiags := block.Body.Content(removedLifecycleBlockSchema)
			diags = diags.Append(lcDiags)

			if attr, ok := lcContent.Attributes["destroy"]; ok {
				valDiags := gohcl.DecodeExpression(attr.Expr, nil, &ret.Destroy)
				diags = diags.Append(valDiags)
			}
		}
	}

	return ret, diags
}

var removedBlockSchema = &hcl.BodySchema{
	Blocks: []hcl.BlockHeaderSchema{
		{Type: "lifecycle"},
	},
	Attributes: []hcl.AttributeSchema{
		{Name: "from", Required: true},
		{Name: "source", Required: true},
		{Name: "version", Required: false},
		{Name: "for_each", Required: false},
		{Name: "providers", Required: false},
	},
}

var removedLifecycleBlockSchema = &hcl.BodySchema{
	Attributes: []hcl.AttributeSchema{
		{Name: "destroy"},
	},
}
