import com.correx.core.events.events.EventMetadata
import com.correx.core.events.events.NewEvent
import com.correx.core.events.events.RepoMapComputedEvent
import com.correx.core.events.events.RepoMapEntry
import com.correx.core.events.events.StoredEvent
import com.correx.core.events.types.EventId
import com.correx.core.events.types.SessionId
import com.correx.core.sessions.projections.Projection
import com.correx.core.sessions.projections.replay.DefaultEventReplayer
import com.correx.infrastructure.persistence.InMemoryEventStore
import kotlinx.coroutines.runBlocking
import kotlinx.datetime.Instant
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Test

/** Collects the latest recorded repo map purely from events — never touches the filesystem. */
private class RepoMapProjection : Projection<List<RepoMapEntry>> {
    override fun initial(): List<RepoMapEntry> = emptyList()
    override fun apply(state: List<RepoMapEntry>, event: StoredEvent): List<RepoMapEntry> =
        when (val p = event.payload) {
            is RepoMapComputedEvent -> p.entries
            else -> state
        }
}

class RepoMapReplayTest {

    @Test
    fun `repo map is reconstructed from the recorded event without re-scanning`(): Unit = runBlocking {
        val sessionId = SessionId("s")
        val store = InMemoryEventStore()
        val entries = listOf(
            RepoMapEntry("src/Main.kt", 0.9, listOf("main", "boot")),
            RepoMapEntry("src/Util.kt", 0.4, listOf("clamp")),
        )
        store.append(
            NewEvent(
                EventMetadata(EventId("rm"), sessionId, Instant.parse("2026-06-04T00:00:00Z"), 1, null, null),
                RepoMapComputedEvent(sessionId, "/repo", entries, Instant.parse("2026-06-04T00:00:00Z")),
            ),
        )

        val rebuilt = DefaultEventReplayer(store, RepoMapProjection()).rebuild(sessionId)

        assertEquals(entries, rebuilt)
    }
}
