package com.correx.testing.contracts.model.inference

import com.correx.infrastructure.inference.commons.GpuStatus
import com.correx.infrastructure.inference.commons.ResourceProbe
import com.correx.infrastructure.inference.commons.ResourceSnapshot
import com.correx.infrastructure.inference.commons.SystemResourceProbe
import com.correx.infrastructure.inference.commons.UnavailableProbe
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Assertions.assertNull
import org.junit.jupiter.api.Test

class SystemResourceProbeTest {

    private val bytesPerKb = 1024L

    @Test
    fun `overlays system RAM onto an unavailable GPU probe (static path, F-001 gauge)`() {
        val probe = SystemResourceProbe(
            gpuProbe = UnavailableProbe,
            systemRamReader = { (4L * bytesPerKb) to (16L * bytesPerKb) },
        )
        val snap = probe.probe()
        assertNull(snap.gpu) // no managed model / no GPU, yet RAM still renders
        assertNull(snap.processRssBytes)
        assertEquals(4L * bytesPerKb, snap.systemRamUsedBytes)
        assertEquals(16L * bytesPerKb, snap.systemRamTotalBytes)
    }

    @Test
    fun `preserves the delegate GPU and process RSS while adding system RAM (managed path)`() {
        val gpuDelegate = ResourceProbe {
            ResourceSnapshot(
                gpu = GpuStatus(memoryUsedMb = 2048, memoryTotalMb = 8192, utilizationPct = 50),
                processRssBytes = 999L,
            )
        }
        val probe = SystemResourceProbe(
            gpuProbe = gpuDelegate,
            systemRamReader = { 100L to 200L },
        )
        val snap = probe.probe()
        assertEquals(2048L, snap.gpu?.memoryUsedMb)
        assertEquals(999L, snap.processRssBytes)
        assertEquals(100L, snap.systemRamUsedBytes)
        assertEquals(200L, snap.systemRamTotalBytes)
    }

    @Test
    fun `fails soft to null system RAM when the reader is unavailable`() {
        val probe = SystemResourceProbe(gpuProbe = UnavailableProbe, systemRamReader = { null })
        val snap = probe.probe()
        assertNull(snap.systemRamUsedBytes)
        assertNull(snap.systemRamTotalBytes)
    }
}
