package com.correx.apps.server.health

import com.correx.core.events.events.HealthSubject
import com.correx.core.events.stores.EventStore

private const val NANOS_PER_MILLI = 1_000_000L

/**
 * Watches event-log append/fsync latency (observability-spec §4: "the organ that must never lie").
 * Each tick times one durable, side-effect-free store probe and reports DEGRADED when it exceeds
 * [warnLatencyMs] — a slow store means the append path (fsync) is contended or the disk is failing.
 *
 * The timed operation is injected so the probe never itself appends an event (that would both spam
 * the health log and break replay determinism). [forStore] wires it in production to
 * [EventStore.lastGlobalSequence], a durable read that rides the same connection an append's fsync
 * uses. The latency reading is a live environment observation; it never affects replay (Invariant #8).
 */
class EventStoreLatencyProbe(
    private val warnLatencyMs: Long,
    private val nanoTime: () -> Long = System::nanoTime,
    private val measure: suspend () -> Unit,
) : HealthProbe {

    override val subject: HealthSubject = HealthSubject.EVENT_STORE

    override suspend fun observe(): HealthObservation {
        val start = nanoTime()
        val failure = runCatching { measure() }.exceptionOrNull()
        val elapsedMs = (nanoTime() - start) / NANOS_PER_MILLI

        return when {
            failure != null -> degraded(
                value = elapsedMs,
                detail = "event store probe failed: ${failure.message ?: failure::class.simpleName}",
            )
            elapsedMs >= warnLatencyMs -> degraded(
                value = elapsedMs,
                detail = "event store probe took ${elapsedMs}ms (warn ≥ ${warnLatencyMs}ms)",
            )
            else -> HealthObservation(
                subject = subject,
                status = HealthStatus.HEALTHY,
                metric = "latency_ms",
                observedValue = elapsedMs,
                threshold = warnLatencyMs,
                detail = "event store probe took ${elapsedMs}ms",
            )
        }
    }

    private fun degraded(value: Long, detail: String) = HealthObservation(
        subject = subject,
        status = HealthStatus.DEGRADED,
        metric = "latency_ms",
        observedValue = value,
        threshold = warnLatencyMs,
        detail = detail,
    )

    companion object {
        /** Production wiring: time a durable, side-effect-free read on [store]. */
        fun forStore(store: EventStore, warnLatencyMs: Long): EventStoreLatencyProbe =
            EventStoreLatencyProbe(warnLatencyMs = warnLatencyMs) { store.lastGlobalSequence() }
    }
}
