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

import static com.iqser.red.service.persistence.management.v1.processor.exception.DossierNotFoundException.DOSSIER_NOT_FOUND_MESSAGE;

import java.util.Comparator;
import java.util.EnumMap;
import java.util.List;
import java.util.stream.Collectors;

import org.springframework.stereotype.Service;

import com.iqser.red.service.persistence.management.v1.processor.entity.dossier.DossierEntity;
import com.iqser.red.service.persistence.management.v1.processor.entity.projection.DossierStatsFileProjection;
import com.iqser.red.service.persistence.management.v1.processor.exception.DossierNotFoundException;
import com.iqser.red.service.persistence.service.v1.api.shared.model.DossierStats;
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.file.FileModel;

import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.file.ProcessingStatus;
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.file.WorkflowStatus;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
@RequiredArgsConstructor
public class DossierStatsService {

    private final DossierService dossierService;
    private final FileStatusService fileStatusService;

//    private Map<String, DossierStats> dossierStatsMap = new HashMap<>();

//    @Scheduled(fixedDelay = 10000, initialDelay = 1000)
//    external void computeDossierStats() {
//        log.info("Computing Dossier Stats ... ");
//        long start = System.currentTimeMillis();
//        Map<String, DossierStats> dossierStatsComputeMap = new HashMap<>();
//        dossierService.getAllDossiers().stream()
//                .filter(d -> !d.getStatus().equals(DossierStatus.DELETED))
//                .forEach(d -> dossierStatsComputeMap.put(d.getId(), computeDossierStats(d)));
//        dossierStatsMap.clear();
//        dossierStatsMap = dossierStatsComputeMap;
//        log.info("Dossier Stats Computed in {}ms", System.currentTimeMillis() - start);
//    }


    public DossierStats getDossierStats(String dossierId) {
//        var stats = dossierStatsMap.get(dossierId);
//        if (stats == null) {
//            stats = computeDossierStats(dossierService.getDossierById(dossierId));
//            dossierStatsMap.put(dossierId, stats);
//        }
        return computeDossierStats(dossierService.getDossierById(dossierId));
    }


    private DossierStats computeDossierStats(DossierEntity dossierEntity) {

        String dossierId = dossierEntity.getId();

        if (dossierEntity.getHardDeletedTime() != null) {
            throw new DossierNotFoundException(DOSSIER_NOT_FOUND_MESSAGE);
        }

        List<DossierStatsFileProjection> files = fileStatusService.getDossierStatsFiles(dossierId);
        int numberOfSoftDeletedFiles = fileStatusService.countSoftDeletedFiles(dossierId);

        DossierStats stats = DossierStats.builder()
                .dossierId(dossierId)
                .numberOfFiles(files.size())
                .numberOfSoftDeletedFiles(numberOfSoftDeletedFiles)
                .fileCountPerProcessingStatus(new EnumMap<>(ProcessingStatus.class))
                .fileCountPerWorkflowStatus(new EnumMap<>(WorkflowStatus.class))
                .build();

        for (DossierStatsFileProjection file : files) {
            stats.setNumberOfPages(stats.getNumberOfPages() + file.getNumberOfPages());
            stats.setNumberOfExcludedPages(stats.getNumberOfExcludedPages() + file.getExcludedPages().size());

            if (file.isHasRedactions()) {
                stats.setHasRedactionsFilePresent(true);
            }
            if (file.isHasHints() && !file.isHasRedactions()) {
                stats.setHasHintsNoRedactionsFilePresent(true);
            }
            if (file.isHasSuggestions()) {
                stats.setHasSuggestionsFilePresent(true);
            }
            if (file.isHasUpdates()) {
                stats.setHasUpdatesFilePresent(true);
            }
            if (!file.isHasRedactions() && !file.isHasHints() && !file.isHasSuggestions() && !file.isHasUpdates()) {
                stats.setHasNoFlagsFilePresent(true);
            }

            stats.getFileCountPerProcessingStatus().merge(file.getProcessingStatus(), 1, Integer::sum);
            stats.getFileCountPerWorkflowStatus().merge(file.getWorkflowStatus(), 1, Integer::sum);

            if (stats.getLastFileUpdateDate() == null ||
                (file.getLastUpdated() != null && file.getLastUpdated().isAfter(stats.getLastFileUpdateDate()))) {
                stats.setLastFileUpdateDate(file.getLastUpdated());
            }

            if (stats.getFileManipulationDate() == null ||
                (file.getFileManipulationDate() != null && file.getFileManipulationDate().isAfter(stats.getFileManipulationDate()))) {
                stats.setFileManipulationDate(file.getFileManipulationDate());
            }
        }

        return stats;
    }

}
