package com.correx.core.critique.model

import com.correx.core.events.events.CritiqueRole
import kotlinx.serialization.Serializable

/** Composite key: critic precision is tracked per model and per role. */
@Serializable
data class CalibrationKey(val modelHash: String, val role: CritiqueRole)

/**
 * Outcome tallies for one [CalibrationKey]. [precision] = upheld / (upheld + dismissed) — the
 * share of *decisive* findings that held up — or null when no decisive findings exist yet.
 * INCONCLUSIVE outcomes count toward [total] but never toward precision.
 */
@Serializable
data class CalibrationStats(
    val upheld: Int = 0,
    val dismissed: Int = 0,
    val inconclusive: Int = 0,
) {
    val total: Int get() = upheld + dismissed + inconclusive
    val decisive: Int get() = upheld + dismissed
    val precision: Double? get() = if (decisive == 0) null else upheld.toDouble() / decisive
}

/**
 * Replay-built view of how each (model, role) critic has performed. Rebuilt from
 * [com.correx.core.events.events.CritiqueOutcomeCorrelatedEvent]s; never persisted directly.
 */
@Serializable
data class CriticCalibrationState(
    val byKey: Map<CalibrationKey, CalibrationStats> = emptyMap(),
)
