package moduletest

import (
	"fmt"
	"log"
	"sync"

	"github.com/zclconf/go-cty/cty"
	"github.com/zclconf/go-cty/cty/gocty"
	ctyjson "github.com/zclconf/go-cty/cty/json"

	"github.com/hashicorp/hcl/v2/hclsyntax"
	"github.com/hashicorp/terraform/internal/configs/configschema"
	"github.com/hashicorp/terraform/internal/providers"
	"github.com/hashicorp/terraform/internal/repl"
	"github.com/hashicorp/terraform/internal/tfdiags"
)

// Provider is an implementation of providers.Interface which we're
// using as a likely-only-temporary vehicle for research on an opinionated
// module testing workflow in Terraform.
//
// We expose this to configuration as "terraform.io/builtin/test", but
// any attempt to configure it will emit a warning that it is experimental
// and likely to change or be removed entirely in future Terraform CLI
// releases.
//
// The testing provider exists to gather up test results during a Terraform
// apply operation. Its "test_results" managed resource type doesn't have any
// user-visible effect on its own, but when used in conjunction with the
// "terraform test" experimental command it is the intermediary that holds
// the test results while the test runs, so that the test command can then
// report them.
//
// For correct behavior of the assertion tracking, the "terraform test"
// command must be sure to use the same instance of Provider for both the
// plan and apply steps, so that the assertions that were planned can still
// be tracked during apply. For other commands that don't explicitly support
// test assertions, the provider will still succeed but the assertions data
// may not be complete if the apply step fails.
type Provider struct {
	// components tracks all of the "component" names that have been
	// used in test assertions resources so far. Each resource must have
	// a unique component name.
	components map[string]*Component

	// Must lock mutex in order to interact with the components map, because
	// test assertions can potentially run concurrently.
	mutex sync.RWMutex
}

var _ providers.Interface = (*Provider)(nil)

// NewProvider returns a new instance of the test provider.
func NewProvider() *Provider {
	return &Provider{
		components: make(map[string]*Component),
	}
}

// TestResults returns the current record of test results tracked inside the
// provider.
//
// The result is a direct reference to the internal state of the provider,
// so the caller mustn't modify it nor store it across calls to provider
// operations.
func (p *Provider) TestResults() map[string]*Component {
	return p.components
}

// Reset returns the recieving provider back to its original state, with no
// recorded test results.
//
// It additionally detaches the instance from any data structure previously
// returned by method TestResults, freeing the caller from the constraints
// in its documentation about mutability and storage.
//
// For convenience in the presumed common case of resetting as part of
// capturing the results for storage, this method also returns the result
// that method TestResults would've returned if called prior to the call
// to Reset.
func (p *Provider) Reset() map[string]*Component {
	p.mutex.Lock()
	log.Print("[TRACE] moduletest.Provider: Reset")
	ret := p.components
	p.components = make(map[string]*Component)
	p.mutex.Unlock()
	return ret
}

// GetProviderSchema returns the complete schema for the provider.
func (p *Provider) GetProviderSchema() providers.GetProviderSchemaResponse {
	return providers.GetProviderSchemaResponse{
		ResourceTypes: map[string]providers.Schema{
			"test_assertions": testAssertionsSchema,
		},
	}
}

// ValidateProviderConfig validates the provider configuration.
func (p *Provider) ValidateProviderConfig(req providers.ValidateProviderConfigRequest) providers.ValidateProviderConfigResponse {
	// This provider has no configurable settings, so nothing to validate.
	var res providers.ValidateProviderConfigResponse
	return res
}

// ConfigureProvider configures and initializes the provider.
func (p *Provider) ConfigureProvider(providers.ConfigureProviderRequest) providers.ConfigureProviderResponse {
	// This provider has no configurable settings, but we use the configure
	// request as an opportunity to generate a warning about it being
	// experimental.
	var res providers.ConfigureProviderResponse
	res.Diagnostics = res.Diagnostics.Append(tfdiags.AttributeValue(
		tfdiags.Warning,
		"The test provider is experimental",
		"The Terraform team is using the test provider (terraform.io/builtin/test) as part of ongoing research about declarative testing of Terraform modules.\n\nThe availability and behavior of this provider is expected to change significantly even in patch releases, so we recommend using this provider only in test configurations and constraining your test configurations to an exact Terraform version.",
		nil,
	))
	return res
}

