package configs

import (
	"fmt"
	"log"
	"sort"

	version "github.com/hashicorp/go-version"
	"github.com/hashicorp/hcl/v2"
	"github.com/hashicorp/terraform/internal/addrs"
	"github.com/hashicorp/terraform/internal/depsfile"
	"github.com/hashicorp/terraform/internal/getproviders"
)

// A Config is a node in the tree of modules within a configuration.
//
// The module tree is constructed by following ModuleCall instances recursively
// through the root module transitively into descendent modules.
//
// A module tree described in *this* package represents the static tree
// represented by configuration. During evaluation a static ModuleNode may
// expand into zero or more module instances depending on the use of count and
// for_each configuration attributes within each call.
type Config struct {
	// RootModule points to the Config for the root module within the same
	// module tree as this module. If this module _is_ the root module then
	// this is self-referential.
	Root *Config

	// ParentModule points to the Config for the module that directly calls
	// this module. If this is the root module then this field is nil.
	Parent *Config

	// Path is a sequence of module logical names that traverse from the root
	// module to this config. Path is empty for the root module.
	//
	// This should only be used to display paths to the end-user in rare cases
	// where we are talking about the static module tree, before module calls
	// have been resolved. In most cases, an addrs.ModuleInstance describing
	// a node in the dynamic module tree is better, since it will then include
	// any keys resulting from evaluating "count" and "for_each" arguments.
	Path addrs.Module

	// ChildModules points to the Config for each of the direct child modules
	// called from this module. The keys in this map match the keys in
	// Module.ModuleCalls.
	Children map[string]*Config

	// Module points to the object describing the configuration for the
	// various elements (variables, resources, etc) defined by this module.
	Module *Module

	// CallRange is the source range for the header of the module block that
	// requested this module.
	//
	// This field is meaningless for the root module, where its contents are undefined.
	CallRange hcl.Range

	// SourceAddr is the source address that the referenced module was requested
	// from, as specified in configuration. SourceAddrRaw is the same
	// information, but as the raw string the user originally entered.
	//
	// These fields are meaningless for the root module, where their contents are undefined.
	SourceAddr    addrs.ModuleSource
	SourceAddrRaw string

	// SourceAddrRange is the location in the configuration source where the
	// SourceAddr value was set, for use in diagnostic messages.
	//
	// This field is meaningless for the root module, where its contents are undefined.
	SourceAddrRange hcl.Range

	// Version is the specific version that was selected for this module,
	// based on version constraints given in configuration.
	//
	// This field is nil if the module was loaded from a non-registry source,
	// since versions are not supported for other sources.
	//
	// This field is meaningless for the root module, where it will always
	// be nil.
	Version *version.Version
}

// ModuleRequirements represents the provider requirements for an individual
// module, along with references to any child modules. This is used to
// determine which modules require which providers.
type ModuleRequirements struct {
	Name         string
	SourceAddr   addrs.ModuleSource
	SourceDir    string
	Requirements getproviders.Requirements
	Children     map[string]*ModuleRequirements
}

// NewEmptyConfig constructs a single-node configuration tree with an empty
// root module. This is generally a pretty useless thing to do, so most callers
// should instead use BuildConfig.
func NewEmptyConfig() *Config {
	ret := &Config{}
	ret.Root = ret
	ret.Children = make(map[string]*Config)
	ret.Module = &Module{}
	return ret
}

// Depth returns the number of "hops" the receiver is from the root of its
// module tree, with the root module having a depth of zero.
func (c *Config) Depth() int {
	ret := 0
	this := c
	for this.Parent != nil {
		ret++
		this = this.Parent
	}
	return ret
}

// DeepEach calls the given function once for each module in the tree, starting
// with the receiver.
//
// A parent is always called before its children and children of a particular
// node are visited in lexicographic order by their names.
func (c *Config) DeepEach(cb func(c *Config)) {
	cb(c)

	names := make([]string, 0, len(c.Children))
	for name := range c.Children {
		names = append(names, name)
	}

	for _, name := range names {
		c.Children[name].DeepEach(cb)
	}
}

