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.CalculOperationNonIT;
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.OperationNonITDTO;
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 EnrichissementOperationNonITService {

    @Autowired
    DonneesEntreeRepository donneesEntreeRepository;
    @Value("${numecoeval.hypotheses.operationNonIt}")
    private String hypothesesOperationNonIt;

    @Autowired
    ReferentielClient referentielClient;

    public CalculOperationNonIT serviceEnrichissementOperationNonIT(OperationNonITDTO operationNonITDTO) {
        if (operationNonITDTO == null) return null;

        log.debug("{} - {} - {} : Enrichissement d'une opération non IT : Nom Item: {}, Type: {}",
                operationNonITDTO.getNomOrganisation(), operationNonITDTO.getNomLot(), operationNonITDTO.getDateLot(),
                operationNonITDTO.getNomItemNonIT(), operationNonITDTO.getType());

        CalculOperationNonIT calculOperationNonIT = new CalculOperationNonIT();

        calculOperationNonIT.setOperationNonIT(operationNonITDTO);

        String etapesFiltrees = donneesEntreeRepository.findEtapes(calculOperationNonIT.getOperationNonIT().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) {
            calculOperationNonIT.setEtapes(referentielClient.getEtapes());
        } else {
            List<EtapeDTO> etapesCalcul = new ArrayList<>();
            for (var etape : referentielClient.getEtapes()) {
                if (etapesList.contains(etape.getCode())) {
                    etapesCalcul.add(etape);
                }
            }
            calculOperationNonIT.setEtapes(etapesCalcul);
        }

        String criteresFiltrees = donneesEntreeRepository.findCriteres(calculOperationNonIT.getOperationNonIT().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) {
            calculOperationNonIT.setCriteres(referentielClient.getCriteres());
        } else {
            List<CritereDTO> criteresCalcul = new ArrayList<>();
            for (var critere : referentielClient.getCriteres()) {
                if (criteresList.contains(critere.getNomCritere())) {
                    criteresCalcul.add(critere);
                }
            }
            calculOperationNonIT.setCriteres(criteresCalcul);
        }

        String nomOrganisation = donneesEntreeRepository.findNomOrganisation(calculOperationNonIT.getOperationNonIT().getNomLot());

        calculOperationNonIT.setTypeItem(referentielClient.getTypeItem(operationNonITDTO.getType(), nomOrganisation));

        var hypotheses = new ArrayList<HypotheseDTO>();
        var hTypeItem = referentielClient.getHypothese(referentielClient.getTypeItem(operationNonITDTO.getType(), nomOrganisation).getRefHypothese(), nomOrganisation);
        if (hTypeItem != null) hypotheses.add(hTypeItem);

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

        calculOperationNonIT.setHypotheses(hypotheses);
        calculOperationNonIT.setFacteurCaracterisations(new ArrayList<>());

        for (var critere : calculOperationNonIT.getCriteres()) {
            for (var etape : calculOperationNonIT.getEtapes()) {
                if (calculOperationNonIT.getTypeItem() != null && StringUtils.isNotBlank(calculOperationNonIT.getTypeItem().getRefItemParDefaut())) {
                    calculOperationNonIT.getFacteurCaracterisations().add(
                            referentielClient.getFacteurCaracterisationByCritereAndEtapeAndNomAndNomOrganisation(
                                    critere.getNomCritere(),
                                    etape.getCode(),
                                    calculOperationNonIT.getTypeItem().getRefItemParDefaut(),
                                    nomOrganisation
                            )
                    );
                }
            }
            var mixElec = referentielClient.getMixElectriqueFromFacteurCaracterisation(critere.getNomCritere(), operationNonITDTO.getLocalisation(), nomOrganisation);
            if (mixElec != null) calculOperationNonIT.getFacteurCaracterisations().add(mixElec);
        }
        return calculOperationNonIT;
    }
}
