package com.correx.infrastructure.inference.commons

/**
 * Whole-device GPU usage at an instant. All fields are device-wide (not per-process) —
 * per-model VRAM attribution is an explicit non-goal.
 */
data class GpuStatus(
    val memoryUsedMb: Long,
    val memoryTotalMb: Long,
    val utilizationPct: Int,
)

/**
 * A point-in-time reading of local-model resource usage. Both fields are nullable so that
 * "unavailable" is representable without exceptions: [gpu] is null when no GPU probe is present
 * (non-NVIDIA box / `nvidia-smi` absent), [processRssBytes] is null when no model is resident.
 */
data class ResourceSnapshot(
    val gpu: GpuStatus?,
    val processRssBytes: Long?,
) {
    companion object {
        val UNAVAILABLE = ResourceSnapshot(gpu = null, processRssBytes = null)
    }
}

/**
 * Vendor-agnostic live gauge of GPU/process resource usage. This is a **live gauge, never recorded
 * as events** — it feeds no core decision, so invariant #9 does not require event-sourcing it, and
 * replay (invariant #8) never reads it. Implementations must degrade gracefully (return
 * [ResourceSnapshot.UNAVAILABLE]-shaped data) rather than throw.
 */
fun interface ResourceProbe {
    fun probe(): ResourceSnapshot
}

/** Always-unavailable probe — used on non-GPU boxes and the static (unmanaged) provider path. */
object UnavailableProbe : ResourceProbe {
    override fun probe(): ResourceSnapshot = ResourceSnapshot.UNAVAILABLE
}
