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

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

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.IntStream;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;

import com.iqser.red.service.peristence.v1.server.integration.client.DictionaryClient;
import com.iqser.red.service.peristence.v1.server.integration.client.DossierTemplateClient;
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.TypeProvider;
import com.iqser.red.service.peristence.v1.server.integration.utils.AbstractPersistenceServerServiceTest;
import com.iqser.red.service.persistence.service.v1.api.shared.model.CreateTypeValue;
import com.iqser.red.service.persistence.service.v1.api.shared.model.Dictionary;
import com.iqser.red.service.persistence.service.v1.api.shared.model.TypeValue;
import com.iqser.red.service.persistence.service.v1.api.shared.model.UpdateTypeValue;
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.type.DictionaryEntryType;
import com.knecon.fforesight.tenantcommons.TenantContext;

import feign.FeignException;

public class DictionaryTest extends AbstractPersistenceServerServiceTest {

    @Autowired
    private TypeProvider typeProvider;

    @Autowired
    private DossierTemplateTesterAndProvider dossierTemplateTesterAndProvider;

    @Autowired
    private DossierTesterAndProvider dossierTesterAndProvider;

    @Autowired
    private DictionaryClient dictionaryClient;

    @Autowired
    private DossierTemplateClient dossierTemplateClient;


    @BeforeEach
    public void createDossierRedactionDictionary() {

        TenantContext.setTenantId("redaction");
    }

    @Test
    public void testAddEntriesToDossierTemplateDictionaryWithDossierDictionaryOnlyFlag() {

        var dossierTemplate = dossierTemplateTesterAndProvider.provideTestTemplate();
        var type = typeProvider.testAndProvideType(dossierTemplate, null, "type1", true);
        assertThat(type.isDossierDictionaryOnly()).isTrue();

        var entries = List.of("word1", "word2");
        var falsePositives = List.of("false_positive1", "false_positive");
        var falseRecommendations = List.of("false_recommendation1", "false_recommendation2");
        Assertions.assertThrows(FeignException.Forbidden.class, () -> dictionaryClient.addEntry(type.getType(), type.getDossierTemplateId(), entries, false, null, DictionaryEntryType.ENTRY));
        Assertions.assertThrows(FeignException.Forbidden.class, () -> dictionaryClient.addEntry(type.getType(), type.getDossierTemplateId(), falsePositives, false, null, DictionaryEntryType.FALSE_POSITIVE));
        Assertions.assertThrows(FeignException.Forbidden.class, () -> dictionaryClient.addEntry(type.getType(), type.getDossierTemplateId(), falseRecommendations, false, null, DictionaryEntryType.FALSE_RECOMMENDATION));

        var loadedType1 = dictionaryClient.getDictionaryForType(type.getType(), type.getDossierTemplateId(), null);
        assertThat(loadedType1).isNotNull();
        assertThat(loadedType1.getEntries()).isEmpty();
        assertThat(loadedType1.getFalsePositiveEntries()).isEmpty();
        assertThat(loadedType1.getFalseRecommendationEntries()).isEmpty();

        Assertions.assertThrows(FeignException.Forbidden.class, () -> dictionaryClient.deleteEntries(type.getType(), type.getDossierTemplateId(), entries, null, DictionaryEntryType.ENTRY));
        Assertions.assertThrows(FeignException.Forbidden.class, () -> dictionaryClient.deleteEntries(type.getType(), type.getDossierTemplateId(), falsePositives, null, DictionaryEntryType.FALSE_POSITIVE));
        Assertions.assertThrows(FeignException.Forbidden.class, () -> dictionaryClient.deleteEntries(type.getType(), type.getDossierTemplateId(), falseRecommendations, null, DictionaryEntryType.FALSE_RECOMMENDATION));
        Assertions.assertThrows(FeignException.Forbidden.class, () -> dictionaryClient.deleteEntry(type.getType(), type.getDossierTemplateId(), entries.get(0), null, DictionaryEntryType.ENTRY));
        Assertions.assertThrows(FeignException.Forbidden.class, () -> dictionaryClient.deleteEntry(type.getType(), type.getDossierTemplateId(), falsePositives.get(0), null, DictionaryEntryType.FALSE_POSITIVE));
        Assertions.assertThrows(FeignException.Forbidden.class, () -> dictionaryClient.deleteEntry(type.getType(), type.getDossierTemplateId(), falseRecommendations.get(0), null, DictionaryEntryType.FALSE_RECOMMENDATION));
    }

