// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

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) (resp providers.PlanResourceChangeResponse) {
	log.Print("[TRACE] moduletest.Provider: PlanResourceChange")

	// this is a destroy plan,
	if req.ProposedNewState.IsNull() {
		resp.PlannedState = req.ProposedNewState
		resp.PlannedPrivate = req.PriorPrivate
		return resp
	}

	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,
						},
					},
				},
			},
		},
	},
}
