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

package globalref

import (
	"github.com/hashicorp/hcl/v2"
	"github.com/hashicorp/terraform/internal/addrs"
	"github.com/hashicorp/terraform/internal/configs/configschema"
	"github.com/hashicorp/terraform/internal/lang"
	"github.com/zclconf/go-cty/cty"
	"github.com/zclconf/go-cty/cty/convert"
	"github.com/zclconf/go-cty/cty/gocty"
)

// MetaReferences inspects the configuration to find the references contained
// within the most specific object that the given address refers to.
//
// This finds only the direct references in that object, not any indirect
// references from those. This is a building block for some other Analyzer
// functions that can walk through multiple levels of reference.
//
// If the given reference refers to something that doesn't exist in the
// configuration we're analyzing then MetaReferences will return no
// meta-references at all, which is indistinguishable from an existing
// object that doesn't refer to anything.
func (a *Analyzer) MetaReferences(ref Reference) []Reference {
	// This function is aiming to encapsulate the fact that a reference
	// is actually quite a complex notion which includes both a specific
	// object the reference is to, where each distinct object type has
	// a very different representation in the configuration, and then
	// also potentially an attribute or block within the definition of that
	// object. Our goal is to make all of these different situations appear
	// mostly the same to the caller, in that all of them can be reduced to
	// a set of references regardless of which expression or expressions we
	// derive those from.

	moduleAddr := ref.ModuleAddr()
	remaining := ref.LocalRef.Remaining

	// Our first task then is to select an appropriate implementation based
	// on which address type the reference refers to.
	switch targetAddr := ref.LocalRef.Subject.(type) {
	case addrs.InputVariable:
		return a.metaReferencesInputVariable(moduleAddr, targetAddr, remaining)
	case addrs.LocalValue:
		return a.metaReferencesLocalValue(moduleAddr, targetAddr, remaining)
	case addrs.ModuleCallInstanceOutput:
		return a.metaReferencesOutputValue(moduleAddr, targetAddr, remaining)
	case addrs.ModuleCallInstance:
		return a.metaReferencesModuleCall(moduleAddr, targetAddr, remaining)
	case addrs.ModuleCall:
		// TODO: It isn't really correct to say that a reference to a module
		// call is a reference to its no-key instance. Really what we want to
		// say here is that it's a reference to _all_ instances, or to an
		// instance with an unknown key, but we don't have any representation
		// of that. For the moment it's pretty immaterial since most of our
		// other analysis ignores instance keys anyway, but maybe we'll revisit
		// this latter to distingish these two cases better.
		return a.metaReferencesModuleCall(moduleAddr, targetAddr.Instance(addrs.NoKey), remaining)
	case addrs.CountAttr, addrs.ForEachAttr:
		if resourceAddr, ok := ref.ResourceInstance(); ok {
			return a.metaReferencesCountOrEach(resourceAddr.ContainingResource())
		}
		return nil
	case addrs.ResourceInstance:
		return a.metaReferencesResourceInstance(moduleAddr, targetAddr, remaining)
	case addrs.Resource:
		// TODO: It isn't really correct to say that a reference to a resource
		// is a reference to its no-key instance. Really what we want to say
		// here is that it's a reference to _all_ instances, or to an instance
		// with an unknown key, but we don't have any representation of that.
		// For the moment it's pretty immaterial since most of our other
		// analysis ignores instance keys anyway, but maybe we'll revisit this
		// latter to distingish these two cases better.
		return a.metaReferencesResourceInstance(moduleAddr, targetAddr.Instance(addrs.NoKey), remaining)
	default:
		// For anything we don't explicitly support we'll just return no
		// references. This includes the reference types that don't really
		// refer to configuration objects at all, like "path.module",
		// and so which cannot possibly generate any references.
		return nil
	}
}

