package com.correx.core.kernel.replay

import com.correx.core.events.events.InferenceCompletedEvent
import com.correx.core.events.stores.EventStore
import com.correx.core.events.types.ProviderId
import com.correx.core.inference.CapabilityScore
import com.correx.core.inference.FinishReason
import com.correx.core.inference.InferenceProvider
import com.correx.core.inference.InferenceRequest
import com.correx.core.inference.InferenceResponse
import com.correx.core.inference.ProviderHealth
import com.correx.core.inference.Token
import com.correx.core.inference.Tokenizer
import com.correx.core.kernel.retry.exception.ReplayArtifactMissingException

class ReplayInferenceProvider(
    private val eventStore: EventStore,
    override val name: String = "Replay Provider",
) : InferenceProvider {

    override val id: ProviderId = ProviderId("replay-provider")

    private companion object {
        /** Rough char→token ratio for the replay tokenizer (no real BPE at replay time). */
        const val CHARS_PER_TOKEN = 4
    }

    override val tokenizer: Tokenizer = object : Tokenizer {
        override suspend fun tokenize(text: String): List<Token> =
            List(text.chunked(CHARS_PER_TOKEN).size) { i -> Token(i) }

        override suspend fun countTokens(text: String): Int =
            (text.length + CHARS_PER_TOKEN - 1) / CHARS_PER_TOKEN
    }

    override suspend fun infer(request: InferenceRequest): InferenceResponse {
        val recorded = eventStore.read(request.sessionId)
            .map { it.payload }
            .filterIsInstance<InferenceCompletedEvent>()
            .firstOrNull { it.stageId == request.stageId }

            ?: throw ReplayArtifactMissingException(request.sessionId, request.stageId)

        return InferenceResponse(
            requestId = request.requestId,
            text = "", // inference text is not recorded — replay produces empty text by design
            finishReason = FinishReason.Stop,
            tokensUsed = recorded.tokensUsed,
            latencyMs = recorded.latencyMs,
        )
    }

    override suspend fun healthCheck(): ProviderHealth = ProviderHealth.Healthy

    override fun capabilities(): Set<CapabilityScore> = emptySet()
}