// AllModules returns a slice of all the receiver and all of its descendent
// nodes in the module tree, in the same order they would be visited by
// DeepEach.
func (c *Config) AllModules() []*Config {
	var ret []*Config
	c.DeepEach(func(c *Config) {
		ret = append(ret, c)
	})
	return ret
}

// Descendent returns the descendent config that has the given path beneath
// the receiver, or nil if there is no such module.
//
// The path traverses the static module tree, prior to any expansion to handle
// count and for_each arguments.
//
// An empty path will just return the receiver, and is therefore pointless.
func (c *Config) Descendent(path addrs.Module) *Config {
	current := c
	for _, name := range path {
		current = current.Children[name]
		if current == nil {
			return nil
		}
	}
	return current
}

// DescendentForInstance is like Descendent except that it accepts a path
// to a particular module instance in the dynamic module graph, returning
// the node from the static module graph that corresponds to it.
//
// All instances created by a particular module call share the same
// configuration, so the keys within the given path are disregarded.
func (c *Config) DescendentForInstance(path addrs.ModuleInstance) *Config {
	current := c
	for _, step := range path {
		current = current.Children[step.Name]
		if current == nil {
			return nil
		}
	}
	return current
}

// EntersNewPackage returns true if this call is to an external module, either
// directly via a remote source address or indirectly via a registry source
// address.
//
// Other behaviors in Terraform may treat package crossings as a special
// situation, because that indicates that the caller and callee can change
// independently of one another and thus we should disallow using any features
// where the caller assumes anything about the callee other than its input
// variables, required provider configurations, and output values.
//
// It's not meaningful to ask if the Config representing the root module enters
// a new package because the root module is always outside of all module
// packages, and so this function will arbitrarily return false in that case.
func (c *Config) EntersNewPackage() bool {
	return moduleSourceAddrEntersNewPackage(c.SourceAddr)
}

// VerifyDependencySelections checks whether the given locked dependencies
// are acceptable for all of the version constraints reported in the
// configuration tree represented by the reciever.
//
// This function will errors only if any of the locked dependencies are out of
// range for corresponding constraints in the configuration. If there are
// multiple inconsistencies then it will attempt to describe as many of them
// as possible, rather than stopping at the first problem.
//
// It's typically the responsibility of "terraform init" to change the locked
// dependencies to conform with the configuration, and so
// VerifyDependencySelections is intended for other commands to check whether
// it did so correctly and to catch if anything has changed in configuration
// since the last "terraform init" which requires re-initialization. However,
// it's up to the caller to decide how to advise users recover from these
// errors, because the advise can vary depending on what operation the user
// is attempting.
func (c *Config) VerifyDependencySelections(depLocks *depsfile.Locks) []error {
	var errs []error

	reqs, diags := c.ProviderRequirements()
	if diags.HasErrors() {
		// It should be very unusual to get here, but unfortunately we can
		// end up here in some edge cases where the config loader doesn't
		// process version constraint strings in exactly the same way as
		// the requirements resolver. (See the addProviderRequirements method
		// for more information.)
		errs = append(errs, fmt.Errorf("failed to determine the configuration's provider requirements: %s", diags.Error()))
	}

	for providerAddr, constraints := range reqs {
		if !depsfile.ProviderIsLockable(providerAddr) {
			continue // disregard builtin providers, and such
		}
		if depLocks != nil && depLocks.ProviderIsOverridden(providerAddr) {
			// The "overridden" case is for unusual special situations like
			// dev overrides, so we'll explicitly note it in the logs just in
			// case we see bug reports with these active and it helps us
			// understand why we ended up using the "wrong" plugin.
			log.Printf("[DEBUG] Config.VerifyDependencySelections: skipping %s because it's overridden by a special configuration setting", providerAddr)
			continue
		}

		var lock *depsfile.ProviderLock
		if depLocks != nil { // Should always be true in main code, but unfortunately sometimes not true in old tests that don't fill out arguments completely
			lock = depLocks.Provider(providerAddr)
		}
		if lock == nil {
			log.Printf("[TRACE] Config.VerifyDependencySelections: provider %s has no lock file entry to satisfy %q", providerAddr, getproviders.VersionConstraintsString(constraints))
			errs = append(errs, fmt.Errorf("provider %s: required by this configuration but no version is selected", providerAddr))
			continue
		}

		selectedVersion := lock.Version()
		allowedVersions := getproviders.MeetingConstraints(constraints)
		log.Printf("[TRACE] Config.VerifyDependencySelections: provider %s has %s to satisfy %q", providerAddr, selectedVersion.String(), getproviders.VersionConstraintsString(constraints))
		if !allowedVersions.Has(selectedVersion) {
			// The most likely cause of this is that the author of a module
			// has changed its constraints, but this could also happen in
			// some other unusual situations, such as the user directly
			// editing the lock file to record something invalid. We'll
			// distinguish those cases here in order to avoid the more
			// specific error message potentially being a red herring in
			// the edge-cases.
			currentConstraints := getproviders.VersionConstraintsString(constraints)
			lockedConstraints := getproviders.VersionConstraintsString(lock.VersionConstraints())
			switch {
			case currentConstraints != lockedConstraints:
				errs = append(errs, fmt.Errorf("provider %s: locked version selection %s doesn't match the updated version constraints %q", providerAddr, selectedVersion.String(), currentConstraints))
			default:
				errs = append(errs, fmt.Errorf("provider %s: version constraints %q don't match the locked version selection %s", providerAddr, currentConstraints, selectedVersion.String()))
			}
		}
	}

	// Return multiple errors in an arbitrary-but-deterministic order.
	sort.Slice(errs, func(i, j int) bool {
		return errs[i].Error() < errs[j].Error()
	})

	return errs
}