func (a *Analyzer) metaReferencesInputVariable(calleeAddr addrs.ModuleInstance, addr addrs.InputVariable, remain hcl.Traversal) []Reference {
	if calleeAddr.IsRoot() {
		// A root module variable definition can never refer to anything,
		// because it conceptually exists outside of any module.
		return nil
	}

	callerAddr, callAddr := calleeAddr.Call()

	// We need to find the module call inside the caller module.
	callerCfg := a.ModuleConfig(callerAddr)
	if callerCfg == nil {
		return nil
	}
	call := callerCfg.ModuleCalls[callAddr.Name]
	if call == nil {
		return nil
	}

	// Now we need to look for an attribute matching the variable name inside
	// the module block body.
	body := call.Config
	schema := &hcl.BodySchema{
		Attributes: []hcl.AttributeSchema{
			{Name: addr.Name},
		},
	}
	// We don't check for errors here because we'll make a best effort to
	// analyze whatever partial result HCL is able to extract.
	content, _, _ := body.PartialContent(schema)
	attr := content.Attributes[addr.Name]
	if attr == nil {
		return nil
	}
	refs, _ := lang.ReferencesInExpr(attr.Expr)
	return absoluteRefs(callerAddr, refs)
}

func (a *Analyzer) metaReferencesOutputValue(callerAddr addrs.ModuleInstance, addr addrs.ModuleCallInstanceOutput, remain hcl.Traversal) []Reference {
	calleeAddr := callerAddr.Child(addr.Call.Call.Name, addr.Call.Key)

	// We need to find the output value declaration inside the callee module.
	calleeCfg := a.ModuleConfig(calleeAddr)
	if calleeCfg == nil {
		return nil
	}

	oc := calleeCfg.Outputs[addr.Name]
	if oc == nil {
		return nil
	}

	// We don't check for errors here because we'll make a best effort to
	// analyze whatever partial result HCL is able to extract.
	refs, _ := lang.ReferencesInExpr(oc.Expr)
	return absoluteRefs(calleeAddr, refs)
}

func (a *Analyzer) metaReferencesLocalValue(moduleAddr addrs.ModuleInstance, addr addrs.LocalValue, remain hcl.Traversal) []Reference {
	modCfg := a.ModuleConfig(moduleAddr)
	if modCfg == nil {
		return nil
	}

	local := modCfg.Locals[addr.Name]
	if local == nil {
		return nil
	}

	// We don't check for errors here because we'll make a best effort to
	// analyze whatever partial result HCL is able to extract.
	refs, _ := lang.ReferencesInExpr(local.Expr)
	return absoluteRefs(moduleAddr, refs)
}

func (a *Analyzer) metaReferencesModuleCall(callerAddr addrs.ModuleInstance, addr addrs.ModuleCallInstance, remain hcl.Traversal) []Reference {
	calleeAddr := callerAddr.Child(addr.Call.Name, addr.Key)

	// What we're really doing here is just rolling up all of the references
	// from all of this module's output values.
	calleeCfg := a.ModuleConfig(calleeAddr)
	if calleeCfg == nil {
		return nil
	}

	var ret []Reference
	for name := range calleeCfg.Outputs {
		outputAddr := addrs.ModuleCallInstanceOutput{
			Call: addr,
			Name: name,
		}
		moreRefs := a.metaReferencesOutputValue(callerAddr, outputAddr, nil)
		ret = append(ret, moreRefs...)
	}
	return ret
}

func (a *Analyzer) metaReferencesCountOrEach(resourceAddr addrs.AbsResource) []Reference {
	return a.ReferencesFromResourceRepetition(resourceAddr)
}

