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

import static org.assertj.core.api.Assertions.assertThat;

import java.io.InputStream;
import java.time.OffsetDateTime;
import java.time.temporal.ChronoUnit;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

import org.jetbrains.annotations.NotNull;
import org.junit.jupiter.api.Test;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mock.web.MockMultipartFile;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Sets;
import com.iqser.red.service.peristence.v1.server.integration.client.DictionaryClient;
import com.iqser.red.service.peristence.v1.server.integration.client.DossierAttributeConfigClient;
import com.iqser.red.service.peristence.v1.server.integration.client.DossierClient;
import com.iqser.red.service.peristence.v1.server.integration.client.DossierStatusClient;
import com.iqser.red.service.peristence.v1.server.integration.client.DossierTemplateClient;
import com.iqser.red.service.peristence.v1.server.integration.client.DownloadClient;
import com.iqser.red.service.peristence.v1.server.integration.client.FileAttributeConfigClient;
import com.iqser.red.service.peristence.v1.server.integration.client.LegalBasisClient;
import com.iqser.red.service.peristence.v1.server.integration.client.ReportTemplateClient;
import com.iqser.red.service.peristence.v1.server.integration.client.WatermarkClient;
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.utils.AbstractPersistenceServerServiceTest;
import com.iqser.red.service.persistence.management.v1.processor.model.DownloadJob;
import com.iqser.red.service.persistence.management.v1.processor.service.FileManagementStorageService;
import com.iqser.red.service.persistence.management.v1.processor.service.export.ExportDownloadMessageReceiver;
import com.iqser.red.service.persistence.service.v1.api.shared.model.CreateTypeValue;
import com.iqser.red.service.persistence.service.v1.api.shared.model.DossierAttributesConfig;
import com.iqser.red.service.persistence.service.v1.api.shared.model.DossierStatusRequest;
import com.iqser.red.service.persistence.service.v1.api.shared.model.DossierTemplateModel;
import com.iqser.red.service.persistence.service.v1.api.shared.model.FileAttributesConfig;
import com.iqser.red.service.persistence.service.v1.api.shared.model.TypeValue;
import com.iqser.red.service.persistence.service.v1.api.shared.model.WatermarkModel;
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.CloneDossierTemplateRequest;
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.DossierAttributeConfig;
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.DossierTemplateStatus;
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.DownloadFileType;
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.configuration.Colors;
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.configuration.WatermarkOrientation;
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.DossierAttributeType;
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.FileAttributeType;
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.importexport.ImportDossierTemplateRequest;
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.legalbasis.LegalBasis;
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.type.DictionaryEntryType;
import com.iqser.red.storage.commons.service.StorageService;
import com.knecon.fforesight.tenantcommons.TenantContext;

import feign.FeignException;
import lombok.SneakyThrows;

public class DossierTemplateTest extends AbstractPersistenceServerServiceTest {

    @Autowired
    private DossierTesterAndProvider dossierTesterAndProvider;

    @Autowired
    private DossierTemplateTesterAndProvider dossierTemplateTesterAndProvider;

    @Autowired
    private DossierTemplateClient dossierTemplateClient;

    @Autowired
    private DossierClient dossierClient;

    @Autowired
    private DictionaryClient dictionaryClient;

    @Autowired
    private DossierAttributeConfigClient dossierAttributeConfigClient;

    @Autowired
    private FileAttributeConfigClient fileAttributeConfigClient;

    @Autowired
    private ReportTemplateClient reportTemplateClient;

    @Autowired
    private WatermarkClient watermarkClient;

    @Autowired
    private DossierStatusClient dossierStatusClient;

    @Autowired
    private DownloadClient downloadClient;

    @Autowired
    private ObjectMapper objectMapper;

    @Autowired
    private ExportDownloadMessageReceiver exportDownloadReportMessageReceiver;

    @Autowired
    private StorageService storageService;

    @Autowired
    private FileManagementStorageService fileManagementStorageService;

    @Autowired
    private LegalBasisClient legalBasisClient;


    @Test
    public void testDownload() {

        var dossierTemplate = dossierTemplateTesterAndProvider.provideTestTemplate();

        // test the export of dossier template
        dossierTemplateClient.prepareExportDownload(dossierTemplate.getId());
        var statuses = downloadClient.getDownloadStatus();
        assertThat(statuses.getDownloadStatus()).isNotEmpty();
    }


