package terraform

import (
	"fmt"
	"log"

	"github.com/hashicorp/terraform/internal/backend"
	"github.com/hashicorp/terraform/internal/backend/remote"
	"github.com/hashicorp/terraform/internal/configs/configschema"
	"github.com/hashicorp/terraform/internal/providers"
	"github.com/hashicorp/terraform/internal/tfdiags"
	"github.com/zclconf/go-cty/cty"

	backendInit "github.com/hashicorp/terraform/internal/backend/init"
)

func dataSourceRemoteStateGetSchema() providers.Schema {
	return providers.Schema{
		Block: &configschema.Block{
			Attributes: map[string]*configschema.Attribute{
				"backend": {
					Type:            cty.String,
					Description:     "The remote backend to use, e.g. `remote` or `http`.",
					DescriptionKind: configschema.StringMarkdown,
					Required:        true,
				},
				"config": {
					Type: cty.DynamicPseudoType,
					Description: "The configuration of the remote backend. " +
						"Although this is optional, most backends require " +
						"some configuration.\n\n" +
						"The object can use any arguments that would be valid " +
						"in the equivalent `terraform { backend \"<TYPE>\" { ... } }` " +
						"block.",
					DescriptionKind: configschema.StringMarkdown,
					Optional:        true,
				},
				"defaults": {
					Type: cty.DynamicPseudoType,
					Description: "Default values for outputs, in case " +
						"the state file is empty or lacks a required output.",
					DescriptionKind: configschema.StringMarkdown,
					Optional:        true,
				},
				"outputs": {
					Type: cty.DynamicPseudoType,
					Description: "An object containing every root-level " +
						"output in the remote state.",
					DescriptionKind: configschema.StringMarkdown,
					Computed:        true,
				},
				"workspace": {
					Type: cty.String,
					Description: "The Terraform workspace to use, if " +
						"the backend supports workspaces.",
					DescriptionKind: configschema.StringMarkdown,
					Optional:        true,
				},
			},
		},
	}
}

func dataSourceRemoteStateValidate(cfg cty.Value) tfdiags.Diagnostics {
	var diags tfdiags.Diagnostics

	// Getting the backend implicitly validates the configuration for it,
	// but we can only do that if it's all known already.
	if cfg.GetAttr("config").IsWhollyKnown() && cfg.GetAttr("backend").IsKnown() {
		_, _, moreDiags := getBackend(cfg)
		diags = diags.Append(moreDiags)
	} else {
		// Otherwise we'll just type-check the config object itself.
		configTy := cfg.GetAttr("config").Type()
		if configTy != cty.DynamicPseudoType && !(configTy.IsObjectType() || configTy.IsMapType()) {
			diags = diags.Append(tfdiags.AttributeValue(
				tfdiags.Error,
				"Invalid backend configuration",
				"The configuration must be an object value.",
				cty.GetAttrPath("config"),
			))
		}
	}

	{
		defaultsTy := cfg.GetAttr("defaults").Type()
		if defaultsTy != cty.DynamicPseudoType && !(defaultsTy.IsObjectType() || defaultsTy.IsMapType()) {
			diags = diags.Append(tfdiags.AttributeValue(
				tfdiags.Error,
				"Invalid default values",
				"Defaults must be given in an object value.",
				cty.GetAttrPath("defaults"),
			))
		}
	}

	return diags
}

