// Package runtime exposes process-level operational state shared between
// HTTP middleware, handlers, and the shutdown loop in main: a live in-flight
// request gauge for /livez, and a draining flag that flips on SIGTERM so
// /health goes non-ready before we wait for in-flight requests to drain.
//
// All state is package-level + atomic so callers don't need to plumb a struct
// through every middleware/handler. The gauge is decremented in a deferred
// call regardless of panics, so a misbehaving handler can't strand the count.
package runtime

import "sync/atomic"

var (
	inFlight atomic.Int64
	draining atomic.Bool
)

// IncInFlight is called when a tracked request begins. Returns the new count.
func IncInFlight() int64 { return inFlight.Add(1) }

// DecInFlight is called when a tracked request completes. Returns the new count.
func DecInFlight() int64 { return inFlight.Add(-1) }

// InFlight returns the current number of tracked requests in progress.
func InFlight() int64 { return inFlight.Load() }

// IsDraining reports whether the process is shutting down. Used by /health
// to advertise non-ready state so Traefik (or any LB doing health-based
// routing) stops sending new requests to this slot before drain begins.
func IsDraining() bool { return draining.Load() }

// SetDraining flips the draining flag. Idempotent — safe to call from a
// signal handler.
func SetDraining(v bool) { draining.Store(v) }
