package terraform

import (
	"fmt"
	"log"
	"strings"

	"github.com/hashicorp/hcl/v2"
	"github.com/hashicorp/hcl/v2/gohcl"
	"github.com/hashicorp/terraform/internal/addrs"
	"github.com/hashicorp/terraform/internal/configs"
	"github.com/hashicorp/terraform/internal/lang/marks"
	"github.com/hashicorp/terraform/internal/tfdiags"
	"github.com/zclconf/go-cty/cty"
	"github.com/zclconf/go-cty/cty/convert"
)

func prepareFinalInputVariableValue(addr addrs.AbsInputVariableInstance, raw *InputValue, cfg *configs.Variable) (cty.Value, tfdiags.Diagnostics) {
	var diags tfdiags.Diagnostics

	convertTy := cfg.ConstraintType
	log.Printf("[TRACE] prepareFinalInputVariableValue: preparing %s", addr)

	var defaultVal cty.Value
	if cfg.Default != cty.NilVal {
		log.Printf("[TRACE] prepareFinalInputVariableValue: %s has a default value", addr)
		var err error
		defaultVal, err = convert.Convert(cfg.Default, convertTy)
		if err != nil {
			// Validation of the declaration should typically catch this,
			// but we'll check it here too to be robust.
			diags = diags.Append(&hcl.Diagnostic{
				Severity: hcl.DiagError,
				Summary:  "Invalid default value for module argument",
				Detail: fmt.Sprintf(
					"The default value for variable %q is incompatible with its type constraint: %s.",
					cfg.Name, err,
				),
				Subject: &cfg.DeclRange,
			})
			// We'll return a placeholder unknown value to avoid producing
			// redundant downstream errors.
			return cty.UnknownVal(cfg.Type), diags
		}
	}

	var sourceRange tfdiags.SourceRange
	var nonFileSource string
	if raw.HasSourceRange() {
		sourceRange = raw.SourceRange
	} else {
		// If the value came from a place that isn't a file and thus doesn't
		// have its own source range, we'll use the declaration range as
		// our source range and generate some slightly different error
		// messages.
		sourceRange = tfdiags.SourceRangeFromHCL(cfg.DeclRange)
		switch raw.SourceType {
		case ValueFromCLIArg:
			nonFileSource = fmt.Sprintf("set using -var=\"%s=...\"", addr.Variable.Name)
		case ValueFromEnvVar:
			nonFileSource = fmt.Sprintf("set using the TF_VAR_%s environment variable", addr.Variable.Name)
		case ValueFromInput:
			nonFileSource = "set using an interactive prompt"
		default:
			nonFileSource = "set from outside of the configuration"
		}
	}

	given := raw.Value
	if given == cty.NilVal { // The variable wasn't set at all (even to null)
		log.Printf("[TRACE] prepareFinalInputVariableValue: %s has no defined value", addr)
		if cfg.Required() {
			// NOTE: The CLI layer typically checks for itself whether all of
			// the required _root_ module variables are set, which would
			// mask this error with a more specific one that refers to the
			// CLI features for setting such variables. We can get here for
			// child module variables, though.
			log.Printf("[ERROR] prepareFinalInputVariableValue: %s is required but is not set", addr)
			diags = diags.Append(&hcl.Diagnostic{
				Severity: hcl.DiagError,
				Summary:  `Required variable not set`,
				Detail:   fmt.Sprintf(`The variable %q is required, but is not set.`, addr.Variable.Name),
				Subject:  cfg.DeclRange.Ptr(),
			})
			// We'll return a placeholder unknown value to avoid producing
			// redundant downstream errors.
			return cty.UnknownVal(cfg.Type), diags
		}

		given = defaultVal // must be set, because we checked above that the variable isn't required
	}

	// Apply defaults from the variable's type constraint to the given value,
	// unless the given value is null. We do not apply defaults to top-level
	// null values, as doing so could prevent assigning null to a nullable
	// variable.
	if cfg.TypeDefaults != nil && !given.IsNull() {
		given = cfg.TypeDefaults.Apply(given)
	}

	val, err := convert.Convert(given, convertTy)
	if err != nil {
		log.Printf("[ERROR] prepareFinalInputVariableValue: %s has unsuitable type\n  got:  %s\n  want: %s", addr, given.Type(), convertTy)
		var detail string
		var subject *hcl.Range
		if nonFileSource != "" {
			detail = fmt.Sprintf(
				"Unsuitable value for %s %s: %s.",
				addr, nonFileSource, err,
			)
			subject = cfg.DeclRange.Ptr()
		} else {
			detail = fmt.Sprintf(
				"The given value is not suitable for %s declared at %s: %s.",
				addr, cfg.DeclRange.String(), err,
			)
			subject = sourceRange.ToHCL().Ptr()

			// In some workflows, the operator running terraform does not have access to the variables
			// themselves. They are for example stored in encrypted files that will be used by the CI toolset
			// and not by the operator directly. In such a case, the failing secret value should not be
			// displayed to the operator
			if cfg.Sensitive {
				detail = fmt.Sprintf(
					"The given value is not suitable for %s, which is sensitive: %s. Invalid value defined at %s.",
					addr, err, sourceRange.ToHCL(),
				)
				subject = cfg.DeclRange.Ptr()
			}
		}

		diags = diags.Append(&hcl.Diagnostic{
			Severity: hcl.DiagError,
			Summary:  "Invalid value for input variable",
			Detail:   detail,
			Subject:  subject,
		})
		// We'll return a placeholder unknown value to avoid producing
		// redundant downstream errors.
		return cty.UnknownVal(cfg.Type), diags
	}

	// By the time we get here, we know:
	// - val matches the variable's type constraint
	// - val is definitely not cty.NilVal, but might be a null value if the given was already null.
	//
	// That means we just need to handle the case where the value is null,
	// which might mean we need to use the default value, or produce an error.
	//
	// For historical reasons we do this only for a "non-nullable" variable.
	// Nullable variables just appear as null if they were set to null,
	// regardless of any default value.
	if val.IsNull() && !cfg.Nullable {
		log.Printf("[TRACE] prepareFinalInputVariableValue: %s is defined as null", addr)
		if defaultVal != cty.NilVal {
			val = defaultVal
		} else {
			log.Printf("[ERROR] prepareFinalInputVariableValue: %s is non-nullable but set to null, and is required", addr)
			if nonFileSource != "" {
				diags = diags.Append(&hcl.Diagnostic{
					Severity: hcl.DiagError,
					Summary:  `Required variable not set`,
					Detail: fmt.Sprintf(
						"Unsuitable value for %s %s: required variable may not be set to null.",
						addr, nonFileSource,
					),
					Subject: cfg.DeclRange.Ptr(),
				})
			} else {
				diags = diags.Append(&hcl.Diagnostic{
					Severity: hcl.DiagError,
					Summary:  `Required variable not set`,
					Detail: fmt.Sprintf(
						"The given value is not suitable for %s defined at %s: required variable may not be set to null.",
						addr, cfg.DeclRange.String(),
					),
					Subject: sourceRange.ToHCL().Ptr(),
				})
			}
			// Stub out our return value so that the semantic checker doesn't
			// produce redundant downstream errors.
			val = cty.UnknownVal(cfg.Type)
		}
	}

	return val, diags
}

