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

package local

import (
	"context"
	"fmt"
	"log"
	"sort"
	"strings"

	"github.com/hashicorp/terraform/internal/backend"
	"github.com/hashicorp/terraform/internal/configs"
	"github.com/hashicorp/terraform/internal/configs/configload"
	"github.com/hashicorp/terraform/internal/plans/planfile"
	"github.com/hashicorp/terraform/internal/states/statemgr"
	"github.com/hashicorp/terraform/internal/terraform"
	"github.com/hashicorp/terraform/internal/tfdiags"
	"github.com/zclconf/go-cty/cty"
)

// backend.Local implementation.
func (b *Local) LocalRun(op *backend.Operation) (*backend.LocalRun, statemgr.Full, tfdiags.Diagnostics) {
	// Make sure the type is invalid. We use this as a way to know not
	// to ask for input/validate. We're modifying this through a pointer,
	// so we're mutating an object that belongs to the caller here, which
	// seems bad but we're preserving it for now until we have time to
	// properly design this API, vs. just preserving whatever it currently
	// happens to do.
	op.Type = backend.OperationTypeInvalid

	op.StateLocker = op.StateLocker.WithContext(context.Background())

	lr, _, stateMgr, diags := b.localRun(op)
	return lr, stateMgr, diags
}

func (b *Local) localRun(op *backend.Operation) (*backend.LocalRun, *configload.Snapshot, statemgr.Full, tfdiags.Diagnostics) {
	var diags tfdiags.Diagnostics

	// Get the latest state.
	log.Printf("[TRACE] backend/local: requesting state manager for workspace %q", op.Workspace)
	s, err := b.StateMgr(op.Workspace)
	if err != nil {
		diags = diags.Append(fmt.Errorf("error loading state: %w", err))
		return nil, nil, nil, diags
	}
	log.Printf("[TRACE] backend/local: requesting state lock for workspace %q", op.Workspace)
	if diags := op.StateLocker.Lock(s, op.Type.String()); diags.HasErrors() {
		return nil, nil, nil, diags
	}

	defer func() {
		// If we're returning with errors, and thus not producing a valid
		// context, we'll want to avoid leaving the workspace locked.
		if diags.HasErrors() {
			diags = diags.Append(op.StateLocker.Unlock())
		}
	}()

	log.Printf("[TRACE] backend/local: reading remote state for workspace %q", op.Workspace)
	if err := s.RefreshState(); err != nil {
		diags = diags.Append(fmt.Errorf("error loading state: %w", err))
		return nil, nil, nil, diags
	}

	ret := &backend.LocalRun{}

	// Initialize our context options
	var coreOpts terraform.ContextOpts
	if v := b.ContextOpts; v != nil {
		coreOpts = *v
	}
	coreOpts.UIInput = op.UIIn
	coreOpts.Hooks = op.Hooks

	var ctxDiags tfdiags.Diagnostics
	var configSnap *configload.Snapshot
	if op.PlanFile != nil {
		var stateMeta *statemgr.SnapshotMeta
		// If the statemgr implements our optional PersistentMeta interface then we'll
		// additionally verify that the state snapshot in the plan file has
		// consistent metadata, as an additional safety check.
		if sm, ok := s.(statemgr.PersistentMeta); ok {
			m := sm.StateSnapshotMeta()
			stateMeta = &m
		}
		log.Printf("[TRACE] backend/local: populating backend.LocalRun from plan file")
		ret, configSnap, ctxDiags = b.localRunForPlanFile(op, op.PlanFile, ret, &coreOpts, stateMeta)
		if ctxDiags.HasErrors() {
			diags = diags.Append(ctxDiags)
			return nil, nil, nil, diags
		}

		// Write sources into the cache of the main loader so that they are
		// available if we need to generate diagnostic message snippets.
		op.ConfigLoader.ImportSourcesFromSnapshot(configSnap)
	} else {
		log.Printf("[TRACE] backend/local: populating backend.LocalRun for current working directory")
		ret, configSnap, ctxDiags = b.localRunDirect(op, ret, &coreOpts, s)
	}
	diags = diags.Append(ctxDiags)
	if diags.HasErrors() {
		return nil, nil, nil, diags
	}

	// If we have an operation, then we automatically do the input/validate
	// here since every option requires this.
	if op.Type != backend.OperationTypeInvalid {
		// If input asking is enabled, then do that
		if op.PlanFile == nil && b.OpInput {
			mode := terraform.InputModeProvider

			log.Printf("[TRACE] backend/local: requesting interactive input, if necessary")
			inputDiags := ret.Core.Input(ret.Config, mode)
			diags = diags.Append(inputDiags)
			if inputDiags.HasErrors() {
				return nil, nil, nil, diags
			}
		}

		// If validation is enabled, validate
		if b.OpValidation {
			log.Printf("[TRACE] backend/local: running validation operation")
			validateDiags := ret.Core.Validate(ret.Config)
			diags = diags.Append(validateDiags)
		}
	}

	return ret, configSnap, s, diags
}

