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

package format

import (
	"github.com/hashicorp/terraform/internal/lang/marks"
	"github.com/zclconf/go-cty/cty"
)

// ObjectValueID takes a value that is assumed to be an object representation
// of some resource instance object and attempts to heuristically find an
// attribute of it that is likely to be a unique identifier in the remote
// system that it belongs to which will be useful to the user.
//
// If such an attribute is found, its name and string value intended for
// display are returned. Both returned strings are empty if no such attribute
// exists, in which case the caller should assume that the resource instance
// address within the Terraform configuration is the best available identifier.
//
// This is only a best-effort sort of thing, relying on naming conventions in
// our resource type schemas. The result is not guaranteed to be unique, but
// should generally be suitable for display to an end-user anyway.
//
// This function will panic if the given value is not of an object type.
func ObjectValueID(obj cty.Value) (k, v string) {
	if obj.IsNull() || !obj.IsKnown() {
		return "", ""
	}

	atys := obj.Type().AttributeTypes()

	switch {

	case atys["id"] == cty.String:
		v := obj.GetAttr("id")
		if v.HasMark(marks.Sensitive) {
			break
		}
		v, _ = v.Unmark()

		if v.IsKnown() && !v.IsNull() {
			return "id", v.AsString()
		}

	case atys["name"] == cty.String:
		// "name" isn't always globally unique, but if there isn't also an
		// "id" then it _often_ is, in practice.
		v := obj.GetAttr("name")
		if v.HasMark(marks.Sensitive) {
			break
		}
		v, _ = v.Unmark()

		if v.IsKnown() && !v.IsNull() {
			return "name", v.AsString()
		}
	}

	return "", ""
}

// ObjectValueName takes a value that is assumed to be an object representation
// of some resource instance object and attempts to heuristically find an
// attribute of it that is likely to be a human-friendly name in the remote
// system that it belongs to which will be useful to the user.
//
// If such an attribute is found, its name and string value intended for
// display are returned. Both returned strings are empty if no such attribute
// exists, in which case the caller should assume that the resource instance
// address within the Terraform configuration is the best available identifier.
//
// This is only a best-effort sort of thing, relying on naming conventions in
// our resource type schemas. The result is not guaranteed to be unique, but
// should generally be suitable for display to an end-user anyway.
//
// Callers that use both ObjectValueName and ObjectValueID at the same time
// should be prepared to get the same attribute key and value from both in
// some cases, since there is overlap betweek the id-extraction and
// name-extraction heuristics.
//
// This function will panic if the given value is not of an object type.
func ObjectValueName(obj cty.Value) (k, v string) {
	if obj.IsNull() || !obj.IsKnown() {
		return "", ""
	}

	atys := obj.Type().AttributeTypes()

	switch {

	case atys["name"] == cty.String:
		v := obj.GetAttr("name")
		if v.HasMark(marks.Sensitive) {
			break
		}
		v, _ = v.Unmark()

		if v.IsKnown() && !v.IsNull() {
			return "name", v.AsString()
		}

	case atys["tags"].IsMapType() && atys["tags"].ElementType() == cty.String:
		tags := obj.GetAttr("tags")
		if tags.IsNull() || !tags.IsWhollyKnown() || tags.HasMark(marks.Sensitive) {
			break
		}
		tags, _ = tags.Unmark()

		switch {
		case tags.HasIndex(cty.StringVal("name")).RawEquals(cty.True):
			v := tags.Index(cty.StringVal("name"))
			if v.HasMark(marks.Sensitive) {
				break
			}
			v, _ = v.Unmark()

			if v.IsKnown() && !v.IsNull() {
				return "tags.name", v.AsString()
			}
		case tags.HasIndex(cty.StringVal("Name")).RawEquals(cty.True):
			// AWS-style naming convention
			v := tags.Index(cty.StringVal("Name"))
			if v.HasMark(marks.Sensitive) {
				break
			}
			v, _ = v.Unmark()

			if v.IsKnown() && !v.IsNull() {
				return "tags.Name", v.AsString()
			}
		}
	}

	return "", ""
}

// ObjectValueIDOrName is a convenience wrapper around both ObjectValueID
// and ObjectValueName (in that preference order) to try to extract some sort
// of human-friendly descriptive string value for an object as additional
// context about an object when it is being displayed in a compact way (where
// not all of the attributes are visible.)
//
// Just as with the two functions it wraps, it is a best-effort and may return
// two empty strings if no suitable attribute can be found for a given object.
func ObjectValueIDOrName(obj cty.Value) (k, v string) {
	k, v = ObjectValueID(obj)
	if k != "" {
		return
	}
	k, v = ObjectValueName(obj)
	return
}
