package com.knecon.fforesight.service.layoutparser.server.queue;

import java.util.Arrays;
import java.util.Locale;
import java.util.Map;
import java.util.stream.Collectors;

import org.springframework.amqp.AmqpRejectAndDontRequeueException;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.stereotype.Service;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.knecon.fforesight.service.layoutparser.internal.api.queue.LayoutParsingFinishedEvent;
import com.knecon.fforesight.service.layoutparser.internal.api.queue.LayoutParsingQueueNames;
import com.knecon.fforesight.service.layoutparser.internal.api.queue.LayoutParsingRequest;
import com.knecon.fforesight.service.layoutparser.internal.api.queue.LayoutParsingType;
import com.knecon.fforesight.service.layoutparser.processor.LayoutParsingPipeline;

import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
@RequiredArgsConstructor
public class MessageHandler {

    private final LayoutParsingPipeline layoutParsingPipeline;
    private final ObjectMapper objectMapper;
    private final RabbitTemplate rabbitTemplate;
    private final static String X_PIPELINE_PREFIX = "X-PIPE-";


    @RabbitHandler
    @RabbitListener(queues = LayoutParsingQueueNames.LAYOUT_PARSING_REQUEST_QUEUE)
    @SneakyThrows
    public void receiveLayoutParsingRequest(Message message) {

        LayoutParsingRequest layoutParsingRequest = objectMapper.readValue(message.getBody(), LayoutParsingRequest.class);

        if (layoutParsingRequest.layoutParsingType().equals(LayoutParsingType.CLARIFYND) && layoutParsingRequest.researchDocumentStorageId() == null) {
            throw new IllegalArgumentException("ResearchDocumentDataStorageId is null!");
        }
        log.info("Layout parsing request received {}", layoutParsingRequest.identifier());
        if (message.getMessageProperties().isRedelivered()) {
            throw new AmqpRejectAndDontRequeueException(String.format("Error during last layout parsing of request with identifier: %s, do not retry.",
                    layoutParsingRequest.identifier()));
        }
        LayoutParsingFinishedEvent layoutParsingFinishedEvent = layoutParsingPipeline.parseLayoutAndSaveFilesToStorage(layoutParsingRequest);
        sendLayoutParsingFinishedEvent(layoutParsingFinishedEvent, message);
    }


    public void sendLayoutParsingFinishedEvent(LayoutParsingFinishedEvent layoutParsingFinishedEvent, Message message) {

        Arrays.stream(layoutParsingFinishedEvent.message().split("\n")).forEach(log::info);
        rabbitTemplate.convertAndSend(LayoutParsingQueueNames.LAYOUT_PARSING_FINISHED_EVENT_QUEUE, layoutParsingFinishedEvent, m -> {
            var forwardHeaders = message.getMessageProperties()
                    .getHeaders()
                    .entrySet()
                    .stream()
                    .filter(e -> e.getKey().toUpperCase(Locale.ROOT).startsWith(X_PIPELINE_PREFIX))
                    .collect(Collectors.toMap(Map.Entry::getKey,
                            Map.Entry::getValue));
            m.getMessageProperties().getHeaders().putAll(forwardHeaders);
            return m;
        });
    }

}
