package com.correx.infrastructure.persistence.artifact

import com.correx.core.artifacts.DefaultArtifactReducer
import com.correx.core.events.events.ArtifactCreatedEvent
import com.correx.core.events.events.ArtifactValidatedEvent
import com.correx.core.events.events.ArtifactValidatingEvent
import com.correx.core.events.types.ArtifactId
import com.correx.core.events.types.ArtifactLifecyclePhase
import com.correx.core.events.types.EventId
import com.correx.core.events.types.SessionId
import com.correx.core.events.types.StageId
import com.correx.infrastructure.persistence.InMemoryEventStore
import com.correx.testing.fixtures.EventFixtures
import kotlinx.coroutines.runBlocking
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Assertions.assertNull
import org.junit.jupiter.api.Test

class LiveArtifactRepositoryTest {

    @Test
    fun `cold access rebuilds artifact state from the persisted log, in order`(): Unit = runBlocking {
        val store = InMemoryEventStore()
        val session = SessionId("s1")
        val artifact = ArtifactId("a1")
        val stage = StageId("stage1")

        // Persist the full lifecycle BEFORE any repository/consumer exists — the pre-fix repo
        // subscribed with replay=0 and never read() this history, so a cold consumer saw null.
        store.append(EventFixtures.newEvent(EventId("e1"), session, ArtifactCreatedEvent(artifact, session, stage, 1)))
        store.append(EventFixtures.newEvent(EventId("e2"), session, ArtifactValidatingEvent(artifact, session, stage)))
        store.append(EventFixtures.newEvent(EventId("e3"), session, ArtifactValidatedEvent(artifact, session, stage)))

        // Fresh repository = cold consumer (mimics a restart / first mid-session access).
        val repo = LiveArtifactRepository(store, DefaultArtifactReducer())

        // Rebuilt, and folded in sequence order — VALIDATED only reachable via CREATED→VALIDATING→VALIDATED.
        assertEquals(ArtifactLifecyclePhase.VALIDATED, repo.getById(session, artifact)?.phase)
        assertNull(repo.getById(session, ArtifactId("does-not-exist")))
    }
}