    @Test
    public void testAddFalsePositiveAndFalseRecommendation() {

        var dossierTemplate = dossierTemplateTesterAndProvider.provideTestTemplate();
        var type = typeProvider.testAndProvideType(dossierTemplate);
        assertThat(type.getRecommendationHexColor()).isEqualTo("#aaaaaa");
        assertThat(type.getSkippedHexColor()).isEqualTo("#aaaaaa");
        assertThat(type.isDossierDictionaryOnly()).isFalse();

        dictionaryClient.addEntry(type.getType(), type.getDossierTemplateId(), List.of("word1", "word2"), false, null, DictionaryEntryType.ENTRY);
        dictionaryClient.addEntry(type.getType(), type.getDossierTemplateId(), List.of("false_positive1", "false_positive"), false, null, DictionaryEntryType.FALSE_POSITIVE);
        dictionaryClient.addEntry(type.getType(),
                type.getDossierTemplateId(),
                List.of("false_recommendation1", "false_recommendation2"),
                false,
                null,
                DictionaryEntryType.FALSE_RECOMMENDATION);

        var loadedType1 = dictionaryClient.getDictionaryForType(type.getType(), type.getDossierTemplateId(), null);

        assertThat(loadedType1.getEntries()).hasSize(2);
        assertThat(loadedType1.getFalsePositiveEntries()).hasSize(2);
        assertThat(loadedType1.getFalseRecommendationEntries()).hasSize(2);

    }


    @Test
    public void testSkippedColor() {

        var dossierTemplate = dossierTemplateTesterAndProvider.provideTestTemplate();
        var type = typeProvider.testAndProvideType(dossierTemplate);
        assertThat(type.getRecommendationHexColor()).isEqualTo("#aaaaaa");
        assertThat(type.getSkippedHexColor()).isEqualTo("#aaaaaa");

        var request = new UpdateTypeValue();
        BeanUtils.copyProperties(type, request);
        type.setSkippedHexColor(null);
        dictionaryClient.updateType(type.getType(), type.getDossierTemplateId(), request);

        var loadedType = dictionaryClient.getDictionaryForType(type.getType(), type.getDossierTemplateId(), null);
        assertThat(loadedType.getSkippedHexColor()).isNotNull();
    }


    @Test
    public void testAddEntriesWithStopWord() {

        var dossier = dossierTesterAndProvider.provideTestDossier();
        createDossierRedactionsDictionary(dossier.getDossierTemplateId());
        var typeId = "dossier_redaction";
        var entries = new ArrayList<String>();
        entries.add("age");
        entries.add("page");
        try {
            dictionaryClient.addEntry(typeId, dossier.getDossierTemplateId(), entries, false, dossier.getId(), DictionaryEntryType.ENTRY);
        } catch (FeignException e) {
            assertThat(e.status()).isEqualTo(400);
        }
    }


    @Test
    public void testAddEntriesWithStopWord2() {

        var dossier = dossierTesterAndProvider.provideTestDossier();
        createDossierRedactionsDictionary(dossier.getDossierTemplateId());
        var type = "dossier_redaction";

        var entries = new ArrayList<String>();
        entries.add("age");
        entries.add("p");

        try {
            dictionaryClient.addEntry(type, dossier.getDossierTemplateId(), entries, false, dossier.getId(), DictionaryEntryType.ENTRY);
        } catch (FeignException e) {
            assertThat(e.status()).isEqualTo(400);
        }
        entries.remove(1);
        entries.add("5");
        try {
            dictionaryClient.addEntry(type, dossier.getDossierTemplateId(), entries, false, dossier.getId(), DictionaryEntryType.ENTRY);
        } catch (FeignException e) {
            assertThat(e.status()).isEqualTo(400);
        }
        entries.remove(1);
        entries.add("12");
        try {
            dictionaryClient.addEntry(type, dossier.getDossierTemplateId(), entries, false, dossier.getId(), DictionaryEntryType.ENTRY);
        } catch (FeignException e) {
            assertThat(e.status()).isEqualTo(400);
        }
        entries.remove(1);
        entries.add(";");
        try {
            dictionaryClient.addEntry(type, dossier.getDossierTemplateId(), entries, false, dossier.getId(), DictionaryEntryType.ENTRY);
        } catch (FeignException e) {
            assertThat(e.status()).isEqualTo(400);
        }
        entries.remove(1);
        entries.add("設");
        dictionaryClient.addEntry(type, dossier.getDossierTemplateId(), entries, false, dossier.getId(), DictionaryEntryType.ENTRY);
    }


