package org.mte.numecoeval.calculs.infrastructure.service.calcul;

import lombok.AllArgsConstructor;
import org.mte.numecoeval.calculs.domain.data.demande.DemandeCalculImpactEquipementPhysique;
import org.mte.numecoeval.calculs.domain.data.demande.OptionsCalcul;
import org.mte.numecoeval.calculs.domain.data.indicateurs.ImpactEquipementPhysique;
import org.mte.numecoeval.calculs.domain.model.CalculEquipementPhysique;
import org.mte.numecoeval.calculs.domain.port.input.service.CalculImpactEquipementPhysiqueService;
import org.mte.numecoeval.calculs.infrastructure.mapper.EntreesMapper;
import org.mte.numecoeval.calculs.infrastructure.mapper.ReferentielMapper;
import org.mte.numecoeval.calculs.infrastructure.repository.DonneesEntreeRepository;
import org.mte.numecoeval.calculs.referentiels.generated.api.model.CritereDTO;
import org.mte.numecoeval.calculs.referentiels.generated.api.model.EtapeDTO;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

@Service
@AllArgsConstructor
public class CalculEquipementPhysiqueService {

    EntreesMapper entreesMapper;

    ReferentielMapper referentielMapper;

    CalculImpactEquipementPhysiqueService calculImpactEquipementPhysiqueService;

    DonneesEntreeRepository donneesEntreeRepository;

    /**
     * Calcule les impacts d'un equipement physique
     * Returne la liste d'impacts en iterant par (etape, critere)
     *
     * @param calculEquipementPhysique l'equipement physique enrichi
     * @return la liste d'impacts
     */
    public List<ImpactEquipementPhysique> calculImpactEquipementPhysique(CalculEquipementPhysique calculEquipementPhysique) {

        LocalDateTime dateCalcul = LocalDateTime.now();

        List<ImpactEquipementPhysique> impactEquipementPhysiqueList = new ArrayList<>();
        String dureeUsage = donneesEntreeRepository.findDureeUsage(calculEquipementPhysique.getEquipementPhysique().getNomLot(), calculEquipementPhysique.getEquipementPhysique().getNomOrganisation());

        for (EtapeDTO etapeDTO : calculEquipementPhysique.getEtapes()) {
            for (CritereDTO critereDTO : calculEquipementPhysique.getCriteres()) {

                DemandeCalculImpactEquipementPhysique demandeCalculImpactEquipementPhysique = DemandeCalculImpactEquipementPhysique.builder()
                        .dateCalcul(dateCalcul)
                        .equipementPhysique(entreesMapper.toDomain(calculEquipementPhysique.getEquipementPhysique()))
                        .etape(referentielMapper.toEtape(etapeDTO))
                        .critere(referentielMapper.toCritere(critereDTO))
                        .typeEquipement(referentielMapper.toTypeEquipement(calculEquipementPhysique.getTypeEquipement()))
                        .correspondanceRefEquipement(referentielMapper.toCorrespondanceRefEquipement(calculEquipementPhysique.getCorrespondanceRefEquipement()))
                        .hypotheses(referentielMapper.toListHypothese(calculEquipementPhysique.getHypotheses()))
                        .mixElectriques(referentielMapper.toListMixElectrique(calculEquipementPhysique.getMixElectriques()))
                        .impactEquipements(referentielMapper.toListImpactEquipement(calculEquipementPhysique.getImpactsEquipement()))
                        .optionsCalcul(new OptionsCalcul(dureeUsage))
                        .build();

                impactEquipementPhysiqueList.add(
                        calculImpactEquipementPhysiqueService.calculerImpactEquipementPhysique(demandeCalculImpactEquipementPhysique)
                );
            }
        }
        return impactEquipementPhysiqueList;

    }
}
