package command

import (
	"fmt"
	"sort"
	"time"

	"github.com/hashicorp/terraform/internal/addrs"
	"github.com/hashicorp/terraform/internal/states"
	"github.com/hashicorp/terraform/internal/states/statemgr"
	"github.com/hashicorp/terraform/internal/tfdiags"

	backendLocal "github.com/hashicorp/terraform/internal/backend/local"
)

// StateMeta is the meta struct that should be embedded in state subcommands.
type StateMeta struct {
	Meta
}

// State returns the state for this meta. This gets the appropriate state from
// the backend, but changes the way that backups are done. This configures
// backups to be timestamped rather than just the original state path plus a
// backup path.
func (c *StateMeta) State() (statemgr.Full, error) {
	var realState statemgr.Full
	backupPath := c.backupPath
	stateOutPath := c.statePath

	// use the specified state
	if c.statePath != "" {
		realState = statemgr.NewFilesystem(c.statePath)
	} else {
		// Load the backend
		b, backendDiags := c.Backend(nil)
		if backendDiags.HasErrors() {
			return nil, backendDiags.Err()
		}

		workspace, err := c.Workspace()
		if err != nil {
			return nil, err
		}

		// Check remote Terraform version is compatible
		remoteVersionDiags := c.remoteVersionCheck(b, workspace)
		c.showDiagnostics(remoteVersionDiags)
		if remoteVersionDiags.HasErrors() {
			return nil, fmt.Errorf("Error checking remote Terraform version")
		}

		// Get the state
		s, err := b.StateMgr(workspace)
		if err != nil {
			return nil, err
		}

		// Get a local backend
		localRaw, backendDiags := c.Backend(&BackendOpts{ForceLocal: true})
		if backendDiags.HasErrors() {
			// This should never fail
			panic(backendDiags.Err())
		}
		localB := localRaw.(*backendLocal.Local)
		_, stateOutPath, _ = localB.StatePaths(workspace)
		if err != nil {
			return nil, err
		}

		realState = s
	}

	// We always backup state commands, so set the back if none was specified
	// (the default is "-", but some tests bypass the flag parsing).
	if backupPath == "-" || backupPath == "" {
		// Determine the backup path. stateOutPath is set to the resulting
		// file where state is written (cached in the case of remote state)
		backupPath = fmt.Sprintf(
			"%s.%d%s",
			stateOutPath,
			time.Now().UTC().Unix(),
			DefaultBackupExtension)
	}

	// If the backend is local (which it should always be, given our asserting
	// of it above) we can now enable backups for it.
	if lb, ok := realState.(*statemgr.Filesystem); ok {
		lb.SetBackupPath(backupPath)
	}

	return realState, nil
}

func (c *StateMeta) lookupResourceInstanceAddr(state *states.State, allowMissing bool, addrStr string) ([]addrs.AbsResourceInstance, tfdiags.Diagnostics) {
	target, diags := addrs.ParseTargetStr(addrStr)
	if diags.HasErrors() {
		return nil, diags
	}

	targetAddr := target.Subject
	var ret []addrs.AbsResourceInstance
	switch addr := targetAddr.(type) {
	case addrs.ModuleInstance:
		// Matches all instances within the indicated module and all of its
		// descendent modules.

		// found is used to identify cases where the selected module has no
		// resources, but one or more of its submodules does.
		found := false
		ms := state.Module(addr)
		if ms != nil {
			found = true
			ret = append(ret, c.collectModuleResourceInstances(ms)...)
		}
		for _, cms := range state.Modules {
			if !addr.Equal(cms.Addr) {
				if addr.IsAncestor(cms.Addr) || addr.TargetContains(cms.Addr) {
					found = true
					ret = append(ret, c.collectModuleResourceInstances(cms)...)
				}
			}
		}

		if !found && !allowMissing {
			diags = diags.Append(tfdiags.Sourceless(
				tfdiags.Error,
				"Unknown module",
				fmt.Sprintf(`The current state contains no module at %s. If you've just added this module to the configuration, you must run "terraform apply" first to create the module's entry in the state.`, addr),
			))
		}

	case addrs.AbsResource:
		// Matches all instances of the specific selected resource.
		rs := state.Resource(addr)
		if rs == nil {
			if !allowMissing {
				diags = diags.Append(tfdiags.Sourceless(
					tfdiags.Error,
					"Unknown resource",
					fmt.Sprintf(`The current state contains no resource %s. If you've just added this resource to the configuration, you must run "terraform apply" first to create the resource's entry in the state.`, addr),
				))
			}
			break
		}
		ret = append(ret, c.collectResourceInstances(addr.Module, rs)...)
	case addrs.AbsResourceInstance:
		is := state.ResourceInstance(addr)
		if is == nil {
			if !allowMissing {
				diags = diags.Append(tfdiags.Sourceless(
					tfdiags.Error,
					"Unknown resource instance",
					fmt.Sprintf(`The current state contains no resource instance %s. If you've just added its resource to the configuration or have changed the count or for_each arguments, you must run "terraform apply" first to update the resource's entry in the state.`, addr),
				))
			}
			break
		}
		ret = append(ret, addr)
	}
	sort.Slice(ret, func(i, j int) bool {
		return ret[i].Less(ret[j])
	})

	return ret, diags
}

func (c *StateMeta) lookupSingleStateObjectAddr(state *states.State, addrStr string) (addrs.Targetable, tfdiags.Diagnostics) {
	target, diags := addrs.ParseTargetStr(addrStr)
	if diags.HasErrors() {
		return nil, diags
	}
	return target.Subject, diags
}

func (c *StateMeta) lookupResourceInstanceAddrs(state *states.State, addrStrs ...string) ([]addrs.AbsResourceInstance, tfdiags.Diagnostics) {
	var ret []addrs.AbsResourceInstance
	var diags tfdiags.Diagnostics
	for _, addrStr := range addrStrs {
		moreAddrs, moreDiags := c.lookupResourceInstanceAddr(state, false, addrStr)
		ret = append(ret, moreAddrs...)
		diags = diags.Append(moreDiags)
	}
	return ret, diags
}

func (c *StateMeta) lookupAllResourceInstanceAddrs(state *states.State) ([]addrs.AbsResourceInstance, tfdiags.Diagnostics) {
	var ret []addrs.AbsResourceInstance
	var diags tfdiags.Diagnostics
	for _, ms := range state.Modules {
		ret = append(ret, c.collectModuleResourceInstances(ms)...)
	}
	sort.Slice(ret, func(i, j int) bool {
		return ret[i].Less(ret[j])
	})
	return ret, diags
}

func (c *StateMeta) collectModuleResourceInstances(ms *states.Module) []addrs.AbsResourceInstance {
	var ret []addrs.AbsResourceInstance
	for _, rs := range ms.Resources {
		ret = append(ret, c.collectResourceInstances(ms.Addr, rs)...)
	}
	return ret
}

func (c *StateMeta) collectResourceInstances(moduleAddr addrs.ModuleInstance, rs *states.Resource) []addrs.AbsResourceInstance {
	var ret []addrs.AbsResourceInstance
	for key := range rs.Instances {
		ret = append(ret, rs.Addr.Instance(key))
	}
	return ret
}

func (c *StateMeta) lookupAllResources(state *states.State) ([]*states.Resource, tfdiags.Diagnostics) {
	var ret []*states.Resource
	var diags tfdiags.Diagnostics
	for _, ms := range state.Modules {
		for _, resource := range ms.Resources {
			ret = append(ret, resource)
		}
	}
	return ret, diags
}