func (b *Local) localRunDirect(op *backend.Operation, run *backend.LocalRun, coreOpts *terraform.ContextOpts, s statemgr.Full) (*backend.LocalRun, *configload.Snapshot, tfdiags.Diagnostics) {
	var diags tfdiags.Diagnostics

	// Load the configuration using the caller-provided configuration loader.
	config, configSnap, configDiags := op.ConfigLoader.LoadConfigWithSnapshot(op.ConfigDir)
	diags = diags.Append(configDiags)
	if configDiags.HasErrors() {
		return nil, nil, diags
	}
	run.Config = config

	if errs := config.VerifyDependencySelections(op.DependencyLocks); len(errs) > 0 {
		var buf strings.Builder
		for _, err := range errs {
			fmt.Fprintf(&buf, "\n  - %s", err.Error())
		}
		var suggestion string
		switch {
		case op.DependencyLocks == nil:
			// If we get here then it suggests that there's a caller that we
			// didn't yet update to populate DependencyLocks, which is a bug.
			suggestion = "This run has no dependency lock information provided at all, which is a bug in Terraform; please report it!"
		case op.DependencyLocks.Empty():
			suggestion = "To make the initial dependency selections that will initialize the dependency lock file, run:\n  terraform init"
		default:
			suggestion = "To update the locked dependency selections to match a changed configuration, run:\n  terraform init -upgrade"
		}
		diags = diags.Append(tfdiags.Sourceless(
			tfdiags.Error,
			"Inconsistent dependency lock file",
			fmt.Sprintf(
				"The following dependency selections recorded in the lock file are inconsistent with the current configuration:%s\n\n%s",
				buf.String(), suggestion,
			),
		))
	}

	var rawVariables map[string]backend.UnparsedVariableValue
	if op.AllowUnsetVariables {
		// Rather than prompting for input, we'll just stub out the required
		// but unset variables with unknown values to represent that they are
		// placeholders for values the user would need to provide for other
		// operations.
		rawVariables = b.stubUnsetRequiredVariables(op.Variables, config.Module.Variables)
	} else {
		// If interactive input is enabled, we might gather some more variable
		// values through interactive prompts.
		// TODO: Need to route the operation context through into here, so that
		// the interactive prompts can be sensitive to its timeouts/etc.
		rawVariables = b.interactiveCollectVariables(context.TODO(), op.Variables, config.Module.Variables, op.UIIn)
	}

	variables, varDiags := backend.ParseVariableValues(rawVariables, config.Module.Variables)
	diags = diags.Append(varDiags)
	if diags.HasErrors() {
		return nil, nil, diags
	}

	planOpts := &terraform.PlanOpts{
		Mode:               op.PlanMode,
		Targets:            op.Targets,
		ForceReplace:       op.ForceReplace,
		SetVariables:       variables,
		SkipRefresh:        op.Type != backend.OperationTypeRefresh && !op.PlanRefresh,
		GenerateConfigPath: op.GenerateConfigOut,
	}
	run.PlanOpts = planOpts

	// For a "direct" local run, the input state is the most recently stored
	// snapshot, from the previous run.
	run.InputState = s.State()

	tfCtx, moreDiags := terraform.NewContext(coreOpts)
	diags = diags.Append(moreDiags)
	if moreDiags.HasErrors() {
		return nil, nil, diags
	}
	run.Core = tfCtx
	return run, configSnap, diags
}