    @Test
    public void testAddWordMultipleTimes() {

        // Arrange
        var dossierTemplate = dossierTemplateTesterAndProvider.provideTestTemplate();
        var type = typeProvider.testAndProvideType(dossierTemplate);
        var word = "Luke Skywalker";

        // Act & Assert: Add same word multiple times; Only one should exist
        var entries = new ArrayList<String>();
        entries.add(word);
        entries.add(word);
        dictionaryClient.addEntry(type.getType(), type.getDossierTemplateId(), entries, false, null, DictionaryEntryType.ENTRY);

        var dictionary = dictionaryClient.getDictionaryForType(type.getType(), type.getDossierTemplateId(), null);

        assertThat(dictionary.getEntries()).hasSize(1);
        assertThat(dictionary.getEntries().iterator().next()).isEqualTo(word);

        // Act & Assert: Add same word again; Only one should exist
        entries = new ArrayList<>();
        entries.add(word);
        dictionaryClient.addEntry(type.getType(), type.getDossierTemplateId(), entries, false, null, DictionaryEntryType.ENTRY);

        dictionary = dictionaryClient.getDictionaryForType(type.getType(), type.getDossierTemplateId(), null);
        assertThat(dictionary.getEntries()).hasSize(1);
        assertThat(dictionary.getEntries().iterator().next()).isEqualTo(word);

        // Act & Assert: Add same word multiple times again; Only one should exist
        entries = new ArrayList<>();
        entries.add(word);
        entries.add(word);
        entries.add(word);
        entries.add(word);
        dictionaryClient.addEntry(type.getType(), type.getDossierTemplateId(), entries, false, null, DictionaryEntryType.ENTRY);

        dictionary = dictionaryClient.getDictionaryForType(type.getType(), type.getDossierTemplateId(), null);
        assertThat(dictionary.getEntries()).hasSize(1);
        assertThat(dictionary.getEntries().iterator().next()).isEqualTo(word);
        assertThat((dictionary.isDossierDictionaryOnly())).isFalse();

        // Act & Assert: Delete word; Should have 'deleted' flag
        entries = new ArrayList<>();
        entries.add(word);
        dictionaryClient.deleteEntries(type.getType(), type.getDossierTemplateId(), entries, null, DictionaryEntryType.ENTRY);

        dictionary = dictionaryClient.getDictionaryForType(type.getType(), type.getDossierTemplateId(), null);
        assertThat(dictionary.getEntries()).hasSize(0);
    }


    @Test
    public void testAddDifferentWordMultipleTimes() {

        // Arrange
        var dossierTemplate = dossierTemplateTesterAndProvider.provideTestTemplate();
        var type = typeProvider.testAndProvideType(dossierTemplate);
        var word1 = "Luke Skywalker";
        var word2 = "Anakin Skywalker";
        var word3 = "Yoda";

        // Act & Assert: Add different words; All three should exist
        var entries = new ArrayList<String>();
        entries.add(word1);
        entries.add(word2);
        entries.add(word3);
        dictionaryClient.addEntry(type.getType(), type.getDossierTemplateId(), entries, false, null, DictionaryEntryType.ENTRY);

        var dictionary = dictionaryClient.getDictionaryForType(type.getType(), type.getDossierTemplateId(), null);

        assertThat(dictionary.getEntries()).hasSize(3);
        assertThat(dictionary.getEntries()).contains(word1, word2, word3);

        // Act & Assert: Add same word again; No duplicate should exist
        entries = new ArrayList<>();
        entries.add(word1);
        dictionaryClient.addEntry(type.getType(), type.getDossierTemplateId(), entries, false, null, DictionaryEntryType.ENTRY);

        dictionary = dictionaryClient.getDictionaryForType(type.getType(), type.getDossierTemplateId(), null);

        assertThat(dictionary.getEntries()).hasSize(3);
        assertThat(dictionary.getEntries()).contains(word1, word2, word3);

        // Act & Assert: Add words multiple times again; No duplicate should exist
        entries = new ArrayList<>();
        entries.add(word1);
        entries.add(word2);
        entries.add(word1);
        entries.add(word1);
        entries.add(word2);
        entries.add(word3);
        dictionaryClient.addEntry(type.getType(), type.getDossierTemplateId(), entries, false, null, DictionaryEntryType.ENTRY);

        dictionary = dictionaryClient.getDictionaryForType(type.getType(), type.getDossierTemplateId(), null);

        assertThat(dictionary.getEntries()).hasSize(3);
        assertThat(dictionary.getEntries()).contains(word1, word2, word3);
    }