    @Test
    public void testDossierTemplate() {

        var dossierTemplate = dossierTemplateTesterAndProvider.provideTestTemplate();

        var allTemplates = dossierTemplateClient.getAllDossierTemplates();
        assertThat(allTemplates.size()).isEqualTo(1);
        assertThat(allTemplates.get(0)).isEqualTo(dossierTemplate);
        assertThat(dossierTemplate.isApplyDictionaryUpdatesToAllDossiersByDefault()).isFalse();

        // update
        var cru = new DossierTemplateModel();
        cru.setDossierTemplateId(dossierTemplate.getId());
        BeanUtils.copyProperties(dossierTemplate, cru);
        cru.setName("Template 1 Update");
        cru.setApplyDictionaryUpdatesToAllDossiersByDefault(true);

        var updated = dossierTemplateClient.createOrUpdateDossierTemplate(cru);
        assertThat(updated.getName()).isEqualTo("Template 1 Update");
        assertThat(updated.isApplyDictionaryUpdatesToAllDossiersByDefault()).isTrue();

        var loadedTemplate = dossierTemplateClient.getDossierTemplate(dossierTemplate.getId());

        assertThat(loadedTemplate).isEqualTo(updated);

        assertThat(loadedTemplate.getDossierTemplateStatus()).isEqualTo(DossierTemplateStatus.ACTIVE);

        updated = dossierTemplateClient.createOrUpdateDossierTemplate(cru);

        assertThat(updated.getName()).isEqualTo("Template 1 Update");

        var testDossier = dossierTesterAndProvider.provideTestDossier(updated);

        try {
            dossierTemplateClient.deleteDossierTemplate(updated.getId());
        } catch (FeignException e) {
            assertThat(e.status()).isEqualTo(409);
        }

        dossierClient.hardDeleteDossiers(Collections.singleton(testDossier.getId()));

        dossierTemplateClient.deleteDossierTemplate(updated.getId());
        assertThat(dossierTemplateClient.getAllDossierTemplates().isEmpty()).isTrue();
    }


    @Test
    public void testDossierTemplateUniqueNameConflict() {

        var dossierTemplate = dossierTemplateTesterAndProvider.provideTestTemplate();
        try {
            var dossierTemplate2 = dossierTemplateTesterAndProvider.provideTestTemplate();
        } catch (FeignException e) {
            assertThat(e.status()).isEqualTo(409);
        }
//        DossierTemplate dossierTemplate2 = null;
//        FeignException thrown = Assertions.assertThrows(FeignException.class, () ->{
//
//         dossierTemplate2 = dossierTemplateTesterAndProvider.provideTestTemplate();
//        })
    }