func (b *Local) localRunForPlanFile(op *backend.Operation, pf *planfile.Reader, run *backend.LocalRun, coreOpts *terraform.ContextOpts, currentStateMeta *statemgr.SnapshotMeta) (*backend.LocalRun, *configload.Snapshot, tfdiags.Diagnostics) {
	var diags tfdiags.Diagnostics

	const errSummary = "Invalid plan file"

	// A plan file has a snapshot of configuration embedded inside it, which
	// is used instead of whatever configuration might be already present
	// in the filesystem.
	snap, err := pf.ReadConfigSnapshot()
	if err != nil {
		diags = diags.Append(tfdiags.Sourceless(
			tfdiags.Error,
			errSummary,
			fmt.Sprintf("Failed to read configuration snapshot from plan file: %s.", err),
		))
		return nil, snap, diags
	}
	loader := configload.NewLoaderFromSnapshot(snap)
	config, configDiags := loader.LoadConfig(snap.Modules[""].Dir)
	diags = diags.Append(configDiags)
	if configDiags.HasErrors() {
		return nil, snap, diags
	}
	run.Config = config

	// NOTE: We're intentionally comparing the current locks with the
	// configuration snapshot, rather than the lock snapshot in the plan file,
	// because it's the current locks which dictate our plugin selections
	// in coreOpts below. However, we'll also separately check that the
	// plan file has identical locked plugins below, and thus we're effectively
	// checking consistency with both here.
	if errs := config.VerifyDependencySelections(op.DependencyLocks); len(errs) > 0 {
		var buf strings.Builder
		for _, err := range errs {
			fmt.Fprintf(&buf, "\n  - %s", err.Error())
		}
		diags = diags.Append(tfdiags.Sourceless(
			tfdiags.Error,
			"Inconsistent dependency lock file",
			fmt.Sprintf(
				"The following dependency selections recorded in the lock file are inconsistent with the configuration in the saved plan:%s\n\nA saved plan can be applied only to the same configuration it was created from. Create a new plan from the updated configuration.",
				buf.String(),
			),
		))
	}

	// This check is an important complement to the check above: the locked
	// dependencies in the configuration must match the configuration, and
	// the locked dependencies in the plan must match the locked dependencies
	// in the configuration, and so transitively we ensure that the locked
	// dependencies in the plan match the configuration too. However, this
	// additionally catches any inconsistency between the two sets of locks
	// even if they both happen to be valid per the current configuration,
	// which is one of several ways we try to catch the mistake of applying
	// a saved plan file in a different place than where we created it.
	depLocksFromPlan, moreDiags := pf.ReadDependencyLocks()
	diags = diags.Append(moreDiags)
	if depLocksFromPlan != nil && !op.DependencyLocks.Equal(depLocksFromPlan) {
		diags = diags.Append(tfdiags.Sourceless(
			tfdiags.Error,
			"Inconsistent dependency lock file",
			"The given plan file was created with a different set of external dependency selections than the current configuration. A saved plan can be applied only to the same configuration it was created from.\n\nCreate a new plan from the updated configuration.",
		))
	}

	// A plan file also contains a snapshot of the prior state the changes
	// are intended to apply to.
	priorStateFile, err := pf.ReadStateFile()
	if err != nil {
		diags = diags.Append(tfdiags.Sourceless(
			tfdiags.Error,
			errSummary,
			fmt.Sprintf("Failed to read prior state snapshot from plan file: %s.", err),
		))
		return nil, snap, diags
	}

	if currentStateMeta != nil {
		// If the caller sets this, we require that the stored prior state
		// has the same metadata, which is an extra safety check that nothing
		// has changed since the plan was created. (All of the "real-world"
		// state manager implementations support this, but simpler test backends
		// may not.)

		// Because the plan always contains a state, even if it is empty, the
		// first plan to be applied will have empty snapshot metadata. In this
		// case we compare only the serial in order to provide a more correct
		// error.
		firstPlan := priorStateFile.Lineage == "" && priorStateFile.Serial == 0

		switch {
		case !firstPlan && priorStateFile.Lineage != currentStateMeta.Lineage:
			diags = diags.Append(tfdiags.Sourceless(
				tfdiags.Error,
				"Saved plan does not match the given state",
				"The given plan file can not be applied because it was created from a different state lineage.",
			))

		case priorStateFile.Serial != currentStateMeta.Serial:
			diags = diags.Append(tfdiags.Sourceless(
				tfdiags.Error,
				"Saved plan is stale",
				"The given plan file can no longer be applied because the state was changed by another operation after the plan was created.",
			))
		}
	}
	// When we're applying a saved plan, the input state is the "prior state"
	// recorded in the plan, which incorporates the result of all of the
	// refreshing we did while building the plan.
	run.InputState = priorStateFile.State

	plan, err := pf.ReadPlan()
	if err != nil {
		diags = diags.Append(tfdiags.Sourceless(
			tfdiags.Error,
			errSummary,
			fmt.Sprintf("Failed to read plan from plan file: %s.", err),
		))
		return nil, snap, diags
	}
	// When we're applying a saved plan, we populate Plan instead of PlanOpts,
	// because a plan object incorporates the subset of data from PlanOps that
	// we need to apply the plan.
	run.Plan = plan

	tfCtx, moreDiags := terraform.NewContext(coreOpts)
	diags = diags.Append(moreDiags)
	if moreDiags.HasErrors() {
		return nil, nil, diags
	}
	run.Core = tfCtx
	return run, snap, diags
}

