package variables

type Kind int

const (
	KindGlobal Kind = iota
	KindRuntime
	KindInput
	KindOutput
	KindNodeRef
	KindItem
	KindRetry
	KindNodeCtx
	KindMetric
	KindCronWorkflow
)

func (k Kind) String() string {
	return [...]string{"global", "runtime", "input", "output", "node-ref", "item", "retry", "node-ctx", "metric", "cron-workflow"}[k]
}

// LifecyclePhase is a coarse point-in-time within one workflow execution.
// Phase names are surfaced verbatim in the generated docs.
type LifecyclePhase string

const (
	PhWorkflowStart      LifecyclePhase = "workflow-start"
	PhPreDispatch        LifecyclePhase = "pre-dispatch"
	PhDuringExecute      LifecyclePhase = "during-execute"
	PhInsideLoop         LifecyclePhase = "inside-loop"
	PhInsideRetry        LifecyclePhase = "inside-retry"
	PhAfterNodeInit      LifecyclePhase = "after-node-init"
	PhAfterPodStart      LifecyclePhase = "after-pod-start"
	PhAfterNodeComplete  LifecyclePhase = "after-node-complete"
	PhAfterNodeSucceeded LifecyclePhase = "after-node-succeeded"
	PhAfterLoop          LifecyclePhase = "after-loop"
	PhExitHandler        LifecyclePhase = "exit-handler"
	PhMetricEmission     LifecyclePhase = "metric-emission"
	PhCronEval           LifecyclePhase = "cron-eval"
)

// TemplateKind categorises a wfv1.Template by its body type.
type TemplateKind string

const (
	TmplAll          TemplateKind = "any"
	TmplContainer    TemplateKind = "container"
	TmplContainerSet TemplateKind = "container-set"
	TmplScript       TemplateKind = "script"
	TmplResource     TemplateKind = "resource"
	TmplSteps        TemplateKind = "steps"
	TmplDAG          TemplateKind = "dag"
	TmplData         TemplateKind = "data"
	TmplSuspend      TemplateKind = "suspend"
	TmplHTTP         TemplateKind = "http"
	TmplPlugin       TemplateKind = "plugin"
	TmplExitHandler  TemplateKind = "exit-handler"
	TmplCronWorkflow TemplateKind = "cron-workflow"
)

var AllTemplateKinds = []TemplateKind{
	TmplContainer, TmplContainerSet, TmplScript, TmplResource,
	TmplSteps, TmplDAG, TmplData,
	TmplSuspend, TmplHTTP, TmplPlugin, TmplExitHandler,
	TmplCronWorkflow,
}

// ReachablePhases returns the lifecycle phases that can actually fire from
// inside a template body of the given kind. Used by the doc generator to
// gate matrix `•` marks: a variable is only shown reachable from a
// TemplateKind column if at least one of its declared phases is in this
// set. This prevents "narrow" phases (PhInsideLoop, PhInsideRetry,
// PhExitHandler, PhCronEval) from leaking into columns that never enter
// those phases — e.g. `item` showing up under the exit-handler column.
//
// TmplExitHandler is treated as a context, not a body type: any leaf body
// (container/script/etc.) can serve as an onExit handler, but the matrix
// renders it as a separate column for catalog readers, so its column
// reflects exit-handler semantics rather than generic body semantics.
func ReachablePhases(k TemplateKind) []LifecyclePhase {
	switch k {
	case TmplCronWorkflow:
		return []LifecyclePhase{PhCronEval}
	case TmplExitHandler:
		return []LifecyclePhase{
			PhWorkflowStart, PhPreDispatch, PhDuringExecute,
			PhAfterNodeInit, PhAfterPodStart, PhAfterNodeComplete,
			PhAfterNodeSucceeded, PhAfterLoop,
			PhExitHandler, PhMetricEmission,
		}
	// Pod-producing leaves (Container/ContainerSet/Script/Resource/Data) and
	// the agent-driven leaves (HTTP/Plugin) share the same reachable phases:
	// retryStrategy demonstrably fires on all of them and {{retries}} /
	// {{lastRetry.*}} substitute inside their bodies.
	case TmplContainer, TmplContainerSet, TmplScript, TmplResource,
		TmplData, TmplHTTP, TmplPlugin:
		return []LifecyclePhase{
			PhWorkflowStart, PhPreDispatch, PhDuringExecute,
			PhInsideLoop, PhInsideRetry, PhMetricEmission,
		}
	case TmplSteps, TmplDAG:
		return []LifecyclePhase{
			PhWorkflowStart, PhPreDispatch, PhDuringExecute,
			PhInsideLoop, PhInsideRetry,
			PhAfterNodeInit, PhAfterPodStart, PhAfterNodeComplete,
			PhAfterNodeSucceeded, PhAfterLoop, PhMetricEmission,
		}
	// Suspend has no realistic failure path — lint accepts retryStrategy on
	// suspend templates but retry vars never actually bind. So PhInsideRetry
	// is intentionally excluded from its reachable set.
	case TmplSuspend:
		return []LifecyclePhase{
			PhWorkflowStart, PhPreDispatch, PhDuringExecute,
			PhInsideLoop, PhMetricEmission,
		}
	}
	return nil
}