func (a *Analyzer) metaReferencesResourceInstance(moduleAddr addrs.ModuleInstance, addr addrs.ResourceInstance, remain hcl.Traversal) []Reference {
	modCfg := a.ModuleConfig(moduleAddr)
	if modCfg == nil {
		return nil
	}

	rc := modCfg.ResourceByAddr(addr.Resource)
	if rc == nil {
		return nil
	}

	// In valid cases we should have the schema for this resource type
	// available. In invalid cases we might be dealing with partial information,
	// and so the schema might be nil so we won't be able to return reference
	// information for this particular situation.
	providerSchema := a.providerSchemas[rc.Provider]
	if providerSchema == nil {
		return nil
	}

	resourceTypeSchema, _ := providerSchema.SchemaForResourceAddr(addr.Resource)
	if resourceTypeSchema == nil {
		return nil
	}

	// When analyzing the resource configuration to look for references, we'll
	// make a best effort to narrow down to only a particular sub-portion of
	// the configuration by following the remaining traversal steps. In the
	// ideal case this will lead us to a specific expression, but as a
	// compromise it might lead us to some nested blocks where at least we
	// can limit our searching only to those.
	bodies := []hcl.Body{rc.Config}
	var exprs []hcl.Expression
	schema := resourceTypeSchema
	var steppingThrough *configschema.NestedBlock
	var steppingThroughType string
	nextStep := func(newBodies []hcl.Body, newExprs []hcl.Expression) {
		// We append exprs but replace bodies because exprs represent extra
		// expressions we collected on the path, such as dynamic block for_each,
		// which can potentially contribute to the final evalcontext, but
		// bodies never contribute any values themselves, and instead just
		// narrow down where we're searching.
		bodies = newBodies
		exprs = append(exprs, newExprs...)
		steppingThrough = nil
		steppingThroughType = ""
		// Caller must also update "schema" if necessary.
	}
	traverseInBlock := func(name string) ([]hcl.Body, []hcl.Expression) {
		if attr := schema.Attributes[name]; attr != nil {
			// When we reach a specific attribute we can't traverse any deeper, because attributes are the leaves of the schema.
			schema = nil
			return traverseAttr(bodies, name)
		} else if blockType := schema.BlockTypes[name]; blockType != nil {
			// We need to take a different action here depending on
			// the nesting mode of the block type. Some require us
			// to traverse in two steps in order to select a specific
			// child block, while others we can just step through
			// directly.
			switch blockType.Nesting {
			case configschema.NestingSingle, configschema.NestingGroup:
				// There should be only zero or one blocks of this
				// type, so we can traverse in only one step.
				schema = &blockType.Block
				return traverseNestedBlockSingle(bodies, name)
			case configschema.NestingMap, configschema.NestingList, configschema.NestingSet:
				steppingThrough = blockType
				return bodies, exprs // Preserve current selections for the second step
			default:
				// The above should be exhaustive, but just in case
				// we add something new in future we'll bail out
				// here and conservatively return everything under
				// the current traversal point.
				schema = nil
				return nil, nil
			}
		}

		// We'll get here if the given name isn't in the schema at all. If so,
		// there's nothing else to be done here.
		schema = nil
		return nil, nil
	}
Steps:
	for _, step := range remain {
		// If we filter out all of our bodies before we finish traversing then
		// we know we won't find anything else, because all of our subsequent
		// traversal steps won't have any bodies to search.
		if len(bodies) == 0 {
			return nil
		}
		// If we no longer have a schema then that suggests we've
		// traversed as deep as what the schema covers (e.g. we reached
		// a specific attribute) and so we'll stop early, assuming that
		// any remaining steps are traversals into an attribute expression
		// result.
		if schema == nil {
			break
		}

		switch step := step.(type) {

		case hcl.TraverseAttr:
			switch {
			case steppingThrough != nil:
				// If we're stepping through a NestingMap block then
				// it's valid to use attribute syntax to select one of
				// the blocks by its label. Other nesting types require
				// TraverseIndex, so can never be valid.
				if steppingThrough.Nesting != configschema.NestingMap {
					nextStep(nil, nil) // bail out
					continue
				}
				nextStep(traverseNestedBlockMap(bodies, steppingThroughType, step.Name))
				schema = &steppingThrough.Block
			default:
				nextStep(traverseInBlock(step.Name))
				if schema == nil {
					// traverseInBlock determined that we've traversed as
					// deep as we can with reference to schema, so we'll
					// stop here and just process whatever's selected.
					break Steps
				}
			}
		case hcl.TraverseIndex:
			switch {
			case steppingThrough != nil:
				switch steppingThrough.Nesting {
				case configschema.NestingMap:
					keyVal, err := convert.Convert(step.Key, cty.String)
					if err != nil { // Invalid traversal, so can't have any refs
						nextStep(nil, nil) // bail out
						continue
					}
					nextStep(traverseNestedBlockMap(bodies, steppingThroughType, keyVal.AsString()))
					schema = &steppingThrough.Block
				case configschema.NestingList:
					idxVal, err := convert.Convert(step.Key, cty.Number)
					if err != nil { // Invalid traversal, so can't have any refs
						nextStep(nil, nil) // bail out
						continue
					}
					var idx int
					err = gocty.FromCtyValue(idxVal, &idx)
					if err != nil { // Invalid traversal, so can't have any refs
						nextStep(nil, nil) // bail out
						continue
					}
					nextStep(traverseNestedBlockList(bodies, steppingThroughType, idx))
					schema = &steppingThrough.Block
				default:
					// Note that NestingSet ends up in here because we don't
					// actually allow traversing into set-backed block types,
					// and so such a reference would be invalid.
					nextStep(nil, nil) // bail out
					continue
				}
			default:
				// When indexing the contents of a block directly we always
				// interpret the key as a string representing an attribute
				// name.
				nameVal, err := convert.Convert(step.Key, cty.String)
				if err != nil { // Invalid traversal, so can't have any refs
					nextStep(nil, nil) // bail out
					continue
				}
				nextStep(traverseInBlock(nameVal.AsString()))
				if schema == nil {
					// traverseInBlock determined that we've traversed as
					// deep as we can with reference to schema, so we'll
					// stop here and just process whatever's selected.
					break Steps
				}
			}
		default:
			// We shouldn't get here, because the above cases are exhaustive
			// for all of the relative traversal types, but we'll be robust in
			// case HCL adds more in future and just pretend the traversal
			// ended a bit early if so.
			break Steps
		}
	}

	if steppingThrough != nil {
		// If we ended in the middle of "stepping through" then we'll conservatively
		// use the bodies of _all_ nested blocks of the type we were stepping
		// through, because the recipient of this value could refer to any
		// of them dynamically.
		var labelNames []string
		if steppingThrough.Nesting == configschema.NestingMap {
			labelNames = []string{"key"}
		}
		blocks := findBlocksInBodies(bodies, steppingThroughType, labelNames)
		for _, block := range blocks {
			bodies, exprs = blockParts(block)
		}
	}

	if len(bodies) == 0 && len(exprs) == 0 {
		return nil
	}

	var refs []*addrs.Reference
	for _, expr := range exprs {
		moreRefs, _ := lang.ReferencesInExpr(expr)
		refs = append(refs, moreRefs...)
	}
	if schema != nil {
		for _, body := range bodies {
			moreRefs, _ := lang.ReferencesInBlock(body, schema)
			refs = append(refs, moreRefs...)
		}
	}
	return absoluteRefs(addr.Absolute(moduleAddr), refs)
}