    @Test
    @SneakyThrows
    public void testCloneDossierTemplate() {

        var dossierTemplate = dossierTemplateTesterAndProvider.provideTestTemplate();

        var type = CreateTypeValue.builder()
                .type("t")
                .dossierTemplateId(dossierTemplate.getId())
                .hexColor("#ddddd")
                .recommendationHexColor("#cccccc")
                .skippedHexColor("#cccccc")
                .rank(999)
                .hint(false)
                .recommendation(false)
                .caseInsensitive(false)
                .description("t.getDescription()")
                .addToDictionaryAction(true)
                .label("t.getLabel()")
                .hasDictionary(true)
                .build();

        var type2 = CreateTypeValue.builder()
                .type("t2")
                .dossierTemplateId(dossierTemplate.getId())
                .hexColor("#12345")
                .recommendationHexColor("#6789a")
                .skippedHexColor("#6789a")
                .rank(1002)
                .hint(false)
                .recommendation(false)
                .caseInsensitive(false)
                .description("t2.getDescription()")
                .addToDictionaryAction(true)
                .label("t2.getLabel()")
                .hasDictionary(true)
                .build();

        var createdType1 = dictionaryClient.addType(type);
        var createdType2 = dictionaryClient.addType(type2);

        var loadedType1 = dictionaryClient.getDictionaryForType(createdType1.getType(), createdType1.getDossierTemplateId(), null);
        var loadedType2 = dictionaryClient.getDictionaryForType(createdType2.getType(), createdType2.getDossierTemplateId(), null);

        dictionaryClient.addEntry(createdType1.getType(), createdType1.getDossierTemplateId(), List.of("entry1", "entry2"), false, null, DictionaryEntryType.ENTRY);
        dictionaryClient.addEntry(createdType1.getType(), createdType1.getDossierTemplateId(), List.of("entry3", "entry4"), false, null, DictionaryEntryType.FALSE_POSITIVE);
        dictionaryClient.addEntry(createdType1.getType(), createdType1.getDossierTemplateId(), List.of("entry5", "entry6"), false, null, DictionaryEntryType.FALSE_RECOMMENDATION);

        dossierAttributeConfigClient.setDossierAttributesConfig(dossierTemplate.getId(),
                new DossierAttributesConfig(List.of(DossierAttributeConfig.builder()
                        .dossierTemplateId(dossierTemplate.getId())
                        .editable(false)
                        .id("dossierAttributeId")
                        .label("labelDossierAttribute")
                        .type(DossierAttributeType.TEXT)
                        .placeholder("placeholderDossier")
                        .build())));
        fileAttributeConfigClient.setFileAttributesConfig(dossierTemplate.getId(),
                new FileAttributesConfig(List.of(FileAttributeConfig.builder()
                        .dossierTemplateId(dossierTemplate.getId())
                        .primaryAttribute(true)
                        .csvColumnHeader("12345")
                        .displayedInFileList(false)
                        .editable(false)
                        .filterable(false)
                        .id("fileAttributeId")
                        .label("labelFileAttribute")
                        .type(FileAttributeType.TEXT)
                        .placeholder("placeholderFile")
                        .build())));
        var template = new MockMultipartFile("template", "asd".getBytes());
        reportTemplateClient.uploadTemplate(template, dossierTemplate.getId(), true, false);
        var col = Colors.builder()
                .dossierTemplateId(dossierTemplate.getId())
                .appliedRedactionColor("#cccccc")
                .recommendationColor("#cccccc")
                .hintColor("#cccccc")
                .skippedColor("#cccccc")
                .requestAddColor("#444444")
                .requestRemoveColor("#666666")
                .analysisColor("#111111")
                .dictionaryRequestColor("#333333")
                .ignoredHintColor("#555555")
                .analysisColor("#777777")
                .previewColor("#888888")
                .redactionColor("#999999")
                .updatedColor("#aaaaaa")
                .build();
        dictionaryClient.setColors(dossierTemplate.getId(), col);
        var dossierStatus = DossierStatusRequest.builder()
                .name("dossStatus1")
                .description("ds description")
                .color("#115599")
                .rank(456)
                .dossierTemplateId(dossierTemplate.getId())
                .build();
        dossierStatusClient.createOrUpdateDossierStatus(dossierStatus);

        var watermark = new WatermarkModel();
        watermark.setName("watermark name");
        watermark.setEnabled(true);
        watermark.setText("Minions ipsum chasy para tu la bodaaa bananaaaa hana dul sae. Chasy hana dul sae pepete hana dul sae belloo! Tatata bala tu ti aamoo! Jeje.");
        watermark.setFontSize(12);
        watermark.setFontType("font");
        watermark.setHexColor("#dddddd");
        watermark.setOpacity(20);
        watermark.setOrientation(WatermarkOrientation.DIAGONAL);
        watermark.setDossierTemplateId(dossierTemplate.getId());
        watermark.setCreatedBy("user");

        watermarkClient.saveWatermark(watermark);

        var allTemplates = dossierTemplateClient.getAllDossierTemplates();
        assertThat(allTemplates.size()).isEqualTo(1);
        assertThat(allTemplates.get(0)).isEqualTo(dossierTemplate);

        CloneDossierTemplateRequest cdtr = CloneDossierTemplateRequest.builder().name("Clone of " + dossierTemplate.getName()).cloningUserId("user").build();
        var clonedDT = dossierTemplateClient.cloneDossierTemplate(dossierTemplate.getId(), cdtr);
        assertThat(clonedDT.getName()).isEqualTo("Clone of " + dossierTemplate.getName());

        var loadedTemplate = dossierTemplateClient.getDossierTemplate(clonedDT.getId());
        assertThat(loadedTemplate.getId()).isEqualTo(clonedDT.getId());
        assertThat(loadedTemplate.getDescription()).isEqualTo(dossierTemplate.getDescription());
        assertThat(loadedTemplate.getValidFrom()).isEqualTo(dossierTemplate.getValidFrom());
        assertThat(loadedTemplate.getValidTo()).isEqualTo(dossierTemplate.getValidTo());
        assertThat(loadedTemplate.getDownloadFileTypes()).isEqualTo(dossierTemplate.getDownloadFileTypes());
        assertThat(loadedTemplate.getModifiedBy()).isEqualTo("user");
        assertThat(loadedTemplate.getCreatedBy()).isEqualTo("user");

        assertThat(dossierAttributeConfigClient.getDossierAttributesConfig(dossierTemplate.getId()).getDossierAttributeConfigs().get(0).getLabel()).isEqualTo(
                dossierAttributeConfigClient.getDossierAttributesConfig(clonedDT.getId()).getDossierAttributeConfigs().get(0).getLabel());
        assertThat(fileAttributeConfigClient.getFileAttributesConfiguration(dossierTemplate.getId()).getFileAttributeConfigs().get(0).getCsvColumnHeader()).isEqualTo(
                fileAttributeConfigClient.getFileAttributesConfiguration(clonedDT.getId()).getFileAttributeConfigs().get(0).getCsvColumnHeader());
        assertThat(fileAttributeConfigClient.getFileAttributesConfiguration(dossierTemplate.getId())
                .getFilenameMappingColumnHeaderName()).isEqualTo(fileAttributeConfigClient.getFileAttributesConfiguration(clonedDT.getId()).getFilenameMappingColumnHeaderName());
        assertThat(fileAttributeConfigClient.getFileAttributesConfiguration(dossierTemplate.getId())
                .getEncoding()).isEqualTo(fileAttributeConfigClient.getFileAttributesConfiguration(clonedDT.getId()).getEncoding());
        assertThat(reportTemplateClient.getAvailableReportTemplates(dossierTemplate.getId()).get(0).getFileName()).isEqualTo(reportTemplateClient.getAvailableReportTemplates(
                clonedDT.getId()).get(0).getFileName());
        assertThat(dictionaryClient.getColors(dossierTemplate.getId()).getRequestAddColor()).isEqualTo(dictionaryClient.getColors(clonedDT.getId()).getRequestAddColor());
        var types = getTypesSortedByRank(dossierTemplate.getId());
        var clonedTypes = getTypesSortedByRank(clonedDT.getId());
        assertThat(types).usingElementComparatorIgnoringFields("typeId", "dossierTemplateId").isEqualTo(clonedTypes);
        assertThat(dossierStatusClient.getAllDossierStatusForTemplate(dossierTemplate.getId())
                .get(0)
                .getDescription()).isEqualTo(dossierStatusClient.getAllDossierStatusForTemplate(clonedDT.getId()).get(0).getDescription());
        assertThat(watermarkClient.getWatermarksForDossierTemplateId(clonedDT.getId()).size()).isEqualTo(1);
        assertThat(watermarkClient.getWatermarksForDossierTemplateId(dossierTemplate.getId())
                .get(0)
                .getName()).isEqualTo(watermarkClient.getWatermarksForDossierTemplateId(clonedDT.getId()).get(0).getName());
    }


