package refactoring

import (
	"fmt"

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

type MoveStatement struct {
	From, To  *addrs.MoveEndpointInModule
	DeclRange tfdiags.SourceRange

	// Implied is true for statements produced by ImpliedMoveStatements, and
	// false for statements produced by FindMoveStatements.
	//
	// An "implied" statement is one that has no explicit "moved" block in
	// the configuration and was instead generated automatically based on a
	// comparison between current configuration and previous run state.
	// For implied statements, the DeclRange field contains the source location
	// of something in the source code that implied the statement, in which
	// case it would probably be confusing to show that source range to the
	// user, e.g. in an error message, without clearly mentioning that it's
	// related to an implied move statement.
	Implied bool
}

// FindMoveStatements recurses through the modules of the given configuration
// and returns a flat set of all "moved" blocks defined within, in a
// deterministic but undefined order.
func FindMoveStatements(rootCfg *configs.Config) []MoveStatement {
	return findMoveStatements(rootCfg, nil)
}

func findMoveStatements(cfg *configs.Config, into []MoveStatement) []MoveStatement {
	modAddr := cfg.Path
	for _, mc := range cfg.Module.Moved {
		fromAddr, toAddr := addrs.UnifyMoveEndpoints(modAddr, mc.From, mc.To)
		if fromAddr == nil || toAddr == nil {
			// Invalid combination should've been caught during original
			// configuration decoding, in the configs package.
			panic(fmt.Sprintf("incompatible move endpoints in %s", mc.DeclRange))
		}

		into = append(into, MoveStatement{
			From:      fromAddr,
			To:        toAddr,
			DeclRange: tfdiags.SourceRangeFromHCL(mc.DeclRange),
			Implied:   false,
		})
	}

	for _, childCfg := range cfg.Children {
		into = findMoveStatements(childCfg, into)
	}

	return into
}

// ImpliedMoveStatements compares addresses in the given state with addresses
// in the given configuration and potentially returns additional MoveStatement
// objects representing moves we infer automatically, even though they aren't
// explicitly recorded in the configuration.
//
// We do this primarily for backward compatibility with behaviors of Terraform
// versions prior to introducing explicit "moved" blocks. Specifically, this
// function aims to achieve the same result as the "NodeCountBoundary"
// heuristic from Terraform v1.0 and earlier, where adding or removing the
// "count" meta-argument from an already-created resource can automatically
// preserve the zeroth or the NoKey instance, depending on the direction of
// the change. We do this only for resources that aren't mentioned already
// in at least one explicit move statement.
//
// As with the previous-version heuristics it replaces, this is a best effort
// and doesn't handle all situations. An explicit move statement is always
// preferred, but our goal here is to match exactly the same cases that the
// old heuristic would've matched, to retain compatibility for existing modules.
//
// We should think very hard before adding any _new_ implication rules for
// moved statements.
func ImpliedMoveStatements(rootCfg *configs.Config, prevRunState *states.State, explicitStmts []MoveStatement) []MoveStatement {
	return impliedMoveStatements(rootCfg, prevRunState, explicitStmts, nil)
}

func impliedMoveStatements(cfg *configs.Config, prevRunState *states.State, explicitStmts []MoveStatement, into []MoveStatement) []MoveStatement {
	modAddr := cfg.Path

	// There can be potentially many instances of the module, so we need
	// to consider each of them separately.
	for _, modState := range prevRunState.ModuleInstances(modAddr) {
		// What we're looking for here is either a no-key resource instance
		// where the configuration has count set or a zero-key resource
		// instance where the configuration _doesn't_ have count set.
		// If so, we'll generate a statement replacing no-key with zero-key or
		// vice-versa.
		for _, rState := range modState.Resources {
			rAddr := rState.Addr
			rCfg := cfg.Module.ResourceByAddr(rAddr.Resource)
			if rCfg == nil {
				// If there's no configuration at all then there can't be any
				// automatic move fixup to do.
				continue
			}
			approxSrcRange := tfdiags.SourceRangeFromHCL(rCfg.DeclRange)

			// NOTE: We're intentionally not checking to see whether the
			// "to" addresses in our implied statements already have
			// instances recorded in state, because ApplyMoves should
			// deal with such conflicts in a deterministic way for both
			// explicit and implicit moves, and we'd rather have that
			// handled all in one place.

			var fromKey, toKey addrs.InstanceKey

			switch {
			case rCfg.Count != nil:
				// If we have a count expression then we'll use _that_ as
				// a slightly-more-precise approximate source range.
				approxSrcRange = tfdiags.SourceRangeFromHCL(rCfg.Count.Range())

				if riState := rState.Instances[addrs.NoKey]; riState != nil {
					fromKey = addrs.NoKey
					toKey = addrs.IntKey(0)
				}
			case rCfg.Count == nil && rCfg.ForEach == nil: // no repetition at all
				if riState := rState.Instances[addrs.IntKey(0)]; riState != nil {
					fromKey = addrs.IntKey(0)
					toKey = addrs.NoKey
				}
			}

			if fromKey != toKey {
				// We mustn't generate an impied statement if the user already
				// wrote an explicit statement referring to this resource,
				// because they may wish to select an instance key other than
				// zero as the one to retain.
				if !haveMoveStatementForResource(rAddr, explicitStmts) {
					into = append(into, MoveStatement{
						From:      addrs.ImpliedMoveStatementEndpoint(rAddr.Instance(fromKey), approxSrcRange),
						To:        addrs.ImpliedMoveStatementEndpoint(rAddr.Instance(toKey), approxSrcRange),
						DeclRange: approxSrcRange,
						Implied:   true,
					})
				}
			}
		}
	}

	for _, childCfg := range cfg.Children {
		into = impliedMoveStatements(childCfg, prevRunState, explicitStmts, into)
	}

	return into
}

func (s *MoveStatement) ObjectKind() addrs.MoveEndpointKind {
	// addrs.UnifyMoveEndpoints guarantees that both of our addresses have
	// the same kind, so we can just arbitrary use From and assume To will
	// match it.
	return s.From.ObjectKind()
}

// Name is used internally for displaying the statement graph
func (s *MoveStatement) Name() string {
	return fmt.Sprintf("%s->%s", s.From, s.To)
}

func haveMoveStatementForResource(addr addrs.AbsResource, stmts []MoveStatement) bool {
	// This is not a particularly optimal way to answer this question,
	// particularly since our caller calls this function in a loop already,
	// but we expect the total number of explicit statements to be small
	// in any reasonable Terraform configuration and so a more complicated
	// approach wouldn't be justified here.

	for _, stmt := range stmts {
		if stmt.From.SelectsResource(addr) {
			return true
		}
		if stmt.To.SelectsResource(addr) {
			return true
		}
	}
	return false
}