// ValidateResourceConfig is used to validate configuration values for a resource.
func (p *Provider) ValidateResourceConfig(req providers.ValidateResourceConfigRequest) providers.ValidateResourceConfigResponse {
	log.Print("[TRACE] moduletest.Provider: ValidateResourceConfig")

	var res providers.ValidateResourceConfigResponse
	if req.TypeName != "test_assertions" { // we only have one resource type
		res.Diagnostics = res.Diagnostics.Append(fmt.Errorf("unsupported resource type %s", req.TypeName))
		return res
	}

	config := req.Config
	if !config.GetAttr("component").IsKnown() {
		res.Diagnostics = res.Diagnostics.Append(tfdiags.AttributeValue(
			tfdiags.Error,
			"Invalid component expression",
			"The component name must be a static value given in the configuration, and may not be derived from a resource type attribute that will only be known during the apply step.",
			cty.GetAttrPath("component"),
		))
	}
	if !hclsyntax.ValidIdentifier(config.GetAttr("component").AsString()) {
		res.Diagnostics = res.Diagnostics.Append(tfdiags.AttributeValue(
			tfdiags.Error,
			"Invalid component name",
			"The component name must be a valid identifier, starting with a letter followed by zero or more letters, digits, and underscores.",
			cty.GetAttrPath("component"),
		))
	}
	for it := config.GetAttr("equal").ElementIterator(); it.Next(); {
		k, obj := it.Element()
		if !hclsyntax.ValidIdentifier(k.AsString()) {
			res.Diagnostics = res.Diagnostics.Append(tfdiags.AttributeValue(
				tfdiags.Error,
				"Invalid assertion name",
				"An assertion name must be a valid identifier, starting with a letter followed by zero or more letters, digits, and underscores.",
				cty.GetAttrPath("equal").Index(k),
			))
		}
		if !obj.GetAttr("description").IsKnown() {
			res.Diagnostics = res.Diagnostics.Append(tfdiags.AttributeValue(
				tfdiags.Error,
				"Invalid description expression",
				"The description must be a static value given in the configuration, and may not be derived from a resource type attribute that will only be known during the apply step.",
				cty.GetAttrPath("equal").Index(k).GetAttr("description"),
			))
		}
	}
	for it := config.GetAttr("check").ElementIterator(); it.Next(); {
		k, obj := it.Element()
		if !hclsyntax.ValidIdentifier(k.AsString()) {
			res.Diagnostics = res.Diagnostics.Append(tfdiags.AttributeValue(
				tfdiags.Error,
				"Invalid assertion name",
				"An assertion name must be a valid identifier, starting with a letter followed by zero or more letters, digits, and underscores.",
				cty.GetAttrPath("check").Index(k),
			))
		}
		if !obj.GetAttr("description").IsKnown() {
			res.Diagnostics = res.Diagnostics.Append(tfdiags.AttributeValue(
				tfdiags.Error,
				"Invalid description expression",
				"The description must be a static value given in the configuration, and may not be derived from a resource type attribute that will only be known during the apply step.",
				cty.GetAttrPath("equal").Index(k).GetAttr("description"),
			))
		}
	}

	return res
}

// ReadResource refreshes a resource and returns its current state.
func (p *Provider) ReadResource(req providers.ReadResourceRequest) providers.ReadResourceResponse {
	log.Print("[TRACE] moduletest.Provider: ReadResource")

	var res providers.ReadResourceResponse
	if req.TypeName != "test_assertions" { // we only have one resource type
		res.Diagnostics = res.Diagnostics.Append(fmt.Errorf("unsupported resource type %s", req.TypeName))
		return res
	}
	// Test assertions are not a real remote object, so there isn't actually
	// anything to refresh here.
	res.NewState = req.PriorState
	return res
}

