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

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.mte.numecoeval.calculs.domain.model.CalculEquipementPhysique;
import org.mte.numecoeval.calculs.infrastructure.client.ReferentielClient;
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.mte.numecoeval.calculs.referentiels.generated.api.model.HypotheseDTO;
import org.mte.numecoeval.topic.data.EquipementPhysiqueDTO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

@Slf4j
@Service
public class EnrichissementEquipementPhysiqueService {
    @Autowired
    DonneesEntreeRepository donneesEntreeRepository;

    @Value("${numecoeval.hypotheses.equipementPhysique}")
    private String hypothesesEquipementPhysique;

    @Autowired
    private ReferentielClient referentielClient;

    public CalculEquipementPhysique serviceEnrichissementEquipementPhysique(EquipementPhysiqueDTO equipementPhysiqueDTO) {
        if (equipementPhysiqueDTO == null) return null;

        log.debug("{} - {} - {} : Enrichissement d'un équipement physique : Nom Equipement: {}, Type: {}, Modele: {}",
                equipementPhysiqueDTO.getNomOrganisation(), equipementPhysiqueDTO.getNomLot(), equipementPhysiqueDTO.getDateLot(),
                equipementPhysiqueDTO.getNomEquipementPhysique(), equipementPhysiqueDTO.getType(), equipementPhysiqueDTO.getModele());

        CalculEquipementPhysique calculEquipementPhysique = new CalculEquipementPhysique();

        calculEquipementPhysique.setEquipementPhysique(equipementPhysiqueDTO);

        String etapesFiltrees = donneesEntreeRepository.findEtapes(calculEquipementPhysique.getEquipementPhysique().getNomLot());
        List<String> etapesList = etapesFiltrees == null ? null : new ArrayList<>(Arrays.asList(etapesFiltrees.split("##")));
        // si etapesList est vide alors on ne filtre pas et on utilise toutes les étapes du référentiel
        if (etapesList == null) {
            calculEquipementPhysique.setEtapes(referentielClient.getEtapes());
        } else {
            List<EtapeDTO> etapesCalcul = new ArrayList<>();
            for (var etape : referentielClient.getEtapes()) {
                if (etapesList.contains(etape.getCode())) {
                    etapesCalcul.add(etape);
                }
            }
            calculEquipementPhysique.setEtapes(etapesCalcul);
        }

        String criteresFiltrees = donneesEntreeRepository.findCriteres(calculEquipementPhysique.getEquipementPhysique().getNomLot());
        List<String> criteresList = criteresFiltrees == null ? null : new ArrayList<>(Arrays.asList(criteresFiltrees.split("##")));
        // si criteresList est vide alors on ne filtre pas et on utilise tous les critères du référentiel
        if (criteresList == null) {
            calculEquipementPhysique.setCriteres(referentielClient.getCriteres());
        } else {
            List<CritereDTO> criteresCalcul = new ArrayList<>();
            for (var critere : referentielClient.getCriteres()) {
                if (criteresList.contains(critere.getNomCritere())) {
                    criteresCalcul.add(critere);
                }
            }
            calculEquipementPhysique.setCriteres(criteresCalcul);
        }

        var hypotheses = new ArrayList<HypotheseDTO>();

        Arrays.stream(hypothesesEquipementPhysique.replaceAll(" +", "").split(","))
                .forEach(hypothese -> {
                    var h = referentielClient.getHypothese(hypothese);
                    if (h != null) hypotheses.add(h);
                });

        calculEquipementPhysique.setHypotheses(hypotheses);

        if (equipementPhysiqueDTO.getModele() != null) {
            calculEquipementPhysique.setCorrespondanceRefEquipement(referentielClient.getCorrespondanceRefEquipement(equipementPhysiqueDTO.getModele()));
        }

        calculEquipementPhysique.setTypeItem(referentielClient.getTypeItem(equipementPhysiqueDTO.getType()));

        calculEquipementPhysique.setFacteurCaracterisations(new ArrayList<>());
        for (var critere : calculEquipementPhysique.getCriteres()) {
            for (var etape : calculEquipementPhysique.getEtapes()) {
                if (calculEquipementPhysique.getCorrespondanceRefEquipement() != null) {
                    calculEquipementPhysique.getFacteurCaracterisations().add(
                            referentielClient.getFacteurCaracterisationByCritereAndEtapeAndNom(
                                    critere.getNomCritere(),
                                    etape.getCode(),
                                    calculEquipementPhysique.getCorrespondanceRefEquipement().getRefEquipementCible()
                            )
                    );
                } else if (calculEquipementPhysique.getTypeItem() != null
                        && StringUtils.isNotBlank(calculEquipementPhysique.getTypeItem().getRefItemParDefaut())) {
                    calculEquipementPhysique.getFacteurCaracterisations().add(
                            referentielClient.getFacteurCaracterisationByCritereAndEtapeAndNom(
                                    critere.getNomCritere(),
                                    etape.getCode(),
                                    calculEquipementPhysique.getTypeItem().getRefItemParDefaut()
                            )
                    );
                }
            }

            var mixElec = referentielClient.getMixElectriqueFromFacteurCaracterisation(critere.getNomCritere(), equipementPhysiqueDTO.getPaysDUtilisation());
            if (mixElec != null) calculEquipementPhysique.getFacteurCaracterisations().add(mixElec);

            if (equipementPhysiqueDTO.getDataCenter() != null
                    && StringUtils.isNotBlank(equipementPhysiqueDTO.getDataCenter().getLocalisation())
                    && !StringUtils.equals(equipementPhysiqueDTO.getPaysDUtilisation(), equipementPhysiqueDTO.getDataCenter().getLocalisation())) {

                var mixElecDataCenter = referentielClient.getMixElectriqueFromFacteurCaracterisation(critere.getNomCritere(), equipementPhysiqueDTO.getDataCenter().getLocalisation());
                if (mixElecDataCenter != null)
                    calculEquipementPhysique.getFacteurCaracterisations().add(mixElecDataCenter);
            }
        }

        return calculEquipementPhysique;
    }
}
