package space.nstart.pcp.pcp_request_service.message

import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Test
import org.springframework.beans.factory.ObjectProvider
import space.nstart.pcp.pcp_request_service.service.SatelliteIcEventService
import space.nstart.pcp.pcp_types_lib.dto.ballistics.MovementModel
import space.nstart.pcp.pcp_types_lib.dto.ballistics.SatelliteICDTO
import tools.jackson.databind.ObjectMapper

class SatelliteIcRvKafkaListenerTest {

    private val objectMapper = ObjectMapper()
    private val satelliteIcEventService = RecordingSatelliteIcEventService()
    private val listener = SatelliteIcRvKafkaListener(
        objectMapperProvider = SingleObjectProvider(objectMapper),
        satelliteIcEventService = satelliteIcEventService
    )

    @Test
    fun `listener parses ICRV placed event payload and delegates to service`() {
        listener.consume(
            """
            {
              "type": "ICRVPlacedEvent",
              "data": {
                "satelliteId": 56756,
                "ic": {
                  "orbPoint": {
                    "time": "2026-04-16T12:00:00",
                    "revolution": 42,
                    "vx": 1.0,
                    "vy": 2.0,
                    "vz": 3.0,
                    "x": 4.0,
                    "y": 5.0,
                    "z": 6.0
                  },
                  "sBall": 0.7,
                  "f81": 140.0
                }
              }
            }
            """.trimIndent()
        )

        assertEquals(56756L, satelliteIcEventService.lastMessage?.satelliteId)
        assertEquals(42L, satelliteIcEventService.lastMessage?.ic?.orbPoint?.revolution)
        assertEquals(140.0, satelliteIcEventService.lastMessage?.ic?.f81)
        assertEquals(MovementModel.FOTO, satelliteIcEventService.lastMessage?.movementModel)
    }

    @Test
    fun `listener substitutes default initial condition coefficients when payload contains nulls`() {
        listener.consume(
            """
            {
              "type": "ICRVPlacedEvent",
                "data": {
                "satelliteId": 56756,
                "movementModel": null,
                "ic": {
                  "orbPoint": {
                    "time": "2026-04-16T12:00:00",
                    "revolution": 42,
                    "vx": 1.0,
                    "vy": 2.0,
                    "vz": 3.0,
                    "x": 4.0,
                    "y": 5.0,
                    "z": 6.0
                  },
                  "sBall": null,
                  "f81": null
                }
              }
            }
            """.trimIndent()
        )

        assertEquals(0.0, satelliteIcEventService.lastMessage?.ic?.sBall)
        assertEquals(147.8, satelliteIcEventService.lastMessage?.ic?.f81)
        assertEquals(MovementModel.FOTO, satelliteIcEventService.lastMessage?.movementModel)
    }

    private class RecordingSatelliteIcEventService : SatelliteIcEventService() {
        var lastMessage: SatelliteICDTO? = null

        override fun handlePlacedIcRv(message: SatelliteICDTO) {
            lastMessage = message
        }
    }

    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
    }
}