// evalVariableValidations ensures that all of the configured custom validations
// for a variable are passing.
//
// This must be used only after any side-effects that make the value of the
// variable available for use in expression evaluation, such as
// EvalModuleCallArgument for variables in descendent modules.
func evalVariableValidations(addr addrs.AbsInputVariableInstance, config *configs.Variable, expr hcl.Expression, ctx EvalContext) (diags tfdiags.Diagnostics) {
	if config == nil || len(config.Validations) == 0 {
		log.Printf("[TRACE] evalVariableValidations: no validation rules declared for %s, so skipping", addr)
		return nil
	}
	log.Printf("[TRACE] evalVariableValidations: validating %s", addr)

	// Variable nodes evaluate in the parent module to where they were declared
	// because the value expression (n.Expr, if set) comes from the calling
	// "module" block in the parent module.
	//
	// Validation expressions are statically validated (during configuration
	// loading) to refer only to the variable being validated, so we can
	// bypass our usual evaluation machinery here and just produce a minimal
	// evaluation context containing just the required value, and thus avoid
	// the problem that ctx's evaluation functions refer to the wrong module.
	val := ctx.GetVariableValue(addr)
	if val == cty.NilVal {
		diags = diags.Append(&hcl.Diagnostic{
			Severity: hcl.DiagError,
			Summary:  "No final value for variable",
			Detail:   fmt.Sprintf("Terraform doesn't have a final value for %s during validation. This is a bug in Terraform; please report it!", addr),
		})
		return diags
	}
	hclCtx := &hcl.EvalContext{
		Variables: map[string]cty.Value{
			"var": cty.ObjectVal(map[string]cty.Value{
				config.Name: val,
			}),
		},
		Functions: ctx.EvaluationScope(nil, EvalDataForNoInstanceKey).Functions(),
	}

	for _, validation := range config.Validations {
		const errInvalidCondition = "Invalid variable validation result"
		const errInvalidValue = "Invalid value for variable"
		var ruleDiags tfdiags.Diagnostics

		result, moreDiags := validation.Condition.Value(hclCtx)
		ruleDiags = ruleDiags.Append(moreDiags)
		errorValue, errorDiags := validation.ErrorMessage.Value(hclCtx)

		// The following error handling is a workaround to preserve backwards
		// compatibility. Due to an implementation quirk, all prior versions of
		// Terraform would treat error messages specified using JSON
		// configuration syntax (.tf.json) as string literals, even if they
		// contained the "${" template expression operator. This behaviour did
		// not match that of HCL configuration syntax, where a template
		// expression would result in a validation error.
		//
		// As a result, users writing or generating JSON configuration syntax
		// may have specified error messages which are invalid template
		// expressions. As we add support for error message expressions, we are
		// unable to perfectly distinguish between these two cases.
		//
		// To ensure that we don't break backwards compatibility, we have the
		// below fallback logic if the error message fails to evaluate. This
		// should only have any effect for JSON configurations. The gohcl
		// DecodeExpression function behaves differently when the source of the
		// expression is a JSON configuration file and a nil context is passed.
		if errorDiags.HasErrors() {
			// Attempt to decode the expression as a string literal. Passing
			// nil as the context forces a JSON syntax string value to be
			// interpreted as a string literal.
			var errorString string
			moreErrorDiags := gohcl.DecodeExpression(validation.ErrorMessage, nil, &errorString)
			if !moreErrorDiags.HasErrors() {
				// Decoding succeeded, meaning that this is a JSON syntax
				// string value. We rewrap that as a cty value to allow later
				// decoding to succeed.
				errorValue = cty.StringVal(errorString)

				// This warning diagnostic explains this odd behaviour, while
				// giving us an escape hatch to change this to a hard failure
				// in some future Terraform 1.x version.
				errorDiags = hcl.Diagnostics{
					&hcl.Diagnostic{
						Severity:    hcl.DiagWarning,
						Summary:     "Validation error message expression is invalid",
						Detail:      fmt.Sprintf("The error message provided could not be evaluated as an expression, so Terraform is interpreting it as a string literal.\n\nIn future versions of Terraform, this will be considered an error. Please file a GitHub issue if this would break your workflow.\n\n%s", errorDiags.Error()),
						Subject:     validation.ErrorMessage.Range().Ptr(),
						Context:     validation.DeclRange.Ptr(),
						Expression:  validation.ErrorMessage,
						EvalContext: hclCtx,
					},
				}
			}

			// We want to either report the original diagnostics if the
			// fallback failed, or the warning generated above if it succeeded.
			ruleDiags = ruleDiags.Append(errorDiags)
		}

		diags = diags.Append(ruleDiags)

		if ruleDiags.HasErrors() {
			log.Printf("[TRACE] evalVariableValidations: %s rule %s check rule evaluation failed: %s", addr, validation.DeclRange, ruleDiags.Err().Error())
		}
		if !result.IsKnown() {
			log.Printf("[TRACE] evalVariableValidations: %s rule %s condition value is unknown, so skipping validation for now", addr, validation.DeclRange)
			continue // We'll wait until we've learned more, then.
		}
		if result.IsNull() {
			diags = diags.Append(&hcl.Diagnostic{
				Severity:    hcl.DiagError,
				Summary:     errInvalidCondition,
				Detail:      "Validation condition expression must return either true or false, not null.",
				Subject:     validation.Condition.Range().Ptr(),
				Expression:  validation.Condition,
				EvalContext: hclCtx,
			})
			continue
		}
		var err error
		result, err = convert.Convert(result, cty.Bool)
		if err != nil {
			diags = diags.Append(&hcl.Diagnostic{
				Severity:    hcl.DiagError,
				Summary:     errInvalidCondition,
				Detail:      fmt.Sprintf("Invalid validation condition result value: %s.", tfdiags.FormatError(err)),
				Subject:     validation.Condition.Range().Ptr(),
				Expression:  validation.Condition,
				EvalContext: hclCtx,
			})
			continue
		}

		// Validation condition may be marked if the input variable is bound to
		// a sensitive value. This is irrelevant to the validation process, so
		// we discard the marks now.
		result, _ = result.Unmark()

		if result.True() {
			continue
		}

		var errorMessage string
		if !errorDiags.HasErrors() && errorValue.IsKnown() && !errorValue.IsNull() {
			var err error
			errorValue, err = convert.Convert(errorValue, cty.String)
			if err != nil {
				diags = diags.Append(&hcl.Diagnostic{
					Severity:    hcl.DiagError,
					Summary:     "Invalid error message",
					Detail:      fmt.Sprintf("Unsuitable value for error message: %s.", tfdiags.FormatError(err)),
					Subject:     validation.ErrorMessage.Range().Ptr(),
					Expression:  validation.ErrorMessage,
					EvalContext: hclCtx,
				})
			} else {
				if marks.Has(errorValue, marks.Sensitive) {
					diags = diags.Append(&hcl.Diagnostic{
						Severity: hcl.DiagError,

						Summary: "Error message refers to sensitive values",
						Detail: `The error expression used to explain this condition refers to sensitive values. Terraform will not display the resulting message.

You can correct this by removing references to sensitive values, or by carefully using the nonsensitive() function if the expression will not reveal the sensitive data.`,

						Subject:     validation.ErrorMessage.Range().Ptr(),
						Expression:  validation.ErrorMessage,
						EvalContext: hclCtx,
					})
					errorMessage = "The error message included a sensitive value, so it will not be displayed."
				} else {
					errorMessage = strings.TrimSpace(errorValue.AsString())
				}
			}
		}
		if errorMessage == "" {
			errorMessage = "Failed to evaluate condition error message."
		}

		if expr != nil {
			diags = diags.Append(&hcl.Diagnostic{
				Severity:    hcl.DiagError,
				Summary:     errInvalidValue,
				Detail:      fmt.Sprintf("%s\n\nThis was checked by the validation rule at %s.", errorMessage, validation.DeclRange.String()),
				Subject:     expr.Range().Ptr(),
				Expression:  validation.Condition,
				EvalContext: hclCtx,
			})
		} else {
			// Since we don't have a source expression for a root module
			// variable, we'll just report the error from the perspective
			// of the variable declaration itself.
			diags = diags.Append(&hcl.Diagnostic{
				Severity:    hcl.DiagError,
				Summary:     errInvalidValue,
				Detail:      fmt.Sprintf("%s\n\nThis was checked by the validation rule at %s.", errorMessage, validation.DeclRange.String()),
				Subject:     config.DeclRange.Ptr(),
				Expression:  validation.Condition,
				EvalContext: hclCtx,
			})
		}
	}

	return diags
}
