package objchange

import (
	"fmt"

	"github.com/zclconf/go-cty/cty"

	"github.com/hashicorp/terraform/internal/configs/configschema"
)

// AssertPlanValid checks checks whether a planned new state returned by a
// provider's PlanResourceChange method is suitable to achieve a change
// from priorState to config. It returns a slice with nonzero length if
// any problems are detected. Because problems here indicate bugs in the
// provider that generated the plannedState, they are written with provider
// developers as an audience, rather than end-users.
//
// All of the given values must have the same type and must conform to the
// implied type of the given schema, or this function may panic or produce
// garbage results.
//
// During planning, a provider may only make changes to attributes that are
// null (unset) in the configuration and are marked as "computed" in the
// resource type schema, in order to insert any default values the provider
// may know about. If the default value cannot be determined until apply time,
// the provider can return an unknown value. Providers are forbidden from
// planning a change that disagrees with any non-null argument in the
// configuration.
//
// As a special exception, providers _are_ allowed to provide attribute values
// conflicting with configuration if and only if the planned value exactly
// matches the corresponding attribute value in the prior state. The provider
// can use this to signal that the new value is functionally equivalent to
// the old and thus no change is required.
func AssertPlanValid(schema *configschema.Block, priorState, config, plannedState cty.Value) []error {
	return assertPlanValid(schema, priorState, config, plannedState, nil)
}

