package org.mte.numecoeval.referentiel.steps;

import io.cucumber.java.DataTableType;
import io.cucumber.java.fr.Alors;
import io.cucumber.java.fr.Et;
import io.cucumber.java.fr.Quand;
import org.mte.numecoeval.referentiel.domain.model.CorrespondanceRefEquipement;
import org.mte.numecoeval.referentiel.infrastructure.jpa.adapter.CorrespondanceRefEquipementJpaAdapter;
import org.mte.numecoeval.referentiel.infrastructure.restapi.controller.correspondance.ReferentielAdministrationCorrespondanceRefEquipementRestApi;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.ResourceUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileNotFoundException;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

import static io.restassured.RestAssured.given;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;

public class CorrespondanceRefEquipementStepDefinitions extends AbstractStepDefinitions {

    @Autowired
    CorrespondanceRefEquipementJpaAdapter jpaAdapter;

    @DataTableType
    public CorrespondanceRefEquipement correspondanceRefEquipement(Map<String, String> entry) {
        return CorrespondanceRefEquipement.builder()
                .modeleEquipementSource(entry.get("modeleEquipementSource"))
                .refEquipementCible(entry.get("refEquipementCible"))
                .build();
    }

    @Quand("le fichier CSV des correspondances d'équipements {string} est importé par API et la réponse est {int}")
    public void importReferentielCorrespondanceRefEquipements(String nomFichier, int codeReponseHttpAttendu) throws FileNotFoundException, NoSuchMethodException {
        setupRestAssured();
        initAlimentationEtapeEtCritere();
        File file = ResourceUtils.getFile("classpath:" + nomFichier);
        String requestPath = Arrays.stream(ReferentielAdministrationCorrespondanceRefEquipementRestApi.class.getMethod("importCSV", MultipartFile.class)
                .getAnnotation(PostMapping.class).path()).findFirst().orElse(null);
        response = given()
                .multiPart("file", file)
                .post(requestPath)
                .thenReturn();
        assertEquals(codeReponseHttpAttendu, response.getStatusCode());
    }

    @Et("La récupération de tous les correspondances d'équipements renvoie {int} lignes")
    public void getAllCorrespondanceRefEquipement(int nombreLignesAttendues) throws NoSuchMethodException {
        List<CorrespondanceRefEquipement> domains = jpaAdapter.getAll();

        assertEquals(nombreLignesAttendues, domains.size());
    }

    @Alors("Vérifications des correspondances d'équipements disponibles")
    public void checkImpactEquipements(List<CorrespondanceRefEquipement> dataTable) {
        List<CorrespondanceRefEquipement> datasInDatabase = jpaAdapter.getAll();

        assertEquals(dataTable.size(), datasInDatabase.size());
        dataTable.forEach(expected -> {
            var dataInDatabase = datasInDatabase.stream().filter(data -> data.getModeleEquipementSource().equals(expected.getModeleEquipementSource())).findFirst().orElse(null);
            assertNotNull(dataInDatabase, "Il existe une correspondance d'équipement avec le modèle %s".formatted(expected.getModeleEquipementSource()));

            assertEquals(expected.getRefEquipementCible(), dataInDatabase.getRefEquipementCible(), "CorrespondanceRefEquipement %s : la référence cible ne matche pas".formatted(expected.getRefEquipementCible()));
        });
    }
}
