package tfdiags

import (
	"github.com/hashicorp/hcl/v2"
	"github.com/zclconf/go-cty/cty"
	"github.com/zclconf/go-cty/cty/gocty"
)

// The "contextual" family of diagnostics are designed to allow separating
// the detection of a problem from placing that problem in context. For
// example, some code that is validating an object extracted from configuration
// may not have access to the configuration that generated it, but can still
// report problems within that object which the caller can then place in
// context by calling IsConfigBody on the returned diagnostics.
//
// When contextual diagnostics are used, the documentation for a method must
// be very explicit about what context is implied for any diagnostics returned,
// to help ensure the expected result.

// contextualFromConfig is an interface type implemented by diagnostic types
// that can elaborate themselves when given information about the configuration
// body they are embedded in, as well as the runtime address associated with
// that configuration.
//
// Usually this entails extracting source location information in order to
// populate the "Subject" range.
type contextualFromConfigBody interface {
	ElaborateFromConfigBody(hcl.Body, string) Diagnostic
}

// InConfigBody returns a copy of the receiver with any config-contextual
// diagnostics elaborated in the context of the given body. An optional address
// argument may be added to indicate which instance of the configuration the
// error related to.
func (diags Diagnostics) InConfigBody(body hcl.Body, addr string) Diagnostics {
	if len(diags) == 0 {
		return nil
	}

	ret := make(Diagnostics, len(diags))
	for i, srcDiag := range diags {
		if cd, isCD := srcDiag.(contextualFromConfigBody); isCD {
			ret[i] = cd.ElaborateFromConfigBody(body, addr)
		} else {
			ret[i] = srcDiag
		}
	}

	return ret
}

// AttributeValue returns a diagnostic about an attribute value in an implied current
// configuration context. This should be returned only from functions whose
// interface specifies a clear configuration context that this will be
// resolved in.
//
// The given path is relative to the implied configuration context. To describe
// a top-level attribute, it should be a single-element cty.Path with a
// cty.GetAttrStep. It's assumed that the path is returning into a structure
// that would be produced by our conventions in the configschema package; it
// may return unexpected results for structures that can't be represented by
// configschema.
//
// Since mapping attribute paths back onto configuration is an imprecise
// operation (e.g. dynamic block generation may cause the same block to be
// evaluated multiple times) the diagnostic detail should include the attribute
// name and other context required to help the user understand what is being
// referenced in case the identified source range is not unique.
//
// The returned attribute will not have source location information until
// context is applied to the containing diagnostics using diags.InConfigBody.
// After context is applied, the source location is the value assigned to the
// named attribute, or the containing body's "missing item range" if no
// value is present.
func AttributeValue(severity Severity, summary, detail string, attrPath cty.Path) Diagnostic {
	return &attributeDiagnostic{
		diagnosticBase: diagnosticBase{
			severity: severity,
			summary:  summary,
			detail:   detail,
		},
		attrPath: attrPath,
	}
}

// GetAttribute extracts an attribute cty.Path from a diagnostic if it contains
// one. Normally this is not accessed directly, and instead the config body is
// added to the Diagnostic to create a more complete message for the user. In
// some cases however, we may want to know just the name of the attribute that
// generated the Diagnostic message.
// This returns a nil cty.Path if it does not exist in the Diagnostic.
func GetAttribute(d Diagnostic) cty.Path {
	if d, ok := d.(*attributeDiagnostic); ok {
		return d.attrPath
	}
	return nil
}

type attributeDiagnostic struct {
	diagnosticBase
	attrPath cty.Path
	subject  *SourceRange // populated only after ElaborateFromConfigBody
}