func assertPlanValid(schema *configschema.Block, priorState, config, plannedState cty.Value, path cty.Path) []error {
	var errs []error
	if plannedState.IsNull() && !config.IsNull() {
		errs = append(errs, path.NewErrorf("planned for absence but config wants existence"))
		return errs
	}
	if config.IsNull() && !plannedState.IsNull() {
		errs = append(errs, path.NewErrorf("planned for existence but config wants absence"))
		return errs
	}
	if plannedState.IsNull() {
		// No further checks possible if the planned value is null
		return errs
	}

	impTy := schema.ImpliedType()

	// verify attributes
	moreErrs := assertPlannedAttrsValid(schema.Attributes, priorState, config, plannedState, path)
	errs = append(errs, moreErrs...)

	for name, blockS := range schema.BlockTypes {
		path := append(path, cty.GetAttrStep{Name: name})
		plannedV := plannedState.GetAttr(name)
		configV := config.GetAttr(name)
		priorV := cty.NullVal(impTy.AttributeType(name))
		if !priorState.IsNull() {
			priorV = priorState.GetAttr(name)
		}
		if plannedV.RawEquals(configV) {
			// Easy path: nothing has changed at all
			continue
		}

		if !configV.IsKnown() {
			// An unknown config block represents a dynamic block where the
			// for_each value is unknown, and therefor cannot be altered by the
			// provider.
			errs = append(errs, path.NewErrorf("planned value %#v for unknown dynamic block", plannedV))
			continue
		}

		if !plannedV.IsKnown() {
			// Only dynamic configuration can set blocks to unknown, so this is
			// not allowed from the provider. This means that either the config
			// and plan should match, or we have an error where the plan
			// changed the config value, both of which have been checked.
			errs = append(errs, path.NewErrorf("attribute representing nested block must not be unknown itself; set nested attribute values to unknown instead"))
			continue
		}

		switch blockS.Nesting {
		case configschema.NestingSingle, configschema.NestingGroup:
			moreErrs := assertPlanValid(&blockS.Block, priorV, configV, plannedV, path)
			errs = append(errs, moreErrs...)
		case configschema.NestingList:
			// A NestingList might either be a list or a tuple, depending on
			// whether there are dynamically-typed attributes inside. However,
			// both support a similar-enough API that we can treat them the
			// same for our purposes here.
			if plannedV.IsNull() {
				errs = append(errs, path.NewErrorf("attribute representing a list of nested blocks must be empty to indicate no blocks, not null"))
				continue
			}

			plannedL := plannedV.LengthInt()
			configL := configV.LengthInt()
			if plannedL != configL {
				errs = append(errs, path.NewErrorf("block count in plan (%d) disagrees with count in config (%d)", plannedL, configL))
				continue
			}

			for it := plannedV.ElementIterator(); it.Next(); {
				idx, plannedEV := it.Element()
				path := append(path, cty.IndexStep{Key: idx})
				if !plannedEV.IsKnown() {
					errs = append(errs, path.NewErrorf("element representing nested block must not be unknown itself; set nested attribute values to unknown instead"))
					continue
				}
				if !configV.HasIndex(idx).True() {
					continue // should never happen since we checked the lengths above
				}
				configEV := configV.Index(idx)
				priorEV := cty.NullVal(blockS.ImpliedType())
				if !priorV.IsNull() && priorV.HasIndex(idx).True() {
					priorEV = priorV.Index(idx)
				}

				moreErrs := assertPlanValid(&blockS.Block, priorEV, configEV, plannedEV, path)
				errs = append(errs, moreErrs...)
			}
		case configschema.NestingMap:
			if plannedV.IsNull() {
				errs = append(errs, path.NewErrorf("attribute representing a map of nested blocks must be empty to indicate no blocks, not null"))
				continue
			}

			// A NestingMap might either be a map or an object, depending on
			// whether there are dynamically-typed attributes inside, but
			// that's decided statically and so all values will have the same
			// kind.
			if plannedV.Type().IsObjectType() {
				plannedAtys := plannedV.Type().AttributeTypes()
				configAtys := configV.Type().AttributeTypes()
				for k := range plannedAtys {
					if _, ok := configAtys[k]; !ok {
						errs = append(errs, path.NewErrorf("block key %q from plan is not present in config", k))
						continue
					}
					path := append(path, cty.GetAttrStep{Name: k})

					plannedEV := plannedV.GetAttr(k)
					if !plannedEV.IsKnown() {
						errs = append(errs, path.NewErrorf("element representing nested block must not be unknown itself; set nested attribute values to unknown instead"))
						continue
					}
					configEV := configV.GetAttr(k)
					priorEV := cty.NullVal(blockS.ImpliedType())
					if !priorV.IsNull() && priorV.Type().HasAttribute(k) {
						priorEV = priorV.GetAttr(k)
					}
					moreErrs := assertPlanValid(&blockS.Block, priorEV, configEV, plannedEV, path)
					errs = append(errs, moreErrs...)
				}
				for k := range configAtys {
					if _, ok := plannedAtys[k]; !ok {
						errs = append(errs, path.NewErrorf("block key %q from config is not present in plan", k))
						continue
					}
				}
			} else {
				plannedL := plannedV.LengthInt()
				configL := configV.LengthInt()
				if plannedL != configL {
					errs = append(errs, path.NewErrorf("block count in plan (%d) disagrees with count in config (%d)", plannedL, configL))
					continue
				}
				for it := plannedV.ElementIterator(); it.Next(); {
					idx, plannedEV := it.Element()
					path := append(path, cty.IndexStep{Key: idx})
					if !plannedEV.IsKnown() {
						errs = append(errs, path.NewErrorf("element representing nested block must not be unknown itself; set nested attribute values to unknown instead"))
						continue
					}
					k := idx.AsString()
					if !configV.HasIndex(idx).True() {
						errs = append(errs, path.NewErrorf("block key %q from plan is not present in config", k))
						continue
					}
					configEV := configV.Index(idx)
					priorEV := cty.NullVal(blockS.ImpliedType())
					if !priorV.IsNull() && priorV.HasIndex(idx).True() {
						priorEV = priorV.Index(idx)
					}
					moreErrs := assertPlanValid(&blockS.Block, priorEV, configEV, plannedEV, path)
					errs = append(errs, moreErrs...)
				}
				for it := configV.ElementIterator(); it.Next(); {
					idx, _ := it.Element()
					if !plannedV.HasIndex(idx).True() {
						errs = append(errs, path.NewErrorf("block key %q from config is not present in plan", idx.AsString()))
						continue
					}
				}
			}
		case configschema.NestingSet:
			if plannedV.IsNull() {
				errs = append(errs, path.NewErrorf("attribute representing a set of nested blocks must be empty to indicate no blocks, not null"))
				continue
			}

			// Because set elements have no identifier with which to correlate
			// them, we can't robustly validate the plan for a nested block
			// backed by a set, and so unfortunately we need to just trust the
			// provider to do the right thing. :(
			//
			// (In principle we could correlate elements by matching the
			// subset of attributes explicitly set in config, except for the
			// special diff suppression rule which allows for there to be a
			// planned value that is constructed by mixing part of a prior
			// value with part of a config value, creating an entirely new
			// element that is not present in either prior nor config.)
			for it := plannedV.ElementIterator(); it.Next(); {
				idx, plannedEV := it.Element()
				path := append(path, cty.IndexStep{Key: idx})
				if !plannedEV.IsKnown() {
					errs = append(errs, path.NewErrorf("element representing nested block must not be unknown itself; set nested attribute values to unknown instead"))
					continue
				}
			}

		default:
			panic(fmt.Sprintf("unsupported nesting mode %s", blockS.Nesting))
		}
	}

	return errs
}

