package com.correx.core.kernel.orchestration

import com.correx.core.events.events.EventMetadata
import com.correx.core.events.events.EventPayload
import com.correx.core.events.events.FileWrittenEvent
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.events.types.ToolInvocationId
import kotlinx.datetime.Instant
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Assertions.assertNotEquals
import org.junit.jupiter.api.Test

class WorkspaceStateKeyTest {

    @Test
    fun `key is stable for the same manifest and independent of write order`() {
        val a = workspaceStateKey(listOf(wrote("a.kt", "h1"), wrote("b.kt", "h2")))
        val b = workspaceStateKey(listOf(wrote("b.kt", "h2"), wrote("a.kt", "h1")))
        assertEquals(a, b)
    }

    @Test
    fun `a later write to a file changes the key`() {
        val before = workspaceStateKey(listOf(wrote("a.kt", "h1")))
        val after = workspaceStateKey(listOf(wrote("a.kt", "h1"), wrote("a.kt", "h2")))
        assertNotEquals(before, after, "a changed post-image must invalidate a prior baseline")
    }

    @Test
    fun `latest post-image hash wins for a repeatedly-written path`() {
        val single = workspaceStateKey(listOf(wrote("a.kt", "h2")))
        val rewritten = workspaceStateKey(listOf(wrote("a.kt", "h1"), wrote("a.kt", "h2")))
        assertEquals(single, rewritten)
    }

    private var seq = 0L
    private fun wrote(path: String, hash: String) = StoredEvent(
        metadata = EventMetadata(
            eventId = EventId("e${seq++}"),
            sessionId = SessionId("s1"),
            timestamp = Instant.parse("2026-01-01T00:00:00Z"),
            schemaVersion = 1,
            causationId = null,
            correlationId = null,
        ),
        sequence = seq,
        sessionSequence = seq,
        payload = FileWrittenEvent(
            invocationId = ToolInvocationId("inv"),
            sessionId = SessionId("s1"),
            path = path,
            postImageHash = hash,
            preExisted = false,
            timestampMs = 1L,
        ) as EventPayload,
    )
}