// UpgradeResourceState is called to allow the provider to adapt the raw value
// stored in the state in case the schema has changed since it was originally
// written.
func (p *Provider) UpgradeResourceState(req providers.UpgradeResourceStateRequest) providers.UpgradeResourceStateResponse {
	log.Print("[TRACE] moduletest.Provider: UpgradeResourceState")

	var res providers.UpgradeResourceStateResponse
	if req.TypeName != "test_assertions" { // we only have one resource type
		res.Diagnostics = res.Diagnostics.Append(fmt.Errorf("unsupported resource type %s", req.TypeName))
		return res
	}

	// We assume here that there can never be a flatmap version of this
	// resource type's data, because this provider was never included in a
	// version of Terraform that used flatmap and this provider's schema
	// contains attributes that are not flatmap-compatible anyway.
	if len(req.RawStateFlatmap) != 0 {
		res.Diagnostics = res.Diagnostics.Append(fmt.Errorf("can't upgrade a flatmap state for %q", req.TypeName))
		return res
	}
	if req.Version != 0 {
		res.Diagnostics = res.Diagnostics.Append(fmt.Errorf("the state for this %s was created by a newer version of the provider", req.TypeName))
		return res
	}

	v, err := ctyjson.Unmarshal(req.RawStateJSON, testAssertionsSchema.Block.ImpliedType())
	if err != nil {
		res.Diagnostics = res.Diagnostics.Append(fmt.Errorf("failed to decode state for %s: %s", req.TypeName, err))
		return res
	}

	res.UpgradedState = v
	return res
}

// PlanResourceChange takes the current state and proposed state of a
// resource, and returns the planned final state.
func (p *Provider) PlanResourceChange(req providers.PlanResourceChangeRequest) providers.PlanResourceChangeResponse {
	log.Print("[TRACE] moduletest.Provider: PlanResourceChange")

	var res providers.PlanResourceChangeResponse
	if req.TypeName != "test_assertions" { // we only have one resource type
		res.Diagnostics = res.Diagnostics.Append(fmt.Errorf("unsupported resource type %s", req.TypeName))
		return res
	}

	// During planning, our job is to gather up all of the planned test
	// assertions marked as pending, which will then allow us to include
	// all of them in test results even if there's a failure during apply
	// that prevents the full completion of the graph walk.
	//
	// In a sense our plan phase is similar to the compile step for a
	// test program written in another language. Planning itself can fail,
	// which means we won't be able to form a complete test plan at all,
	// but if we succeed in planning then subsequent problems can be treated
	// as test failures at "runtime", while still keeping a full manifest
	// of all of the tests that ought to have run if the apply had run to
	// completion.

	proposed := req.ProposedNewState
	res.PlannedState = proposed
	componentName := proposed.GetAttr("component").AsString() // proven known during validate
	p.mutex.Lock()
	defer p.mutex.Unlock()
	// NOTE: Ideally we'd do something here to verify if two assertions
	// resources in the configuration attempt to declare the same component,
	// but we can't actually do that because Terraform calls PlanResourceChange
	// during both plan and apply, and so the second one would always fail.
	// Since this is just providing a temporary pseudo-syntax for writing tests
	// anyway, we'll live with this for now and aim to solve it with a future
	// iteration of testing that's better integrated into the Terraform
	// language.
	/*
		if _, exists := p.components[componentName]; exists {
			res.Diagnostics = res.Diagnostics.Append(tfdiags.AttributeValue(
				tfdiags.Error,
				"Duplicate test component",
				fmt.Sprintf("Another test_assertions resource already declared assertions for the component name %q.", componentName),
				cty.GetAttrPath("component"),
			))
			return res
		}
	*/

	component := Component{
		Assertions: make(map[string]*Assertion),
	}

	for it := proposed.GetAttr("equal").ElementIterator(); it.Next(); {
		k, obj := it.Element()
		name := k.AsString()
		if _, exists := component.Assertions[name]; exists {
			// We can't actually get here in practice because so far we've
			// only been pulling keys from one map, and so any duplicates
			// would've been caught during config decoding, but this is here
			// just to make these two blocks symmetrical to avoid mishaps in
			// future refactoring/reorganization.
			res.Diagnostics = res.Diagnostics.Append(tfdiags.AttributeValue(
				tfdiags.Error,
				"Duplicate test assertion",
				fmt.Sprintf("Another assertion block in this resource already declared an assertion named %q.", name),
				cty.GetAttrPath("equal").Index(k),
			))
			continue
		}

		var desc string
		descVal := obj.GetAttr("description")
		if descVal.IsNull() {
			descVal = cty.StringVal("")
		}
		err := gocty.FromCtyValue(descVal, &desc)
		if err != nil {
			// We shouldn't get here because we've already validated everything
			// that would make FromCtyValue fail above and during validate.
			res.Diagnostics = res.Diagnostics.Append(err)
		}

		component.Assertions[name] = &Assertion{
			Outcome:     Pending,
			Description: desc,
		}
	}

	for it := proposed.GetAttr("check").ElementIterator(); it.Next(); {
		k, obj := it.Element()
		name := k.AsString()
		if _, exists := component.Assertions[name]; exists {
			res.Diagnostics = res.Diagnostics.Append(tfdiags.AttributeValue(
				tfdiags.Error,
				"Duplicate test assertion",
				fmt.Sprintf("Another assertion block in this resource already declared an assertion named %q.", name),
				cty.GetAttrPath("check").Index(k),
			))
			continue
		}

		var desc string
		descVal := obj.GetAttr("description")
		if descVal.IsNull() {
			descVal = cty.StringVal("")
		}
		err := gocty.FromCtyValue(descVal, &desc)
		if err != nil {
			// We shouldn't get here because we've already validated everything
			// that would make FromCtyValue fail above and during validate.
			res.Diagnostics = res.Diagnostics.Append(err)
		}

		component.Assertions[name] = &Assertion{
			Outcome:     Pending,
			Description: desc,
		}
	}

	p.components[componentName] = &component
	return res
}