func traverseAttr(bodies []hcl.Body, name string) ([]hcl.Body, []hcl.Expression) {
	if len(bodies) == 0 {
		return nil, nil
	}
	schema := &hcl.BodySchema{
		Attributes: []hcl.AttributeSchema{
			{Name: name},
		},
	}
	// We can find at most one expression per body, because attribute names
	// are always unique within a body.
	retExprs := make([]hcl.Expression, 0, len(bodies))
	for _, body := range bodies {
		content, _, _ := body.PartialContent(schema)
		if attr := content.Attributes[name]; attr != nil && attr.Expr != nil {
			retExprs = append(retExprs, attr.Expr)
		}
	}
	return nil, retExprs
}

func traverseNestedBlockSingle(bodies []hcl.Body, typeName string) ([]hcl.Body, []hcl.Expression) {
	if len(bodies) == 0 {
		return nil, nil
	}

	blocks := findBlocksInBodies(bodies, typeName, nil)
	var retBodies []hcl.Body
	var retExprs []hcl.Expression
	for _, block := range blocks {
		moreBodies, moreExprs := blockParts(block)
		retBodies = append(retBodies, moreBodies...)
		retExprs = append(retExprs, moreExprs...)
	}
	return retBodies, retExprs
}

func traverseNestedBlockMap(bodies []hcl.Body, typeName string, key string) ([]hcl.Body, []hcl.Expression) {
	if len(bodies) == 0 {
		return nil, nil
	}

	blocks := findBlocksInBodies(bodies, typeName, []string{"key"})
	var retBodies []hcl.Body
	var retExprs []hcl.Expression
	for _, block := range blocks {
		switch block.Type {
		case "dynamic":
			// For dynamic blocks we allow the key to be chosen dynamically
			// and so we'll just conservatively include all dynamic block
			// bodies. However, we need to also look for references in some
			// arguments of the dynamic block itself.
			argExprs, contentBody := dynamicBlockParts(block.Body)
			retExprs = append(retExprs, argExprs...)
			if contentBody != nil {
				retBodies = append(retBodies, contentBody)
			}
		case typeName:
			if len(block.Labels) == 1 && block.Labels[0] == key && block.Body != nil {
				retBodies = append(retBodies, block.Body)
			}
		}
	}
	return retBodies, retExprs
}

