package com.iqser.red.service.peristence.v1.server.integration.tests;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.when;

import java.io.ByteArrayInputStream;
import java.nio.charset.StandardCharsets;
import java.time.OffsetDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mock.web.MockMultipartFile;

import com.google.common.collect.Sets;
import com.google.common.hash.HashFunction;
import com.google.common.hash.Hashing;
import com.iqser.red.service.peristence.v1.server.integration.client.DossierClient;
import com.iqser.red.service.peristence.v1.server.integration.client.DossierTemplateClient;
import com.iqser.red.service.peristence.v1.server.integration.client.FileAttributeClient;
import com.iqser.red.service.peristence.v1.server.integration.client.FileAttributeConfigClient;
import com.iqser.red.service.peristence.v1.server.integration.client.FileClient;
import com.iqser.red.service.peristence.v1.server.integration.client.FileManagementClient;
import com.iqser.red.service.peristence.v1.server.integration.client.ManualRedactionClient;
import com.iqser.red.service.peristence.v1.server.integration.client.ReanalysisClient;
import com.iqser.red.service.peristence.v1.server.integration.client.RedactionLogClient;
import com.iqser.red.service.peristence.v1.server.integration.client.UploadClient;
import com.iqser.red.service.peristence.v1.server.integration.client.ViewedPagesClient;
import com.iqser.red.service.peristence.v1.server.integration.service.DossierTemplateTesterAndProvider;
import com.iqser.red.service.peristence.v1.server.integration.service.DossierTesterAndProvider;
import com.iqser.red.service.peristence.v1.server.integration.service.FileTesterAndProvider;
import com.iqser.red.service.peristence.v1.server.integration.service.TypeProvider;
import com.iqser.red.service.peristence.v1.server.integration.service.UserProvider;
import com.iqser.red.service.peristence.v1.server.integration.utils.AbstractPersistenceServerServiceTest;
import com.iqser.red.service.persistence.management.v1.processor.service.FileManagementStorageService;
import com.iqser.red.service.persistence.service.v1.api.shared.model.DossierTemplateModel;
import com.iqser.red.service.persistence.service.v1.api.shared.model.FileAttributes;
import com.iqser.red.service.persistence.service.v1.api.shared.model.FileAttributesConfig;
import com.iqser.red.service.persistence.service.v1.api.shared.model.FileStatus;
import com.iqser.red.service.persistence.service.v1.api.shared.model.FileUploadResult;
import com.iqser.red.service.persistence.service.v1.api.shared.model.PageExclusionRequest;
import com.iqser.red.service.persistence.service.v1.api.shared.model.PageRange;
import com.iqser.red.service.persistence.service.v1.api.shared.model.ViewedPagesRequest;
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.Dossier;
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.file.FileAttributeConfig;
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.file.FileType;
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 com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.type.DictionaryEntryType;
import com.iqser.red.service.persistence.service.v1.api.shared.model.manual.AddCommentRequestModel;
import com.iqser.red.service.persistence.service.v1.api.shared.model.manual.AddRedactionRequestModel;
import com.iqser.red.service.persistence.service.v1.api.shared.model.manual.ForceRedactionRequestModel;
import com.iqser.red.service.persistence.service.v1.api.shared.model.manual.LegalBasisChangeRequestModel;
import com.iqser.red.service.persistence.service.v1.api.shared.model.manual.RecategorizationRequestModel;
import com.iqser.red.service.persistence.service.v1.api.shared.model.manual.RemoveRedactionRequestModel;
import com.iqser.red.service.persistence.service.v1.api.shared.model.redactionlog.RedactionLog;
import com.iqser.red.service.persistence.service.v1.api.shared.model.redactionlog.RedactionLogEntry;

import feign.FeignException;
import lombok.SneakyThrows;

public class FileTest extends AbstractPersistenceServerServiceTest {

    @Autowired
    private DossierTemplateTesterAndProvider dossierTemplateTesterAndProvider;

    @Autowired
    private FileTesterAndProvider fileTesterAndProvider;