    @NotNull
    private List<TypeValue> getTypesSortedByRank(String dossierTemplateId) {

        return dictionaryClient.getAllTypes(dossierTemplateId, null, false).getTypes().stream().sorted(DossierTemplateTest::compareByRank).toList();
    }


    private static int compareByRank(TypeValue o1, TypeValue o2) {

        return o1.getRank() - o2.getRank();
    }


    @SneakyThrows
    @Test
    public void testExportDossierTemplate() {
//        TenantContext.setTenantId(DEFAULT_TENANT);
        var dossierTemplate = dossierTemplateTesterAndProvider.provideTestTemplate();
        setupDossierTemplate(dossierTemplate);

        dossierTemplateClient.prepareExportDownload(dossierTemplate.getId());
        var statuses = downloadClient.getDownloadStatus();
        assertThat(statuses.getDownloadStatus()).isNotEmpty();

    }


    private void setupDossierTemplate(DossierTemplateModel dossierTemplate) {

        var type = CreateTypeValue.builder()
                .type("t")
                .dossierTemplateId(dossierTemplate.getId())
                .hexColor("#ddddd")
                .recommendationHexColor("#cccccc")
                .skippedHexColor("#cccccc")
                .rank(999)
                .hint(false)
                .recommendation(false)
                .caseInsensitive(false)
                .description("t.getDescription()")
                .addToDictionaryAction(true)
                .label("t.getLabel()")
                .hasDictionary(true)
                .build();
        var type2 = CreateTypeValue.builder()
                .type("t2")
                .dossierTemplateId(dossierTemplate.getId())
                .hexColor("#12345")
                .recommendationHexColor("#6789a")
                .skippedHexColor("#6789a")
                .rank(1002)
                .hint(false)
                .recommendation(false)
                .caseInsensitive(false)
                .description("t2.getDescription()")
                .addToDictionaryAction(true)
                .label("t2.getLabel()")
                .hasDictionary(true)
                .build();

        var createdType1 = dictionaryClient.addType(type);
        var createdType2 = dictionaryClient.addType(type2);

        var loadedType1 = dictionaryClient.getDictionaryForType(createdType1.getType(), createdType1.getDossierTemplateId(), null);
        var loadedType2 = dictionaryClient.getDictionaryForType(createdType2.getType(), createdType2.getDossierTemplateId(), null);

        dictionaryClient.addEntry(createdType1.getType(), createdType1.getDossierTemplateId(), List.of("entry1", "entry2"), false, null, DictionaryEntryType.ENTRY);
        dictionaryClient.addEntry(createdType1.getType(), createdType1.getDossierTemplateId(), List.of("entry3", "entry4"), false, null, DictionaryEntryType.FALSE_POSITIVE);
        dictionaryClient.addEntry(createdType1.getType(), createdType1.getDossierTemplateId(), List.of("entry5", "entry6"), false, null, DictionaryEntryType.FALSE_RECOMMENDATION);

        dossierAttributeConfigClient.setDossierAttributesConfig(dossierTemplate.getId(),
                new DossierAttributesConfig(List.of(DossierAttributeConfig.builder()
                        .dossierTemplateId(dossierTemplate.getId())
                        .editable(false)
                        .id("dossierAttributeId")
                        .label("labelDossierAttribute")
                        .type(DossierAttributeType.TEXT)
                        .placeholder("placeholderDossier")
                        .build())));
        fileAttributeConfigClient.setFileAttributesConfig(dossierTemplate.getId(),
                new FileAttributesConfig(List.of(FileAttributeConfig.builder()
                        .dossierTemplateId(dossierTemplate.getId())
                        .primaryAttribute(true)
                        .csvColumnHeader("12345")
                        .displayedInFileList(false)
                        .editable(false)
                        .filterable(false)
                        .id("fileAttributeId")
                        .label("labelFileAttribute")
                        .type(FileAttributeType.TEXT)
                        .placeholder("placeholderFile")
                        .build())));

        var template = new MockMultipartFile("template", "asd".getBytes());
        reportTemplateClient.uploadTemplate(template, dossierTemplate.getId(), true, false);
        var col = Colors.builder()
                .dossierTemplateId(dossierTemplate.getId())
                .appliedRedactionColor("#cccccc")
                .recommendationColor("#cccccc")
                .hintColor("#cccccc")
                .skippedColor("#cccccc")
                .requestAddColor("#444444")
                .requestRemoveColor("#666666")
                .analysisColor("#111111")
                .dictionaryRequestColor("#333333")
                .ignoredHintColor("#555555")
                .analysisColor("#777777")
                .previewColor("#888888")
                .redactionColor("#999999")
                .updatedColor("#aaaaaa")
                .build();
        dictionaryClient.setColors(dossierTemplate.getId(), col);
        var dossierStatus = DossierStatusRequest.builder()
                .name("dossStatus1")
                .description("ds description")
                .color("#115599")
                .rank(456)
                .dossierTemplateId(dossierTemplate.getId())
                .build();
        dossierStatusClient.createOrUpdateDossierStatus(dossierStatus);

        var watermark = new WatermarkModel();
        watermark.setName("watermark name");
        watermark.setEnabled(true);
        watermark.setText("Minions ipsum chasy para tu la bodaaa bananaaaa hana dul sae. Chasy hana dul sae pepete hana dul sae belloo! Tatata bala tu ti aamoo! Jeje.");
        watermark.setFontSize(12);
        watermark.setFontType("font");
        watermark.setHexColor("#dddddd");
        watermark.setOpacity(20);
        watermark.setOrientation(WatermarkOrientation.DIAGONAL);
        watermark.setDossierTemplateId(dossierTemplate.getId());
        watermark.setCreatedBy("user");

        watermarkClient.saveWatermark(watermark);
    }