func traverseNestedBlockList(bodies []hcl.Body, typeName string, idx int) ([]hcl.Body, []hcl.Expression) {
	if len(bodies) == 0 {
		return nil, nil
	}

	schema := &hcl.BodySchema{
		Blocks: []hcl.BlockHeaderSchema{
			{Type: typeName, LabelNames: nil},
			{Type: "dynamic", LabelNames: []string{"type"}},
		},
	}
	var retBodies []hcl.Body
	var retExprs []hcl.Expression
	for _, body := range bodies {
		content, _, _ := body.PartialContent(schema)
		blocks := content.Blocks

		// A tricky aspect of this scenario is that if there are any "dynamic"
		// blocks then we can't statically predict how many concrete blocks they
		// will generate, and so consequently we can't predict the indices of
		// any statically-defined blocks that might appear after them.
		firstDynamic := -1 // -1 means "no dynamic blocks"
		for i, block := range blocks {
			if block.Type == "dynamic" {
				firstDynamic = i
				break
			}
		}

		switch {
		case firstDynamic >= 0 && idx >= firstDynamic:
			// This is the unfortunate case where the selection could be
			// any of the blocks from firstDynamic onwards, and so we
			// need to conservatively include all of them in our result.
			for _, block := range blocks[firstDynamic:] {
				moreBodies, moreExprs := blockParts(block)
				retBodies = append(retBodies, moreBodies...)
				retExprs = append(retExprs, moreExprs...)
			}
		default:
			// This is the happier case where we can select just a single
			// static block based on idx. Note that this one is guaranteed
			// to never be dynamic but we're using blockParts here just
			// for consistency.
			moreBodies, moreExprs := blockParts(blocks[idx])
			retBodies = append(retBodies, moreBodies...)
			retExprs = append(retExprs, moreExprs...)
		}
	}

	return retBodies, retExprs
}

func findBlocksInBodies(bodies []hcl.Body, typeName string, labelNames []string) []*hcl.Block {
	// We need to look for both static blocks of the given type, and any
	// dynamic blocks whose label gives the expected type name.
	schema := &hcl.BodySchema{
		Blocks: []hcl.BlockHeaderSchema{
			{Type: typeName, LabelNames: labelNames},
			{Type: "dynamic", LabelNames: []string{"type"}},
		},
	}
	var blocks []*hcl.Block
	for _, body := range bodies {
		// We ignore errors here because we'll just make a best effort to analyze
		// whatever partial result HCL returns in that case.
		content, _, _ := body.PartialContent(schema)

		for _, block := range content.Blocks {
			switch block.Type {
			case "dynamic":
				if len(block.Labels) != 1 { // Invalid
					continue
				}
				if block.Labels[0] == typeName {
					blocks = append(blocks, block)
				}
			case typeName:
				blocks = append(blocks, block)
			}
		}
	}

	// NOTE: The caller still needs to check for dynamic vs. static in order
	// to do further processing. The callers above all aim to encapsulate
	// that.
	return blocks
}

func blockParts(block *hcl.Block) ([]hcl.Body, []hcl.Expression) {
	switch block.Type {
	case "dynamic":
		exprs, contentBody := dynamicBlockParts(block.Body)
		var bodies []hcl.Body
		if contentBody != nil {
			bodies = []hcl.Body{contentBody}
		}
		return bodies, exprs
	default:
		if block.Body == nil {
			return nil, nil
		}
		return []hcl.Body{block.Body}, nil
	}
}

func dynamicBlockParts(body hcl.Body) ([]hcl.Expression, hcl.Body) {
	if body == nil {
		return nil, nil
	}

	// This is a subset of the "dynamic" block schema defined by the HCL
	// dynblock extension, covering only the two arguments that are allowed
	// to be arbitrary expressions possibly referring elsewhere.
	schema := &hcl.BodySchema{
		Attributes: []hcl.AttributeSchema{
			{Name: "for_each"},
			{Name: "labels"},
		},
		Blocks: []hcl.BlockHeaderSchema{
			{Type: "content"},
		},
	}
	content, _, _ := body.PartialContent(schema)
	var exprs []hcl.Expression
	if len(content.Attributes) != 0 {
		exprs = make([]hcl.Expression, 0, len(content.Attributes))
	}
	for _, attr := range content.Attributes {
		if attr.Expr != nil {
			exprs = append(exprs, attr.Expr)
		}
	}
	var contentBody hcl.Body
	for _, block := range content.Blocks {
		if block != nil && block.Type == "content" && block.Body != nil {
			contentBody = block.Body
		}
	}
	return exprs, contentBody
}