    @Autowired
    private DossierTesterAndProvider dossierTesterAndProvider;

    @Autowired
    private TypeProvider typeProvider;

    @Autowired
    private FileClient fileClient;

    @Autowired
    private UploadClient uploadClient;

    @Autowired
    private ManualRedactionClient manualRedactionClient;

    @Autowired
    private DossierClient dossierClient;

    @Autowired
    private ViewedPagesClient viewedPagesClient;

    @Autowired
    private RedactionLogClient redactionLogClient;

    @Autowired
    private FileAttributeClient fileAttributeClient;

    @Autowired
    private FileAttributeConfigClient fileAttributeConfigClient;

    @Autowired
    private FileManagementClient fileManagementClient;

    @Autowired
    private ReanalysisClient reanalysisClient;

    @Autowired
    private UserProvider userProvider;

    @Autowired
    private DossierTemplateClient dossierTemplateClient;

    @Autowired
    private FileManagementStorageService fileManagementStorageService;


    @Test
    public void testFileSoftDeleteReupload() {

        var filename = "test";
        var dossier = dossierTesterAndProvider.provideTestDossier();

        var file = fileTesterAndProvider.testAndProvideFile(dossier, filename);

        assertThat(fileClient.getDossierStatus(dossier.getId()).size()).isEqualTo(1);
        var loadedFile = fileClient.getFileStatus(dossier.getId(), file.getId());

        fileManagementClient.deleteFile(dossier.getId(), file.getId());

        var nrOfFiles = fileClient.getSoftDeletedDossierStatus(dossier.getId()).size();
        assertThat(nrOfFiles).isEqualTo(1);
        loadedFile = fileClient.getSoftDeletedDossierStatus(dossier.getId()).get(0);

        var fileUploaded = fileTesterAndProvider.testAndProvideFile(dossier);
        loadedFile = fileClient.getFileStatus(dossier.getId(), file.getId());

        assertThat(loadedFile.getFilename()).startsWith(filename);
    }


    @Test
    public void testFileOverwrite() {

        var filename = "test";
        var dossier = dossierTesterAndProvider.provideTestDossier();

        var file = fileTesterAndProvider.testAndProvideFile(dossier, filename);

        assertThat(fileClient.getDossierStatus(dossier.getId()).size()).isEqualTo(1);
        var loadedFile = fileClient.getFileStatus(dossier.getId(), file.getId());

        var userId = userProvider.getUserId();
        fileClient.setStatusUnderApproval(dossier.getId(), file.getId(), userId);
        reanalysisClient.toggleAutomaticAnalysis(dossier.getId(), file.getId(), true);

        List<FileAttributeConfig> configs = new ArrayList<>();
        configs.add(FileAttributeConfig.builder().csvColumnHeader("Name").primaryAttribute(true).label("Name").build());
        configs.add(FileAttributeConfig.builder().csvColumnHeader("Attribute A").primaryAttribute(true).label("Attribute A").build());
        var loadedConfig = fileAttributeConfigClient.setFileAttributesConfig(dossier.getDossierTemplateId(), new FileAttributesConfig(configs));
        fileAttributeClient.setFileAttributes(dossier.getId(), file.getId(), new FileAttributes(Map.of(loadedConfig.getFileAttributeConfigs().get(0).getId(), "123")));

        loadedFile = fileClient.getFileStatus(dossier.getId(), file.getId());
        assertThat(loadedFile.isExcludedFromAutomaticAnalysis()).isTrue();
        assertThat(loadedFile.getFileAttributes().getAttributeIdToValue()).size().isEqualTo(1);
        assertThat(loadedFile.getFileAttributes().getAttributeIdToValue()).isEqualTo(Map.of(loadedConfig.getFileAttributeConfigs().get(0).getId(), "123"));

        viewedPagesClient.addPage(file.getDossierId(), file.getFileId(), new ViewedPagesRequest(1));
        var viewedPages = viewedPagesClient.getViewedPages(file.getDossierId(), file.getFileId());

        assertThat(viewedPages.getPages().size()).isEqualTo(1);

        var fileUpload = new MockMultipartFile("test.pdf", "test.pdf", "application/pdf", "content".getBytes());
        var uploadResult = uploadClient.upload(fileUpload, dossier.getId(), false);

        loadedFile = fileClient.getFileStatus(dossier.getId(), uploadResult.getFileIds().iterator().next());
        assertThat(loadedFile.isExcludedFromAutomaticAnalysis()).isFalse();
        assertThat(loadedFile.getFileAttributes().getAttributeIdToValue()).size().isEqualTo(0);

        fileClient.setStatusUnderReview(dossier.getId(), file.getId(), userId);

        viewedPages = viewedPagesClient.getViewedPages(file.getDossierId(), file.getFileId());
        assertThat(viewedPages.getPages().size()).isEqualTo(0);
    }


