package dp.kotul.starter.messaging.service

import com.fasterxml.jackson.databind.ObjectMapper
import dp.kotul.starter.filter.CorrelationHeaderAndLoggingFilter
import dp.kotul.starter.messaging.model.BaseMessage
import dp.kotul.starter.messaging.model.Router
import org.slf4j.Logger
import org.springframework.messaging.Message
import org.springframework.stereotype.Component

interface GenericMessageReceiver {
    fun receiveMessage(incoming: Message<Any>, routingKey: String, routerList: List<Router<*>>, logBaseMessage: Boolean = false)
}

@Component
class GenericMessageReceiverImpl(val log: Logger, val mapper: ObjectMapper) : GenericMessageReceiver {
    override fun receiveMessage(incoming: Message<Any>, routingKey: String, routerList: List<Router<*>>, logBaseMessage: Boolean) {
        val router = routerList.find { it.routingKey == routingKey } as Router<BaseMessage>?
        if (router == null) {
            log.error("Routing key $routingKey not specified in routerList $routerList")
            return
        }

        val message: BaseMessage

        try {
            message = mapper.convertValue(incoming.payload, router.type)
        } catch(e: Exception) {
            log.error("An error occurred when receiving a message for routing key: $routingKey", e)
            return
        }

        CorrelationHeaderAndLoggingFilter.setCorrelationId(message.correlationId)

        val messageToLog = if (logBaseMessage) {
            message.toStringBase()
        } else {
            message.toString()
        }

        try {
            log.debug("Receiving ${routingKey}, message: $messageToLog")
            router.consumer.accept(message)
        } catch (e: Exception) {
            log.error("An error occurred when receiving a message: $messageToLog for routing key: $routingKey", e)
        }
    }
}
