package org.mte.numecoeval.referentiel.infrastructure.jpa;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mte.numecoeval.referentiel.domain.exception.ReferentielException;
import org.mte.numecoeval.referentiel.domain.model.Etape;
import org.mte.numecoeval.referentiel.domain.model.id.EtapeId;
import org.mte.numecoeval.referentiel.infrastructure.jpa.adapter.EtapeJpaAdapter;
import org.mte.numecoeval.referentiel.infrastructure.jpa.adapter.ImpactEquipementJpaAdapter;
import org.mte.numecoeval.referentiel.infrastructure.jpa.adapter.ImpactReseauJpaAdapter;
import org.mte.numecoeval.referentiel.infrastructure.jpa.entity.EtapeEntity;
import org.mte.numecoeval.referentiel.infrastructure.jpa.repository.EtapeRepository;
import org.mte.numecoeval.referentiel.infrastructure.mapper.EtapeMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

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

@ContextConfiguration(classes = {EtapeJpaAdapter.class})
@ExtendWith(SpringExtension.class)
class EtapeJpaAdapterTest {
    @Autowired
    private EtapeJpaAdapter etapeJpaAdapter;

    @MockBean
    private EtapeMapper etapeMapper;

    @MockBean
    private EtapeRepository etapeRepository;

    // Pour les purges des données filles
    @MockBean
    ImpactReseauJpaAdapter impactReseauJpaAdapter;
    @MockBean
    ImpactEquipementJpaAdapter impactEquipementJpaAdapter;

    /**
     * Method under test: {@link EtapeJpaAdapter#save(Etape)}
     */
    @Test
    void testSave() throws ReferentielException {
        Etape etape = new Etape();
        etape.setCode("Code");
        etape.setLibelle("Libelle");
        assertNull(etapeJpaAdapter.save(etape));
    }

    /**
     * Method under test: {@link EtapeJpaAdapter#save(Etape)}
     */
    @Test
    void testSave2() throws ReferentielException {
        Etape etape = new Etape();
        etape.setCode("Code");
        etape.setLibelle("Libelle");

        Etape etape1 = new Etape();
        etape1.setCode("Code");
        etape1.setLibelle("Libelle");
        Etape etape2 = mock(Etape.class);
        when(etape2.setCode((String) any())).thenReturn(etape);
        when(etape2.setLibelle((String) any())).thenReturn(etape1);
        etape2.setCode("Code");
        etape2.setLibelle("Libelle");
        assertNull(etapeJpaAdapter.save(etape2));
        verify(etape2).setCode((String) any());
        verify(etape2).setLibelle((String) any());
    }

    /**
     * Method under test: {@link EtapeJpaAdapter#saveAll(Collection)}
     */
    @Test
    void testSaveAll() throws ReferentielException {
        when(etapeMapper.toEntities((Collection<Etape>) any())).thenReturn(new ArrayList<>());
        when(etapeRepository.saveAll((Iterable<EtapeEntity>) any())).thenReturn(new ArrayList<>());
        etapeJpaAdapter.saveAll(new ArrayList<>());
        verify(etapeMapper).toEntities((Collection<Etape>) any());
        verify(etapeRepository).saveAll((Iterable<EtapeEntity>) any());
        assertTrue(etapeJpaAdapter.getAll().isEmpty());
    }

    /**
     * Method under test: {@link EtapeJpaAdapter#get(EtapeId)}
     */
    @Test
    void testGet() throws ReferentielException {
        EtapeId etapeId = new EtapeId();
        etapeId.setCode("Code");
        assertNull(etapeJpaAdapter.get(etapeId));
    }

    /**
     * Method under test: {@link EtapeJpaAdapter#get(EtapeId)}
     */
    @Test
    void testGet2() throws ReferentielException {
        EtapeId etapeId = new EtapeId();
        etapeId.setCode("Code");
        EtapeId etapeId1 = mock(EtapeId.class);
        when(etapeId1.setCode((String) any())).thenReturn(etapeId);
        etapeId1.setCode("Code");
        assertNull(etapeJpaAdapter.get(etapeId1));
        verify(etapeId1).setCode((String) any());
    }

    /**
     * Method under test: {@link EtapeJpaAdapter#purge()}
     */
    @Test
    void testPurge() {
        doNothing().when(impactReseauJpaAdapter).purge();
        doNothing().when(impactEquipementJpaAdapter).purge();
        doNothing().when(etapeRepository).deleteAll();

        etapeJpaAdapter.purge();

        // Purge des données filles
        verify(impactReseauJpaAdapter, times(0)).purge();
        verify(impactEquipementJpaAdapter, times(0)).purge();
        verify(etapeRepository).deleteAll();
        assertTrue(etapeJpaAdapter.getAll().isEmpty());
    }

    /**
     * Method under test: {@link EtapeJpaAdapter#getAll()}
     */
    @Test
    void testGetAll() {
        ArrayList<Etape> etapeList = new ArrayList<>();
        when(etapeMapper.toDomains((List<EtapeEntity>) any())).thenReturn(etapeList);
        when(etapeRepository.findAll()).thenReturn(new ArrayList<>());
        List<Etape> actualAll = etapeJpaAdapter.getAll();
        assertSame(etapeList, actualAll);
        assertTrue(actualAll.isEmpty());
        verify(etapeMapper).toDomains((List<EtapeEntity>) any());
        verify(etapeRepository).findAll();
    }
}