    @Test
    public void testFileOverwriteAndKeepManualRedactions() {

        var filename = "test";
        var dossier = dossierTesterAndProvider.provideTestDossier();
        var userId = userProvider.getUserId();

        var file = fileTesterAndProvider.testAndProvideFile(dossier, filename);

        fileClient.setStatusUnderReview(dossier.getId(), file.getId(), userId);
        reanalysisClient.excludePages(dossier.getId(), file.getId(), new PageExclusionRequest(List.of(new PageRange(1, 1))));
        var redactionLog = redactionLogClient.getRedactionLog(dossier.getId(), file.getId(), null, false, true);

        assertThat(fileClient.getDossierStatus(dossier.getId()).size()).isEqualTo(1);
        var loadedFile = fileClient.getFileStatus(dossier.getId(), file.getId());

        fileClient.setStatusUnderApproval(dossier.getId(), file.getId(), userId);
        reanalysisClient.toggleAutomaticAnalysis(dossier.getId(), file.getId(), true);
        loadedFile = fileClient.getFileStatus(dossier.getId(), file.getId());
        assertThat(loadedFile.isExcludedFromAutomaticAnalysis()).isTrue();

        viewedPagesClient.addPage(file.getDossierId(), file.getFileId(), new ViewedPagesRequest(1));
        var viewedPages = viewedPagesClient.getViewedPages(file.getDossierId(), file.getFileId());

        assertThat(viewedPages.getPages()).hasSize(1);

        var fileUpload = new MockMultipartFile(file.getFilename(), file.getFilename(), "application/pdf", "content".getBytes());
        var uploadResult = uploadClient.upload(fileUpload, dossier.getId(), false);

        loadedFile = fileClient.getFileStatus(dossier.getId(), uploadResult.getFileIds().iterator().next());
        assertThat(loadedFile.isExcludedFromAutomaticAnalysis()).isFalse();

    }


