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

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.exception.ValidationException;
import org.mte.numecoeval.expositiondonneesentrees.domain.model.DemandeCalcul;
import org.mte.numecoeval.expositiondonneesentrees.domain.ports.input.SoumissionCalculPort;
import org.mte.numecoeval.expositiondonneesentrees.infrastructure.jdbc.SoumissionCalculPortJdbcImpl;
import org.springframework.jdbc.core.JdbcTemplate;

import static org.junit.jupiter.api.Assertions.*;

class SoumissionCalculPortImplTest {

    @Mock
    JdbcTemplate jdbcTemplate;

    SoumissionCalculPort soumissionCalculPort;

    @BeforeEach
    public void init() {
        MockitoAnnotations.openMocks(this);
        soumissionCalculPort = new SoumissionCalculPortJdbcImpl(jdbcTemplate);
    }

    @Test
    void whenDemandeIsNull_validateShouldThrowException() {
        var exception = assertThrows(ValidationException.class, () -> soumissionCalculPort.validate(null));
        assertEquals("Corps de la demande obligatoire", exception.getErreur());
    }

    @Test
    void whenDateLotIsNull_validateShouldThrowException() {
        var demande = DemandeCalcul.builder()
                .dateLot(null)
                .nomOrganisation(null)
                .nomLot(null)
                .build();
        var exception = assertThrows(ValidationException.class, () -> soumissionCalculPort.validate(demande));
        assertEquals("Nom de lot obligatoire", exception.getErreur());
    }

    @Test
    void whenDemandeIsValid_soumissionShouldBeOK() {
        var demande = DemandeCalcul.builder()
                .nomLot("TEST|2023-01-01")
                .build();
        Mockito.when(jdbcTemplate.update(Mockito.contains("en_donnees_entrees"), Mockito.anyString(), Mockito.anyString(), Mockito.anyString())).thenReturn(1);
        Mockito.when(jdbcTemplate.update(Mockito.contains("en_data_center"), Mockito.anyString(), Mockito.anyString(), Mockito.anyString())).thenReturn(2);
        Mockito.when(jdbcTemplate.update(Mockito.contains("en_equipement_physique"), Mockito.anyString(), Mockito.anyString(), Mockito.anyString())).thenReturn(5);
        Mockito.when(jdbcTemplate.update(Mockito.contains("en_messagerie"), Mockito.anyString(), Mockito.anyString(), Mockito.anyString())).thenReturn(20);

        var resultat = soumissionCalculPort.soumissionCalcul(demande);

        assertNotNull(resultat);
        assertEquals(2, resultat.getNbrDataCenter());
        assertEquals(5, resultat.getNbrEquipementPhysique());
        assertNull(resultat.getNbrEquipementVirtuel());
        assertNull(resultat.getNbrApplication());
        assertEquals(20, resultat.getNbrMessagerie());
    }

    @Test
    void whenDemandeIsValid_rejeuShouldBeOK() {
        var demande = DemandeCalcul.builder()
                .nomLot("TEST|2023-01-01")
                .build();
        Mockito.when(jdbcTemplate.update(Mockito.contains("en_donnees_entrees"), Mockito.anyString(), Mockito.anyString())).thenReturn(1);
        Mockito.when(jdbcTemplate.update(Mockito.contains("en_data_center"), Mockito.anyString(), Mockito.anyString())).thenReturn(2);
        Mockito.when(jdbcTemplate.update(Mockito.contains("en_equipement_physique"), Mockito.anyString(), Mockito.anyString())).thenReturn(5);
        Mockito.when(jdbcTemplate.update(Mockito.contains("en_messagerie"), Mockito.anyString(), Mockito.anyString())).thenReturn(20);

        var resultat = soumissionCalculPort.rejeuCalcul(demande);

        assertNotNull(resultat);
        assertEquals(2, resultat.getNbrDataCenter());
        assertEquals(5, resultat.getNbrEquipementPhysique());
        assertNull(resultat.getNbrEquipementVirtuel());
        assertNull(resultat.getNbrApplication());
        assertEquals(20, resultat.getNbrMessagerie());
    }

}
