package com.correx.core.context.compression

import com.correx.core.context.model.ContextEntry
import com.correx.core.context.model.ContextLayer
import com.correx.core.context.model.EntryRole

/**
 * Stage 0 of the pipeline: tag each entry as static, structured, or freeform. The class
 * decides which downstream stages are eligible — static content is cached and never pruned,
 * structured content is format-compressed but its exact values are never altered, freeform
 * content is the only class the lossy stages (prune/summarize/merge) touch.
 */
enum class ContextClass { STATIC, STRUCTURED, FREEFORM }

class ContextClassifier {

    fun classify(entry: ContextEntry): ContextClass = when {
        entry.sourceType in STATIC_SOURCES -> ContextClass.STATIC
        entry.sourceType in STRUCTURED_SOURCES -> ContextClass.STRUCTURED
        // A pinned L0 directive that isn't one of the known static prompts is still exact-value
        // content — never prune it. Keyed on LAYER alone since #312: L0 means "pinned standing
        // context" (a budget/pinning property), while role now means "which chat message type"
        // (a rendering property). Several L0 entries are deliberately USER-role now — a mutating
        // verified baseline, claimed task, clarification answer — and token-pruning those as
        // freeform prose would shred exactly the directives they exist to carry.
        entry.layer == ContextLayer.L0 -> ContextClass.STATIC
        entry.role == EntryRole.TOOL -> ContextClass.STRUCTURED
        else -> ContextClass.FREEFORM
    }

    private companion object {
        val STATIC_SOURCES = setOf("systemPrompt", "toolSchema", "fewShot")
        // "assistantToolCall" carries the model's own tool-call JSON (id + function + args). It is
        // load-bearing structured history: token-pruning it (it was FREEFORM by role=ASSISTANT)
        // shredded the JSON to a bare id + protected path, giving the model amnesia about what it
        // had already done → it re-issued the same call and looped. Structured = format-compress
        // ok, never pruned.
        val STRUCTURED_SOURCES = setOf(
            "toolLog", "artifact", "config", "structured", "steeringNote", "assistantToolCall",
        )
    }
}
