// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1

package stackstate

import (
	"github.com/zclconf/go-cty/cty"
	"google.golang.org/protobuf/types/known/anypb"

	"github.com/hashicorp/terraform/internal/addrs"
	"github.com/hashicorp/terraform/internal/collections"
	"github.com/hashicorp/terraform/internal/stacks/stackaddrs"
	"github.com/hashicorp/terraform/internal/stacks/stackstate/statekeys"
	"github.com/hashicorp/terraform/internal/states"
)

// State represents a previous run's state snapshot.
//
// Unlike [states.State] and its associates, State is an immutable data
// structure constructed to represent only the previous run state. It should
// not be modified after it's been constructed; results of planning or applying
// changes are represented in other ways inside the stacks language runtime.
type State struct {
	componentInstances collections.Map[stackaddrs.AbsComponentInstance, *componentInstanceState]
	outputs            map[stackaddrs.OutputValue]cty.Value
	inputs             map[stackaddrs.InputVariable]cty.Value

	// discardUnsupportedKeys is the set of state keys that we encountered
	// during decoding which are of types that are not supported by this
	// version of Terraform, if and only if they are of a type which is
	// specified as being discarded when unrecognized. We should emit
	// events during the apply phase to delete the objects associated with
	// these keys.
	discardUnsupportedKeys collections.Set[statekeys.Key]

	inputRaw map[string]*anypb.Any
}

// NewState constructs a new, empty state.
func NewState() *State {
	return &State{
		componentInstances:     collections.NewMap[stackaddrs.AbsComponentInstance, *componentInstanceState](),
		outputs:                make(map[stackaddrs.OutputValue]cty.Value),
		inputs:                 make(map[stackaddrs.InputVariable]cty.Value),
		discardUnsupportedKeys: statekeys.NewKeySet(),
		inputRaw:               nil,
	}
}

// RootInputVariables returns the values for the input variables currently in
// the state. An address that is in the map and maps to cty.NilVal is an
// ephemeral input, so it was present during the last operation but the value
// in unknown. Compared to an input variable not in the map at all, which
// indicates a new input variable that wasn't in the configuration during the
// last operation.
func (s *State) RootInputVariables() map[stackaddrs.InputVariable]cty.Value {
	return s.inputs
}

// RootInputVariable returns the input variable defined at the given address.
// If the second return value is true, then the value is present but is
// ephemeral and not known. If the first returned value is cty.NilVal and the
// second is false then the value isn't present in the state.
func (s *State) RootInputVariable(addr stackaddrs.InputVariable) cty.Value {
	return s.inputs[addr]
}

func (s *State) RootOutputValues() map[stackaddrs.OutputValue]cty.Value {
	return s.outputs
}

func (s *State) RootOutputValue(addr stackaddrs.OutputValue) cty.Value {
	return s.outputs[addr]
}

func (s *State) HasComponentInstance(addr stackaddrs.AbsComponentInstance) bool {
	return s.componentInstances.HasKey(addr)
}

// AllComponentInstances returns a set of addresses for all of the component
// instances that are tracked in the state.
//
// This includes both instances that were explicitly represented in the source
// raw state _and_ any that were missing but implied by a resource instance
// existing inside them. There should typically be an explicit component
// instance record tracked in raw state, but it can potentially be absent in
// exceptional cases such as if Terraform Core crashed partway through the
// previous run.
func (s *State) AllComponentInstances() collections.Set[stackaddrs.AbsComponentInstance] {
	var ret collections.Set[stackaddrs.AbsComponentInstance]
	if s.componentInstances.Len() == 0 {
		return ret
	}
	ret = collections.NewSet[stackaddrs.AbsComponentInstance]()
	for key := range s.componentInstances.All() {
		ret.Add(key)
	}
	return ret
}

// ComponentInstances returns the set of component instances that belong to the
// given component, or an empty set if no such component is tracked in the
// state.
//
// This will always be a subset of AllComponentInstances.
func (s *State) ComponentInstances(addr stackaddrs.AbsComponent) collections.Set[stackaddrs.ComponentInstance] {
	ret := collections.NewSet[stackaddrs.ComponentInstance]()
	for key := range s.componentInstances.All() {
		if key.Stack.String() != addr.Stack.String() {
			// Then
			continue
		}
		if key.Item.Component.Name != addr.Item.Name {
			continue
		}
		ret.Add(key.Item)
	}
	return ret
}

func (s *State) componentInstanceState(addr stackaddrs.AbsComponentInstance) *componentInstanceState {
	return s.componentInstances.Get(addr)
}

// DependenciesForComponent returns the list of components that are required by
// the given component instance, or an empty set if no such component instance
// is tracked in the state.
func (s *State) DependenciesForComponent(addr stackaddrs.AbsComponentInstance) collections.Set[stackaddrs.AbsComponent] {
	cs := s.componentInstanceState(addr)
	if cs == nil {
		return collections.NewSet[stackaddrs.AbsComponent]()
	}
	return cs.dependencies
}