    @SneakyThrows
    @Test
    public void testExportDossierTemplateWithFileAttributeGeneralConfigNotPresent() {

        var dossierTemplate = dossierTemplateTesterAndProvider.provideTestTemplate();

        dossierTemplateClient.prepareExportDownload(dossierTemplate.getId());
        var statuses = downloadClient.getDownloadStatus();
        assertThat(statuses.getDownloadStatus()).isNotEmpty();

    }


    @SneakyThrows
    @Test
    public void testExportAndImportDossierTemplateWithJustificationsNotPresent() {

        TenantContext.setTenantId("redaction");

        var dossierTemplate = dossierTemplateTesterAndProvider.provideTestTemplate();
        assertThat(dossierTemplate).isNotNull();

        var existingLegalBasis = legalBasisClient.getLegalBasisMapping(dossierTemplate.getId());
        assertThat(existingLegalBasis.size()).isEqualTo(1);

        // delete justifications for export
        legalBasisClient.deleteLegalBasis(dossierTemplate.getId(), existingLegalBasis.stream().map(LegalBasis::getName).collect(Collectors.toList()));
        existingLegalBasis = legalBasisClient.getLegalBasisMapping(dossierTemplate.getId());
        assertThat(existingLegalBasis.isEmpty()).isTrue();

        dossierTemplateClient.prepareExportDownload(dossierTemplate.getId());
        var statuses = downloadClient.getDownloadStatus();
        assertThat(statuses.getDownloadStatus()).isNotEmpty();

        var status = statuses.getDownloadStatus().iterator().next();
        exportDownloadReportMessageReceiver.receive(new DownloadJob(status.getUserId(), status.getStorageId()));

        // add new justifications
        legalBasisClient.setLegalBasisMapping(List.of(new LegalBasis("nameAgain", "description", "reason")), dossierTemplate.getId());
        existingLegalBasis = legalBasisClient.getLegalBasisMapping(dossierTemplate.getId());
        assertThat(existingLegalBasis.size()).isEqualTo(1);

        // update dossier template metadata
        var cru = new DossierTemplateModel();
        cru.setDossierTemplateId(dossierTemplate.getId());
        BeanUtils.copyProperties(dossierTemplate, cru);
        cru.setName("Template 1 Update");
        cru.setDescription("new description");
        cru.setKeepImageMetadata(true);

        var updated = dossierTemplateClient.createOrUpdateDossierTemplate(cru);
        assertThat(updated.getName()).isNotEqualTo(dossierTemplate.getName());

        var storedObject = fileManagementStorageService.getObject(TenantContext.getTenantId(), status.getStorageId());

        var importTemplate = new MockMultipartFile("import.zip", "import.zip", "application/zip", storedObject);

        var dossierImported = dossierTemplateClient.importDossierTemplate(importTemplate, dossierTemplate.getId(), true);
//        assertThat(dossierImported).isNotNull();

        existingLegalBasis = legalBasisClient.getLegalBasisMapping(dossierTemplate.getId());
        assertThat(existingLegalBasis.isEmpty()).isTrue();
    }


