package space.nstart.pcp.pcp_mission_planing_service.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.routes.RoutePassportDto
import space.nstart.pcp.pcp_types_lib.message.KafkaMessage
import space.nstart.pcp.pcp_types_lib.message.PcpKafkaEvent

@ConditionalOnProperty(name = ["spring.kafka.bootstrap-servers"], matchIfMissing = false)
@Component
class ModeStatusChangedKafkaListener(
    objectMapperProvider: ObjectProvider<ObjectMapper>,
    private val missionPlaningService: MissionPlaningService,
) {

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

    @KafkaListener(
        topics = ["\${app.kafka.topics.mode-status-changed:pcp.route.in.v1}"],
        groupId = "\${spring.kafka.consumer.group-id}-mode-status-changed"
    )
    fun consume(message: String) {
        try {
            val kafkaMessage = objectMapper.readValue(
                message,
                object : TypeReference<KafkaMessage<RoutePassportDto>>() {},
            )
            if (kafkaMessage.type != PcpKafkaEvent.ModeStatusChangedEvent) {
                logger.debug("Ignoring Kafka message with unsupported type {}", kafkaMessage.type)
                return
            }

            val routePassport = kafkaMessage.data
            val mode = missionPlaningService.findMode(routePassport)
            if (mode?.id == null) {
                logger.error(
                    "Survey mode not found for ModeStatusChangedEvent: routeId={}, satelliteNumber={}, revolution={}, intervalBegin={}, routeStatus={}, traceId={}, source={}",
                    routePassport.routeId,
                    routePassport.kaShort,
                    routePassport.orbitNumber,
                    routePassport.intervalBegin,
                    routePassport.routeStatus,
                    kafkaMessage.traceId,
                    kafkaMessage.source,
                )
                return
            }

            missionPlaningService.updateSurveyModeStatus(mode.id, routePassport.routeStatus)
            logger.info(
                "Mode status changed event processed: routeId={}, surveyModeId={}, satelliteNumber={}, revolution={}, intervalBegin={}, routeStatus={}, traceId={}, source={}",
                routePassport.routeId,
                mode.id,
                routePassport.kaShort,
                routePassport.orbitNumber,
                routePassport.intervalBegin,
                routePassport.routeStatus,
                kafkaMessage.traceId,
                kafkaMessage.source,
            )
        } catch (exception: Exception) {
            logger.error("Failed to process ModeStatusChangedEvent Kafka payload", exception)
            throw exception
        }
    }
}