// DependentsForComponent returns the list of components that are require the
// given component instance, or an empty set if no such component instance is
// tracked in the state.
func (s *State) DependentsForComponent(addr stackaddrs.AbsComponentInstance) collections.Set[stackaddrs.AbsComponent] {
	cs := s.componentInstanceState(addr)
	if cs == nil {
		return collections.NewSet[stackaddrs.AbsComponent]()
	}
	return cs.dependents
}

// ResultsForComponent returns the output values for the given component
// instance, or nil if no such component instance is tracked in the state.
func (s *State) ResultsForComponent(addr stackaddrs.AbsComponentInstance) map[addrs.OutputValue]cty.Value {
	cs := s.componentInstanceState(addr)
	if cs == nil {
		return nil
	}
	return cs.outputValues
}

// InputsForComponent returns the input values for the given component
// instance, or nil if no such component instance is tracked in the state.
func (s *State) InputsForComponent(addr stackaddrs.AbsComponentInstance) map[addrs.InputVariable]cty.Value {
	cs := s.componentInstanceState(addr)
	if cs == nil {
		return nil
	}
	return cs.inputVariables
}

type IdentitySrc struct {
	IdentitySchemaVersion uint64
	IdentityJSON          []byte
}

// IdentitiesForComponent returns the identity values for the given component
// instance, or nil if no such component instance is tracked in the state.
func (s *State) IdentitiesForComponent(addr stackaddrs.AbsComponentInstance) map[*addrs.AbsResourceInstanceObject]IdentitySrc {
	cs := s.componentInstanceState(addr)
	if cs == nil {
		return nil
	}

	res := make(map[*addrs.AbsResourceInstanceObject]IdentitySrc)
	for _, rio := range cs.resourceInstanceObjects.Elements() {
		res[&rio.Key] = IdentitySrc{
			IdentitySchemaVersion: rio.Value.src.IdentitySchemaVersion,
			IdentityJSON:          rio.Value.src.IdentityJSON,
		}
	}

	return res
}

// ComponentInstanceResourceInstanceObjects returns a set of addresses for
// all of the resource instance objects belonging to the component instance
// with the given address.
func (s *State) ComponentInstanceResourceInstanceObjects(addr stackaddrs.AbsComponentInstance) collections.Set[stackaddrs.AbsResourceInstanceObject] {
	var ret collections.Set[stackaddrs.AbsResourceInstanceObject]
	cs, ok := s.componentInstances.GetOk(addr)
	if !ok {
		return ret
	}
	ret = collections.NewSet[stackaddrs.AbsResourceInstanceObject]()
	for _, elem := range cs.resourceInstanceObjects.Elems {
		objKey := stackaddrs.AbsResourceInstanceObject{
			Component: addr,
			Item:      elem.Key,
		}
		ret.Add(objKey)
	}
	return ret
}

// AllResourceInstanceObjects returns a set of addresses for all of the resource
// instance objects that are tracked in the state, across all components.
func (s *State) AllResourceInstanceObjects() collections.Set[stackaddrs.AbsResourceInstanceObject] {
	ret := collections.NewSet[stackaddrs.AbsResourceInstanceObject]()
	for key, elem := range s.componentInstances.All() {
		componentAddr := key
		for _, elem := range elem.resourceInstanceObjects.Elems {
			objKey := stackaddrs.AbsResourceInstanceObject{
				Component: componentAddr,
				Item:      elem.Key,
			}
			ret.Add(objKey)
		}
	}
	return ret
}

// ResourceInstanceObjectSrc returns the source (i.e. still encoded) version of
// the resource instance object for the given address, or nil if no such
// object is tracked in the state.
func (s *State) ResourceInstanceObjectSrc(addr stackaddrs.AbsResourceInstanceObject) *states.ResourceInstanceObjectSrc {
	rios := s.resourceInstanceObjectState(addr)
	if rios == nil {
		return nil
	}
	return rios.src
}

// RequiredProviderInstances returns a description of all of the provider
// instance slots that are required to satisfy the resource instances
// belonging to the given component instance.
//
// See also stackeval.ComponentConfig.RequiredProviderInstances for a similar
// function that operates on the configuration of a component instance rather
// than the state of one.
func (s *State) RequiredProviderInstances(component stackaddrs.AbsComponentInstance) addrs.Set[addrs.RootProviderConfig] {
	state, ok := s.componentInstances.GetOk(component)
	if !ok {
		// Then we have no state for this component, which is fine.
		return addrs.MakeSet[addrs.RootProviderConfig]()
	}

	providerInstances := addrs.MakeSet[addrs.RootProviderConfig]()
	for _, elem := range state.resourceInstanceObjects.Elems {
		providerInstances.Add(addrs.RootProviderConfig{
			Provider: elem.Value.providerConfigAddr.Provider,
			Alias:    elem.Value.providerConfigAddr.Alias,
		})
	}
	return providerInstances
}

