package com.iqser.red.service.persistence.management.v1.processor.service.queue;

import java.io.IOException;
import java.time.OffsetDateTime;
import java.time.temporal.ChronoUnit;

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

import com.fasterxml.jackson.databind.ObjectMapper;
import com.iqser.red.service.persistence.management.v1.processor.configuration.MessagingConfiguration;
import com.iqser.red.service.persistence.management.v1.processor.model.PyInfraRequest;
import com.iqser.red.service.persistence.management.v1.processor.service.FileStatusProcessingUpdateService;
import com.iqser.red.service.persistence.management.v1.processor.service.FileStatusService;
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.file.FileErrorInfo;

import io.micrometer.observation.ObservationRegistry;
import lombok.AccessLevel;
import lombok.RequiredArgsConstructor;
import lombok.experimental.FieldDefaults;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
@RequiredArgsConstructor
@FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true)
public class ChunkingMessageReceiver {

    public static final String CHUNKING_RESPONSE_LISTENER_ID = "chunking-response-listener";

    FileStatusService fileStatusService;
    ObservationRegistry observationRegistry;
    FileStatusProcessingUpdateService fileStatusProcessingUpdateService;
    ObjectMapper mapper;


    @RabbitListener(id = CHUNKING_RESPONSE_LISTENER_ID)
    public void receive(Message message) {

        PyInfraRequest pyInfraRequest = parsePyInfraRequest(message);
        addFileIdToTrace(pyInfraRequest.getFileUuid());

        log.info("Received message {} for dossierId {} and fileId  {}", MessagingConfiguration.CHUNKING_RESPONSE_EXCHANGE, pyInfraRequest.getDossierUuid(), pyInfraRequest.getFileUuid());
        fileStatusService.setStatusAnalyse(pyInfraRequest.getDossierUuid(), pyInfraRequest.getFileUuid(), false);
    }


    @RabbitListener(queues = MessagingConfiguration.CHUNKING_DLQ)
    public void handleDLQ(Message message) {

        PyInfraRequest pyInfraRequest = parsePyInfraRequest(message);
        addFileIdToTrace(pyInfraRequest.getFileUuid());

        log.warn("Received message {} for dossierId {} and fileId {}", MessagingConfiguration.CHUNKING_DLQ, pyInfraRequest.getDossierUuid(), pyInfraRequest.getFileUuid());
        fileStatusProcessingUpdateService.analysisFailed(pyInfraRequest.getDossierUuid(),
                                                         pyInfraRequest.getFileUuid(),
                                                         new FileErrorInfo("chunking service failed",
                                                                           MessagingConfiguration.CHUNKING_DLQ,
                                                                           "junker-chunker-service",
                                                                           OffsetDateTime.now().truncatedTo(ChronoUnit.MILLIS)));
    }


    private PyInfraRequest parsePyInfraRequest(Message message) {

        PyInfraRequest pyInfraRequest = null;
        try {
            pyInfraRequest = mapper.readValue(message.getBody(), PyInfraRequest.class);
        } catch (IOException e) {
            log.error("Could not decode message {}", new String(message.getBody()));
            throw new RuntimeException(e);
        }
        return pyInfraRequest;
    }


    // This can be removed if tracing is implemented in python services.
    private void addFileIdToTrace(String fileId) {

        if (observationRegistry.getCurrentObservation() != null) {
            observationRegistry.getCurrentObservation().highCardinalityKeyValue("fileId", fileId);
        }
    }

}
