package org.nstart.dep265.requestservice.kafka

import com.fasterxml.jackson.core.type.TypeReference
import com.fasterxml.jackson.databind.ObjectMapper
import jakarta.validation.ConstraintViolationException
import jakarta.validation.Validator
import org.nstart.dep265.requestservice.mapper.RoutePassportMapper
import org.nstart.dep265.requestservice.service.RouteMatchingService
import org.slf4j.LoggerFactory
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

@Component
class RequestKafkaListener(
    private val objectMapper: ObjectMapper,

    private val validator: Validator,

    private val routeMatchingService: RouteMatchingService,

    private val routePassportMapper: RoutePassportMapper,
) {
    private val log = LoggerFactory.getLogger(this::class.java)

    @KafkaListener(
        topics = ["\${app.kafka.topics.route}"],
        groupId = "\${spring.kafka.consumer.group-id}-route",
    )
    fun consumeRoute(message: String) {
        try {
            val routeMessage = objectMapper.readValue(
                message,
                object : TypeReference<KafkaMessage<RoutePassportDto>>() {},
            )
            val route = routePassportMapper.toRouteDto(routeMessage.data)
            validate(route)
            routeMatchingService.process(route)
        } catch (exception: Exception) {
            log.error("Failed to process Kafka route payload", exception)
            throw exception
        }
    }

    private fun validate(value: Any) {
        val violations = validator.validate(value)
        if (violations.isNotEmpty()) {
            throw ConstraintViolationException(violations)
        }
    }
}
