package org.mte.numecoeval.expositiondonneesentrees.domain.port.input;

import org.apache.commons.lang3.tuple.Pair;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.mte.numecoeval.expositiondonneesentrees.domain.model.*;
import org.mte.numecoeval.expositiondonneesentrees.domain.ports.input.impl.ImportDonneesEntreePortImpl;
import org.mte.numecoeval.expositiondonneesentrees.domain.ports.output.ReferentielServicePort;
import org.mte.numecoeval.expositiondonneesentrees.infrastructure.service.DefaultValueService;
import org.mte.numecoeval.expositiondonneesentrees.infrastructure.service.ErrorManagementService;
import org.springframework.web.multipart.MultipartFile;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.List;
import java.util.Map;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

class ImportDonneesEntreePortImplTest {
    @Mock
    MultipartFile fileToRead;

    @Mock
    ReferentielServicePort referentielServicePort;

    Map<String, String> errorMessages = Map.of();

    ImportDonneesEntreePortImpl importDonneesEntreePort;
    ErrorManagementService errorManagementService;
    DefaultValueService defaultValueService;

    @BeforeEach
    public void init() {
        MockitoAnnotations.openMocks(this);
        importDonneesEntreePort = new ImportDonneesEntreePortImpl(referentielServicePort, errorManagementService, defaultValueService, errorMessages);
    }

    @Test
    void importDataCenter_onIOException_shouldReturnReportWith1Error() throws IOException {
        Mockito.when(fileToRead.getInputStream()).thenThrow(new IOException("Test"));

        Pair<RapportImport, List<DataCenter>> resultImport = importDonneesEntreePort.importDataCenter(null, null, null, fileToRead);

        assertTrue(resultImport.getValue().isEmpty());
        assertEquals("Le fichier CSV des DataCenter n'est pas lisible par le système.", resultImport.getKey().getErreurs().get(0));
    }

    @Test
    void importDataCenter_onFileNotFoundException_shouldReturnReportWith1Error() throws IOException {
        Mockito.when(fileToRead.getInputStream()).thenThrow(new FileNotFoundException("Test"));

        Pair<RapportImport, List<DataCenter>> resultImport = importDonneesEntreePort.importDataCenter(null, null, null, fileToRead);

        assertTrue(resultImport.getValue().isEmpty());
        assertEquals("Le fichier CSV des DataCenters n'est pas trouvable.", resultImport.getKey().getErreurs().get(0));
    }

    @Test
    void importEquipementsPhysiques_onIOException_shouldReturnReportWith1Error() throws IOException {
        Mockito.when(fileToRead.getInputStream()).thenThrow(new IOException("Test"));

        Pair<RapportImport, List<EquipementPhysique>> resultImport = importDonneesEntreePort.importEquipementsPhysiques(null, null, null, fileToRead);

        assertTrue(resultImport.getValue().isEmpty());
        assertEquals("Le fichier CSV des équipements physiques n'est pas lisible par le système.", resultImport.getKey().getErreurs().get(0));
    }

    @Test
    void importEquipementsPhysiques_onFileNotFoundException_shouldReturnReportWith1Error() throws IOException {
        Mockito.when(fileToRead.getInputStream()).thenThrow(new FileNotFoundException("Test"));

        Pair<RapportImport, List<EquipementPhysique>> resultImport = importDonneesEntreePort.importEquipementsPhysiques(null, null, null, fileToRead);

        assertTrue(resultImport.getValue().isEmpty());
        assertEquals("Le fichier CSV des équipements physiques n'est pas trouvable.", resultImport.getKey().getErreurs().get(0));
    }

    @Test
    void importEquipementsVirtuels_onIOException_shouldReturnReportWith1Error() throws IOException {
        Mockito.when(fileToRead.getInputStream()).thenThrow(new IOException("Test"));

        Pair<RapportImport, List<EquipementVirtuel>> resultImport = importDonneesEntreePort.importEquipementsVirtuels(null, null, null, fileToRead);

        assertTrue(resultImport.getValue().isEmpty());
        assertEquals("Le fichier CSV des équipements virtuels n'est pas lisible par le système.", resultImport.getKey().getErreurs().get(0));
    }

    @Test
    void importEquipementsVirtuels_onFileNotFoundException_shouldReturnReportWith1Error() throws IOException {
        Mockito.when(fileToRead.getInputStream()).thenThrow(new FileNotFoundException("Test"));

        Pair<RapportImport, List<EquipementVirtuel>> resultImport = importDonneesEntreePort.importEquipementsVirtuels(null, null, null, fileToRead);

        assertTrue(resultImport.getValue().isEmpty());
        assertEquals("Le fichier CSV des équipements virtuels n'est pas trouvable.", resultImport.getKey().getErreurs().get(0));
    }