    @Test
    public void testFile() {

        var start = OffsetDateTime.now();

        var dossier = dossierTesterAndProvider.provideTestDossier();

        var file = fileTesterAndProvider.testAndProvideFile(dossier);
        var userId = userProvider.getUserId();
        var altUserId = userProvider.getAltUserId();

        var changes = dossierClient.changesSince(JSONPrimitive.of(start));
        assertThat(changes).isNotEmpty();
        assertThat(changes.iterator().next().isFileChanges()).isTrue();
        assertThat(changes.iterator().next().isDossierChanges()).isTrue();

        assertThat(fileClient.getDossierStatus(dossier.getId()).size()).isEqualTo(1);
        var loadedFile = fileClient.getFileStatus(dossier.getId(), file.getId());
        assertThat(loadedFile.getFileManipulationDate()).isNotNull();

        fileClient.setCurrentFileAssignee(dossier.getId(), file.getId(), userId);
        loadedFile = fileClient.getFileStatus(dossier.getId(), file.getId());
        assertThat(loadedFile.getAssignee()).isEqualTo(userId);
        assertThat(loadedFile.getWorkflowStatus()).isEqualTo(WorkflowStatus.NEW);
        assertThat(loadedFile.getLastReviewer()).isNull();
        assertThat(loadedFile.getLastApprover()).isNull();

        reanalysisClient.excludePages(dossier.getId(), file.getId(), new PageExclusionRequest(List.of(new PageRange(1, 1))));
        loadedFile = fileClient.getFileStatus(dossier.getId(), file.getId());
        assertThat(loadedFile.getExcludedPages()).containsExactlyInAnyOrder(1);

        reanalysisClient.includePages(dossier.getId(), file.getId(), new PageExclusionRequest(List.of(new PageRange(1, 1))));
        loadedFile = fileClient.getFileStatus(dossier.getId(), file.getId());
        assertThat(loadedFile.getExcludedPages()).isEmpty();

        fileClient.setCurrentFileAssignee(dossier.getId(), file.getId(), userId);
        loadedFile = fileClient.getFileStatus(dossier.getId(), file.getId());
        assertThat(loadedFile.getAssignee()).isEqualTo(userId);
        assertThat(loadedFile.getWorkflowStatus()).isEqualTo(WorkflowStatus.NEW);
        assertThat(loadedFile.getLastReviewer()).isNull();
        assertThat(loadedFile.getLastApprover()).isNull();

        fileClient.setStatusUnderReview(dossier.getId(), file.getId(), null);
        loadedFile = fileClient.getFileStatus(dossier.getId(), file.getId());
        assertThat(loadedFile.getWorkflowStatus()).isEqualTo(WorkflowStatus.UNDER_REVIEW);
        assertThat(loadedFile.getAssignee()).isEqualTo(userId);
        assertThat(loadedFile.getLastReviewer()).isEqualTo(userId);
        assertThat(loadedFile.getLastApprover()).isNull();

        fileClient.setStatusUnderApproval(dossier.getId(), file.getId(), userId);
        loadedFile = fileClient.getFileStatus(dossier.getId(), file.getId());
        assertThat(loadedFile.getWorkflowStatus()).isEqualTo(WorkflowStatus.UNDER_APPROVAL);
        assertThat(loadedFile.getAssignee()).isEqualTo(userId);
        assertThat(loadedFile.getLastReviewer()).isEqualTo(userId);
        assertThat(loadedFile.getLastApprover()).isEqualTo(userId);

        fileTesterAndProvider.markFileAsProcessed(file.getFileId());
        fileClient.setStatusApproved(dossier.getId(), file.getId());
        loadedFile = fileClient.getFileStatus(dossier.getId(), file.getId());
        assertThat(loadedFile.getWorkflowStatus()).isEqualTo(WorkflowStatus.APPROVED);
        assertThat(loadedFile.getAssignee()).isEqualTo(userId);
        assertThat(loadedFile.getLastReviewer()).isEqualTo(userId);
        assertThat(loadedFile.getLastApprover()).isEqualTo(userId);
        assertThat(loadedFile.isExcludedFromAutomaticAnalysis()).isTrue();

        fileClient.setStatusUnderReview(dossier.getId(), file.getId(), altUserId);
        loadedFile = fileClient.getFileStatus(dossier.getId(), file.getId());
        assertThat(loadedFile.getWorkflowStatus()).isEqualTo(WorkflowStatus.UNDER_REVIEW);
        assertThat(loadedFile.getAssignee()).isEqualTo(altUserId);
        assertThat(loadedFile.getLastReviewer()).isEqualTo(userId);
        assertThat(loadedFile.getLastApprover()).isEqualTo(userId);
        assertThat(loadedFile.isExcludedFromAutomaticAnalysis()).isTrue();

        fileClient.setStatusUnderApproval(dossier.getId(), file.getId(), altUserId);
        loadedFile = fileClient.getFileStatus(dossier.getId(), file.getId());
        assertThat(loadedFile.getWorkflowStatus()).isEqualTo(WorkflowStatus.UNDER_APPROVAL);
        assertThat(loadedFile.getAssignee()).isEqualTo(altUserId);
        assertThat(loadedFile.getLastReviewer()).isEqualTo(userId);
        assertThat(loadedFile.getLastApprover()).isEqualTo(altUserId);

        fileClient.setStatusApproved(dossier.getId(), file.getId());
        loadedFile = fileClient.getFileStatus(dossier.getId(), file.getId());
        assertThat(loadedFile.getWorkflowStatus()).isEqualTo(WorkflowStatus.APPROVED);
        assertThat(loadedFile.getAssignee()).isEqualTo(userId);
        assertThat(loadedFile.getLastReviewer()).isEqualTo(userId);
        assertThat(loadedFile.getLastApprover()).isEqualTo(altUserId);

        fileClient.setStatusUnderReview(dossier.getId(), file.getId(), null);

        reanalysisClient.toggleExclusion(dossier.getId(), file.getId(), true);
        loadedFile = fileClient.getFileStatus(dossier.getId(), file.getId());
        assertThat(loadedFile.isExcluded()).isTrue();

        reanalysisClient.toggleExclusion(dossier.getId(), file.getId(), false);
        loadedFile = fileClient.getFileStatus(dossier.getId(), file.getId());
        assertThat(loadedFile.isExcluded()).isFalse();

        fileManagementClient.deleteFile(dossier.getId(), file.getId());

        var softDeletedFiles = fileClient.getSoftDeletedDossierStatus(dossier.getId());
        assertThat(softDeletedFiles.size()).isEqualTo(1);
        var activeFiles = fileClient.getDossierStatus(dossier.getId());
        assertThat(activeFiles.size()).isEqualTo(0);

        fileManagementClient.restoreFiles(dossier.getId(), Sets.newHashSet(file.getId()));
        softDeletedFiles = fileClient.getSoftDeletedDossierStatus(dossier.getId());
        assertThat(softDeletedFiles.size()).isEqualTo(0);
        activeFiles = fileClient.getDossierStatus(dossier.getId());
        assertThat(activeFiles.size()).isEqualTo(1);

        fileManagementClient.hardDeleteFiles(dossier.getId(), Sets.newHashSet(file.getId()));
        softDeletedFiles = fileClient.getSoftDeletedDossierStatus(dossier.getId());
        assertThat(softDeletedFiles.size()).isEqualTo(0);

        activeFiles = fileClient.getDossierStatus(dossier.getId());
        assertThat(activeFiles.size()).isEqualTo(0);

    }