    @Test
    @SneakyThrows
    public void testImportDossierTemplateUpdateExisting() {
// TODO MIGRATION ***
//        var dossierTemplate = dossierTemplateTesterAndProvider.provideTestTemplate();
//        setupDossierTemplate(dossierTemplate);
//        // prepare an archive
//        dossierTemplateClient.prepareExportDownload(dossierTemplate.getId());
//
//        var statuses = downloadClient.getDownloadStatus();
//        assertThat(statuses.getDownloadStatus()).isNotEmpty();
//        assertThat(statuses.get(0).getStatus()).isEqualTo(DownloadStatusValue.READY);
//
//        // add legal basis
//        legalBasisClient.addOrUpdateLegalBasis(dossierTemplate.getId(), new LegalBasis("name2", "description2", "reason2"));
//        var legalBasis = legalBasisClient.getLegalBasisMapping(dossierTemplate.getId());
//        assertThat(legalBasis.size()).isEqualTo(2);
//
//        //add report
//        var template = new MockMultipartFile("template","asd".getBytes());
//        reportTemplateClient.uploadTemplate(template, dossierTemplate.getId(),true,false);
//        var reports = reportTemplateClient.getAvailableReportTemplates(dossierTemplate.getId());
//        assertThat(reports.size()).isEqualTo(2);
//        ImportDossierTemplateRequest request1 = ImportDossierTemplateRequest.builder()
//                .dossierTemplateId(dossierTemplate.getId())
//                .updateExistingDossierTemplate(true)
//                .userId("1")
//                .archive(storageService.getObject(storageId).getInputStream().readAllBytes())
//                .build();
//
//        dossierTemplateClient.importDossierTemplate(request1);
//        var updatedDossierTemplate = dossierTemplateClient.getDossierTemplate(dossierTemplate.getId());
//        assertThat(updatedDossierTemplate.getModifiedBy()).isEqualTo("1");
//        assertThat(updatedDossierTemplate.getDateModified()).isNotNull();
//        assertThat(watermarkClient.getWatermarksForDossierTemplateId(updatedDossierTemplate.getId()).size()).isEqualTo(1);
//
//        reports = reportTemplateClient.getAvailableReportTemplates(dossierTemplate.getId());
//        assertThat(reports.size()).isEqualTo(1);
//
//        legalBasis = legalBasisClient.getLegalBasisMapping(dossierTemplate.getId());
//        assertThat(legalBasis.size()).isEqualTo(1);

    }


