package com.correx.apps.server.research

import com.correx.core.events.EventDispatcher
import com.correx.core.events.events.EgressHostsGrantedEvent
import com.correx.core.events.types.SessionId
import com.correx.infrastructure.persistence.InMemoryEventStore
import kotlinx.coroutines.test.runTest
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.Test

class SourceListApprovalTest {

    private val sessionId = SessionId("s1")

    private fun grants(store: InMemoryEventStore, session: SessionId = sessionId): List<EgressHostsGrantedEvent> =
        store.read(session).map { it.payload }.filterIsInstance<EgressHostsGrantedEvent>()

    @Test
    fun `emits exactly one EgressHostsGrantedEvent with the extracted hosts for the session`() = runTest {
        val store = InMemoryEventStore()
        val granted = approveSourceList(
            dispatcher = EventDispatcher(store),
            sessionId = sessionId,
            urls = listOf(
                "https://example.com/a",
                "https://example.com/b",
                "https://docs.kotlinlang.org/spec",
            ),
        )

        assertEquals(setOf("example.com", "docs.kotlinlang.org"), granted)

        val emitted = grants(store)
        assertEquals(1, emitted.size)
        val event = emitted.single()
        assertEquals(sessionId, event.sessionId)
        assertEquals(setOf("example.com", "docs.kotlinlang.org"), event.hosts)
        assertEquals(BATCH_SOURCE_LIST_REASON, event.reason)
    }

    @Test
    fun `grant is recorded under the right session`() = runTest {
        val store = InMemoryEventStore()
        approveSourceList(EventDispatcher(store), sessionId, listOf("https://only-mine.com/x"))

        assertEquals(1, grants(store).size)
        assertTrue(grants(store, SessionId("other")).isEmpty())
    }

    @Test
    fun `no parseable host emits no event`() = runTest {
        val store = InMemoryEventStore()
        val granted = approveSourceList(
            dispatcher = EventDispatcher(store),
            sessionId = sessionId,
            urls = listOf("/relative", "just text", ""),
        )

        assertTrue(granted.isEmpty())
        assertTrue(grants(store).isEmpty())
    }
}