// ProviderRequirements searches the full tree of modules under the receiver
// for both explicit and implicit dependencies on providers.
//
// The result is a full manifest of all of the providers that must be available
// in order to work with the receiving configuration.
//
// If the returned diagnostics includes errors then the resulting Requirements
// may be incomplete.
func (c *Config) ProviderRequirements() (getproviders.Requirements, hcl.Diagnostics) {
	reqs := make(getproviders.Requirements)
	diags := c.addProviderRequirements(reqs, true)

	return reqs, diags
}

// ProviderRequirementsShallow searches only the direct receiver for explicit
// and implicit dependencies on providers. Descendant modules are ignored.
//
// If the returned diagnostics includes errors then the resulting Requirements
// may be incomplete.
func (c *Config) ProviderRequirementsShallow() (getproviders.Requirements, hcl.Diagnostics) {
	reqs := make(getproviders.Requirements)
	diags := c.addProviderRequirements(reqs, false)

	return reqs, diags
}

// ProviderRequirementsByModule searches the full tree of modules under the
// receiver for both explicit and implicit dependencies on providers,
// constructing a tree where the requirements are broken out by module.
//
// If the returned diagnostics includes errors then the resulting Requirements
// may be incomplete.
func (c *Config) ProviderRequirementsByModule() (*ModuleRequirements, hcl.Diagnostics) {
	reqs := make(getproviders.Requirements)
	diags := c.addProviderRequirements(reqs, false)

	children := make(map[string]*ModuleRequirements)
	for name, child := range c.Children {
		childReqs, childDiags := child.ProviderRequirementsByModule()
		childReqs.Name = name
		children[name] = childReqs
		diags = append(diags, childDiags...)
	}

	ret := &ModuleRequirements{
		SourceAddr:   c.SourceAddr,
		SourceDir:    c.Module.SourceDir,
		Requirements: reqs,
		Children:     children,
	}

	return ret, diags
}

