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.apache.commons.lang3.math.NumberUtils;
import org.mte.numecoeval.referentiel.domain.model.ImpactEquipement;
import org.mte.numecoeval.referentiel.infrastructure.jpa.adapter.ImpactEquipementJpaAdapter;
import org.mte.numecoeval.referentiel.infrastructure.restapi.controller.impactequipement.ReferentielAdministrationImpactEquipementRestApi;
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.assertTrue;

public class ImpactImpactEquipementStepDefinitions extends AbstractStepDefinitions {

    @Autowired
    ImpactEquipementJpaAdapter jpaAdapter;

    @DataTableType
    public ImpactEquipement impactEquipement(Map<String, String> entry) {
        var impact = new ImpactEquipement();
        impact.setEtape(entry.get("etape"));
        impact.setCritere(entry.get("critere"));
        impact.setRefEquipement(entry.get("refEquipement"));
        impact.setValeur(NumberUtils.createDouble(entry.get("valeur")));
        impact.setConsoElecMoyenne(NumberUtils.createDouble(entry.get("consoElecMoyenne")));
        impact.setSource(entry.get("source"));
        impact.setType(entry.get("type"));
        impact.setDescription(entry.get("description"));
        return impact;
    }

    @Quand("le fichier CSV des impacts d'équipements {string} est importé par API et la réponse est {int}")
    public void importReferentielImpactEquipements(String nomFichier, int codeReponseHttpAttendu) throws FileNotFoundException, NoSuchMethodException {
        setupRestAssured();
        initAlimentationEtapeEtCritere();
        File file = ResourceUtils.getFile("classpath:" + nomFichier);
        String requestPath = Arrays.stream(ReferentielAdministrationImpactEquipementRestApi.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 impacts d'équipements renvoie {int} lignes")
    public void getAllImpactEquipements(int nombreLignesAttendues) throws NoSuchMethodException {
        List<ImpactEquipement> impactEquipements = jpaAdapter.getAll();

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

    @Alors("Vérifications des impacts équipements disponibles")
    public void checkImpactEquipements(List<ImpactEquipement> dataTable) {
        List<ImpactEquipement> impactEquipements = jpaAdapter.getAll();

        assertEquals(dataTable.size(), impactEquipements.size());
        dataTable.forEach( expected ->
                assertTrue(
                        impactEquipements.stream().anyMatch(impactEquipement1 -> impactEquipement1.equals(expected)),
                        "L'équipement étape: %s, critere: %s, refEquipement: %s n'est pas disponible".formatted(
                                expected.getEtape(),
                                expected.getCritere(),
                                expected.getRefEquipement()
                        )
                )
        );
    }
}