// ElaborateFromConfigBody finds the most accurate possible source location
// for a diagnostic's attribute path within the given body.
//
// Backing out from a path back to a source location is not always entirely
// possible because we lose some information in the decoding process, so
// if an exact position cannot be found then the returned diagnostic will
// refer to a position somewhere within the containing body, which is assumed
// to be better than no location at all.
//
// If possible it is generally better to report an error at a layer where
// source location information is still available, for more accuracy. This
// is not always possible due to system architecture, so this serves as a
// "best effort" fallback behavior for such situations.
func (d *attributeDiagnostic) ElaborateFromConfigBody(body hcl.Body, addr string) Diagnostic {
	// don't change an existing address
	if d.address == "" {
		d.address = addr
	}

	if len(d.attrPath) < 1 {
		// Should never happen, but we'll allow it rather than crashing.
		return d
	}

	if d.subject != nil {
		// Don't modify an already-elaborated diagnostic.
		return d
	}

	ret := *d

	// This function will often end up re-decoding values that were already
	// decoded by an earlier step. This is non-ideal but is architecturally
	// more convenient than arranging for source location information to be
	// propagated to every place in Terraform, and this happens only in the
	// presence of errors where performance isn't a concern.

	traverse := d.attrPath[:]
	final := d.attrPath[len(d.attrPath)-1]

	// Index should never be the first step
	// as indexing of top blocks (such as resources & data sources)
	// is handled elsewhere
	if _, isIdxStep := traverse[0].(cty.IndexStep); isIdxStep {
		subject := SourceRangeFromHCL(body.MissingItemRange())
		ret.subject = &subject
		return &ret
	}

	// Process index separately
	idxStep, hasIdx := final.(cty.IndexStep)
	if hasIdx {
		final = d.attrPath[len(d.attrPath)-2]
		traverse = d.attrPath[:len(d.attrPath)-1]
	}

	// If we have more than one step after removing index
	// then we'll first try to traverse to a child body
	// corresponding to the requested path.
	if len(traverse) > 1 {
		body = traversePathSteps(traverse, body)
	}

	// Default is to indicate a missing item in the deepest body we reached
	// while traversing.
	subject := SourceRangeFromHCL(body.MissingItemRange())
	ret.subject = &subject

	// Once we get here, "final" should be a GetAttr step that maps to an
	// attribute in our current body.
	finalStep, isAttr := final.(cty.GetAttrStep)
	if !isAttr {
		return &ret
	}

	content, _, contentDiags := body.PartialContent(&hcl.BodySchema{
		Attributes: []hcl.AttributeSchema{
			{
				Name:     finalStep.Name,
				Required: true,
			},
		},
	})
	if contentDiags.HasErrors() {
		return &ret
	}

	if attr, ok := content.Attributes[finalStep.Name]; ok {
		hclRange := attr.Expr.Range()
		if hasIdx {
			// Try to be more precise by finding index range
			hclRange = hclRangeFromIndexStepAndAttribute(idxStep, attr)
		}
		subject = SourceRangeFromHCL(hclRange)
		ret.subject = &subject
	}

	return &ret
}