    @Test
    public void testCreateDossierDictionaryForTwoDossiers() {

        var dossier = dossierTesterAndProvider.provideTestDossier();

        var dossierTemplate = dossierTemplateClient.getDossierTemplate(dossier.getDossierTemplateId());
        var dossier2 = dossierTesterAndProvider.provideTestDossier(dossierTemplate, "dossier2");

        var returnedtype1 = dictionaryClient.addType(CreateTypeValue.builder()
                .type("dossier_redaction_1")
                .label("Dossier Redactions")
                .hexColor("#fcba03")
                .rank(100)
                .hint(false)
                .caseInsensitive(false)
                .recommendation(false)
                .description("Something")
                .addToDictionaryAction(false)
                .dossierTemplateId(dossier.getDossierTemplateId())
                .dossierDictionaryOnly(true)
                .build());
        assertThat(returnedtype1.isDossierDictionaryOnly()).isTrue();

        assertThat(dictionaryClient.getAllTypes(dossier.getDossierTemplateId(), null, false).getTypes().size()).isEqualTo(1);
        assertThat(dictionaryClient.getAllTypes(dossier.getDossierTemplateId(), dossier.getId(), false).getTypes().size()).isEqualTo(2);
        var dictionary = dictionaryClient.getDictionaryForType(returnedtype1.getType(), dossier.getDossierTemplateId(), dossier2.getId());
        assertThat(dictionaryClient.getAllTypes(dossier.getDossierTemplateId(), dossier2.getId(), false).getTypes().size()).isEqualTo(2);
    }


    @Test
    public void testDeleteAndRecreateDictionary() {

        var dossierTemplate = dossierTemplateTesterAndProvider.provideTestTemplate();

        var type = CreateTypeValue.builder()
                .type("dossier_redaction")
                .label("Dossier Redactions")
                .hexColor("#fcba03")
                .rank(100)
                .description("Something")
                .hasDictionary(true)
                .addToDictionaryAction(false)
                .dossierTemplateId(dossierTemplate.getId())
                .build();

        var createdType = dictionaryClient.addType(type);

        var word1 = "Luke Skywalker";
        var word2 = "Anakin Skywalker";
        var word3 = "Yoda";

        // Act & Assert: Add different words; All three should exist
        var entries = new ArrayList<String>();
        entries.add(word1);
        entries.add(word2);
        entries.add(word3);
        dictionaryClient.addEntry(createdType.getType(), createdType.getDossierTemplateId(), entries, false, null, DictionaryEntryType.ENTRY);

        var dictionary = dictionaryClient.getDictionaryForType(type.getType(), type.getDossierTemplateId(), null);

        var actualEntries = dictionary.getEntries();
        assertThat(actualEntries.size()).isEqualTo(3);
        assertThat(actualEntries).usingComparator(new ListContentWithoutOrderAndWithoutDuplicatesComparator<>()).isEqualTo(entries);

        dictionaryClient.deleteType(createdType.getType(), createdType.getDossierTemplateId());
        assertThat(dictionaryClient.getAllTypes(createdType.getDossierTemplateId(), null, false).getTypes().size()).isEqualTo(0);

        dictionaryClient.addType(type);

        dictionary = dictionaryClient.getDictionaryForType(type.getType(), type.getDossierTemplateId(), null);

        actualEntries = dictionary.getEntries();
        assertThat(actualEntries.size()).isEqualTo(0);
    }