// ApplyResourceChange takes the planned state for a resource, which may
// yet contain unknown computed values, and applies the changes returning
// the final state.
func (p *Provider) ApplyResourceChange(req providers.ApplyResourceChangeRequest) providers.ApplyResourceChangeResponse {
	log.Print("[TRACE] moduletest.Provider: ApplyResourceChange")

	var res providers.ApplyResourceChangeResponse
	if req.TypeName != "test_assertions" { // we only have one resource type
		res.Diagnostics = res.Diagnostics.Append(fmt.Errorf("unsupported resource type %s", req.TypeName))
		return res
	}

	// During apply we actually check the assertions and record the results.
	// An assertion failure isn't reflected as an error from the apply call
	// because if possible we'd like to continue exercising other objects
	// downstream in case that allows us to gather more information to report.
	// (If something downstream returns an error then that could prevent us
	// from completing other assertions, though.)

	planned := req.PlannedState
	res.NewState = planned
	if res.NewState.IsNull() {
		// If we're destroying then we'll just quickly return success to
		// allow the test process to clean up after itself.
		return res
	}
	componentName := planned.GetAttr("component").AsString() // proven known during validate

	p.mutex.Lock()
	defer p.mutex.Unlock()
	component := p.components[componentName]
	if component == nil {
		// We might get here when using this provider outside of the
		// "terraform test" command, where there won't be any mechanism to
		// preserve the test provider instance between the plan and apply
		// phases. In that case, we assume that nobody will come looking to
		// collect the results anyway, and so we can just silently skip
		// checking.
		return res
	}

	for it := planned.GetAttr("equal").ElementIterator(); it.Next(); {
		k, obj := it.Element()
		name := k.AsString()
		var desc string
		if plan, exists := component.Assertions[name]; exists {
			desc = plan.Description
		}
		assert := &Assertion{
			Outcome:     Pending,
			Description: desc,
		}

		gotVal := obj.GetAttr("got")
		wantVal := obj.GetAttr("want")
		switch {
		case wantVal.RawEquals(gotVal):
			assert.Outcome = Passed
			gotStr := repl.FormatValue(gotVal, 4)
			assert.Message = fmt.Sprintf("correct value\n    got: %s\n", gotStr)
		default:
			assert.Outcome = Failed
			gotStr := repl.FormatValue(gotVal, 4)
			wantStr := repl.FormatValue(wantVal, 4)
			assert.Message = fmt.Sprintf("wrong value\n    got:  %s\n    want: %s\n", gotStr, wantStr)
		}

		component.Assertions[name] = assert
	}

	for it := planned.GetAttr("check").ElementIterator(); it.Next(); {
		k, obj := it.Element()
		name := k.AsString()
		var desc string
		if plan, exists := component.Assertions[name]; exists {
			desc = plan.Description
		}
		assert := &Assertion{
			Outcome:     Pending,
			Description: desc,
		}

		condVal := obj.GetAttr("condition")
		switch {
		case condVal.IsNull():
			res.Diagnostics = res.Diagnostics.Append(tfdiags.AttributeValue(
				tfdiags.Error,
				"Invalid check condition",
				"The condition value must be a boolean expression, not null.",
				cty.GetAttrPath("check").Index(k).GetAttr("condition"),
			))
			continue
		case condVal.True():
			assert.Outcome = Passed
			assert.Message = "condition passed"
		default:
			assert.Outcome = Failed
			// For "check" we can't really return a decent error message
			// because we've lost all of the context by the time we get here.
			// "equal" will be better for most tests for that reason, and also
			// this is one reason why in the long run it would be better for
			// test assertions to be a first-class language feature rather than
			// just a provider-based concept.
			assert.Message = "condition failed"
		}

		component.Assertions[name] = assert
	}

	return res
}

