package checks

import (
	"fmt"

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

// These are the "Report"-prefixed methods of Checks used by Terraform Core
// to gradually signal the results of checks during a plan or apply operation.

// ReportCheckableObjects is the interface by which Terraform Core should
// tell the State object which specific checkable objects were declared
// by the given configuration object.
//
// This method will panic if the given configuration address isn't one known
// by this Checks to have pending checks, and if any of the given object
// addresses don't belong to the given configuration address.
func (c *State) ReportCheckableObjects(configAddr addrs.ConfigCheckable, objectAddrs addrs.Set[addrs.Checkable]) {
	c.mu.Lock()
	defer c.mu.Unlock()

	st, ok := c.statuses.GetOk(configAddr)
	if !ok {
		panic(fmt.Sprintf("checkable objects report for unknown configuration object %s", configAddr))
	}
	if st.objects.Elems != nil {
		// Can only report checkable objects once per configuration object
		panic(fmt.Sprintf("duplicate checkable objects report for %s ", configAddr))
	}

	// At this point we pre-populate all of the check results as StatusUnknown,
	// so that even if we never hear from Terraform Core again we'll still
	// remember that these results were all pending.
	st.objects = addrs.MakeMap[addrs.Checkable, map[addrs.CheckType][]Status]()
	for _, objectAddr := range objectAddrs {
		if gotConfigAddr := objectAddr.ConfigCheckable(); !addrs.Equivalent(configAddr, gotConfigAddr) {
			// All of the given object addresses must belong to the specified configuration address
			panic(fmt.Sprintf("%s belongs to %s, not %s", objectAddr, gotConfigAddr, configAddr))
		}

		checks := make(map[addrs.CheckType][]Status, len(st.checkTypes))
		for checkType, count := range st.checkTypes {
			// NOTE: This is intentionally a slice of count of the zero value
			// of Status, which is StatusUnknown to represent that we don't
			// yet have a report for that particular check.
			checks[checkType] = make([]Status, count)
		}

		st.objects.Put(objectAddr, checks)
	}
}

// ReportCheckResult is the interface by which Terraform Core should tell the
// State object the result of a specific check for an object that was
// previously registered with ReportCheckableObjects.
//
// If the given object address doesn't match a previously-reported object,
// or if the check index is out of bounds for the number of checks expected
// of the given type, this method will panic to indicate a bug in the caller.
//
// This method will also panic if the specified check already had a known
// status; each check should have its result reported only once.
func (c *State) ReportCheckResult(objectAddr addrs.Checkable, checkType addrs.CheckType, index int, status Status) {
	c.mu.Lock()
	defer c.mu.Unlock()

	c.reportCheckResult(objectAddr, checkType, index, status)
}

// ReportCheckFailure is a more specialized version of ReportCheckResult which
// captures a failure outcome in particular, giving the opportunity to capture
// an author-specified error message string along with the failure.
//
// This always records the given check as having StatusFail. Don't use this for
// situations where the check condition was itself invalid, because that
// should be represented by StatusError instead, and the error signalled via
// diagnostics as normal.
func (c *State) ReportCheckFailure(objectAddr addrs.Checkable, checkType addrs.CheckType, index int, errorMessage string) {
	c.mu.Lock()
	defer c.mu.Unlock()

	c.reportCheckResult(objectAddr, checkType, index, StatusFail)
	if c.failureMsgs.Elems == nil {
		c.failureMsgs = addrs.MakeMap[addrs.Check, string]()
	}
	checkAddr := addrs.NewCheck(objectAddr, checkType, index)
	c.failureMsgs.Put(checkAddr, errorMessage)
}

// reportCheckResult is shared between both ReportCheckResult and
// ReportCheckFailure, and assumes its caller already holds the mutex.
func (c *State) reportCheckResult(objectAddr addrs.Checkable, checkType addrs.CheckType, index int, status Status) {
	configAddr := objectAddr.ConfigCheckable()

	st, ok := c.statuses.GetOk(configAddr)
	if !ok {
		panic(fmt.Sprintf("checkable object status report for unknown configuration object %s", configAddr))
	}

	checks, ok := st.objects.GetOk(objectAddr)
	if !ok {
		panic(fmt.Sprintf("checkable object status report for unexpected checkable object %s", objectAddr))
	}

	if index >= len(checks[checkType]) {
		panic(fmt.Sprintf("%s index %d out of range for %s", checkType, index, objectAddr))
	}
	if checks[checkType][index] != StatusUnknown {
		panic(fmt.Sprintf("duplicate status report for %s %s %d", objectAddr, checkType, index))
	}

	checks[checkType][index] = status

}
