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

import java.util.List;
import java.util.Optional;

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

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.iqser.red.service.persistence.management.v1.processor.entity.annotations.ManualRedactionEntryEntity;
import com.iqser.red.service.persistence.management.v1.processor.entity.annotations.ManualResizeRedactionEntity;
import com.iqser.red.service.persistence.management.v1.processor.entity.annotations.RectangleEntity;
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.annotations.AddRedactionPersistenceService;
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.annotations.ResizeRedactionPersistenceService;
import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.Position;
import com.iqser.red.service.redaction.v1.model.AnalyzeResponse;

import io.opentelemetry.api.internal.StringUtils;
import lombok.AccessLevel;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.experimental.FieldDefaults;
import lombok.extern.slf4j.Slf4j;

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

    public static final String REDACTION_RESPONSE_LISTENER_ID = "redaction-response-listener";

    ObjectMapper objectMapper;
    AddRedactionPersistenceService addRedactionPersistenceService;
    ResizeRedactionPersistenceService resizeRedactionPersistenceService;


    @SneakyThrows
    @RabbitHandler
    @RabbitListener(id = REDACTION_RESPONSE_LISTENER_ID)
    public void receive(Message message) throws JsonProcessingException {

        AnalyzeResponse analyzeResponse = objectMapper.readValue(message.getBody(), new TypeReference<>() {
        });
        String fileId = analyzeResponse.getFileId();

        log.info("Received Surrounding Text Analysis response for file: {}", fileId);
        analyzeResponse.getUnprocessedManualEntities()
                .forEach(unprocessedManualEntity -> {
                    Optional<ManualRedactionEntryEntity> optionalManualRedactionEntry = addRedactionPersistenceService.findById(unprocessedManualEntity.getAnnotationId(), fileId);

                    if (optionalManualRedactionEntry.isPresent()) {
                        ManualRedactionEntryEntity manualRedactionEntry = optionalManualRedactionEntry.get();
                        manualRedactionEntry.setTextBefore(unprocessedManualEntity.getTextBefore());
                        manualRedactionEntry.setTextAfter(unprocessedManualEntity.getTextAfter());
                        manualRedactionEntry.setPositions(convertPositions(unprocessedManualEntity.getPositions()));
                        if (StringUtils.isNullOrEmpty(manualRedactionEntry.getSection()) || (!StringUtils.isNullOrEmpty(unprocessedManualEntity.getSection())
                                                                                             && !manualRedactionEntry.getSection().equals(unprocessedManualEntity.getSection()))) {
                            manualRedactionEntry.setSection(unprocessedManualEntity.getSection());
                        }
                        addRedactionPersistenceService.update(manualRedactionEntry);
                    }

                    Optional<ManualResizeRedactionEntity> optionalManualResizeRedactionEntity = resizeRedactionPersistenceService.findResizeRedactionById(fileId,
                                                                                                                                                          unprocessedManualEntity.getAnnotationId());
                    if (optionalManualResizeRedactionEntity.isPresent()) {
                        ManualResizeRedactionEntity manualResizeRedaction = optionalManualResizeRedactionEntity.get();
                        resizeRedactionPersistenceService.updateSurroundingText(manualResizeRedaction.getId(),
                                                                                unprocessedManualEntity.getTextBefore(),
                                                                                unprocessedManualEntity.getTextAfter());
                    }
                });
    }


    private List<RectangleEntity> convertPositions(List<Position> positions) {

        return positions.stream()
                .map(position -> RectangleEntity.builder()
                        .page(position.getPageNumber())
                        .height(position.h())
                        .width(position.w())
                        .topLeftX(position.x())
                        .topLeftY(position.y())
                        .build())
                .toList();
    }

}