    @Test
    public void testAddEntries() {

        var dossierTemplate = dossierTemplateTesterAndProvider.provideTestTemplate();

        var createdType = createDossierRedactionsDictionary(dossierTemplate.getId());

        var word1 = "Luke Skywalker";
        var word2 = "Anakin Skywalker";
        var word3 = "Yoda";

        // Act & Assert: Add different words; All three should exist
        var entries = new ArrayList<String>();
        entries.add(word1);
        entries.add(word2);
        entries.add(word3);
        dictionaryClient.addEntry(createdType.getType(), createdType.getDossierTemplateId(), entries, false, null, DictionaryEntryType.ENTRY);

        var word4 = "Padme";
        var word5 = "Obiwan";
        entries.clear();
        entries.add(word4);
        entries.add(word5);
        dictionaryClient.addEntry(createdType.getType(), createdType.getDossierTemplateId(), entries, true, null, DictionaryEntryType.ENTRY);

        entries.add(word1);
        entries.add(word2);
        entries.add(word3);
        dictionaryClient.addEntry(createdType.getType(), createdType.getDossierTemplateId(), entries, false, null, DictionaryEntryType.ENTRY);

        var dictionary = dictionaryClient.getDictionaryForType(createdType.getType(), createdType.getDossierTemplateId(), null);

        assertThat(dictionary.getEntries().size()).isEqualTo(5);
    }

    @Test
    public void testDossierTemplateAndDossierMissmatched() {
        var dossierTemplate = dossierTemplateTesterAndProvider.provideTestTemplate();
        var dossierTemplate1 = dossierTemplateTesterAndProvider.provideTestTemplate("dossierTemplate1");
        var dossier = dossierTesterAndProvider.provideTestDossier(dossierTemplate, "Dossier");
        var type = typeProvider.testAndProvideType(dossierTemplate);

        Assertions.assertThrows(FeignException.BadRequest.class, () -> dictionaryClient.getAllTypes(dossierTemplate1.getDossierTemplateId(), dossier.getDossierId(), false));

        Assertions.assertThrows(FeignException.BadRequest.class, () -> dictionaryClient.getDictionaryForType(type.getType(), dossierTemplate1.getDossierTemplateId(), dossier.getDossierId()));

    }

    @Test
    public void testGetMergedDictionaries() {

        var dossierTemplate = dossierTemplateTesterAndProvider.provideTestTemplate();
        var dossier = dossierTesterAndProvider.provideTestDossier(dossierTemplate, "Dossier");
        var type = typeProvider.testAndProvideType(dossierTemplate);
        assertThat(type.getRecommendationHexColor()).isEqualTo("#aaaaaa");
        assertThat(type.getSkippedHexColor()).isEqualTo("#aaaaaa");
        assertThat(type.isDossierDictionaryOnly()).isFalse();

        dictionaryClient.addEntry(type.getType(), type.getDossierTemplateId(), List.of("word1", "word2", "word3"), false, null, DictionaryEntryType.ENTRY);
        dictionaryClient.addEntry(type.getType(), type.getDossierTemplateId(), List.of("false_positive1", "false_positive"), false, null, DictionaryEntryType.FALSE_POSITIVE);
        dictionaryClient.addEntry(type.getType(),
                type.getDossierTemplateId(),
                List.of("false_recommendation1", "false_recommendation2"),
                false,
                null,
                DictionaryEntryType.FALSE_RECOMMENDATION);

        var loadedType1 = dictionaryClient.getDictionaryForType(type.getType(), type.getDossierTemplateId(), null);

        assertThat(loadedType1.getEntries()).hasSize(3);
        assertThat(loadedType1.getFalsePositiveEntries()).hasSize(2);
        assertThat(loadedType1.getFalseRecommendationEntries()).hasSize(2);

        dictionaryClient.addEntry(type.getType(), type.getDossierTemplateId(), List.of("word1", "word4"), false, dossier.getDossierId(), DictionaryEntryType.ENTRY);
        dictionaryClient.deleteEntries(type.getType(), type.getDossierTemplateId(), List.of("word2"), dossier.getDossierId(), DictionaryEntryType.ENTRY);
        dictionaryClient.addEntry(type.getType(), type.getDossierTemplateId(), List.of("false_positive1", "false_positive3"), false, dossier.getDossierId(), DictionaryEntryType.FALSE_POSITIVE);
        dictionaryClient.addEntry(type.getType(),
                type.getDossierTemplateId(),
                List.of("false_recommendation3", "false_recommendation4"),
                false,
                dossier.getDossierId(),
                DictionaryEntryType.FALSE_RECOMMENDATION);
       Assertions.assertThrows(FeignException.Unauthorized.class, () -> dictionaryClient.getMergedDictionaries(type.getType() + ";", dossierTemplate.getDossierTemplateId(), dossier.getDossierId()));

        Dictionary mergedDict = dictionaryClient.getMergedDictionaries(type.getType(), dossierTemplate.getDossierTemplateId(), dossier.getDossierId());
        assertThat(mergedDict).isNotNull();
        assertThat(mergedDict.getEntries().size()).isEqualTo(3);
        assertThat(mergedDict.getFalsePositiveEntries().size()).isEqualTo(3);
        assertThat(mergedDict.getFalseRecommendationEntries().size()).isEqualTo(4);
    }