    @Test
    void importApplications_onIOException_shouldReturnReportWith1Error() throws IOException {
        Mockito.when(fileToRead.getInputStream()).thenThrow(new IOException("Test"));

        Pair<RapportImport, List<Application>> resultImport = importDonneesEntreePort.importApplications(null, null, null, fileToRead);

        assertTrue(resultImport.getValue().isEmpty());
        assertEquals("Le fichier CSV des Applications n'est pas lisible par le système.", resultImport.getKey().getErreurs().get(0));
    }

    @Test
    void importApplications_onFileNotFoundException_shouldReturnReportWith1Error() throws IOException {
        Mockito.when(fileToRead.getInputStream()).thenThrow(new FileNotFoundException("Test"));

        Pair<RapportImport, List<Application>> resultImport = importDonneesEntreePort.importApplications(null, null, null, fileToRead);

        assertTrue(resultImport.getValue().isEmpty());
        assertEquals("Le fichier CSV des Applications n'est pas trouvable.", resultImport.getKey().getErreurs().get(0));
    }

    @Test
    void importOperationsNonIT_onIOException_shouldReturnReportWith1Error() throws IOException {
        Mockito.when(fileToRead.getInputStream()).thenThrow(new IOException("Test"));

        Pair<RapportImport, List<OperationNonIT>> resultImport = importDonneesEntreePort.importOperationsNonIT(null, null, null, fileToRead);

        assertTrue(resultImport.getValue().isEmpty());
        assertEquals("Le fichier CSV des opérations non IT n'est pas lisible par le système.", resultImport.getKey().getErreurs().get(0));
    }

    @Test
    void importOperationsNonIT_onFileNotFoundException_shouldReturnReportWith1Error() throws IOException {
        Mockito.when(fileToRead.getInputStream()).thenThrow(new FileNotFoundException("Test"));

        Pair<RapportImport, List<OperationNonIT>> resultImport = importDonneesEntreePort.importOperationsNonIT(null, null, null, fileToRead);

        assertTrue(resultImport.getValue().isEmpty());
        assertEquals("Le fichier CSV des opérations non IT n'est pas trouvable.", resultImport.getKey().getErreurs().get(0));
    }

    @Test
    void importMessageries_onIOException_shouldReturnReportWith1Error() throws IOException {
        Mockito.when(fileToRead.getInputStream()).thenThrow(new IOException("Test"));

        Pair<RapportImport, List<Messagerie>> resultImport = importDonneesEntreePort.importMessageries(null, null, null, fileToRead);

        assertTrue(resultImport.getValue().isEmpty());
        assertEquals("Le fichier CSV de la messagerie n'est pas lisible par le système.", resultImport.getKey().getErreurs().get(0));
    }

    @Test
    void importMessageries_onFileNotFoundException_shouldReturnReportWith1Error() throws IOException {
        Mockito.when(fileToRead.getInputStream()).thenThrow(new FileNotFoundException("Test"));

        Pair<RapportImport, List<Messagerie>> resultImport = importDonneesEntreePort.importMessageries(null, null, null, fileToRead);

        assertTrue(resultImport.getValue().isEmpty());
        assertEquals("Le fichier CSV de la messagerie n'est pas trouvable.", resultImport.getKey().getErreurs().get(0));
    }

    @Test
    void importEntite_onIOException_shouldReturnReportWith1Error() throws IOException {
        Mockito.when(fileToRead.getInputStream()).thenThrow(new IOException("Test"));

        var resultImport = importDonneesEntreePort.importEntite(null, null, null, fileToRead);

        assertTrue(resultImport.getValue().isEmpty());
        assertEquals("Le fichier CSV des entités n'est pas lisible par le système.", resultImport.getKey().getErreurs().get(0));
    }

    @Test
    void importEntite_onFileNotFoundException_shouldReturnReportWith1Error() throws IOException {
        Mockito.when(fileToRead.getInputStream()).thenThrow(new FileNotFoundException("Test"));

        var resultImport = importDonneesEntreePort.importEntite(null, null, null, fileToRead);

        assertTrue(resultImport.getValue().isEmpty());
        assertEquals("Le fichier CSV des entités n'est pas trouvable.", resultImport.getKey().getErreurs().get(0));
    }
}
