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

package terraform

import (
	"log"

	"github.com/hashicorp/hcl/v2/hclsyntax"

	"github.com/hashicorp/terraform/internal/addrs"
	"github.com/hashicorp/terraform/internal/checks"
	"github.com/hashicorp/terraform/internal/configs"
	"github.com/hashicorp/terraform/internal/dag"
	"github.com/hashicorp/terraform/internal/lang"
	"github.com/hashicorp/terraform/internal/tfdiags"
)

var (
	_ GraphNodeModulePath = (*nodeReportCheck)(nil)
	_ GraphNodeExecutable = (*nodeReportCheck)(nil)
)

// nodeReportCheck calls the ReportCheckableObjects function for our assertions
// within the check blocks.
//
// We need this to happen before the checks are actually verified and before any
// nested data blocks, so the creator of this structure should make sure this
// node is a parent of any nested data blocks.
//
// This needs to be separate to nodeExpandCheck, because the actual checks
// should happen after referenced data blocks rather than before.
type nodeReportCheck struct {
	addr addrs.ConfigCheck
}

func (n *nodeReportCheck) ModulePath() addrs.Module {
	return n.addr.Module
}

func (n *nodeReportCheck) Execute(ctx EvalContext, _ walkOperation) tfdiags.Diagnostics {
	exp := ctx.InstanceExpander()
	modInsts := exp.ExpandModule(n.ModulePath())

	instAddrs := addrs.MakeSet[addrs.Checkable]()
	for _, modAddr := range modInsts {
		instAddrs.Add(n.addr.Check.Absolute(modAddr))
	}
	ctx.Checks().ReportCheckableObjects(n.addr, instAddrs)
	return nil
}

func (n *nodeReportCheck) Name() string {
	return n.addr.String() + " (report)"
}

var (
	_ GraphNodeModulePath        = (*nodeExpandCheck)(nil)
	_ GraphNodeDynamicExpandable = (*nodeExpandCheck)(nil)
	_ GraphNodeReferencer        = (*nodeExpandCheck)(nil)
)

// nodeExpandCheck creates child nodes that actually execute the assertions for
// a given check block.
//
// This must happen after any other nodes/resources/data sources that are
// referenced, so we implement GraphNodeReferencer.
//
// This needs to be separate to nodeReportCheck as nodeReportCheck must happen
// first, while nodeExpandCheck must execute after any referenced blocks.
type nodeExpandCheck struct {
	addr   addrs.ConfigCheck
	config *configs.Check

	makeInstance func(addrs.AbsCheck, *configs.Check) dag.Vertex
}

func (n *nodeExpandCheck) ModulePath() addrs.Module {
	return n.addr.Module
}

func (n *nodeExpandCheck) DynamicExpand(ctx EvalContext) (*Graph, error) {
	exp := ctx.InstanceExpander()
	modInsts := exp.ExpandModule(n.ModulePath())

	var g Graph
	for _, modAddr := range modInsts {
		testAddr := n.addr.Check.Absolute(modAddr)
		log.Printf("[TRACE] nodeExpandCheck: Node for %s", testAddr)
		g.Add(n.makeInstance(testAddr, n.config))
	}
	addRootNodeToGraph(&g)

	return &g, nil
}

func (n *nodeExpandCheck) References() []*addrs.Reference {
	var refs []*addrs.Reference
	for _, assert := range n.config.Asserts {
		// Check blocks reference anything referenced by conditions or messages
		// in their check rules.
		condition, _ := lang.ReferencesInExpr(assert.Condition)
		message, _ := lang.ReferencesInExpr(assert.ErrorMessage)
		refs = append(refs, condition...)
		refs = append(refs, message...)
	}
	if n.config.DataResource != nil {
		// We'll also always reference our nested data block if it exists, as
		// there is nothing enforcing that it has to also be referenced by our
		// conditions or messages.
		//
		// We don't need to make this addr absolute, because the check block and
		// the data resource are always within the same module/instance.
		traversal, _ := hclsyntax.ParseTraversalAbs(
			[]byte(n.config.DataResource.Addr().String()),
			n.config.DataResource.DeclRange.Filename,
			n.config.DataResource.DeclRange.Start)
		ref, _ := addrs.ParseRef(traversal)
		refs = append(refs, ref)
	}
	return refs
}

func (n *nodeExpandCheck) Name() string {
	return n.addr.String() + " (expand)"
}

var (
	_ GraphNodeModuleInstance = (*nodeCheckAssert)(nil)
	_ GraphNodeExecutable     = (*nodeCheckAssert)(nil)
)

type nodeCheckAssert struct {
	addr   addrs.AbsCheck
	config *configs.Check

	// We only want to actually execute the checks during the plan and apply
	// operations, but we still want to validate our config during
	// other operations.
	executeChecks bool
}

func (n *nodeCheckAssert) ModulePath() addrs.Module {
	return n.Path().Module()
}

func (n *nodeCheckAssert) Path() addrs.ModuleInstance {
	return n.addr.Module
}

func (n *nodeCheckAssert) Execute(ctx EvalContext, _ walkOperation) tfdiags.Diagnostics {

	// We only want to actually execute the checks during specific
	// operations, such as plan and applies.
	if n.executeChecks {
		if status := ctx.Checks().ObjectCheckStatus(n.addr); status == checks.StatusFail || status == checks.StatusError {
			// This check is already failing, so we won't try and evaluate it.
			// This typically means there was an error in a data block within
			// the check block.
			return nil
		}

		return evalCheckRules(
			addrs.CheckAssertion,
			n.config.Asserts,
			ctx,
			n.addr,
			EvalDataForNoInstanceKey,
			tfdiags.Warning)

	}

	// Otherwise let's still validate the config and references and return
	// diagnostics if references do not exist etc.
	var diags tfdiags.Diagnostics
	for _, assert := range n.config.Asserts {
		_, _, moreDiags := validateCheckRule(addrs.CheckAssertion, assert, ctx, n.addr, EvalDataForNoInstanceKey)
		diags = diags.Append(moreDiags)
	}
	return diags
}

func (n *nodeCheckAssert) Name() string {
	return n.addr.String() + " (assertions)"
}

var (
	_ GraphNodeExecutable = (*nodeCheckStart)(nil)
)

// We need to ensure that any nested data sources execute after all other
// resource changes have been applied. This node acts as a single point of
// dependency that can enforce this ordering.
type nodeCheckStart struct{}

func (n *nodeCheckStart) Execute(context EvalContext, operation walkOperation) tfdiags.Diagnostics {
	// This node doesn't actually do anything, except simplify the underlying
	// graph structure.
	return nil
}

func (n *nodeCheckStart) Name() string {
	return "(execute checks)"
}
