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

import static com.iqser.red.service.persistence.management.v1.processor.utils.TypeIdUtils.toTypeId;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.when;

import java.util.Set;

import org.assertj.core.util.Lists;
import org.junit.jupiter.api.Test;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.mock.mockito.MockBean;

import com.iqser.red.service.peristence.v1.server.integration.client.DictionaryClient;
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.management.v1.processor.exception.BadRequestException;
import com.iqser.red.service.persistence.management.v1.processor.service.DossierService;
import com.iqser.red.service.persistence.service.v1.api.shared.model.CreateTypeValue;
import com.iqser.red.service.persistence.service.v1.api.shared.model.TypeResponse;
import com.iqser.red.service.persistence.service.v1.api.shared.model.UpdateTypeValue;
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.type.DictionaryEntryType;

import feign.FeignException;

public class TypeTest extends AbstractPersistenceServerServiceTest {

    @Autowired
    private TypeProvider typeProvider;

    @Autowired
    private DossierTemplateTesterAndProvider dossierTemplateTesterAndProvider;

    @Autowired
    private DossierTesterAndProvider dossierTesterAndProvider;

    @Autowired
    private DictionaryClient dictionaryClient;


    @Test
    public void testType() {

        var dossierTemplate = dossierTemplateTesterAndProvider.provideTestTemplate();

        var type = typeProvider.testAndProvideType(dossierTemplate);

        dictionaryClient.addEntry(type.getType(), type.getDossierTemplateId(), Lists.newArrayList("aaa", "bbb", "ccc"), true, null, DictionaryEntryType.ENTRY);

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

        assertThat(loadedType.getEntries().size()).isEqualTo(3);

        var dict = loadedType.getEntries();

        assertThat(dict.size()).isEqualTo(3);

        dictionaryClient.deleteEntries(type.getType(), type.getDossierTemplateId(), Lists.newArrayList("aaa", "bbb", "ccc"), null, DictionaryEntryType.ENTRY);

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

        dict = loadedType.getEntries();

        assertThat(dict.size()).isEqualTo(0);

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

        loadedType = dictionaryClient.getDictionaryForType(type.getType(), type.getDossierTemplateId(), null);
        assertThat(loadedType.getRank()).isEqualTo(99);

        dictionaryClient.deleteType(type.getType(), type.getDossierTemplateId());

        var typesForTemplate = dictionaryClient.getAllTypes(loadedType.getDossierTemplateId(), null, false).getTypes();
        assertThat(typesForTemplate).hasSize(8);

        var dossier = dossierTesterAndProvider.provideTestDossier(dossierTemplate);
        var dossierType = typeProvider.testAndProvideType(dossierTemplate, dossier, "dossier-dict");

        var typesForDossier = dictionaryClient.getAllTypes(dossierType.getDossierTemplateId(), dossier.getId(), false).getTypes();
        assertThat(typesForDossier).isNotEmpty();

    }


    @Test
    public void testColors() {

        var dossierTemplate = dossierTemplateTesterAndProvider.provideTestTemplate();

        var colors = new Colors();

        colors.setRequestAddColor("#dddddd");
        colors.setRequestRemoveColor("#dddddd");
        colors.setDictionaryRequestColor("#dddddd");
        colors.setPreviewColor("#dddddd");
        colors.setAnalysisColor("#dddddd");
        colors.setUpdatedColor("#dddddd");
        colors.setRecommendationColor("#dddddd");
        colors.setHintColor("#dddddd");
        colors.setRedactionColor("#dddddd");
        colors.setIgnoredHintColor("#dddddd");
        colors.setSkippedColor("#dddddd");
        colors.setAppliedRedactionColor("#dddddd");

        colors.setDossierTemplateId(dossierTemplate.getId());

        dictionaryClient.setColors(dossierTemplate.getId(), colors);

        var savedColors = dictionaryClient.getColors(dossierTemplate.getId());
        assertThat(savedColors).isEqualTo(colors);
        assertThat(savedColors.getRequestAddColor()).isEqualTo(colors.getRequestAddColor());
        assertThat(savedColors.getRequestRemoveColor()).isEqualTo(colors.getRequestRemoveColor());
        assertThat(savedColors.getDictionaryRequestColor()).isEqualTo(colors.getDictionaryRequestColor());
        assertThat(savedColors.getPreviewColor()).isEqualTo(colors.getPreviewColor());
        assertThat(savedColors.getAnalysisColor()).isEqualTo(colors.getAnalysisColor());
        assertThat(savedColors.getUpdatedColor()).isEqualTo(colors.getUpdatedColor());
        assertThat(savedColors.getRecommendationColor()).isEqualTo(colors.getRecommendationColor());
        assertThat(savedColors.getHintColor()).isEqualTo(colors.getHintColor());
        assertThat(savedColors.getRedactionColor()).isEqualTo(colors.getRedactionColor());
        assertThat(savedColors.getIgnoredHintColor()).isEqualTo(colors.getIgnoredHintColor());
        assertThat(savedColors.getSkippedColor()).isEqualTo(colors.getSkippedColor());
        assertThat(savedColors.getAppliedRedactionColor()).isEqualTo(colors.getAppliedRedactionColor());
    }