func assertPlannedAttrsValid(schema map[string]*configschema.Attribute, priorState, config, plannedState cty.Value, path cty.Path) []error {
	var errs []error
	for name, attrS := range schema {
		moreErrs := assertPlannedAttrValid(name, attrS, priorState, config, plannedState, path)
		errs = append(errs, moreErrs...)
	}
	return errs
}

func assertPlannedAttrValid(name string, attrS *configschema.Attribute, priorState, config, plannedState cty.Value, path cty.Path) []error {
	plannedV := plannedState.GetAttr(name)
	configV := config.GetAttr(name)
	priorV := cty.NullVal(attrS.Type)
	if !priorState.IsNull() {
		priorV = priorState.GetAttr(name)
	}
	path = append(path, cty.GetAttrStep{Name: name})

	return assertPlannedValueValid(attrS, priorV, configV, plannedV, path)
}

func assertPlannedValueValid(attrS *configschema.Attribute, priorV, configV, plannedV cty.Value, path cty.Path) []error {
	var errs []error
	if plannedV.RawEquals(configV) {
		// This is the easy path: provider didn't change anything at all.
		return errs
	}
	if plannedV.RawEquals(priorV) && !priorV.IsNull() && !configV.IsNull() {
		// Also pretty easy: there is a prior value and the provider has
		// returned it unchanged. This indicates that configV and plannedV
		// are functionally equivalent and so the provider wishes to disregard
		// the configuration value in favor of the prior.
		return errs
	}

	// the provider is allowed to insert values when the config is
	// null, but only if the attribute is computed.
	if configV.IsNull() {
		if attrS.Computed {
			return errs
		}

		// if the attribute is not computed, then any planned value is incorrect
		if !plannedV.IsNull() {
			if attrS.Sensitive {
				errs = append(errs, path.NewErrorf("sensitive planned value for a non-computed attribute"))
			} else {
				errs = append(errs, path.NewErrorf("planned value %#v for a non-computed attribute", plannedV))
			}
			return errs
		}
	}

	// If this attribute has a NestedType, validate the nested object
	if attrS.NestedType != nil {
		return assertPlannedObjectValid(attrS.NestedType, priorV, configV, plannedV, path)
	}

	// If none of the above conditions match, the provider has made an invalid
	// change to this attribute.
	if priorV.IsNull() {
		if attrS.Sensitive {
			errs = append(errs, path.NewErrorf("sensitive planned value does not match config value"))
		} else {
			errs = append(errs, path.NewErrorf("planned value %#v does not match config value %#v", plannedV, configV))
		}
		return errs
	}

	if attrS.Sensitive {
		errs = append(errs, path.NewErrorf("sensitive planned value does not match config value nor prior value"))
	} else {
		errs = append(errs, path.NewErrorf("planned value %#v does not match config value %#v nor prior value %#v", plannedV, configV, priorV))
	}

	return errs
}