    @Test
    @SneakyThrows
    public void testImportDossierTemplateNewTemplateWithNullDossierTemplateId() {
// TODO MIGRATION ***
//        var dossierTemplate = dossierTemplateTesterAndProvider.provideTestTemplate();
//        setupDossierTemplate(dossierTemplate);
//        // prepare an archive
//        dossierTemplateClient.prepareExportDownload(ExportDownloadRequest.builder().userId("1").dossierTemplateId(dossierTemplate.getId()).build());
//        String storageId = StorageIdUtils.getStorageId("1", dossierTemplate.getId());
//        dossierTemplateClient.createExportDownload("1", storageId);
//
//        var statuses = downloadClient.getDownloadStatus("1");
//        assertThat(statuses).isNotEmpty();
//        assertThat(statuses.get(0).getStatus()).isEqualTo(DownloadStatusValue.READY);
//
//        // update
//        CreateOrUpdateDossierTemplateRequest cru = new CreateOrUpdateDossierTemplateRequest();
//        cru.setDossierTemplateId(dossierTemplate.getId());
//        BeanUtils.copyProperties(dossierTemplate, cru);
//        cru.setName("Template 1 Update");
//
//        var updated = dossierTemplateClient.createOrUpdateDossierTemplate(cru);
//        assertThat(updated.getName()).isEqualTo(cru.getName());
//
//        ImportDossierTemplateRequest request1 = ImportDossierTemplateRequest.builder()
//                .dossierTemplateId(null)
//                .updateExistingDossierTemplate(true)
//                .userId("1")
//                .archive(storageService.getObject(storageId).getInputStream().readAllBytes())
//                .build();
//
//        var newDossierTemplate = dossierTemplateClient.importDossierTemplate(request1);
//        var allDossierTemplates = dossierTemplateClient.getAllDossierTemplates();
//        assertThat(allDossierTemplates.size()).isEqualTo(2);

    }


    @Test
    @SneakyThrows
    public void testImportDossierTemplateNewTemplate() {
// TODO MIGRATION ***
//        var dossierTemplate = dossierTemplateTesterAndProvider.provideTestTemplate();
//        setupDossierTemplate(dossierTemplate);
//        // prepare an archive
//        dossierTemplateClient.prepareExportDownload(ExportDownloadRequest.builder().userId("1").dossierTemplateId(dossierTemplate.getId()).build());
//        String storageId = StorageIdUtils.getStorageId("1", dossierTemplate.getId());
//        dossierTemplateClient.createExportDownload("1", storageId);
//
//        var statuses = downloadClient.getDownloadStatus("1");
//        assertThat(statuses).isNotEmpty();
//        assertThat(statuses.get(0).getStatus()).isEqualTo(DownloadStatusValue.READY);
//
//        // update
//        CreateOrUpdateDossierTemplateRequest cru = new CreateOrUpdateDossierTemplateRequest();
//        cru.setDossierTemplateId(dossierTemplate.getId());
//        BeanUtils.copyProperties(dossierTemplate, cru);
//        cru.setName("Template 1 Update");
//
//        var updated = dossierTemplateClient.createOrUpdateDossierTemplate(cru);
//        assertThat(updated.getName()).isEqualTo(cru.getName());
//
//        ImportDossierTemplateRequest request1 = ImportDossierTemplateRequest.builder()
//                .dossierTemplateId("sds")
//                .updateExistingDossierTemplate(true)
//                .userId("1")
//                .archive(storageService.getObject(storageId).getInputStream().readAllBytes())
//                .build();
//
//        var newDossierTemplate = dossierTemplateClient.importDossierTemplate(request1);
//        var allDossierTemplates = dossierTemplateClient.getAllDossierTemplates();
//        assertThat(allDossierTemplates.size()).isEqualTo(2);

    }


    @Test
    @SneakyThrows
    public void testImportDossierTemplateUpdateTemplate() {
// TODO MIGRATION ***
//        var dossierTemplate = dossierTemplateTesterAndProvider.provideTestTemplate();
//        setupDossierTemplate(dossierTemplate);
//        // prepare an archive
//        dossierTemplateClient.prepareExportDownload(ExportDownloadRequest.builder().userId("1").dossierTemplateId(dossierTemplate.getId()).build());
//        String storageId = StorageIdUtils.getStorageId("1", dossierTemplate.getId());
//        dossierTemplateClient.createExportDownload("1", storageId);
//
//        var statuses = downloadClient.getDownloadStatus("1");
//        assertThat(statuses).isNotEmpty();
//        assertThat(statuses.get(0).getStatus()).isEqualTo(DownloadStatusValue.READY);
//
//        ImportDossierTemplateRequest request1 = ImportDossierTemplateRequest.builder()
//                .dossierTemplateId(dossierTemplate.getId())
//                .updateExistingDossierTemplate(true)
//                .userId("1")
//                .archive(storageService.getObject(storageId).getInputStream().readAllBytes())
//                .build();
//
//        assertThat(dossierTemplate.getDateModified()).isNull();
//        var fileAttributes = fileAttributeConfigClient.getFileAttributeConfigs(dossierTemplate.getId());
//        assertThat(fileAttributes.get(0).isPrimaryAttribute()).isTrue();
//        var updatedDossierTemplate = dossierTemplateClient.importDossierTemplate(request1);
//        var allDossierTemplates = dossierTemplateClient.getAllDossierTemplates();
//        assertThat(allDossierTemplates.size()).isEqualTo(1);
//        assertThat(updatedDossierTemplate.getDateModified()).isNotNull();
//        assertThat(updatedDossierTemplate.getId()).isEqualTo(dossierTemplate.getId());
//        var typeIdForT = "t:" + dossierTemplate.getId();
//        var updatedEntries = dictionaryClient.getEntriesForType("t:" + dossierTemplate.getId(), null, DictionaryEntryType.ENTRY);
//        assertThat(updatedEntries.size()).isEqualTo(2);
//        fileAttributes = fileAttributeConfigClient.getFileAttributeConfigs(dossierTemplate.getId());
//        assertThat(fileAttributes.get(0).isPrimaryAttribute()).isTrue();

    }