func (s *State) resourceInstanceObjectState(addr stackaddrs.AbsResourceInstanceObject) *resourceInstanceObjectState {
	cs, ok := s.componentInstances.GetOk(addr.Component)
	if !ok {
		return nil
	}
	return cs.resourceInstanceObjects.Get(addr.Item)
}

// ComponentInstanceStateForModulesRuntime returns a [states.State]
// representation of the objects tracked for the given component instance.
//
// This produces only a very bare-bones [states.State] that should be
// sufficient for use as a prior state for the modules runtime's plan function
// to consider, but likely won't be of much other use.
func (s *State) ComponentInstanceStateForModulesRuntime(addr stackaddrs.AbsComponentInstance) *states.State {
	return states.BuildState(func(ss *states.SyncState) {
		objAddrs := s.ComponentInstanceResourceInstanceObjects(addr)
		for objAddr := range objAddrs.All() {
			rios := s.resourceInstanceObjectState(objAddr)

			if objAddr.Item.IsCurrent() {
				ss.SetResourceInstanceCurrent(
					objAddr.Item.ResourceInstance,
					rios.src, rios.providerConfigAddr,
				)
			} else {
				ss.SetResourceInstanceDeposed(
					objAddr.Item.ResourceInstance, objAddr.Item.DeposedKey,
					rios.src, rios.providerConfigAddr,
				)
			}
		}
	})
}

// RawKeysToDiscard returns a set of raw state keys that the apply phase should
// emit "delete" events for to remove objects from the raw state map that
// will no longer be relevant or meaningful after this plan is applied.
//
// Do not modify the returned set.
func (s *State) RawKeysToDiscard() collections.Set[statekeys.Key] {
	return s.discardUnsupportedKeys
}

// InputRaw returns the raw representation of state that this object was built
// from, or nil if this object wasn't constructed by decoding a protocol buffers
// representation.
//
// All callers of this method get the same map, so callers must not modify
// the map or anything reachable through it.
func (s *State) InputRaw() map[string]*anypb.Any {
	return s.inputRaw
}

func (s *State) addOutputValue(addr stackaddrs.OutputValue, value cty.Value) {
	s.outputs[addr] = value
}

func (s *State) addInputVariable(addr stackaddrs.InputVariable, value cty.Value) {
	s.inputs[addr] = value
}

func (s *State) ensureComponentInstanceState(addr stackaddrs.AbsComponentInstance) *componentInstanceState {
	if existing, ok := s.componentInstances.GetOk(addr); ok {
		return existing
	}
	s.componentInstances.Put(addr, &componentInstanceState{
		dependencies:            collections.NewSet[stackaddrs.AbsComponent](),
		dependents:              collections.NewSet[stackaddrs.AbsComponent](),
		outputValues:            make(map[addrs.OutputValue]cty.Value),
		inputVariables:          make(map[addrs.InputVariable]cty.Value),
		resourceInstanceObjects: addrs.MakeMap[addrs.AbsResourceInstanceObject, *resourceInstanceObjectState](),
	})
	return s.componentInstances.Get(addr)
}

func (s *State) addResourceInstanceObject(addr stackaddrs.AbsResourceInstanceObject, src *states.ResourceInstanceObjectSrc, providerConfigAddr addrs.AbsProviderConfig) {
	cs := s.ensureComponentInstanceState(addr.Component)

	cs.resourceInstanceObjects.Put(addr.Item, &resourceInstanceObjectState{
		src:                src,
		providerConfigAddr: providerConfigAddr,
	})
}

type componentInstanceState struct {
	// dependencies is the set of component instances that this component
	// depended on the last time it was updated.
	dependencies collections.Set[stackaddrs.AbsComponent]

	// dependents is a set of component instances that depended on this
	// component the last time it was updated.
	dependents collections.Set[stackaddrs.AbsComponent]

	// outputValues is a map from output value addresses to their values at
	// completion of the last apply operation.
	outputValues map[addrs.OutputValue]cty.Value

	// inputVariables is a map from input variable addresses to their values at
	// completion of the last apply operation.
	inputVariables map[addrs.InputVariable]cty.Value

	// resourceInstanceObjects is a map from resource instance object addresses
	// to their state.
	resourceInstanceObjects addrs.Map[addrs.AbsResourceInstanceObject, *resourceInstanceObjectState]
}

type resourceInstanceObjectState struct {
	src                *states.ResourceInstanceObjectSrc
	providerConfigAddr addrs.AbsProviderConfig
}
