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

package plans

import (
	"sort"
	"time"

	"github.com/hashicorp/terraform/internal/addrs"
	"github.com/hashicorp/terraform/internal/configs/configschema"
	"github.com/hashicorp/terraform/internal/lang/globalref"
	"github.com/hashicorp/terraform/internal/states"
	"github.com/zclconf/go-cty/cty"
)

// Plan is the top-level type representing a planned set of changes.
//
// A plan is a summary of the set of changes required to move from a current
// state to a goal state derived from configuration. The described changes
// are not applied directly, but contain an approximation of the final
// result that will be completed during apply by resolving any values that
// cannot be predicted.
//
// A plan must always be accompanied by the configuration it was built from,
// since the plan does not itself include all of the information required to
// make the changes indicated.
type Plan struct {
	// Mode is the mode under which this plan was created.
	//
	// This is only recorded to allow for UI differences when presenting plans
	// to the end-user, and so it must not be used to influence apply-time
	// behavior. The actions during apply must be described entirely by
	// the Changes field, regardless of how the plan was created.
	//
	// FIXME: destroy operations still rely on DestroyMode being set, because
	// there is no other source of this information in the plan. New behavior
	// should not be added based on this flag, and changing the flag should be
	// checked carefully against existing destroy behaviors.
	UIMode Mode

	VariableValues    map[string]DynamicValue
	Changes           *Changes
	DriftedResources  []*ResourceInstanceChangeSrc
	TargetAddrs       []addrs.Targetable
	ForceReplaceAddrs []addrs.AbsResourceInstance
	Backend           Backend

	// Errored is true if the Changes information is incomplete because
	// the planning operation failed. An errored plan cannot be applied,
	// but can be cautiously inspected for debugging purposes.
	Errored bool

	// Checks captures a snapshot of the (probably-incomplete) check results
	// at the end of the planning process.
	//
	// If this plan is applyable (that is, if the planning process completed
	// without errors) then the set of checks here should be complete even
	// though some of them will likely have StatusUnknown where the check
	// condition depends on values we won't know until the apply step.
	Checks *states.CheckResults

	// RelevantAttributes is a set of resource instance addresses and
	// attributes that are either directly affected by proposed changes or may
	// have indirectly contributed to them via references in expressions.
	//
	// This is the result of a heuristic and is intended only as a hint to
	// the UI layer in case it wants to emphasize or de-emphasize certain
	// resources. Don't use this to drive any non-cosmetic behavior, especially
	// including anything that would be subject to compatibility constraints.
	RelevantAttributes []globalref.ResourceAttr

	// PrevRunState and PriorState both describe the situation that the plan
	// was derived from:
	//
	// PrevRunState is a representation of the outcome of the previous
	// Terraform operation, without any updates from the remote system but
	// potentially including some changes that resulted from state upgrade
	// actions.
	//
	// PriorState is a representation of the current state of remote objects,
	// which will differ from PrevRunState if the "refresh" step returned
	// different data, which might reflect drift.
	//
	// PriorState is the main snapshot we use for actions during apply.
	// PrevRunState is only here so that we can diff PriorState against it in
	// order to report to the user any out-of-band changes we've detected.
	PrevRunState *states.State
	PriorState   *states.State

	// Timestamp is the record of truth for when the plan happened.
	Timestamp time.Time
}

// CanApply returns true if and only if the recieving plan includes content
// that would make sense to apply. If it returns false, the plan operation
// should indicate that there's nothing to do and Terraform should exit
// without prompting the user to confirm the changes.
//
// This function represents our main business logic for making the decision
// about whether a given plan represents meaningful "changes", and so its
// exact definition may change over time; the intent is just to centralize the
// rules for that rather than duplicating different versions of it at various
// locations in the UI code.
func (p *Plan) CanApply() bool {
	switch {
	case p.Errored:
		// An errored plan can never be applied, because it is incomplete.
		// Such a plan is only useful for describing the subset of actions
		// planned so far in case they are useful for understanding the
		// causes of the errors.
		return false

	case !p.Changes.Empty():
		// "Empty" means that everything in the changes is a "NoOp", so if
		// not empty then there's at least one non-NoOp change.
		return true

	case !p.PriorState.ManagedResourcesEqual(p.PrevRunState):
		// If there are no changes planned but we detected some
		// outside-Terraform changes while refreshing then we consider
		// that applyable in isolation only if this was a refresh-only
		// plan where we expect updating the state to include these
		// changes was the intended goal.
		//
		// (We don't treat a "refresh only" plan as applyable in normal
		// planning mode because historically the refresh result wasn't
		// considered part of a plan at all, and so it would be
		// a disruptive breaking change if refreshing alone suddenly
		// became applyable in the normal case and an existing configuration
		// was relying on ignore_changes in order to be convergent in spite
		// of intentional out-of-band operations.)
		return p.UIMode == RefreshOnlyMode

	default:
		// Otherwise, there are either no changes to apply or they are changes
		// our cases above don't consider as worthy of applying in isolation.
		return false
	}
}

// ProviderAddrs returns a list of all of the provider configuration addresses
// referenced throughout the receiving plan.
//
// The result is de-duplicated so that each distinct address appears only once.
func (p *Plan) ProviderAddrs() []addrs.AbsProviderConfig {
	if p == nil || p.Changes == nil {
		return nil
	}

	m := map[string]addrs.AbsProviderConfig{}
	for _, rc := range p.Changes.Resources {
		m[rc.ProviderAddr.String()] = rc.ProviderAddr
	}
	if len(m) == 0 {
		return nil
	}

	// This is mainly just so we'll get stable results for testing purposes.
	keys := make([]string, 0, len(m))
	for k := range m {
		keys = append(keys, k)
	}
	sort.Strings(keys)

	ret := make([]addrs.AbsProviderConfig, len(keys))
	for i, key := range keys {
		ret[i] = m[key]
	}

	return ret
}

// Backend represents the backend-related configuration and other data as it
// existed when a plan was created.
type Backend struct {
	// Type is the type of backend that the plan will apply against.
	Type string

	// Config is the configuration of the backend, whose schema is decided by
	// the backend Type.
	Config DynamicValue

	// Workspace is the name of the workspace that was active when the plan
	// was created. It is illegal to apply a plan created for one workspace
	// to the state of another workspace.
	// (This constraint is already enforced by the statefile lineage mechanism,
	// but storing this explicitly allows us to return a better error message
	// in the situation where the user has the wrong workspace selected.)
	Workspace string
}

func NewBackend(typeName string, config cty.Value, configSchema *configschema.Block, workspaceName string) (*Backend, error) {
	dv, err := NewDynamicValue(config, configSchema.ImpliedType())
	if err != nil {
		return nil, err
	}

	return &Backend{
		Type:      typeName,
		Config:    dv,
		Workspace: workspaceName,
	}, nil
}
