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

package addrs

import (
	"fmt"

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

	"github.com/hashicorp/terraform/internal/tfdiags"
)

// OutputValue is the address of an output value, in the context of the module
// that is defining it.
//
// This is related to but separate from ModuleCallOutput, which represents
// a module output from the perspective of its parent module. Since output
// values cannot be represented from the module where they are defined,
// OutputValue is not Referenceable, while ModuleCallOutput is.
type OutputValue struct {
	Name string
}

func (v OutputValue) String() string {
	return "output." + v.Name
}

// Absolute converts the receiver into an absolute address within the given
// module instance.
func (v OutputValue) Absolute(m ModuleInstance) AbsOutputValue {
	return AbsOutputValue{
		Module:      m,
		OutputValue: v,
	}
}

// InModule converts the receiver into a config address within the given
// module.
func (v OutputValue) InModule(m Module) ConfigOutputValue {
	return ConfigOutputValue{
		Module:      m,
		OutputValue: v,
	}
}

// AbsOutputValue is the absolute address of an output value within a module instance.
//
// This represents an output globally within the namespace of a particular
// configuration. It is related to but separate from ModuleCallOutput, which
// represents a module output from the perspective of its parent module.
type AbsOutputValue struct {
	Module      ModuleInstance
	OutputValue OutputValue
}

// OutputValue returns the absolute address of an output value of the given
// name within the receiving module instance.
func (m ModuleInstance) OutputValue(name string) AbsOutputValue {
	return AbsOutputValue{
		Module: m,
		OutputValue: OutputValue{
			Name: name,
		},
	}
}

func (v AbsOutputValue) CheckRule(t CheckRuleType, i int) CheckRule {
	return CheckRule{
		Container: v,
		Type:      t,
		Index:     i,
	}
}

func (v AbsOutputValue) String() string {
	if v.Module.IsRoot() {
		return v.OutputValue.String()
	}
	return fmt.Sprintf("%s.%s", v.Module.String(), v.OutputValue.String())
}

func (v AbsOutputValue) Equal(o AbsOutputValue) bool {
	return v.OutputValue == o.OutputValue && v.Module.Equal(o.Module)
}

func (v AbsOutputValue) ConfigOutputValue() ConfigOutputValue {
	return ConfigOutputValue{
		Module:      v.Module.Module(),
		OutputValue: v.OutputValue,
	}
}

func (v AbsOutputValue) checkableSigil() {
	// Output values are checkable
}

func (v AbsOutputValue) ConfigCheckable() ConfigCheckable {
	// Output values are declared by "output" blocks in the configuration,
	// represented as ConfigOutputValue.
	return v.ConfigOutputValue()
}

func (v AbsOutputValue) CheckableKind() CheckableKind {
	return CheckableOutputValue
}

func (v AbsOutputValue) UniqueKey() UniqueKey {
	return absOutputValueUniqueKey(v.String())
}

type absOutputValueUniqueKey string

func (k absOutputValueUniqueKey) uniqueKeySigil() {}

func ParseAbsOutputValue(traversal hcl.Traversal) (AbsOutputValue, tfdiags.Diagnostics) {
	path, remain, diags := parseModuleInstancePrefix(traversal)
	if diags.HasErrors() {
		return AbsOutputValue{}, diags
	}

	if len(remain) != 2 {
		diags = diags.Append(&hcl.Diagnostic{
			Severity: hcl.DiagError,
			Summary:  "Invalid address",
			Detail:   "An output name is required.",
			Subject:  traversal.SourceRange().Ptr(),
		})
		return AbsOutputValue{}, diags
	}

	if remain.RootName() != "output" {
		diags = diags.Append(&hcl.Diagnostic{
			Severity: hcl.DiagError,
			Summary:  "Invalid address",
			Detail:   "Output address must start with \"output.\".",
			Subject:  remain[0].SourceRange().Ptr(),
		})
		return AbsOutputValue{}, diags
	}

	var name string
	switch tt := remain[1].(type) {
	case hcl.TraverseAttr:
		name = tt.Name
	default:
		diags = diags.Append(&hcl.Diagnostic{
			Severity: hcl.DiagError,
			Summary:  "Invalid address",
			Detail:   "An output name is required.",
			Subject:  remain[1].SourceRange().Ptr(),
		})
		return AbsOutputValue{}, diags
	}

	return AbsOutputValue{
		Module: path,
		OutputValue: OutputValue{
			Name: name,
		},
	}, diags
}

func ParseAbsOutputValueStr(str string) (AbsOutputValue, tfdiags.Diagnostics) {
	var diags tfdiags.Diagnostics

	traversal, parseDiags := hclsyntax.ParseTraversalAbs([]byte(str), "", hcl.Pos{Line: 1, Column: 1})
	diags = diags.Append(parseDiags)
	if parseDiags.HasErrors() {
		return AbsOutputValue{}, diags
	}

	addr, addrDiags := ParseAbsOutputValue(traversal)
	diags = diags.Append(addrDiags)
	return addr, diags
}

// ModuleCallOutput converts an AbsModuleOutput into a ModuleCallOutput,
// returning also the module instance that the ModuleCallOutput is relative
// to.
//
// The root module does not have a call, and so this method cannot be used
// with outputs in the root module, and will panic in that case.
func (v AbsOutputValue) ModuleCallOutput() (ModuleInstance, ModuleCallInstanceOutput) {
	if v.Module.IsRoot() {
		panic("ReferenceFromCall used with root module output")
	}

	caller, call := v.Module.CallInstance()
	return caller, ModuleCallInstanceOutput{
		Call: call,
		Name: v.OutputValue.Name,
	}
}

// ConfigOutputValue represents a particular "output" block in the
// configuration, which might have many AbsOutputValue addresses associated
// with it at runtime if it belongs to a module that was called using
// "count" or "for_each".
type ConfigOutputValue struct {
	Module      Module
	OutputValue OutputValue
}

func (v ConfigOutputValue) String() string {
	if v.Module.IsRoot() {
		return v.OutputValue.String()
	}
	return fmt.Sprintf("%s.%s", v.Module.String(), v.OutputValue.String())
}

func (v ConfigOutputValue) configCheckableSigil() {
	// ConfigOutputValue is the ConfigCheckable for AbsOutputValue.
}

func (v ConfigOutputValue) CheckableKind() CheckableKind {
	return CheckableOutputValue
}

func (v ConfigOutputValue) UniqueKey() UniqueKey {
	return configOutputValueUniqueKey(v.String())
}

type configOutputValueUniqueKey string

func (k configOutputValueUniqueKey) uniqueKeySigil() {}
