package space.nstart.pcp.complan.service

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.boot.autoconfigure.condition.ConditionalOnProperty
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.pcp_types_lib.message.PcpKafkaEvent

private const val SATELLITE_DELETED_CONSUMER_GROUP = "pcp-dynamic-plan-service-satellite-deleted"

@ConditionalOnProperty(name = ["spring.kafka.bootstrap-servers"], matchIfMissing = false)
@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(
        topics = ["\${app.kafka.topics.satellites:pcp.satellites}"],
        groupId = SATELLITE_DELETED_CONSUMER_GROUP
    )
    fun consume(message: String) {
        try {
            val kafkaMessage = objectMapper.readValue(
                message,
                object : TypeReference<KafkaMessage<SatelliteDeletedEventDTO>>() {}
            )
            if (kafkaMessage.type != PcpKafkaEvent.SatelliteDeletedEvent) {
                logger.debug("Ignoring Kafka message with unsupported type {}", kafkaMessage.type)
                return
            }

            val event = kafkaMessage.data
            logger.info(
                "Received SatelliteDeletedEvent in pcp-dynamic-plan-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 pcp-dynamic-plan-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 pcp-dynamic-plan-service", exception)
            throw exception
        }
    }

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