package space.nstart.pcp.pcp_request_service.message

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_request_service.service.SatelliteService
import space.nstart.pcp.pcp_types_lib.dto.satellite.SatelliteDeletedEventDTO
import tools.jackson.databind.ObjectMapper

private const val SATELLITE_DELETED_CONSUMER_GROUP = "pcp-ballistics-service-satellite-deleted"

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

    private val logger = LoggerFactory.getLogger(this::class.java)
    private val objectMapper = objectMapperProvider.ifAvailable
        ?: throw IllegalStateException("ObjectMapper bean is required for SatelliteDeletedKafkaListener")

    @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 rootNode = objectMapper.readTree(message)
            val payloadNode = rootNode["data"] ?: throw IllegalArgumentException("В сообщении отсутствует поле data")
            val event = objectMapper.treeToValue(payloadNode, SatelliteDeletedEventDTO::class.java)
            logger.info(
                "Received SatelliteDeletedEvent in ballistics-service: satelliteId={}, noradId={}, consumerGroup={}",
                event.satelliteId,
                event.noradId,
                SATELLITE_DELETED_CONSUMER_GROUP
            )
            deleteByIdentifiers(event)
        } catch (exception: Exception) {
            logger.error("Failed to process SatelliteDeletedEvent in ballistics-service: {}", exception.message, exception)
            throw exception
        }
    }

    private fun deleteByIdentifiers(event: SatelliteDeletedEventDTO) {
        event.deleteIdentifiers().forEach { satelliteId ->
            satelliteService.clear(satelliteId)
        }
        logger.info(
            "SatelliteDeletedEvent processed in ballistics-service: satelliteId={}, noradId={}, consumerGroup={}",
            event.satelliteId,
            event.noradId,
            SATELLITE_DELETED_CONSUMER_GROUP
        )
    }

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