    @Test
    public void testFileWithRedactions() {

        var dossierTemplate = dossierTemplateTesterAndProvider.provideTestTemplate();

        var dossier = dossierTesterAndProvider.provideTestDossier(dossierTemplate);
        String dossierId = dossier.getId();

        var file = fileTesterAndProvider.testAndProvideFile(dossier);
        String fileId = file.getId();

        var type = typeProvider.testAndProvideType(dossierTemplate, null, "manual");

        var annotationId = "imagine_this_makes_sense";
        RedactionLog redactionLog = new RedactionLog();
        RedactionLogEntry redactionLogEntry = RedactionLogEntry.builder().type(type.getType()).id(annotationId).build();
        redactionLog.getRedactionLogEntry().add(redactionLogEntry);

        when(redactionLogService.getRedactionLog(Mockito.any(), Mockito.any())).thenReturn(redactionLog);

        assertThat(fileClient.getDossierStatus(dossier.getId()).size()).isEqualTo(1);

        var addRedactionRequest = AddRedactionRequestModel.builder()
                .addToDictionary(true)
                .type(type.getType())
                .addToAllDossiers(true)
                .reason("1")
                .value("test")
                .legalBasis("1")
                .dictionaryEntryType(DictionaryEntryType.ENTRY)
                .build();
        manualRedactionClient.addRedactionBulk(dossierId, fileId, Set.of(addRedactionRequest));

        manualRedactionClient.removeRedactionBulk(dossierId,
                fileId,
                Set.of(RemoveRedactionRequestModel.builder().annotationId(annotationId).comment("comment").removeFromDictionary(false).build()));
        manualRedactionClient.forceRedactionBulk(dossierId,
                fileId,
                Set.of(ForceRedactionRequestModel.builder().annotationId("forceRedactionAnnotation").comment("comment").legalBasis("1").build()));
        manualRedactionClient.legalBasisChangeBulk(dossierId,
                fileId,
                Set.of(LegalBasisChangeRequestModel.builder().annotationId("legalBasisChangeAnnotation").comment("comment").legalBasis("1").build()));
        manualRedactionClient.recategorizeBulk(dossierId,
                fileId,
                Set.of(RecategorizationRequestModel.builder().annotationId(annotationId).comment("comment").type("new-type").build()));

        var loadedFile = fileClient.getFileStatus(dossierId, fileId);

        fileManagementClient.deleteFile(dossier.getId(), file.getId());
        var softDeletedFiles = fileClient.getSoftDeletedDossierStatus(dossier.getId());
        assertThat(softDeletedFiles.size()).isEqualTo(1);
        var activeFiles = fileClient.getDossierStatus(dossier.getId());
        assertThat(activeFiles.size()).isEqualTo(0);

        fileManagementClient.restoreFiles(dossier.getId(), Sets.newHashSet(file.getId()));
        softDeletedFiles = fileClient.getSoftDeletedDossierStatus(dossier.getId());
        assertThat(softDeletedFiles.size()).isEqualTo(0);
        activeFiles = fileClient.getDossierStatus(dossier.getId());
        assertThat(activeFiles.size()).isEqualTo(1);

        fileManagementClient.hardDeleteFiles(dossier.getId(), Sets.newHashSet(file.getId()));
        softDeletedFiles = fileClient.getSoftDeletedDossierStatus(dossier.getId());
        assertThat(softDeletedFiles.size()).isEqualTo(0);

        activeFiles = fileClient.getDossierStatus(dossier.getId());
        assertThat(activeFiles.size()).isEqualTo(0);

    }