func assertPlannedObjectValid(schema *configschema.Object, prior, config, planned cty.Value, path cty.Path) []error {
	var errs []error

	if planned.IsNull() && !config.IsNull() {
		errs = append(errs, path.NewErrorf("planned for absence but config wants existence"))
		return errs
	}
	if config.IsNull() && !planned.IsNull() {
		errs = append(errs, path.NewErrorf("planned for existence but config wants absence"))
		return errs
	}
	if planned.IsNull() {
		// No further checks possible if the planned value is null
		return errs
	}

	switch schema.Nesting {
	case configschema.NestingSingle, configschema.NestingGroup:
		moreErrs := assertPlannedAttrsValid(schema.Attributes, prior, config, planned, path)
		errs = append(errs, moreErrs...)

	case configschema.NestingList:
		// A NestingList might either be a list or a tuple, depending on
		// whether there are dynamically-typed attributes inside. However,
		// both support a similar-enough API that we can treat them the
		// same for our purposes here.

		plannedL := planned.LengthInt()
		configL := config.LengthInt()
		if plannedL != configL {
			errs = append(errs, path.NewErrorf("count in plan (%d) disagrees with count in config (%d)", plannedL, configL))
			return errs
		}
		for it := planned.ElementIterator(); it.Next(); {
			idx, plannedEV := it.Element()
			path := append(path, cty.IndexStep{Key: idx})
			if !config.HasIndex(idx).True() {
				continue // should never happen since we checked the lengths above
			}
			configEV := config.Index(idx)
			priorEV := cty.NullVal(schema.ImpliedType())
			if !prior.IsNull() && prior.HasIndex(idx).True() {
				priorEV = prior.Index(idx)
			}

			moreErrs := assertPlannedAttrsValid(schema.Attributes, priorEV, configEV, plannedEV, path)
			errs = append(errs, moreErrs...)
		}

	case configschema.NestingMap:
		// A NestingMap might either be a map or an object, depending on
		// whether there are dynamically-typed attributes inside, so we will
		// break these down to maps to handle them both in the same manner.
		plannedVals := map[string]cty.Value{}
		configVals := map[string]cty.Value{}
		priorVals := map[string]cty.Value{}

		if !planned.IsNull() {
			plannedVals = planned.AsValueMap()
		}
		if !config.IsNull() {
			configVals = config.AsValueMap()
		}
		if !prior.IsNull() {
			priorVals = prior.AsValueMap()
		}

		for k, plannedEV := range plannedVals {
			configEV, ok := configVals[k]
			if !ok {
				errs = append(errs, path.NewErrorf("map key %q from plan is not present in config", k))
				continue
			}
			path := append(path, cty.GetAttrStep{Name: k})

			priorEV, ok := priorVals[k]
			if !ok {
				priorEV = cty.NullVal(schema.ImpliedType())
			}
			moreErrs := assertPlannedAttrsValid(schema.Attributes, priorEV, configEV, plannedEV, path)
			errs = append(errs, moreErrs...)
		}
		for k := range configVals {
			if _, ok := plannedVals[k]; !ok {
				errs = append(errs, path.NewErrorf("map key %q from config is not present in plan", k))
				continue
			}
		}

	case configschema.NestingSet:
		plannedL := planned.LengthInt()
		configL := config.LengthInt()
		if plannedL != configL {
			errs = append(errs, path.NewErrorf("count in plan (%d) disagrees with count in config (%d)", plannedL, configL))
			return errs
		}
		// Because set elements have no identifier with which to correlate
		// them, we can't robustly validate the plan for a nested object
		// backed by a set, and so unfortunately we need to just trust the
		// provider to do the right thing.
	}

	return errs
}