// interactiveCollectVariables attempts to complete the given existing
// map of variables by interactively prompting for any variables that are
// declared as required but not yet present.
//
// If interactive input is disabled for this backend instance then this is
// a no-op. If input is enabled but fails for some reason, the resulting
// map will be incomplete. For these reasons, the caller must still validate
// that the result is complete and valid.
//
// This function does not modify the map given in "existing", but may return
// it unchanged if no modifications are required. If modifications are required,
// the result is a new map with all of the elements from "existing" plus
// additional elements as appropriate.
//
// Interactive prompting is a "best effort" thing for first-time user UX and
// not something we expect folks to be relying on for routine use. Terraform
// is primarily a non-interactive tool and so we prefer to report in error
// messages that variables are not set rather than reporting that input failed:
// the primary resolution to missing variables is to provide them by some other
// means.
func (b *Local) interactiveCollectVariables(ctx context.Context, existing map[string]backend.UnparsedVariableValue, vcs map[string]*configs.Variable, uiInput terraform.UIInput) map[string]backend.UnparsedVariableValue {
	var needed []string
	if b.OpInput && uiInput != nil {
		for name, vc := range vcs {
			if !vc.Required() {
				continue // We only prompt for required variables
			}
			if _, exists := existing[name]; !exists {
				needed = append(needed, name)
			}
		}
	} else {
		log.Print("[DEBUG] backend/local: Skipping interactive prompts for variables because input is disabled")
	}
	if len(needed) == 0 {
		return existing
	}

	log.Printf("[DEBUG] backend/local: will prompt for input of unset required variables %s", needed)

	// If we get here then we're planning to prompt for at least one additional
	// variable's value.
	sort.Strings(needed) // prompt in lexical order
	ret := make(map[string]backend.UnparsedVariableValue, len(vcs))
	for k, v := range existing {
		ret[k] = v
	}
	for _, name := range needed {
		vc := vcs[name]
		rawValue, err := uiInput.Input(ctx, &terraform.InputOpts{
			Id:          fmt.Sprintf("var.%s", name),
			Query:       fmt.Sprintf("var.%s", name),
			Description: vc.Description,
			Secret:      vc.Sensitive,
		})
		if err != nil {
			// Since interactive prompts are best-effort, we'll just continue
			// here and let subsequent validation report this as a variable
			// not specified.
			log.Printf("[WARN] backend/local: Failed to request user input for variable %q: %s", name, err)
			continue
		}
		ret[name] = unparsedInteractiveVariableValue{Name: name, RawValue: rawValue}
	}
	return ret
}