    @Test
    public void testToggleEnableRedactionTwice() {

        var dossierTemplate = dossierTemplateTesterAndProvider.provideTestTemplate();

        var dossier = dossierTesterAndProvider.provideTestDossier(dossierTemplate);
        String dossierId = dossier.getId();

        var file = fileTesterAndProvider.testAndProvideFile(dossier);
        String fileId = file.getId();

        var type = typeProvider.testAndProvideType(dossierTemplate, null, "manual");

        assertThat(fileClient.getDossierStatus(dossier.getId()).size()).isEqualTo(1);

        var userId = userProvider.getUserId();

        fileClient.setStatusUnderReview(dossier.getId(), file.getId(), userId);

        var addRedaction = manualRedactionClient.addRedactionBulk(dossierId,
                fileId,
                Set.of(AddRedactionRequestModel.builder()
                        .addToDictionary(true)
                        .addToAllDossiers(true)
                        .comment(new AddCommentRequestModel("comment"))
                        .type(type.getType())
                        .reason("1")
                        .value("test")
                        .legalBasis("1")
                        .dictionaryEntryType(DictionaryEntryType.ENTRY)
                        .build())).iterator().next();

        var loadedFile = fileClient.getFileStatus(dossier.getId(), file.getId());

        reanalysisClient.toggleExclusion(dossier.getId(), file.getId(), true);
        loadedFile = fileClient.getFileStatus(dossier.getId(), file.getId());
        assertThat(loadedFile.isExcluded()).isTrue();

        reanalysisClient.toggleExclusion(dossier.getId(), file.getId(), false);
        loadedFile = fileClient.getFileStatus(dossier.getId(), file.getId());
        assertThat(loadedFile.isExcluded()).isFalse();
    }


