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

import java.util.Comparator;
import java.util.List;

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.springframework.amqp.core.AmqpAdmin;
import org.springframework.stereotype.Service;

import com.iqser.red.service.persistence.management.v1.processor.configuration.MessagingConfiguration;
import com.iqser.red.service.persistence.management.v1.processor.service.FileStatusService;
import com.iqser.red.service.persistence.management.v1.processor.settings.FileManagementServiceSettings;
import com.iqser.red.service.persistence.management.v1.processor.utils.TenantUtils;
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.file.FileModel;
import com.knecon.fforesight.tenantcommons.TenantContext;
import com.knecon.fforesight.tenantcommons.TenantProvider;
import com.knecon.fforesight.tenantcommons.model.UpdateDetailsRequest;

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

@Slf4j
@Service
@RequiredArgsConstructor
public class AutomaticAnalysisJob implements Job {

    private final AmqpAdmin amqpAdmin;
    private final FileManagementServiceSettings fileManagementServiceSettings;
    private final FileStatusService fileStatusService;
    private final TenantProvider tenantProvider;

    @Setter
    private boolean schedulingStopped;


    @Override
    public void execute(JobExecutionContext jobExecutionContext) {

        if (fileManagementServiceSettings.isMigrateOnly() || schedulingStopped) {
            log.info("Skipping scheduling during migration");
            return;
        }

        tenantProvider.getTenants().forEach(tenant -> {

            if (!TenantUtils.isTenantReadyForPersistence(tenant)) {
                return;
            }

            TenantContext.setTenantId(tenant.getTenantId());

            var redactionQueueInfo = amqpAdmin.getQueueInfo(MessagingConfiguration.REDACTION_QUEUE);
            if (redactionQueueInfo != null) {
                log.debug("[Tenant:{}] Checking queue status to see if background analysis can happen. Currently {} holds {} elements and has {} consumers",
                        tenant.getTenantId(),
                        MessagingConfiguration.REDACTION_QUEUE,
                        redactionQueueInfo.getMessageCount(),
                        redactionQueueInfo.getConsumerCount());
                // only 1 file in queue
                var consumerCount = redactionQueueInfo.getConsumerCount();
                if (redactionQueueInfo.getMessageCount() <= consumerCount * 5) {
                    // queue up 5 files
                    var allStatuses = getAllRelevantStatuses();

                    allStatuses.sort(Comparator.comparing(FileModel::getLastUpdated));

                    var allStatusesIterator = allStatuses.iterator();
                    log.debug("[Tenant:{}] Files that require reanalysis: {}", TenantContext.getTenantId(), allStatuses.size());

                    var queuedFiles = 0;

                    while (queuedFiles < (consumerCount * 5) && allStatusesIterator.hasNext()) {
                        var next = allStatusesIterator.next();
                        // in case the file doesn't have numberOfPages set, we assume an average.

                        if (next.isFullAnalysisRequired()) {
                            log.info("[Tenant:{}] Queued file: {} for automatic full analysis! ", TenantContext.getTenantId(), next.getFilename());
                            fileStatusService.setStatusFullReprocess(next.getDossierId(), next.getId(), false, false);
                        } else if (next.isReanalysisRequired()) {
                            log.info("[Tenant:{}] Queued file: {} for automatic reanalysis! ", TenantContext.getTenantId(), next.getFilename());
                            fileStatusService.setStatusReprocess(next.getDossierId(), next.getId(), false);
                        }

                        queuedFiles++;
                    }
                }

            } else {
                log.info("[Tenant:{}] Failed to obtain queue info for queue: {}", TenantContext.getTenantId(), MessagingConfiguration.REDACTION_QUEUE);
            }

        });
    }


    private List<FileModel> getAllRelevantStatuses() {

        return fileStatusService.getAllRelevantStatusesForReanalysisScheduler();
    }

}