// ImportResourceState requests that the given resource be imported.
func (p *Provider) ImportResourceState(req providers.ImportResourceStateRequest) providers.ImportResourceStateResponse {
	var res providers.ImportResourceStateResponse
	res.Diagnostics = res.Diagnostics.Append(fmt.Errorf("%s is not importable", req.TypeName))
	return res
}

// ValidateDataResourceConfig is used to to validate the resource configuration values.
func (p *Provider) ValidateDataResourceConfig(req providers.ValidateDataResourceConfigRequest) providers.ValidateDataResourceConfigResponse {
	// This provider has no data resouce types at all.
	var res providers.ValidateDataResourceConfigResponse
	res.Diagnostics = res.Diagnostics.Append(fmt.Errorf("unsupported data source %s", req.TypeName))
	return res
}

// ReadDataSource returns the data source's current state.
func (p *Provider) ReadDataSource(req providers.ReadDataSourceRequest) providers.ReadDataSourceResponse {
	// This provider has no data resouce types at all.
	var res providers.ReadDataSourceResponse
	res.Diagnostics = res.Diagnostics.Append(fmt.Errorf("unsupported data source %s", req.TypeName))
	return res
}

// Stop is called when the provider should halt any in-flight actions.
func (p *Provider) Stop() error {
	// This provider doesn't do anything that can be cancelled.
	return nil
}

// Close is a noop for this provider, since it's run in-process.
func (p *Provider) Close() error {
	return nil
}

var testAssertionsSchema = providers.Schema{
	Block: &configschema.Block{
		Attributes: map[string]*configschema.Attribute{
			"component": {
				Type:            cty.String,
				Description:     "The name of the component being tested. This is just for namespacing assertions in a result report.",
				DescriptionKind: configschema.StringPlain,
				Required:        true,
			},
		},
		BlockTypes: map[string]*configschema.NestedBlock{
			"equal": {
				Nesting: configschema.NestingMap,
				Block: configschema.Block{
					Attributes: map[string]*configschema.Attribute{
						"description": {
							Type:            cty.String,
							Description:     "An optional human-readable description of what's being tested by this assertion.",
							DescriptionKind: configschema.StringPlain,
							Required:        true,
						},
						"got": {
							Type:            cty.DynamicPseudoType,
							Description:     "The actual result value generated by the relevant component.",
							DescriptionKind: configschema.StringPlain,
							Required:        true,
						},
						"want": {
							Type:            cty.DynamicPseudoType,
							Description:     "The value that the component is expected to have generated.",
							DescriptionKind: configschema.StringPlain,
							Required:        true,
						},
					},
				},
			},
			"check": {
				Nesting: configschema.NestingMap,
				Block: configschema.Block{
					Attributes: map[string]*configschema.Attribute{
						"description": {
							Type:            cty.String,
							Description:     "An optional (but strongly recommended) human-readable description of what's being tested by this assertion.",
							DescriptionKind: configschema.StringPlain,
							Required:        true,
						},
						"condition": {
							Type:            cty.Bool,
							Description:     "An expression that must be true in order for the test to pass.",
							DescriptionKind: configschema.StringPlain,
							Required:        true,
						},
					},
				},
			},
		},
	},
}