    @Test
    public void testFileDeleteReupload() {

        // Upload file
        var dossierTemplate = dossierTemplateTesterAndProvider.provideTestTemplate();

        var dossier = dossierTesterAndProvider.provideTestDossier(dossierTemplate);
        String dossierId = dossier.getId();

        String fileName = "may_the_force_with_you.pdf";
        var file = fileTesterAndProvider.testAndProvideFile(dossier, fileName);
        String fileId = file.getId();

        var type = typeProvider.testAndProvideType(dossierTemplate, null, "manual");

        assertThat(fileClient.getDossierStatus(dossier.getId()).size()).isEqualTo(1);

        reanalysisClient.excludePages(dossierId, fileId, new PageExclusionRequest(List.of(new PageRange(1, 1))));
        assertThat(fileClient.getFileStatus(dossierId, fileId).getExcludedPages().size()).isEqualTo(1);
        assertThat(fileClient.getFileStatus(dossierId, fileId).getExcludedPages()).contains(1);

        // Delete file
        fileManagementClient.deleteFile(dossierId, fileId);
        var softDeletedFiles = fileClient.getSoftDeletedDossierStatus(dossierId);
        assertThat(softDeletedFiles.size()).isEqualTo(1);
        var activeFiles = fileClient.getDossierStatus(dossierId);
        assertThat(activeFiles.size()).isEqualTo(0);

        fileManagementClient.hardDeleteFiles(dossierId, Sets.newHashSet(fileId));
        softDeletedFiles = fileClient.getSoftDeletedDossierStatus(dossierId);
        assertThat(softDeletedFiles.size()).isEqualTo(0);

        activeFiles = fileClient.getDossierStatus(dossierId);
        assertThat(activeFiles.size()).isEqualTo(0);

        // Reupload file
        file = fileTesterAndProvider.testAndProvideFile(dossier, fileName);

        assertThat(file.getId()).isEqualTo(fileId);
        assertThat(fileClient.getFileStatus(dossierId, fileId).getExcludedPages()).isNullOrEmpty();

    }


    @Test
    public void testFile4424() {

        var start = OffsetDateTime.now();
        var dossier = dossierTesterAndProvider.provideTestDossier();
        var file = fileTesterAndProvider.testAndProvideFile(dossier);
        var userId = userProvider.getUserId();
        var altUserId = userProvider.getAltUserId();

        var loadedFile = fileClient.getFileStatus(dossier.getId(), file.getId());
        assertThat(loadedFile.getAssignee()).isNull();
        assertThat(loadedFile.getWorkflowStatus()).isEqualTo(WorkflowStatus.NEW);
        assertThat(loadedFile.getLastReviewer()).isNull();
        assertThat(loadedFile.getLastApprover()).isNull();

        fileClient.setStatusUnderReview(dossier.getId(), file.getId(), userId);
        loadedFile = fileClient.getFileStatus(dossier.getId(), file.getId());
        assertThat(loadedFile.getWorkflowStatus()).isEqualTo(WorkflowStatus.UNDER_REVIEW);
        assertThat(loadedFile.getAssignee()).isEqualTo(userId);
        assertThat(loadedFile.getLastReviewer()).isNull();
        assertThat(loadedFile.getLastApprover()).isNull();

        fileClient.setCurrentFileAssignee(dossier.getId(), file.getId(), altUserId);
        loadedFile = fileClient.getFileStatus(dossier.getId(), file.getId());
        assertThat(loadedFile.getWorkflowStatus()).isEqualTo(WorkflowStatus.UNDER_REVIEW);
        assertThat(loadedFile.getAssignee()).isEqualTo(altUserId);
        assertThat(loadedFile.getLastReviewer()).isEqualTo(userId);
        assertThat(loadedFile.getLastApprover()).isNull();

        fileClient.setStatusUnderApproval(dossier.getId(), file.getId(), altUserId);
        loadedFile = fileClient.getFileStatus(dossier.getId(), file.getId());
        assertThat(loadedFile.getWorkflowStatus()).isEqualTo(WorkflowStatus.UNDER_APPROVAL);
        assertThat(loadedFile.getAssignee()).isEqualTo(altUserId);
        assertThat(loadedFile.getLastReviewer()).isEqualTo(userId);
        assertThat(loadedFile.getLastApprover()).isEqualTo(altUserId);

        fileClient.setCurrentFileAssignee(dossier.getId(), file.getId(), userId);
        loadedFile = fileClient.getFileStatus(dossier.getId(), file.getId());
        assertThat(loadedFile.getWorkflowStatus()).isEqualTo(WorkflowStatus.UNDER_APPROVAL);
        assertThat(loadedFile.getAssignee()).isEqualTo(userId);
        assertThat(loadedFile.getLastReviewer()).isEqualTo(userId);
        assertThat(loadedFile.getLastApprover()).isEqualTo(altUserId);

    }


