package space.nstart.pcp.tle_monitoring_service.message

import com.fasterxml.jackson.core.type.TypeReference
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import org.slf4j.LoggerFactory
import org.springframework.beans.factory.ObjectProvider
import org.springframework.kafka.annotation.KafkaListener
import org.springframework.stereotype.Component
import space.nstart.pcp.pcp_types_lib.dto.satellite.SatelliteDeletedEventDTO
import space.nstart.pcp.pcp_types_lib.message.KafkaMessage
import space.nstart.pcp.tle_monitoring_service.service.SatelliteDeletedService

private const val SATELLITE_DELETED_CONSUMER_GROUP = "pcp-tle-monitoring-service-satellite-deleted"

@Component
class SatelliteDeletedKafkaListener(
    objectMapperProvider: ObjectProvider<ObjectMapper>,
    private val satelliteDeletedService: SatelliteDeletedService
) {

    private val logger = LoggerFactory.getLogger(this::class.java)
    private val objectMapper = objectMapperProvider.ifAvailable ?: jacksonObjectMapper().findAndRegisterModules()

    @KafkaListener(
        id = "satelliteDeletedFilter",
        topics = ["\${app.kafka.topics.satellites:pcp.satellites}"],
        groupId = SATELLITE_DELETED_CONSUMER_GROUP,
        filter = "satelliteDeletedFilter"
    )
    fun consume(message: String?) {
        if (message.isNullOrBlank()) {
            logger.warn("Received empty SatelliteDeletedEvent Kafka message")
            return
        }

        try {
            val kafkaMessage = objectMapper.readValue(
                message,
                object : TypeReference<KafkaMessage<SatelliteDeletedEventDTO>>() {}
            )
            val event = kafkaMessage.data
            logger.info(
                "Received SatelliteDeletedEvent in tle-monitoring-service: satelliteId={}, noradId={}, eventId={}, traceId={}, source={}, consumerGroup={}",
                event.satelliteId,
                event.noradId,
                kafkaMessage.id,
                kafkaMessage.traceId,
                kafkaMessage.source,
                SATELLITE_DELETED_CONSUMER_GROUP
            )
            event.deleteIdentifiers().forEach { satelliteId ->
                satelliteDeletedService.deleteSatelliteData(satelliteId)
            }
            logger.info(
                "SatelliteDeletedEvent processed in tle-monitoring-service: satelliteId={}, noradId={}, eventId={}, traceId={}, source={}, consumerGroup={}",
                event.satelliteId,
                event.noradId,
                kafkaMessage.id,
                kafkaMessage.traceId,
                kafkaMessage.source,
                SATELLITE_DELETED_CONSUMER_GROUP
            )
        } catch (exception: Exception) {
            logger.error("Failed to process SatelliteDeletedEvent in tle-monitoring-service", exception)
            throw exception
        }
    }

    private fun SatelliteDeletedEventDTO.deleteIdentifiers(): List<Long> =
        listOfNotNull(satelliteId, noradId).distinct()
}
