package com.correx.core.context.model

import com.correx.core.events.types.ContextEntryId
import kotlinx.serialization.Serializable

enum class EntryRole { SYSTEM, USER, ASSISTANT, TOOL }

/**
 * Budget class of an entry. REQUIRED entries (task, constraints, loaded inputs, failures) are
 * never lossily compressed or dropped — if they alone exceed the budget the build fails fast
 * instead of silently trimming. OPTIONAL entries (repo map, retrieval, journal, profiles) share
 * whatever budget remains, each source type under its own ceiling.
 */
@Serializable
enum class ContextBucket { REQUIRED, OPTIONAL }

@Serializable
data class ContextEntry(
    val id: ContextEntryId,
    val layer: ContextLayer,
    val content: String,
    val sourceType: String,
    val sourceId: String,
    val tokenEstimate: Int,
    val role: EntryRole = EntryRole.USER,
    // Monotonic chronological position within a single context assembly. Stamped by
    // DefaultContextPackBuilder from input order so that grouping/compression (which
    // reorder by sourceType/layer) and PromptRenderer can recover true turn order.
    // Entries built outside that builder (e.g. router chat) leave this at 0 and fall
    // back to layer-priority ordering in PromptRenderer.
    val ordinal: Int = 0,
    // Default OPTIONAL keeps prior behavior for callers that don't stamp buckets (router chat);
    // the orchestrator stamps REQUIRED on task/constraint/input/failure entries.
    val bucket: ContextBucket = ContextBucket.OPTIONAL,
    // Chain-of-thought that preceded this ASSISTANT turn (assistantToolCall entries only), as
    // captured on InferenceResponse.reasoning. Carried as a side channel, not JSON-encoded into
    // `content`, so FORMAT_COMPRESS's dotted-line flatten of the tool-call JSON never touches it.
    // Threaded back into the request as ChatMessage.reasoning so models that expect their own
    // prior reasoning ahead of a tool-call turn (e.g. Gemma) don't degenerate into re-deriving it.
    val reasoning: String? = null,
)