func traversePathSteps(traverse []cty.PathStep, body hcl.Body) hcl.Body {
	for i := 0; i < len(traverse); i++ {
		step := traverse[i]

		switch tStep := step.(type) {
		case cty.GetAttrStep:

			var next cty.PathStep
			if i < (len(traverse) - 1) {
				next = traverse[i+1]
			}

			// Will be indexing into our result here?
			var indexType cty.Type
			var indexVal cty.Value
			if nextIndex, ok := next.(cty.IndexStep); ok {
				indexVal = nextIndex.Key
				indexType = indexVal.Type()
				i++ // skip over the index on subsequent iterations
			}

			var blockLabelNames []string
			if indexType == cty.String {
				// Map traversal means we expect one label for the key.
				blockLabelNames = []string{"key"}
			}

			// For intermediate steps we expect to be referring to a child
			// block, so we'll attempt decoding under that assumption.
			content, _, contentDiags := body.PartialContent(&hcl.BodySchema{
				Blocks: []hcl.BlockHeaderSchema{
					{
						Type:       tStep.Name,
						LabelNames: blockLabelNames,
					},
				},
			})
			if contentDiags.HasErrors() {
				return body
			}
			filtered := make([]*hcl.Block, 0, len(content.Blocks))
			for _, block := range content.Blocks {
				if block.Type == tStep.Name {
					filtered = append(filtered, block)
				}
			}
			if len(filtered) == 0 {
				// Step doesn't refer to a block
				continue
			}

			switch indexType {
			case cty.NilType: // no index at all
				if len(filtered) != 1 {
					return body
				}
				body = filtered[0].Body
			case cty.Number:
				var idx int
				err := gocty.FromCtyValue(indexVal, &idx)
				if err != nil || idx >= len(filtered) {
					return body
				}
				body = filtered[idx].Body
			case cty.String:
				key := indexVal.AsString()
				var block *hcl.Block
				for _, candidate := range filtered {
					if candidate.Labels[0] == key {
						block = candidate
						break
					}
				}
				if block == nil {
					// No block with this key, so we'll just indicate a
					// missing item in the containing block.
					return body
				}
				body = block.Body
			default:
				// Should never happen, because only string and numeric indices
				// are supported by cty collections.
				return body
			}

		default:
			// For any other kind of step, we'll just return our current body
			// as the subject and accept that this is a little inaccurate.
			return body
		}
	}
	return body
}

func hclRangeFromIndexStepAndAttribute(idxStep cty.IndexStep, attr *hcl.Attribute) hcl.Range {
	switch idxStep.Key.Type() {
	case cty.Number:
		var idx int
		err := gocty.FromCtyValue(idxStep.Key, &idx)
		items, diags := hcl.ExprList(attr.Expr)
		if diags.HasErrors() {
			return attr.Expr.Range()
		}
		if err != nil || idx >= len(items) {
			return attr.NameRange
		}
		return items[idx].Range()
	case cty.String:
		pairs, diags := hcl.ExprMap(attr.Expr)
		if diags.HasErrors() {
			return attr.Expr.Range()
		}
		stepKey := idxStep.Key.AsString()
		for _, kvPair := range pairs {
			key, diags := kvPair.Key.Value(nil)
			if diags.HasErrors() {
				return attr.Expr.Range()
			}
			if key.AsString() == stepKey {
				startRng := kvPair.Value.StartRange()
				return startRng
			}
		}
		return attr.NameRange
	}
	return attr.Expr.Range()
}

func (d *attributeDiagnostic) Source() Source {
	return Source{
		Subject: d.subject,
	}
}

// WholeContainingBody returns a diagnostic about the body that is an implied
// current configuration context. This should be returned only from
// functions whose interface specifies a clear configuration context that this
// will be resolved in.
//
// The returned attribute will not have source location information until
// context is applied to the containing diagnostics using diags.InConfigBody.
// After context is applied, the source location is currently the missing item
// range of the body. In future, this may change to some other suitable
// part of the containing body.
func WholeContainingBody(severity Severity, summary, detail string) Diagnostic {
	return &wholeBodyDiagnostic{
		diagnosticBase: diagnosticBase{
			severity: severity,
			summary:  summary,
			detail:   detail,
		},
	}
}

type wholeBodyDiagnostic struct {
	diagnosticBase
	subject *SourceRange // populated only after ElaborateFromConfigBody
}

func (d *wholeBodyDiagnostic) ElaborateFromConfigBody(body hcl.Body, addr string) Diagnostic {
	// don't change an existing address
	if d.address == "" {
		d.address = addr
	}

	if d.subject != nil {
		// Don't modify an already-elaborated diagnostic.
		return d
	}

	ret := *d
	rng := SourceRangeFromHCL(body.MissingItemRange())
	ret.subject = &rng
	return &ret
}

func (d *wholeBodyDiagnostic) Source() Source {
	return Source{
		Subject: d.subject,
	}
}
