package org.mte.numecoeval.expositiondonneesentrees.infrastructure.service;

import lombok.RequiredArgsConstructor;
import org.mte.numecoeval.expositiondonneesentrees.domain.exception.ValidationException;
import org.mte.numecoeval.expositiondonneesentrees.generated.api.model.DureeUsage;
import org.mte.numecoeval.expositiondonneesentrees.infrastructure.adapters.ReferentielRestClient;
import org.mte.numecoeval.expositiondonneesentrees.infrastructure.jpa.entity.DonneesEntreesEntity;
import org.mte.numecoeval.expositiondonneesentrees.infrastructure.jpa.repository.DonneesEntreesRepository;
import org.mte.numecoeval.expositiondonneesentrees.referentiels.generated.api.model.CritereDTO;
import org.mte.numecoeval.expositiondonneesentrees.referentiels.generated.api.model.EtapeDTO;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.HashSet;
import java.util.List;

import static org.mte.numecoeval.expositiondonneesentrees.infrastructure.controller.CalculController.TYPE_CALCUL_SOUMISSION;

@Service
@RequiredArgsConstructor
public class DonneesEntreesService {

    @Value("${regle-par-defaut-duree-usage}")
    private String defaultDureeUsage;

    final ReferentielRestClient referentielRestClient;
    final DonneesEntreesRepository donneesEntreesRepository;

    public void manageDonneesEntrees(String nomLot, DureeUsage modeDureeUsage, List<String> etapes, List<String> criteres, String nomOrganisation, String typeCalcul) {
        var donneeEntreeEntity = donneesEntreesRepository.findByNomLot(nomLot).getFirst();
        donneeEntreeEntity = enrichi(donneeEntreeEntity, modeDureeUsage, etapes, criteres, nomOrganisation, typeCalcul);
        donneesEntreesRepository.save(donneeEntreeEntity);
    }

    private DonneesEntreesEntity enrichi(DonneesEntreesEntity donneeEntreeEntity, DureeUsage dureeUsage, List<String> etapes, List<String> criteres, String nomOrganisation, String typeCalcul) {
        if (typeCalcul.equals(TYPE_CALCUL_SOUMISSION)) {
            var modeDureeUsage = dureeUsage == null ? DureeUsage.fromValue(defaultDureeUsage) : dureeUsage;
            if (DureeUsage.REEL != modeDureeUsage) {
                modeDureeUsage = DureeUsage.FIXE;
            }
            donneeEntreeEntity.setDureeUsage(String.valueOf(modeDureeUsage));
            donneeEntreeEntity.setNomOrganisation(nomOrganisation);
        }
        if (etapes != null) {
            var allEtapes = referentielRestClient.getAllEtapes().stream().map(EtapeDTO::getCode).toList();
            if (!new HashSet<>(allEtapes).containsAll(etapes)) {
                throw new ValidationException(
                        "La liste d'étapes n'est pas valide, elle doit être comprise dans: " + allEtapes
                );
            }
            donneeEntreeEntity.setEtapes(String.join("##", etapes));
        } else {
            donneeEntreeEntity.setEtapes(null);
        }
        if (criteres != null) {
            var allCriteres = referentielRestClient.getAllCriteres().stream().map(CritereDTO::getNomCritere).toList();
            if (!new HashSet<>(allCriteres).containsAll(criteres)) {
                throw new ValidationException(
                        "La liste de critères n'est pas valide, elle doit être comprise dans: " + allCriteres
                );
            }
            donneeEntreeEntity.setCriteres(String.join("##", criteres));
        } else {
            donneeEntreeEntity.setCriteres(null);
        }
        return donneeEntreeEntity;
    }
}