// addProviderRequirements is the main part of the ProviderRequirements
// implementation, gradually mutating a shared requirements object to
// eventually return. If the recurse argument is true, the requirements will
// include all descendant modules; otherwise, only the specified module.
func (c *Config) addProviderRequirements(reqs getproviders.Requirements, recurse bool) hcl.Diagnostics {
	var diags hcl.Diagnostics

	// First we'll deal with the requirements directly in _our_ module...
	if c.Module.ProviderRequirements != nil {
		for _, providerReqs := range c.Module.ProviderRequirements.RequiredProviders {
			fqn := providerReqs.Type
			if _, ok := reqs[fqn]; !ok {
				// We'll at least have an unconstrained dependency then, but might
				// add to this in the loop below.
				reqs[fqn] = nil
			}
			// The model of version constraints in this package is still the
			// old one using a different upstream module to represent versions,
			// so we'll need to shim that out here for now. The two parsers
			// don't exactly agree in practice 🙄 so this might produce new errors.
			// TODO: Use the new parser throughout this package so we can get the
			// better error messages it produces in more situations.
			constraints, err := getproviders.ParseVersionConstraints(providerReqs.Requirement.Required.String())
			if err != nil {
				diags = diags.Append(&hcl.Diagnostic{
					Severity: hcl.DiagError,
					Summary:  "Invalid version constraint",
					// The errors returned by ParseVersionConstraint already include
					// the section of input that was incorrect, so we don't need to
					// include that here.
					Detail:  fmt.Sprintf("Incorrect version constraint syntax: %s.", err.Error()),
					Subject: providerReqs.Requirement.DeclRange.Ptr(),
				})
			}
			reqs[fqn] = append(reqs[fqn], constraints...)
		}
	}

	// Each resource in the configuration creates an *implicit* provider
	// dependency, though we'll only record it if there isn't already
	// an explicit dependency on the same provider.
	for _, rc := range c.Module.ManagedResources {
		fqn := rc.Provider
		if _, exists := reqs[fqn]; exists {
			// Explicit dependency already present
			continue
		}
		reqs[fqn] = nil
	}
	for _, rc := range c.Module.DataResources {
		fqn := rc.Provider
		if _, exists := reqs[fqn]; exists {
			// Explicit dependency already present
			continue
		}
		reqs[fqn] = nil
	}

	// "provider" block can also contain version constraints
	for _, provider := range c.Module.ProviderConfigs {
		fqn := c.Module.ProviderForLocalConfig(addrs.LocalProviderConfig{LocalName: provider.Name})
		if _, ok := reqs[fqn]; !ok {
			// We'll at least have an unconstrained dependency then, but might
			// add to this in the loop below.
			reqs[fqn] = nil
		}
		if provider.Version.Required != nil {
			// The model of version constraints in this package is still the
			// old one using a different upstream module to represent versions,
			// so we'll need to shim that out here for now. The two parsers
			// don't exactly agree in practice 🙄 so this might produce new errors.
			// TODO: Use the new parser throughout this package so we can get the
			// better error messages it produces in more situations.
			constraints, err := getproviders.ParseVersionConstraints(provider.Version.Required.String())
			if err != nil {
				diags = diags.Append(&hcl.Diagnostic{
					Severity: hcl.DiagError,
					Summary:  "Invalid version constraint",
					// The errors returned by ParseVersionConstraint already include
					// the section of input that was incorrect, so we don't need to
					// include that here.
					Detail:  fmt.Sprintf("Incorrect version constraint syntax: %s.", err.Error()),
					Subject: provider.Version.DeclRange.Ptr(),
				})
			}
			reqs[fqn] = append(reqs[fqn], constraints...)
		}
	}

	if recurse {
		for _, childConfig := range c.Children {
			moreDiags := childConfig.addProviderRequirements(reqs, true)
			diags = append(diags, moreDiags...)
		}
	}

	return diags
}

