package com.correx.apps.server.tasks

import com.correx.core.artifactstore.ArtifactStore
import com.correx.core.events.events.ArtifactContentStoredEvent
import com.correx.core.events.events.ArtifactCreatedEvent
import com.correx.core.events.stores.EventStore
import com.correx.core.events.types.ArtifactId
import com.correx.core.tasks.ResolvedArtifact
import com.correx.core.tasks.TaskArtifactResolver
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext

private const val EXCERPT_MAX = 280

/**
 * Resolves ARTIFACT link targets for the task context bundle by scanning the event log for the
 * artifact's lifecycle events: [ArtifactCreatedEvent]/[ArtifactContentStoredEvent] give the
 * producing stage + session, and the content hash is dereferenced against the CAS [ArtifactStore]
 * for an excerpt. Returns null when no events match the id — the link then stays a raw related link.
 */
class EventStoreTaskArtifactResolver(
    private val eventStore: EventStore,
    private val artifactStore: ArtifactStore,
    private val excerptMax: Int = EXCERPT_MAX,
) : TaskArtifactResolver {

    override suspend fun resolve(targetId: String): ResolvedArtifact? = withContext(Dispatchers.IO) {
        val artifactId = ArtifactId(targetId)
        var stage: String? = null
        var sessionId: String? = null
        var contentHash: ArtifactId? = null
        eventStore.allEvents().forEach { stored ->
            when (val p = stored.payload) {
                is ArtifactCreatedEvent -> if (p.artifactId == artifactId) {
                    stage = p.stageId.value
                    sessionId = p.sessionId.value
                }
                is ArtifactContentStoredEvent -> if (p.artifactId == artifactId) {
                    stage = stage ?: p.stageId.value
                    sessionId = sessionId ?: p.sessionId.value
                    contentHash = p.contentHash
                }
                else -> Unit
            }
        }
        if (stage == null && sessionId == null && contentHash == null) return@withContext null
        val excerpt = contentHash?.let { hash ->
            runCatching { artifactStore.get(hash) }.getOrNull()
                ?.toString(Charsets.UTF_8)?.trim()?.takeIf { it.isNotEmpty() }?.take(excerptMax)
        }
        ResolvedArtifact(stage = stage, sessionId = sessionId, excerpt = excerpt)
    }
}