    @Test
    public void testSoftDeletedTimeForTypes() {

        var dossierTemplate = dossierTemplateTesterAndProvider.provideTestTemplate();
        var type1 = typeProvider.testAndProvideType(dossierTemplate, "type1", 100);
        var type2 = typeProvider.testAndProvideType(dossierTemplate, "type2", 101);

        var types = dictionaryClient.getAllTypes(dossierTemplate.getId(), null, true);
        assertEquals(types.getTypes().size(), 10);
        assertTrue(types.getTypes()
                           .stream()
                           .allMatch(typeValue -> typeValue.getSoftDeletedTime() == null));

        dictionaryClient.deleteType(type2.getType(), dossierTemplate.getId());
        types = dictionaryClient.getAllTypes(dossierTemplate.getId(), null, true);
        assertEquals(types.getTypes().size(), 10);
        assertNull(types.getTypes()
                           .stream()
                           .filter(t -> t.getType().equals(type1.getType()))
                           .findFirst()
                           .get().getSoftDeletedTime());
        assertNotNull(types.getTypes()
                              .stream()
                              .filter(t -> t.getType().equals(type2.getType()))
                              .findFirst()
                              .get().getSoftDeletedTime());
    }


    @Test
    public void testAddTypeWithLongName() {

        var dossierTemplate = dossierTemplateTesterAndProvider.provideTestTemplate();
        var dossier = dossierTesterAndProvider.provideTestDossier(dossierTemplate);

        var type = new CreateTypeValue();
        type.setAddToDictionaryAction(false);
        type.setAutoHideSkipped(false);
        type.setCaseInsensitive(false);
        type.setDossierDictionaryOnly(false);
        type.setDossierTemplateId(dossierTemplate.getId());
        type.setHasDictionary(false);
        type.setHexColor("#dddddd");
        type.setHint(false);
        String label = "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculussdfridiculussdfridiculussdfridiculussdfridiculussdfridiculussdfridiculussdfridiculussdfridiculussdfridiculussdfridiculussdfridiculussdf";
        type.setLabel(label);
        type.setRank(-4);
        type.setRecommendation(false);
        type.setRecommendationHexColor("#aaaaaa");
        type.setSkippedHexColor("#aaaaaa");
        String typeName = "lorem_ipsum_dolor_sit_amet_consectetuer_adipiscing_elit_aenean_commodo_ligula_eget_dolor_aenean_massa_cum_sociis_natoque_penatibus_et_magnis_dis_parturient_montes_nascetur_ridiculussdfridiculussdfridiculussdfridiculussdfridiculussdfridiculussdfridiculussdfridiculussdfridiculussdfridiculussdfridiculussdfridiculussdf";
        type.setType(typeName);

        String typeId = toTypeId(typeName, dossierTemplate.getId(), dossier.getId());

        assertTrue(label.length() > 255 || typeId.length() > 512);
        assertThatThrownBy(() -> dictionaryClient.addType(type)).hasMessageContaining("Value is too long.").isInstanceOf(FeignException.class);

    }



}
