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

import static com.iqser.red.service.persistence.service.v1.api.external.resource.FileAttributesResource.UTF_ENCODING;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.when;

import org.apache.commons.io.IOUtils;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
import org.springframework.mock.web.MockMultipartFile;

import com.iqser.red.service.peristence.v1.server.integration.client.DossierTemplateExternalClient;
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.entity.ComponentMappingEntity;
import com.iqser.red.service.persistence.management.v1.processor.entity.dossier.DossierTemplateEntity;
import com.iqser.red.service.persistence.management.v1.processor.service.ComponentMappingPersistenceService;
import com.iqser.red.service.persistence.service.v2.api.external.model.ComponentMappingMetadataModel;

import feign.FeignException;
import lombok.SneakyThrows;

@EnableJpaAuditing
public class ComponentMappingTest extends AbstractPersistenceServerServiceTest {

    @Autowired
    private DossierTesterAndProvider dossierTesterAndProvider;

    @Autowired
    private DossierTemplateTesterAndProvider dossierTemplateTesterAndProvider;

    @Autowired
    private DossierTemplateExternalClient dossierTemplateExternalClient;

    @MockBean
    private ComponentMappingPersistenceService componentMappingPersistenceService;


    @Test
    @SneakyThrows
    public void testComponentMappingUpdate() {

        var dossierTemplate = dossierTemplateTesterAndProvider.provideTestTemplate();

        var mockMultipartFile = new MockMultipartFile("file.csv",
                                                      "file.csv",
                                                      "application/csv",
                                                      IOUtils.toByteArray(new ClassPathResource("files/componentmapping/file.csv").getInputStream()));

        ComponentMappingMetadataModel componentMappingMetadataModel = dossierTemplateExternalClient.uploadMapping(dossierTemplate.getId(),
                                                                                                                  mockMultipartFile,
                                                                                                                  "file",
                                                                                                                  UTF_ENCODING,
                                                                                                                  ",",
                                                                                                                  "\"");

        assertEquals(componentMappingMetadataModel.getFileName(), mockMultipartFile.getOriginalFilename());

        var updateMockMultipartFile = new MockMultipartFile("update_file.csv",
                                                            "update_file.csv",
                                                            "application/csv",
                                                            IOUtils.toByteArray(new ClassPathResource("files/componentmapping/update_file.csv").getInputStream()));

        when(componentMappingPersistenceService.getEntityById(anyString(), anyString())).thenReturn(ComponentMappingEntity.builder()
                                                                                                            .id(componentMappingMetadataModel.getId())
                                                                                                            .dossierTemplate(new DossierTemplateEntity())
                                                                                                            .storageId(buildStorageId(dossierTemplate.getId(),
                                                                                                                                      componentMappingMetadataModel.getId(),
                                                                                                                                      "file",
                                                                                                                                      "update_file.csv"))
                                                                                                            .fileName("update_file.csv")
                                                                                                            .build());

        componentMappingMetadataModel = dossierTemplateExternalClient.updateMapping(dossierTemplate.getId(),
                                                                                    componentMappingMetadataModel.getId(),
                                                                                    updateMockMultipartFile,
                                                                                    "file",
                                                                                    UTF_ENCODING,
                                                                                    ",",
                                                                                    "\"");

        assertEquals(componentMappingMetadataModel.getFileName(), updateMockMultipartFile.getOriginalFilename());
    }


    @Test
    @SneakyThrows
    public void testCreateComponentMappingWithEmptyCsv() {

        var dossierTemplate = dossierTemplateTesterAndProvider.provideTestTemplate();

        var mockMultipartFile = new MockMultipartFile("file.csv",
                                                      "empty.csv",
                                                      "application/csv",
                                                      IOUtils.toByteArray(new ClassPathResource("files/componentmapping/empty.csv").getInputStream()));

        String id = dossierTemplate.getId();
        var result = assertThrows(FeignException.class, () -> dossierTemplateExternalClient.uploadMapping(id, mockMultipartFile, "file", UTF_ENCODING, ",", "\""));
        assertTrue(result.getMessage().contains("CSV file can not be empty!"));
    }


    public static String buildStorageId(String dossierTemplateId, String id, String name, String fileName) {

        return dossierTemplateId + "/" + id + "_" + name + "_" + fileName;
    }

}