    @Test
    @SneakyThrows
    public void testImportDossierTemplateNewTemplatewithCompressionRatioThresholdSurpassed() {

        String fileZip = "files/dossiertemplates/EFSA_sanitisation_GFL_v1_adress_parts.zip";
        try (InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(fileZip)) {
            if (inputStream == null) {
                throw new RuntimeException("Resource " + fileZip + " was not found on the classpath or is not readable");
            }

            ImportDossierTemplateRequest request1 = ImportDossierTemplateRequest.builder()
                    .dossierTemplateId("sds")
                    .updateExistingDossierTemplate(false)
                    .userId("1")
                    .archive(inputStream.readAllBytes())
                    .build();
        }

// TODO MIGRATION ***
//        try {
//            var newDossierTemplate = dossierTemplateClient.importDossierTemplate(request1);
//        } catch (FeignException.FeignClientException e) {
//            assertThat(e.status()).isEqualTo(400);
//        }
    }

    @Test
    public void testDossierTemplateWithOcrByDefault() {

        String name = "Test Dossier Template";

        DossierTemplateModel dossierTemplateModel = new DossierTemplateModel();
        dossierTemplateModel.setDownloadFileTypes(Sets.newHashSet(DownloadFileType.ORIGINAL));
        dossierTemplateModel.setName(name);
        dossierTemplateModel.setDescription("Template 1");
        dossierTemplateModel.setValidFrom(OffsetDateTime.now().truncatedTo(ChronoUnit.MILLIS));
        dossierTemplateModel.setValidTo(OffsetDateTime.now().plusHours(1).truncatedTo(ChronoUnit.MILLIS));
        dossierTemplateModel.setOcrByDefault(true);

        DossierTemplateModel result = dossierTemplateClient.createOrUpdateDossierTemplate(dossierTemplateModel);
        assertThat(result.getName()).isEqualTo(name);
        assertThat(result.isOcrByDefault()).isTrue();

        DossierTemplateModel loadedTemplate = dossierTemplateClient.getDossierTemplate(result.getDossierTemplateId());
        assertThat(loadedTemplate).isEqualTo(result);

        dossierTemplateModel.setName("Test Dossier Template Update");
        dossierTemplateModel.setOcrByDefault(false);
        loadedTemplate = dossierTemplateClient.createOrUpdateDossierTemplate(dossierTemplateModel);
        assertThat(loadedTemplate.isOcrByDefault()).isFalse();
    }

    @Test
    public void testDossierTemplateWithRemoveWatermark() {

        String name = "Test Dossier Template";

        DossierTemplateModel dossierTemplateModel = new DossierTemplateModel();
        dossierTemplateModel.setDownloadFileTypes(Sets.newHashSet(DownloadFileType.ORIGINAL));
        dossierTemplateModel.setName(name);
        dossierTemplateModel.setDescription("Template 1");
        dossierTemplateModel.setValidFrom(OffsetDateTime.now().truncatedTo(ChronoUnit.MILLIS));
        dossierTemplateModel.setValidTo(OffsetDateTime.now().plusHours(1).truncatedTo(ChronoUnit.MILLIS));
        dossierTemplateModel.setRemoveWatermark(true);

        DossierTemplateModel result = dossierTemplateClient.createOrUpdateDossierTemplate(dossierTemplateModel);
        assertThat(result.getName()).isEqualTo(name);
        assertThat(result.isRemoveWatermark()).isTrue();

        DossierTemplateModel loadedTemplate = dossierTemplateClient.getDossierTemplate(result.getDossierTemplateId());
        assertThat(loadedTemplate).isEqualTo(result);

        dossierTemplateModel.setName("Test Dossier Template Update");
        dossierTemplateModel.setRemoveWatermark(false);
        loadedTemplate = dossierTemplateClient.createOrUpdateDossierTemplate(dossierTemplateModel);
        assertThat(loadedTemplate.isRemoveWatermark()).isFalse();
    }

}
