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

import java.time.OffsetDateTime;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import org.springframework.stereotype.Service;

import com.iqser.red.service.persistence.management.v1.processor.exception.BadRequestException;
import com.iqser.red.service.persistence.service.v1.api.shared.model.common.JSONPrimitive;
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.WorkflowStatus;
import com.iqser.red.service.search.v1.model.IndexMessageType;

import lombok.RequiredArgsConstructor;

@Service
@RequiredArgsConstructor
public class FileStatusManagementService {

    private final FileStatusService fileStatusService;
    private final ExcludeFromAnalysisService excludeFromAnalysis;
    private final AnalysisFlagsCalculationService analysisFlagsCalculationService;
    private final IndexingService indexingService;


    public JSONPrimitive<Boolean> hasChangesSince(String dossierId, JSONPrimitive<OffsetDateTime> since) {

        return JSONPrimitive.of(fileStatusService.hasChangesSince(dossierId, since.getValue()));
    }


    public List<FileModel> getDossierStatus(String dossierId) {

        return fileStatusService.getDossierStatus(dossierId).stream().filter(f -> !f.isSoftOrHardDeleted()).collect(Collectors.toList());
    }


    public List<FileModel> getAllDossierStatus(String dossierId) {

        return fileStatusService.getDossierStatus(dossierId);
    }


    public List<FileModel> getSoftDeletedDossierStatus(String dossierId) {

        return fileStatusService.getDossierStatus(dossierId)
                .stream()
                .filter(f3 -> f3.getDeleted() != null && f3.getHardDeletedTime() == null)
                .sorted((f11, f21) -> f21.getDeleted().compareTo(f11.getDeleted()))
                .collect(Collectors.toList());
    }


    public List<FileModel> getSoftDeletedForDossierList(List<String> dossierIds) {

        return fileStatusService.getSoftDeletedForDossierList(dossierIds);
    }


    public FileModel getFileStatus(String fileId) {

        return fileStatusService.getStatus(fileId);
    }


    public void updateFileModificationDate(String fileId) {

        this.fileStatusService.updateFileModificationDate(fileId, OffsetDateTime.now());
    }


    public void setCurrentFileAssignee(String dossierId, String fileId, String assigneeId) {

        fileStatusService.setAssignee(fileId, assigneeId);
        indexingService.addToIndexingQueue(IndexMessageType.UPDATE, null, dossierId, fileId, 2);
    }


    public void setStatusUnderReview(String dossierId, String fileId, String userId) {

        FileModel fileStatus = fileStatusService.getStatus(fileId);
        String assignee = fileStatus.getAssignee();
        if (userId != null) {
            assignee = userId;
        }
        fileStatusService.setStatusSuccessful(fileId, assignee != null ? WorkflowStatus.UNDER_REVIEW : WorkflowStatus.NEW);
        fileStatusService.setAssignee(fileId, assignee);
        analysisFlagsCalculationService.calculateFlags(dossierId, fileId);
        indexingService.addToIndexingQueue(IndexMessageType.UPDATE, null, dossierId, fileId, 2);
    }


    public void setStatusUnderApproval(String dossierId, String fileId, String approverId) {

        FileModel fileStatus = fileStatusService.getStatus(fileId);
        String assignee = fileStatus.getAssignee();
        if (approverId != null) {
            assignee = approverId;

        }
        fileStatusService.setStatusSuccessful(fileId, assignee != null ? WorkflowStatus.UNDER_APPROVAL : WorkflowStatus.NEW);
        fileStatusService.setAssignee(fileId, approverId);
        analysisFlagsCalculationService.calculateFlags(dossierId, fileId);
        indexingService.addToIndexingQueue(IndexMessageType.UPDATE, null, dossierId, fileId, 2);
    }


    public void setStatusApproved(String dossierId, String fileId, String approverId) {

        FileModel fileStatus = fileStatusService.getStatus(fileId);
        String assignee = fileStatus.getAssignee();
        if (assignee == null && approverId == null) {
            throw new BadRequestException("No user assigned for the approval");
        }
        if (approverId != null) {
            assignee = approverId;
        }
        fileStatusService.setAssignee(fileId, assignee);
        fileStatusService.setApprovalStatusSuccessful(dossierId, fileId, WorkflowStatus.APPROVED);
        indexingService.addToIndexingQueue(IndexMessageType.UPDATE, null, dossierId, fileId, 2);

    }


    public void setStatusNew(String dossierId, String fileId) {

        FileModel fileStatus = fileStatusService.getStatus(fileId);
        if (!WorkflowStatus.UNDER_REVIEW.equals(fileStatus.getWorkflowStatus())) {
            throw new BadRequestException("Allowed transition not possible from: " + fileStatus.getWorkflowStatus() + " to status NEW");
        }
        fileStatusService.setAssignee(fileId, null);
        fileStatusService.setStatusSuccessful(fileId, WorkflowStatus.NEW);
    }


    public void toggleExclusion(String dossierId, String fileId, boolean excluded) {

        excludeFromAnalysis.toggleExclusion(dossierId, fileId, excluded);

    }


    public void toggleAutomaticAnalysis(String dossierId, String fileId, boolean excludedFromAutomaticAnalysis) {

        excludeFromAnalysis.toggleAutomaticAnalysis(dossierId, fileId, excludedFromAutomaticAnalysis);

    }


    public void excludePages(String dossierId, String fileId, Set<Integer> pages) {

        FileModel fileStatus = fileStatusService.getStatus(fileId);
        Set<Integer> excludedPages = fileStatus.getExcludedPages();
        excludedPages.addAll(pages);

        fileStatusService.setExcludedPages(fileId, excludedPages);
        analysisFlagsCalculationService.calculateFlags(dossierId, fileId);
    }


    public void includePages(String dossierId, String fileId, Set<Integer> pages) {

        FileModel fileStatus = fileStatusService.getStatus(fileId);
        Set<Integer> excludedPages = fileStatus.getExcludedPages();
        excludedPages.removeAll(pages);
        fileStatusService.setExcludedPages(fileId, excludedPages);
        analysisFlagsCalculationService.calculateFlags(dossierId, fileId);
    }

}
