package org.mte.numecoeval.referentiel.steps;

import io.cucumber.java.fr.Alors;
import io.cucumber.java.fr.Et;
import io.cucumber.java.fr.Quand;
import io.restassured.http.ContentType;
import io.restassured.response.Response;
import org.mte.numecoeval.referentiel.infrastructure.restapi.dto.CritereDTO;
import org.mte.numecoeval.referentiel.domain.ports.input.impl.ImportCriterePortImpl;
import org.mte.numecoeval.referentiel.infrastructure.restapi.controller.critere.ReferentielAdministrationCritereRestApi;
import org.mte.numecoeval.referentiel.infrastructure.restapi.controller.critere.ReferentielCritereRestApi;
import org.springframework.util.ResourceUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;

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

public class CritereStepdefs extends AbstractStepDefinitions {

    private List<CritereDTO> critereDTOS;

    private List<CritereDTO> critereCSV;

    @Quand("le fichier CSV {string} est inject")
    public void leFichierCSVEstInject(String nomFichier) throws FileNotFoundException, NoSuchMethodException {
        setupRestAssured();
        File file = ResourceUtils.getFile("classpath:" + nomFichier);

        // Chargement des données
        critereCSV = new ImportCriterePortImpl().importCSV(new FileInputStream(file)).getObjects();

        String requestPath = Arrays.stream(ReferentielAdministrationCritereRestApi.class.getMethod("importCSV", MultipartFile.class)
                .getAnnotation(PostMapping.class).path()).findFirst().orElse(null);
        Response response = given()
                .multiPart("file", file)
                .post(requestPath)
                .thenReturn();
        //check que le status est OK
        assertEquals(200, response.getStatusCode());
    }

    @Alors("Il existe {int} elements dans le referentiel critere")
    public void ilExisteElementsDansLeReferentielCritere(int nombreElements) throws NoSuchMethodException {
        String requestPath = Arrays.stream(ReferentielCritereRestApi.class.getMethod("getAll")
                .getAnnotation(GetMapping.class).path()).findFirst().orElse(null);
        Response response = given()
                .contentType(ContentType.JSON)
                .get(requestPath)
                .thenReturn();
        critereDTOS = Arrays.asList(response.as(CritereDTO[].class));
        assertEquals(nombreElements, response.as(List.class).size());

    }

    @Et("chacun des elements du referential ajouté est identique au element du fichier csv")
    public void chacunDesElementsDuReferentialAjouteEstIdentiqueAuElementDuFichierCsv() {
        List<CritereDTO> resultEgalite = critereCSV.stream().filter(critereEntity ->
                critereDTOS.stream().anyMatch(api ->
                        Optional.of(critereEntity.getDescription()).equals(Optional.of(api.getDescription()))
                                && critereEntity.getNomCritere().equals(api.getNomCritere())
                                && critereEntity.getUnite().equals(api.getUnite())
                )).toList();
        assertEquals(critereCSV.size(), resultEgalite.size());
    }
}