    @Test
    public void testFile6034SetUnderReview() {

        var start = OffsetDateTime.now();
        var dossier = dossierTesterAndProvider.provideTestDossier();
        var file = fileTesterAndProvider.testAndProvideFile(dossier);
        var userId = userProvider.getUserId();
        var altUserId = userProvider.getAltUserId();
        var user2 = userProvider.getMemberUserId();

        assertThat(dossier.getMemberIds().contains(user2)).isFalse();

        var loadedFile = fileClient.getFileStatus(dossier.getId(), file.getId());
        assertThat(loadedFile.getAssignee()).isNull();
        assertThat(loadedFile.getWorkflowStatus()).isEqualTo(WorkflowStatus.NEW);
        assertThat(loadedFile.getLastReviewer()).isNull();
        assertThat(loadedFile.getLastApprover()).isNull();

        Exception exception = Assertions.assertThrows(FeignException.BadRequest.class, () -> {
            fileClient.setStatusUnderReview(dossier.getId(), file.getId(), null);
        });

        String expectedMessage = "File is already unassigned!";
        String actualMessage = exception.getMessage();

        assertThat(actualMessage).contains(expectedMessage);

        exception = Assertions.assertThrows(FeignException.BadRequest.class, () -> {
            fileClient.setStatusUnderReview(dossier.getId(), file.getId(), user2);
        });

        expectedMessage = "User must be dossier member";
        actualMessage = exception.getMessage();

        assertThat(actualMessage).contains(expectedMessage);

        fileClient.setStatusUnderReview(dossier.getId(), file.getId(), altUserId);
        loadedFile = fileClient.getFileStatus(dossier.getId(), file.getId());
        assertThat(loadedFile.getWorkflowStatus()).isEqualTo(WorkflowStatus.UNDER_REVIEW);
        assertThat(loadedFile.getAssignee()).isEqualTo(altUserId);
        assertThat(loadedFile.getLastReviewer()).isNull();
        assertThat(loadedFile.getLastApprover()).isNull();
    }


    @Test
    @SneakyThrows
    public void testUploadFileIsInOcrProcessingWithOcrByDefaultFlagTrue() {

        DossierTemplateModel dossierTemplate = dossierTemplateTesterAndProvider.provideTestTemplate(true);
        Dossier dossier = dossierTesterAndProvider.provideTestDossier(dossierTemplate, "1");
        String fileName = "test";
        HashFunction hashFunction = Hashing.murmur3_128();
        String fileId = hashFunction.hashBytes(((fileName + ".pdf") + dossier.getId()).getBytes(StandardCharsets.UTF_8)).toString();

        fileManagementStorageService.storeObject(dossier.getId(), fileId, FileType.ORIGIN, new ByteArrayInputStream("test".getBytes(StandardCharsets.UTF_8)));
        MockMultipartFile mff = new MockMultipartFile(fileName, fileName + ".pdf", "application/pdf", "lorem ipsum".getBytes());
        FileUploadResult uploadResult = uploadClient.upload(mff, dossier.getId(), false);

        fileId = uploadResult.getFileIds().iterator().next();
        FileStatus file = fileClient.getFileStatus(dossier.getId(), fileId);

        assertThat(file.getProcessingStatus()).isEqualTo(ProcessingStatus.OCR_PROCESSING_QUEUED);
    }

}