// stubUnsetVariables ensures that all required variables defined in the
// configuration exist in the resulting map, by adding new elements as necessary.
//
// The stubbed value of any additions will be an unknown variable conforming
// to the variable's configured type constraint, meaning that no particular
// value is known and that one must be provided by the user in order to get
// a complete result.
//
// Unset optional attributes (those with default values) will not be populated
// by this function, under the assumption that a later step will handle those.
// In this sense, stubUnsetRequiredVariables is essentially a non-interactive,
// non-error-producing variant of interactiveCollectVariables that creates
// placeholders for values the user would be prompted for interactively on
// other operations.
//
// This function should be used only in situations where variables values
// will not be directly used and the variables map is being constructed only
// to produce a complete Terraform context for some ancillary functionality
// like "terraform console", "terraform state ...", etc.
//
// This function is guaranteed not to modify the given map, but it may return
// the given map unchanged if no additions are required. If additions are
// required then the result will be a new map containing everything in the
// given map plus additional elements.
func (b *Local) stubUnsetRequiredVariables(existing map[string]backend.UnparsedVariableValue, vcs map[string]*configs.Variable) map[string]backend.UnparsedVariableValue {
	var missing bool // Do we need to add anything?
	for name, vc := range vcs {
		if !vc.Required() {
			continue // We only stub required variables
		}
		if _, exists := existing[name]; !exists {
			missing = true
		}
	}
	if !missing {
		return existing
	}

	// If we get down here then there's at least one variable value to add.
	ret := make(map[string]backend.UnparsedVariableValue, len(vcs))
	for k, v := range existing {
		ret[k] = v
	}
	for name, vc := range vcs {
		if !vc.Required() {
			continue
		}
		if _, exists := existing[name]; !exists {
			ret[name] = unparsedUnknownVariableValue{Name: name, WantType: vc.Type}
		}
	}
	return ret
}

type unparsedInteractiveVariableValue struct {
	Name, RawValue string
}

var _ backend.UnparsedVariableValue = unparsedInteractiveVariableValue{}

func (v unparsedInteractiveVariableValue) ParseVariableValue(mode configs.VariableParsingMode) (*terraform.InputValue, tfdiags.Diagnostics) {
	var diags tfdiags.Diagnostics
	val, valDiags := mode.Parse(v.Name, v.RawValue)
	diags = diags.Append(valDiags)
	if diags.HasErrors() {
		return nil, diags
	}
	return &terraform.InputValue{
		Value:      val,
		SourceType: terraform.ValueFromInput,
	}, diags
}

type unparsedUnknownVariableValue struct {
	Name     string
	WantType cty.Type
}

var _ backend.UnparsedVariableValue = unparsedUnknownVariableValue{}

func (v unparsedUnknownVariableValue) ParseVariableValue(mode configs.VariableParsingMode) (*terraform.InputValue, tfdiags.Diagnostics) {
	return &terraform.InputValue{
		Value:      cty.UnknownVal(v.WantType),
		SourceType: terraform.ValueFromInput,
	}, nil
}
