package terraform

import (
	"fmt"
	"sort"

	"github.com/hashicorp/hcl/v2"

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

// StaticValidateReferences checks the given references against schemas and
// other statically-checkable rules, producing error diagnostics if any
// problems are found.
//
// If this method returns errors for a particular reference then evaluating
// that reference is likely to generate a very similar error, so callers should
// not run this method and then also evaluate the source expression(s) and
// merge the two sets of diagnostics together, since this will result in
// confusing redundant errors.
//
// This method can find more errors than can be found by evaluating an
// expression with a partially-populated scope, since it checks the referenced
// names directly against the schema rather than relying on evaluation errors.
//
// The result may include warning diagnostics if, for example, deprecated
// features are referenced.
func (d *evaluationStateData) StaticValidateReferences(refs []*addrs.Reference, self addrs.Referenceable) tfdiags.Diagnostics {
	var diags tfdiags.Diagnostics
	for _, ref := range refs {
		moreDiags := d.staticValidateReference(ref, self)
		diags = diags.Append(moreDiags)
	}
	return diags
}

func (d *evaluationStateData) staticValidateReference(ref *addrs.Reference, self addrs.Referenceable) tfdiags.Diagnostics {
	modCfg := d.Evaluator.Config.DescendentForInstance(d.ModulePath)
	if modCfg == nil {
		// This is a bug in the caller rather than a problem with the
		// reference, but rather than crashing out here in an unhelpful way
		// we'll just ignore it and trust a different layer to catch it.
		return nil
	}

	if ref.Subject == addrs.Self {
		// The "self" address is a special alias for the address given as
		// our self parameter here, if present.
		if self == nil {
			var diags tfdiags.Diagnostics
			diags = diags.Append(&hcl.Diagnostic{
				Severity: hcl.DiagError,
				Summary:  `Invalid "self" reference`,
				// This detail message mentions some current practice that
				// this codepath doesn't really "know about". If the "self"
				// object starts being supported in more contexts later then
				// we'll need to adjust this message.
				Detail:  `The "self" object is not available in this context. This object can be used only in resource provisioner, connection, and postcondition blocks.`,
				Subject: ref.SourceRange.ToHCL().Ptr(),
			})
			return diags
		}

		synthRef := *ref // shallow copy
		synthRef.Subject = self
		ref = &synthRef
	}

	switch addr := ref.Subject.(type) {

	// For static validation we validate both resource and resource instance references the same way.
	// We mostly disregard the index, though we do some simple validation of
	// its _presence_ in staticValidateSingleResourceReference and
	// staticValidateMultiResourceReference respectively.
	case addrs.Resource:
		var diags tfdiags.Diagnostics
		diags = diags.Append(d.staticValidateSingleResourceReference(modCfg, addr, ref.Remaining, ref.SourceRange))
		diags = diags.Append(d.staticValidateResourceReference(modCfg, addr, ref.Remaining, ref.SourceRange))
		return diags
	case addrs.ResourceInstance:
		var diags tfdiags.Diagnostics
		diags = diags.Append(d.staticValidateMultiResourceReference(modCfg, addr, ref.Remaining, ref.SourceRange))
		diags = diags.Append(d.staticValidateResourceReference(modCfg, addr.ContainingResource(), ref.Remaining, ref.SourceRange))
		return diags

	// We also handle all module call references the same way, disregarding index.
	case addrs.ModuleCall:
		return d.staticValidateModuleCallReference(modCfg, addr, ref.Remaining, ref.SourceRange)
	case addrs.ModuleCallInstance:
		return d.staticValidateModuleCallReference(modCfg, addr.Call, ref.Remaining, ref.SourceRange)
	case addrs.ModuleCallInstanceOutput:
		// This one is a funny one because we will take the output name referenced
		// and use it to fake up a "remaining" that would make sense for the
		// module call itself, rather than for the specific output, and then
		// we can just re-use our static module call validation logic.
		remain := make(hcl.Traversal, len(ref.Remaining)+1)
		copy(remain[1:], ref.Remaining)
		remain[0] = hcl.TraverseAttr{
			Name: addr.Name,

			// Using the whole reference as the source range here doesn't exactly
			// match how HCL would normally generate an attribute traversal,
			// but is close enough for our purposes.
			SrcRange: ref.SourceRange.ToHCL(),
		}
		return d.staticValidateModuleCallReference(modCfg, addr.Call.Call, remain, ref.SourceRange)

	default:
		// Anything else we'll just permit through without any static validation
		// and let it be caught during dynamic evaluation, in evaluate.go .
		return nil
	}
}

func (d *evaluationStateData) staticValidateSingleResourceReference(modCfg *configs.Config, addr addrs.Resource, remain hcl.Traversal, rng tfdiags.SourceRange) tfdiags.Diagnostics {
	// If we have at least one step in "remain" and this resource has
	// "count" set then we know for sure this in invalid because we have
	// something like:
	//     aws_instance.foo.bar
	// ...when we really need
	//     aws_instance.foo[count.index].bar

	// It is _not_ safe to do this check when remain is empty, because that
	// would also match aws_instance.foo[count.index].bar due to `count.index`
	// not being statically-resolvable as part of a reference, and match
	// direct references to the whole aws_instance.foo tuple.
	if len(remain) == 0 {
		return nil
	}

	var diags tfdiags.Diagnostics

	cfg := modCfg.Module.ResourceByAddr(addr)
	if cfg == nil {
		// We'll just bail out here and catch this in our subsequent call to
		// staticValidateResourceReference, then.
		return diags
	}

	if cfg.Count != nil {
		diags = diags.Append(&hcl.Diagnostic{
			Severity: hcl.DiagError,
			Summary:  `Missing resource instance key`,
			Detail:   fmt.Sprintf("Because %s has \"count\" set, its attributes must be accessed on specific instances.\n\nFor example, to correlate with indices of a referring resource, use:\n    %s[count.index]", addr, addr),
			Subject:  rng.ToHCL().Ptr(),
		})
	}
	if cfg.ForEach != nil {
		diags = diags.Append(&hcl.Diagnostic{
			Severity: hcl.DiagError,
			Summary:  `Missing resource instance key`,
			Detail:   fmt.Sprintf("Because %s has \"for_each\" set, its attributes must be accessed on specific instances.\n\nFor example, to correlate with indices of a referring resource, use:\n    %s[each.key]", addr, addr),
			Subject:  rng.ToHCL().Ptr(),
		})
	}

	return diags
}

func (d *evaluationStateData) staticValidateMultiResourceReference(modCfg *configs.Config, addr addrs.ResourceInstance, remain hcl.Traversal, rng tfdiags.SourceRange) tfdiags.Diagnostics {
	var diags tfdiags.Diagnostics

	cfg := modCfg.Module.ResourceByAddr(addr.ContainingResource())
	if cfg == nil {
		// We'll just bail out here and catch this in our subsequent call to
		// staticValidateResourceReference, then.
		return diags
	}

	if addr.Key == addrs.NoKey {
		// This is a different path into staticValidateSingleResourceReference
		return d.staticValidateSingleResourceReference(modCfg, addr.ContainingResource(), remain, rng)
	} else {
		if cfg.Count == nil && cfg.ForEach == nil {
			diags = diags.Append(&hcl.Diagnostic{
				Severity: hcl.DiagError,
				Summary:  `Unexpected resource instance key`,
				Detail:   fmt.Sprintf(`Because %s does not have "count" or "for_each" set, references to it must not include an index key. Remove the bracketed index to refer to the single instance of this resource.`, addr.ContainingResource()),
				Subject:  rng.ToHCL().Ptr(),
			})
		}
	}

	return diags
}

func (d *evaluationStateData) staticValidateResourceReference(modCfg *configs.Config, addr addrs.Resource, remain hcl.Traversal, rng tfdiags.SourceRange) tfdiags.Diagnostics {
	var diags tfdiags.Diagnostics

	var modeAdjective string
	switch addr.Mode {
	case addrs.ManagedResourceMode:
		modeAdjective = "managed"
	case addrs.DataResourceMode:
		modeAdjective = "data"
	default:
		// should never happen
		modeAdjective = "<invalid-mode>"
	}

	cfg := modCfg.Module.ResourceByAddr(addr)
	if cfg == nil {
		var suggestion string
		// A common mistake is omitting the data. prefix when trying to refer
		// to a data resource, so we'll add a special hint for that.
		if addr.Mode == addrs.ManagedResourceMode {
			candidateAddr := addr // not a pointer, so this is a copy
			candidateAddr.Mode = addrs.DataResourceMode
			if candidateCfg := modCfg.Module.ResourceByAddr(candidateAddr); candidateCfg != nil {
				suggestion = fmt.Sprintf("\n\nDid you mean the data resource %s?", candidateAddr)
			}
		}

		diags = diags.Append(&hcl.Diagnostic{
			Severity: hcl.DiagError,
			Summary:  `Reference to undeclared resource`,
			Detail:   fmt.Sprintf(`A %s resource %q %q has not been declared in %s.%s`, modeAdjective, addr.Type, addr.Name, moduleConfigDisplayAddr(modCfg.Path), suggestion),
			Subject:  rng.ToHCL().Ptr(),
		})
		return diags
	}

	providerFqn := modCfg.Module.ProviderForLocalConfig(cfg.ProviderConfigAddr())
	schema, _, err := d.Evaluator.Plugins.ResourceTypeSchema(providerFqn, addr.Mode, addr.Type)
	if err != nil {
		// Prior validation should've taken care of a schema lookup error,
		// so we should never get here but we'll handle it here anyway for
		// robustness.
		diags = diags.Append(&hcl.Diagnostic{
			Severity: hcl.DiagError,
			Summary:  `Failed provider schema lookup`,
			Detail:   fmt.Sprintf(`Couldn't load schema for %s resource type %q in %s: %s.`, modeAdjective, addr.Type, providerFqn.String(), err),
			Subject:  rng.ToHCL().Ptr(),
		})
	}

	if schema == nil {
		// Prior validation should've taken care of a resource block with an
		// unsupported type, so we should never get here but we'll handle it
		// here anyway for robustness.
		diags = diags.Append(&hcl.Diagnostic{
			Severity: hcl.DiagError,
			Summary:  `Invalid resource type`,
			Detail:   fmt.Sprintf(`A %s resource type %q is not supported by provider %q.`, modeAdjective, addr.Type, providerFqn.String()),
			Subject:  rng.ToHCL().Ptr(),
		})
		return diags
	}

	// As a special case we'll detect attempts to access an attribute called
	// "count" and produce a special error for it, since versions of Terraform
	// prior to v0.12 offered this as a weird special case that we can no
	// longer support.
	if len(remain) > 0 {
		if step, ok := remain[0].(hcl.TraverseAttr); ok && step.Name == "count" {
			diags = diags.Append(&hcl.Diagnostic{
				Severity: hcl.DiagError,
				Summary:  `Invalid resource count attribute`,
				Detail:   fmt.Sprintf(`The special "count" attribute is no longer supported after Terraform v0.12. Instead, use length(%s) to count resource instances.`, addr),
				Subject:  rng.ToHCL().Ptr(),
			})
			return diags
		}
	}

	// If we got this far then we'll try to validate the remaining traversal
	// steps against our schema.
	moreDiags := schema.StaticValidateTraversal(remain)
	diags = diags.Append(moreDiags)

	return diags
}

func (d *evaluationStateData) staticValidateModuleCallReference(modCfg *configs.Config, addr addrs.ModuleCall, remain hcl.Traversal, rng tfdiags.SourceRange) tfdiags.Diagnostics {
	var diags tfdiags.Diagnostics

	// For now, our focus here is just in testing that the referenced module
	// call exists. All other validation is deferred until evaluation time.
	_, exists := modCfg.Module.ModuleCalls[addr.Name]
	if !exists {
		var suggestions []string
		for name := range modCfg.Module.ModuleCalls {
			suggestions = append(suggestions, name)
		}
		sort.Strings(suggestions)
		suggestion := didyoumean.NameSuggestion(addr.Name, suggestions)
		if suggestion != "" {
			suggestion = fmt.Sprintf(" Did you mean %q?", suggestion)
		}

		diags = diags.Append(&hcl.Diagnostic{
			Severity: hcl.DiagError,
			Summary:  `Reference to undeclared module`,
			Detail:   fmt.Sprintf(`No module call named %q is declared in %s.%s`, addr.Name, moduleConfigDisplayAddr(modCfg.Path), suggestion),
			Subject:  rng.ToHCL().Ptr(),
		})
		return diags
	}

	return diags
}

// moduleConfigDisplayAddr returns a string describing the given module
// address that is appropriate for returning to users in situations where the
// root module is possible. Specifically, it returns "the root module" if the
// root module instance is given, or a string representation of the module
// address otherwise.
func moduleConfigDisplayAddr(addr addrs.Module) string {
	switch {
	case addr.IsRoot():
		return "the root module"
	default:
		return addr.String()
	}
}
