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

package views

import (
	"github.com/opentofu/opentofu/internal/command/arguments"
	"github.com/opentofu/opentofu/internal/lang/marks"
	"github.com/opentofu/opentofu/internal/tfdiags"
)

// Used to track duplicate diagnostic entries in DeprecationDiagnosticAllowed()
type DeprecationDiagnosticAllowedSeen map[any]any

// DeprecationDiagnosticAllowed is used to determine if a diagnostic generated by a deprecation check against an
// output or a variable should be allowed to be shown to the user based on the given DeprecationWarningLevel.
// This is making use of tfdiags.Diagnostic#ExtraInfo() to figure out if the diagnostic is generated by a deprecation check.
func (v *View) DeprecationDiagnosticAllowed(diag tfdiags.Diagnostic, seen DeprecationDiagnosticAllowedSeen) bool {
	cause, causeOk := marks.DiagnosticDeprecationCause(diag)
	if !causeOk {
		// If it's not a deprecation warning diagnostic, always allow it to not filter out diagnostics unrelated with deprecation
		return true
	}

	// Check for dupes
	if _, causeSeen := seen[cause]; causeSeen {
		// Already processed
		return false
	}
	seen[cause] = cause

	switch v.ModuleDeprecationWarnLvl {
	case arguments.DeprecationWarningLevelAll:
		return true
	case arguments.DeprecationWarningLevelLocal:
		// do not allow deprecation warnings for outputs from remote module calls
		return !v.isRemoteModuleSource(cause.ModuleInstance().Module())
	case arguments.DeprecationWarningLevelNone:
		return false
	}
	panic("unreachable")
}

func (v *View) DeprecationKeyExtra(diag tfdiags.Diagnostic) string {
	cause, causeOk := marks.DiagnosticDeprecationCause(diag)
	if !causeOk {
		// If it's not a deprecation warning diagnostic, always allow it to not filter out diagnostics unrelated with deprecation
		return ""
	}

	desc := diag.Description()
	moduleString := cause.ModuleInstance().Module().String()
	if addr := v.moduleSourceAddrs(cause.ModuleInstance().Module()); addr != nil {
		// Try to use the module source address if at all possible for cleaner consolidation
		moduleString = addr.String()
	}
	return desc.Summary + cause.ExtraInfoKey() + moduleString

}
