package space.nstart.pcp.slots_service.service

import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.Test
import org.springframework.beans.factory.ObjectProvider
import space.nstart.pcp.pcp_types_lib.dto.requests.slots.BookedSlotStatus
import space.nstart.pcp.pcp_types_lib.dto.requests.slots.BookedSlotsStatusChangedEvent
import space.nstart.pcp.pcp_types_lib.message.KafkaMessage
import space.nstart.pcp.pcp_types_lib.message.PcpKafkaEvent
import java.time.LocalDateTime
import java.util.UUID

class BookedSlotsKafkaListenerTest {

    private val objectMapper = jacksonObjectMapper().findAndRegisterModules()
    private val bookedSlotStatusService = RecordingBookedSlotStatusUpdater()
    private val listener = BookedSlotsKafkaListener(SingleObjectProvider(objectMapper), bookedSlotStatusService)

    @Test
    fun `consumer forwards booked slot status event to status service`() {
        val payload = objectMapper.writeValueAsString(
            KafkaMessage(
                type = PcpKafkaEvent.BookedSlotsStatusChangedEvent,
                data = BookedSlotsStatusChangedEvent(
                    bookedSlotIds = listOf(10L, 20L),
                    status = BookedSlotStatus.PROCESSED,
                    occurredAt = LocalDateTime.of(2026, 3, 31, 12, 0),
                    sourceService = "pcp-mission-planing-service",
                    missionId = UUID.randomUUID(),
                    modeId = 100L,
                    satelliteId = 77L
                )
            )
        )

        listener.consume(payload)

        assertEquals(listOf(10L, 20L), bookedSlotStatusService.lastBookedSlotIds)
        assertEquals(BookedSlotStatus.PROCESSED, bookedSlotStatusService.lastStatus)
        assertTrue(bookedSlotStatusService.lastContext.startsWith("kafka:pcp-mission-planing-service:"))
    }

    private class RecordingBookedSlotStatusUpdater : BookedSlotStatusUpdater {
        var lastBookedSlotIds: List<Long> = emptyList()
        var lastStatus: BookedSlotStatus? = null
        var lastContext: String = ""

        override fun updateBookedSlotsStatus(
            bookedSlotIds: List<Long>,
            targetStatus: BookedSlotStatus,
            context: String
        ): Int {
            lastBookedSlotIds = bookedSlotIds
            lastStatus = targetStatus
            lastContext = context
            return bookedSlotIds.size
        }
    }

    private class SingleObjectProvider<T : Any>(private val value: T) : ObjectProvider<T> {
        override fun getObject(vararg args: Any?): T = value
        override fun getIfAvailable(): T = value
        override fun getIfUnique(): T = value
        override fun getObject(): T = value
    }
}
