package com.correx.testing.contracts.fixtures.projections

import com.correx.core.events.types.EventId
import com.correx.core.events.types.SessionId
import com.correx.core.sessions.SessionCounterProjection
import com.correx.core.sessions.SessionCounterState
import com.correx.core.sessions.projections.DefaultStateBuilder
import com.correx.testing.fixtures.EventFixtures.stored
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Test

open class CountingProjectionContractTest : ProjectionContractTest<SessionCounterState>() {

    override fun projection() =
        SessionCounterProjection("s1")

    @Test
    fun `projection reflects event count`() {
        val events = (0 until 42).map {
            stored(EventId(it.toString()), sessionId = SessionId("s1"), sequence = it.toLong())
        }

        val state = DefaultStateBuilder(
            projection()
        ).build(events)

        assertEquals(42, state.count)
    }

    @Test
    fun `projection is order sensitive but deterministic`() {
        val events = listOf(
            stored(EventId("1"), sessionId = SessionId("s1"), sequence = 0),
            stored(EventId("2"), sessionId = SessionId("s1"), sequence = 1),
            stored(EventId("3"), sessionId = SessionId("s1"), sequence = 2)
        )

        val state = DefaultStateBuilder(
            projection()
        ).build(events)

        assertEquals(3, state.count)
    }

    @Test
    fun `projection handles empty stream`() {
        val state = DefaultStateBuilder(
            projection()
        ).build(emptyList())

        assertEquals(0, state.count)
    }
}