    @Test
    public void testGetDictionaryForType() {

        var dossierTemplate = dossierTemplateTesterAndProvider.provideTestTemplate();
        var dossier = dossierTesterAndProvider.provideTestDossier(dossierTemplate, "Dossier");
        var type = typeProvider.testAndProvideType(dossierTemplate);

        dictionaryClient.addEntry(type.getType(), type.getDossierTemplateId(), List.of("word1", "word2", "word3"), false, null, DictionaryEntryType.ENTRY);
        dictionaryClient.addEntry(type.getType(), type.getDossierTemplateId(), List.of("false_positive1", "false_positive"), false, null, DictionaryEntryType.FALSE_POSITIVE);
        dictionaryClient.addEntry(type.getType(),
                type.getDossierTemplateId(),
                List.of("false_recommendation1", "false_recommendation2"),
                false,
                null,
                DictionaryEntryType.FALSE_RECOMMENDATION);

        var loadedType1 = dictionaryClient.getDictionaryForType(type.getType(), type.getDossierTemplateId(), null);

        assertThat(loadedType1.getEntries()).hasSize(3);
        assertThat(loadedType1.getFalsePositiveEntries()).hasSize(2);
        assertThat(loadedType1.getFalseRecommendationEntries()).hasSize(2);

        dictionaryClient.addEntry(type.getType(), type.getDossierTemplateId(), List.of("word1", "word4"), false, dossier.getDossierId(), DictionaryEntryType.ENTRY);
        dictionaryClient.deleteEntries(type.getType(), type.getDossierTemplateId(), List.of("word2"), dossier.getDossierId(), DictionaryEntryType.ENTRY);
        dictionaryClient.addEntry(type.getType(), type.getDossierTemplateId(), List.of("false_positive1", "false_positive3"), false, dossier.getDossierId(), DictionaryEntryType.FALSE_POSITIVE);
        dictionaryClient.addEntry(type.getType(),
                type.getDossierTemplateId(),
                List.of("false_recommendation3", "false_recommendation4"),
                false,
                dossier.getDossierId(),
                DictionaryEntryType.FALSE_RECOMMENDATION);

         var loadedType2 = dictionaryClient.getDictionaryForType(type.getType(), type.getDossierTemplateId(), dossier.getDossierId());

        assertThat(loadedType2.getEntries()).hasSize(2);
        assertThat(loadedType2.getFalsePositiveEntries()).hasSize(2);
        assertThat(loadedType2.getFalseRecommendationEntries()).hasSize(2);

//        var result = dictionaryClient.downloadDictionary(type.getType(), dossierTemplate.getDossierTemplateId(), dossier.getDossierId(), DictionaryEntryType.ENTRY);
//        assertThat(result.getStatusCode().value()).isEqualTo(HttpStatus.OK.value());
    }