// resolveProviderTypes walks through the providers in the module and ensures
// the true types are assigned based on the provider requirements for the
// module.
func (c *Config) resolveProviderTypes() {
	for _, child := range c.Children {
		child.resolveProviderTypes()
	}

	// collect the required_providers, and then add any missing default providers
	providers := map[string]addrs.Provider{}
	for name, p := range c.Module.ProviderRequirements.RequiredProviders {
		providers[name] = p.Type
	}

	// ensure all provider configs know their correct type
	for _, p := range c.Module.ProviderConfigs {
		addr, required := providers[p.Name]
		if required {
			p.providerType = addr
		} else {
			addr := addrs.NewDefaultProvider(p.Name)
			p.providerType = addr
			providers[p.Name] = addr
		}
	}

	// connect module call providers to the correct type
	for _, mod := range c.Module.ModuleCalls {
		for _, p := range mod.Providers {
			if addr, known := providers[p.InParent.Name]; known {
				p.InParent.providerType = addr
			}
		}
	}

	// fill in parent module calls too
	if c.Parent != nil {
		for _, mod := range c.Parent.Module.ModuleCalls {
			for _, p := range mod.Providers {
				if addr, known := providers[p.InChild.Name]; known {
					p.InChild.providerType = addr
				}
			}
		}
	}
}

// ProviderTypes returns the FQNs of each distinct provider type referenced
// in the receiving configuration.
//
// This is a helper for easily determining which provider types are required
// to fully interpret the configuration, though it does not include version
// information and so callers are expected to have already dealt with
// provider version selection in an earlier step and have identified suitable
// versions for each provider.
func (c *Config) ProviderTypes() []addrs.Provider {
	// Ignore diagnostics here because they relate to version constraints
	reqs, _ := c.ProviderRequirements()

	ret := make([]addrs.Provider, 0, len(reqs))
	for k := range reqs {
		ret = append(ret, k)
	}
	sort.Slice(ret, func(i, j int) bool {
		return ret[i].String() < ret[j].String()
	})
	return ret
}

// ResolveAbsProviderAddr returns the AbsProviderConfig represented by the given
// ProviderConfig address, which must not be nil or this method will panic.
//
// If the given address is already an AbsProviderConfig then this method returns
// it verbatim, and will always succeed. If it's a LocalProviderConfig then
// it will consult the local-to-FQN mapping table for the given module
// to find the absolute address corresponding to the given local one.
//
// The module address to resolve local addresses in must be given in the second
// argument, and must refer to a module that exists under the receiver or
// else this method will panic.
func (c *Config) ResolveAbsProviderAddr(addr addrs.ProviderConfig, inModule addrs.Module) addrs.AbsProviderConfig {
	switch addr := addr.(type) {

	case addrs.AbsProviderConfig:
		return addr

	case addrs.LocalProviderConfig:
		// Find the descendent Config that contains the module that this
		// local config belongs to.
		mc := c.Descendent(inModule)
		if mc == nil {
			panic(fmt.Sprintf("ResolveAbsProviderAddr with non-existent module %s", inModule.String()))
		}

		var provider addrs.Provider
		if providerReq, exists := c.Module.ProviderRequirements.RequiredProviders[addr.LocalName]; exists {
			provider = providerReq.Type
		} else {
			provider = addrs.ImpliedProviderForUnqualifiedType(addr.LocalName)
		}

		return addrs.AbsProviderConfig{
			Module:   inModule,
			Provider: provider,
			Alias:    addr.Alias,
		}

	default:
		panic(fmt.Sprintf("cannot ResolveAbsProviderAddr(%v, ...)", addr))
	}

}

// ProviderForConfigAddr returns the FQN for a given addrs.ProviderConfig, first
// by checking for the provider in module.ProviderRequirements and falling
// back to addrs.NewDefaultProvider if it is not found.
func (c *Config) ProviderForConfigAddr(addr addrs.LocalProviderConfig) addrs.Provider {
	if provider, exists := c.Module.ProviderRequirements.RequiredProviders[addr.LocalName]; exists {
		return provider.Type
	}
	return c.ResolveAbsProviderAddr(addr, addrs.RootModule).Provider
}
