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

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.stereotype.Service;

import com.fasterxml.jackson.core.JsonProcessingException;
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.entity.dossier.DossierEntity;
import com.iqser.red.service.persistence.management.v1.processor.entity.dossier.FileEntity;
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.FileStatusPersistenceService;
import com.iqser.red.service.search.v1.model.IndexMessage;
import com.iqser.red.service.search.v1.model.IndexMessageType;

import lombok.RequiredArgsConstructor;

@Service
@RequiredArgsConstructor
public class IndexingService {

    private final RabbitTemplate rabbitTemplate;
    private final ObjectMapper objectMapper;
    private final DossierService dossierService;
    private final FileStatusPersistenceService fileStatusPersistenceService;


    public void reindex(String dossierId, Set<String> fileIds, boolean dropIndex) {

        if (dropIndex) {
            addToIndexingQueue(IndexMessageType.DROP, null, null, null, 2);
        } else {
            List<Pair<String, String>> reindexDossierIds = new ArrayList<>();
            if (dossierId == null) {
                List<DossierEntity> dossiers = dossierService.getAllDossiers();
                for (DossierEntity dossier : dossiers) {
                    if (dossier.getSoftDeletedTime() == null || dossier.getArchivedTime() != null) {
                        reindexDossierIds.add(new ImmutablePair<>(dossier.getDossierTemplateId(), dossier.getId()));
                    }
                }
            } else {
                DossierEntity dossier = dossierService.getDossierById(dossierId);
                if (dossier.getSoftDeletedTime() == null || dossier.getArchivedTime() != null) {
                    reindexDossierIds.add(new ImmutablePair<>(dossier.getDossierTemplateId(), dossier.getId()));
                }
            }

            for (Pair<String, String> reindexDossierId : reindexDossierIds) {
                List<FileEntity> fileStatuses = fileStatusPersistenceService.getStatusesForDossier(reindexDossierId.getRight());
                for (FileEntity fileStatus : fileStatuses) {
                    if (fileStatus.isSoftOrHardDeleted()) {
                        continue;
                    }
                    if (fileIds != null && !fileIds.isEmpty() && !fileIds.contains(fileStatus.getId())) {
                        continue;
                    }
                    addToIndexingQueue(IndexMessageType.INSERT, reindexDossierId.getLeft(), reindexDossierId.getRight(), fileStatus.getId(), 2);
                }
            }
        }
    }


    public void addToIndexingQueue(IndexMessageType indexMessageType, String dossierTemplateId, String dossierId, String fileId, int priority) {

        rabbitTemplate.convertAndSend(MessagingConfiguration.INDEXING_QUEUE,
                IndexMessage.builder().messageType(indexMessageType).dossierTemplateId(dossierTemplateId).dossierId(dossierId).fileId(fileId).build(),
                message -> {
                    message.getMessageProperties().setPriority(priority);
                    return message;
                });
    }


    public void addToDeleteFromIndexQueue(String dossierId, String fileId, int priority) {

        rabbitTemplate.convertAndSend(MessagingConfiguration.DELETE_FROM_INDEX_QUEUE, IndexMessage.builder().dossierId(dossierId).fileId(fileId).build(), message -> {
            message.getMessageProperties().setPriority(priority);
            return message;
        });
    }

}
