package com.correx.core.events.events

import com.correx.core.events.types.ArtifactId
import com.correx.core.events.types.SessionId
import com.correx.core.events.types.StageId
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
@SerialName("ArtifactValidating")
data class ArtifactValidatingEvent(
    val artifactId: ArtifactId,
    val sessionId: SessionId,
    val stageId: StageId,
) : EventPayload

@Serializable
@SerialName("ArtifactValidated")
data class ArtifactValidatedEvent(
    val artifactId: ArtifactId,
    val sessionId: SessionId,
    val stageId: StageId,
) : EventPayload

/**
 * ⚠️ ORDERING TRAP: despite the name, this is emitted at the *validation* phase — AFTER
 * [ArtifactContentStoredEvent] (which fires at inference time). Any fold that derives per-artifact
 * state must NOT assume `ArtifactCreated` is the first event for an [artifactId]; seed accumulators
 * from whichever artifact event arrives first (see StreamQueries.planArtifacts, which was bitten by
 * exactly this — the content hash arrives one event earlier).
 */
@Serializable
@SerialName("ArtifactCreated")
data class ArtifactCreatedEvent(
    val artifactId: ArtifactId,
    val sessionId: SessionId,
    val stageId: StageId,
    val schemaVersion: Int,
) : EventPayload

/**
 * Records the slot→CAS-hash mapping for a produced artifact. Emitted at inference time, so it
 * precedes [ArtifactCreatedEvent] for the same [artifactId] (see the ordering note there).
 */
@Serializable
@SerialName("ArtifactContentStored")
data class ArtifactContentStoredEvent(
    val artifactId: ArtifactId,
    val contentHash: ArtifactId, // CAS content hash returned by ArtifactStore.put(...)
    val sessionId: SessionId,
    val stageId: StageId,
) : EventPayload

/**
 * A near-miss producer output was routed through the artifact-emission repair ladder. Only the
 * nondeterministic rung (`rung = "LLM"`) is replay-relevant — the deterministic rungs recompute —
 * but both are recorded for observability. See docs/specs/2026-07-04-artifact-emission-pipeline.md.
 */
@Serializable
@SerialName("ArtifactRepairAttempted")
data class ArtifactRepairAttemptedEvent(
    val artifactId: ArtifactId,
    val classification: String, // ArtifactFailure name
    val rung: String,           // "DETERMINISTIC" | "LLM"
    val sessionId: SessionId,
    val stageId: StageId,
) : EventPayload

/** The repair ladder produced a schema-valid artifact. [contentHash] feeds the normal store path. */
@Serializable
@SerialName("ArtifactRepairResolved")
data class ArtifactRepairResolvedEvent(
    val artifactId: ArtifactId,
    val contentHash: ArtifactId,
    val sessionId: SessionId,
    val stageId: StageId,
) : EventPayload

/** The repair ladder gave up; [decision] records the policy dispatch (retry/regenerate/abort/escalate). */
@Serializable
@SerialName("ArtifactRepairFailed")
data class ArtifactRepairFailedEvent(
    val artifactId: ArtifactId,
    val classification: String,
    val decision: String,
    val reason: String,
    val sessionId: SessionId,
    val stageId: StageId,
) : EventPayload