    @Test
    public void testSortedEntries() {

        var dossierTemplate = dossierTemplateTesterAndProvider.provideTestTemplate();
        var dossier = dossierTesterAndProvider.provideTestDossier(dossierTemplate, "Dossier");
        var type = typeProvider.testAndProvideType(dossierTemplate);
        assertThat(type.getRecommendationHexColor()).isEqualTo("#aaaaaa");
        assertThat(type.getSkippedHexColor()).isEqualTo("#aaaaaa");
        assertThat(type.isDossierDictionaryOnly()).isFalse();

        dictionaryClient.addEntry(type.getType(), type.getDossierTemplateId(), List.of("Charalampos", "Carina Wilson", "carlsen"), false, null, DictionaryEntryType.ENTRY);
        dictionaryClient.addEntry(type.getType(), type.getDossierTemplateId(), List.of("false_positive1", "false_positive"), false, null, DictionaryEntryType.FALSE_POSITIVE);
        dictionaryClient.addEntry(type.getType(),
                type.getDossierTemplateId(),
                List.of("false_recommendation1", "afalse_recommendation2"),
                false,
                null,
                DictionaryEntryType.FALSE_RECOMMENDATION);

        var loadedType1 = dictionaryClient.getDictionaryForType(type.getType(), type.getDossierTemplateId(), null);

        var entries = loadedType1.getEntries();
        assertThat(entries).hasSize(3);
        assertThat(entries.get(0)).isEqualTo("Carina Wilson");
        assertThat(entries.get(1)).isEqualTo("carlsen");
        assertThat(entries.get(2)).isEqualTo("Charalampos");
        assertThat(loadedType1.getFalsePositiveEntries()).hasSize(2);
        assertThat(loadedType1.getFalsePositiveEntries().get(0)).isEqualTo("false_positive");
        assertThat(loadedType1.getFalsePositiveEntries().get(1)).isEqualTo("false_positive1");
        assertThat(loadedType1.getFalseRecommendationEntries()).hasSize(2);
        assertThat(loadedType1.getFalseRecommendationEntries().get(0)).isEqualTo("afalse_recommendation2");
        assertThat(loadedType1.getFalseRecommendationEntries().get(1)).isEqualTo("false_recommendation1");
    }



    @Test
    public void testCreateAndDeleteLargeDictionary() {

        var dossierTemplate = dossierTemplateTesterAndProvider.provideTestTemplate();

        var type = CreateTypeValue.builder()
                .type("dossier_redaction")
                .label("Dossier Redactions")
                .hexColor("#fcba03")
                .rank(100)
                .description("Something")
                .hasDictionary(true)
                .addToDictionaryAction(false)
                .dossierTemplateId(dossierTemplate.getId())
                .build();

        var createdType = dictionaryClient.addType(type);

        var entries = createDummyEntries(10_000);

        dictionaryClient.addEntry(createdType.getType(), createdType.getDossierTemplateId(), entries, false, null, DictionaryEntryType.ENTRY);

        var dictionary = dictionaryClient.getDictionaryForType(type.getType(), type.getDossierTemplateId(), null);

        var actualEntries = dictionary.getEntries();
        assertThat(actualEntries.size()).isEqualTo(entries.size());
        assertThat(actualEntries).usingComparator(new ListContentWithoutOrderAndWithoutDuplicatesComparator<>()).isEqualTo(entries);

        dictionaryClient.deleteEntries(type.getType(), dossierTemplate.getDossierTemplateId(), entries, null, null);

        dictionary = dictionaryClient.getDictionaryForType(type.getType(), type.getDossierTemplateId(), null);

        actualEntries = dictionary.getEntries();
        assertThat(actualEntries.size()).isEqualTo(0);
    }


    @SuppressWarnings("SameParameterValue")
    private List<String> createDummyEntries(int numberOfEntries) {

        return IntStream.range(0, numberOfEntries).mapToObj(i -> "someWord" + i).toList();
    }


    private static final class ListContentWithoutOrderAndWithoutDuplicatesComparator<T> implements Comparator<List<? extends T>> {

        @SuppressWarnings("SuspiciousMethodCalls")
        @Override
        public int compare(List<? extends T> l1, List<? extends T> l2) {

            return l1.containsAll(l2) ? 0 : -1;
        }

    }


    private TypeValue createDossierRedactionsDictionary(String dossierTemplateId){
        return dictionaryClient.addType(CreateTypeValue.builder()
                .type("dossier_redaction")
                .label("Dossier Redaction")
                .addToDictionaryAction(true)
                .hasDictionary(true)
                .hint(false)
                .rank(100)
                .dossierTemplateId(dossierTemplateId)
                .hexColor("#FFFFFF")
                .recommendationHexColor("#FFFFFF")
                .build());
    }




}