func dataSourceRemoteStateRead(d cty.Value) (cty.Value, tfdiags.Diagnostics) {
	var diags tfdiags.Diagnostics

	b, cfg, moreDiags := getBackend(d)
	diags = diags.Append(moreDiags)
	if moreDiags.HasErrors() {
		return cty.NilVal, diags
	}

	configureDiags := b.Configure(cfg)
	if configureDiags.HasErrors() {
		diags = diags.Append(configureDiags.Err())
		return cty.NilVal, diags
	}

	newState := make(map[string]cty.Value)
	newState["backend"] = d.GetAttr("backend")
	newState["config"] = d.GetAttr("config")

	workspaceVal := d.GetAttr("workspace")
	// This attribute is not computed, so we always have to store the state
	// value, even if we implicitly use a default.
	newState["workspace"] = workspaceVal

	workspaceName := backend.DefaultStateName
	if !workspaceVal.IsNull() {
		workspaceName = workspaceVal.AsString()
	}

	state, err := b.StateMgr(workspaceName)
	if err != nil {
		diags = diags.Append(tfdiags.AttributeValue(
			tfdiags.Error,
			"Error loading state error",
			fmt.Sprintf("error loading the remote state: %s", err),
			cty.Path(nil).GetAttr("backend"),
		))
		return cty.NilVal, diags
	}

	if err := state.RefreshState(); err != nil {
		diags = diags.Append(err)
		return cty.NilVal, diags
	}

	outputs := make(map[string]cty.Value)

	if defaultsVal := d.GetAttr("defaults"); !defaultsVal.IsNull() {
		newState["defaults"] = defaultsVal
		it := defaultsVal.ElementIterator()
		for it.Next() {
			k, v := it.Element()
			outputs[k.AsString()] = v
		}
	} else {
		newState["defaults"] = cty.NullVal(cty.DynamicPseudoType)
	}

	remoteState := state.State()
	if remoteState == nil {
		diags = diags.Append(tfdiags.AttributeValue(
			tfdiags.Error,
			"Unable to find remote state",
			"No stored state was found for the given workspace in the given backend.",
			cty.Path(nil).GetAttr("workspace"),
		))
		newState["outputs"] = cty.EmptyObjectVal
		return cty.ObjectVal(newState), diags
	}
	mod := remoteState.RootModule()
	if mod != nil { // should always have a root module in any valid state
		for k, os := range mod.OutputValues {
			outputs[k] = os.Value
		}
	}

	newState["outputs"] = cty.ObjectVal(outputs)

	return cty.ObjectVal(newState), diags
}

func getBackend(cfg cty.Value) (backend.Backend, cty.Value, tfdiags.Diagnostics) {
	var diags tfdiags.Diagnostics

	backendType := cfg.GetAttr("backend").AsString()

	// Don't break people using the old _local syntax - but note warning above
	if backendType == "_local" {
		log.Println(`[INFO] Switching old (unsupported) backend "_local" to "local"`)
		backendType = "local"
	}

	// Create the client to access our remote state
	log.Printf("[DEBUG] Initializing remote state backend: %s", backendType)
	f := getBackendFactory(backendType)
	if f == nil {
		detail := fmt.Sprintf("There is no backend type named %q.", backendType)
		if msg, removed := backendInit.RemovedBackends[backendType]; removed {
			detail = msg
		}

		diags = diags.Append(tfdiags.AttributeValue(
			tfdiags.Error,
			"Invalid backend configuration",
			detail,
			cty.Path(nil).GetAttr("backend"),
		))
		return nil, cty.NilVal, diags
	}
	b := f()

	config := cfg.GetAttr("config")
	if config.IsNull() {
		// We'll treat this as an empty configuration and see if the backend's
		// schema and validation code will accept it.
		config = cty.EmptyObjectVal
	}

	if config.Type().IsMapType() { // The code below expects an object type, so we'll convert
		config = cty.ObjectVal(config.AsValueMap())
	}

	schema := b.ConfigSchema()
	// Try to coerce the provided value into the desired configuration type.
	configVal, err := schema.CoerceValue(config)
	if err != nil {
		diags = diags.Append(tfdiags.AttributeValue(
			tfdiags.Error,
			"Invalid backend configuration",
			fmt.Sprintf("The given configuration is not valid for backend %q: %s.", backendType,
				tfdiags.FormatError(err)),
			cty.Path(nil).GetAttr("config"),
		))
		return nil, cty.NilVal, diags
	}

	newVal, validateDiags := b.PrepareConfig(configVal)
	diags = diags.Append(validateDiags)
	if validateDiags.HasErrors() {
		return nil, cty.NilVal, diags
	}

	// If this is the enhanced remote backend, we want to disable the version
	// check, because this is a read-only operation
	if rb, ok := b.(*remote.Remote); ok {
		rb.IgnoreVersionConflict()
	}

	return b, newVal, diags
}

// overrideBackendFactories allows test cases to control the set of available
// backends to allow for more self-contained tests. This should never be set
// in non-test code.
var overrideBackendFactories map[string]backend.InitFn

func getBackendFactory(backendType string) backend.InitFn {
	if len(overrideBackendFactories) > 0 {
		// Tests may override the set of backend factories.
		return overrideBackendFactories[backendType]
	}

	return backendInit.Backend(backendType)
}
