package org.mte.numecoeval.calculs.infrastructure.client;

import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.mte.numecoeval.calculs.domain.exception.ExternalApiException;
import org.mte.numecoeval.calculs.domain.utils.Constants;
import org.mte.numecoeval.calculs.referentiels.generated.api.client.InterneNumEcoEvalApi;
import org.mte.numecoeval.calculs.referentiels.generated.api.model.*;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.http.HttpStatusCode;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClientResponseException;

import java.util.List;

@Slf4j
@Service
@AllArgsConstructor
public class ReferentielClient {

    private InterneNumEcoEvalApi interneNumEcoEvalApi;

    @Cacheable("Etapes")
    public List<EtapeDTO> getEtapes() {

        try {
            var result = interneNumEcoEvalApi.getAllEtapes().collectList().block();
            return result == null ? List.of() : result;
        } catch (WebClientResponseException e) {
            if (e.getStatusCode() != HttpStatusCode.valueOf(404)) {
                throw new ExternalApiException(e);
            }
        }
        return List.of();
    }

    @Cacheable("Criteres")
    public List<CritereDTO> getCriteres() {
        try {
            var result = interneNumEcoEvalApi.getAllCriteres().collectList().block();
            return result == null ? List.of() : result;
        } catch (WebClientResponseException e) {
            if (e.getStatusCode() != HttpStatusCode.valueOf(404)) {
                throw new ExternalApiException(e);
            }
        }
        return List.of();
    }

    @Cacheable(value = "Hypothese")
    public HypotheseDTO getHypothese(String code) {
        try {
            return interneNumEcoEvalApi.getHypothese(code).block();
        } catch (WebClientResponseException e) {
            if (e.getStatusCode() != HttpStatusCode.valueOf(404)) {
                throw new ExternalApiException(e);
            }
        }
        return null;
    }

    @Cacheable(value = "CorrespondanceRefEquipement")
    public CorrespondanceRefEquipementDTO getCorrespondanceRefEquipement(String modele) {
        try {
            return interneNumEcoEvalApi.getCorrespondanceRefEquipement(modele).block();
        } catch (WebClientResponseException e) {
            if (e.getStatusCode() != HttpStatusCode.valueOf(404)) {
                throw new ExternalApiException(e);
            }
        }
        return null;
    }

    @Cacheable(value = "TypeEquipement")
    public TypeEquipementDTO getTypeEquipement(String type) {
        try {
            return interneNumEcoEvalApi.getTypeEquipement(type).block();
        } catch (WebClientResponseException e) {
            if (e.getStatusCode() != HttpStatusCode.valueOf(404)) {
                throw new ExternalApiException(e);
            }
        }
        return null;
    }

    @Cacheable(value = "TypeItem")
    public TypeItemDTO getTypeItem(String type) {
        try {
            return interneNumEcoEvalApi.getTypeItem(type).block();
        } catch (WebClientResponseException e) {
            if (e.getStatusCode() != HttpStatusCode.valueOf(404)) {
                throw new ExternalApiException(e);
            }
        }
        return null;
    }

    @Cacheable(value = "ImpactEquipement")
    public ImpactEquipementDTO getImpactEquipement(String refEquipement, String critere, String etape) {
        try {
            return interneNumEcoEvalApi.getImpactEquipement(refEquipement, critere, etape).block();
        } catch (WebClientResponseException e) {
            if (e.getStatusCode() != HttpStatusCode.valueOf(404)) {
                throw new ExternalApiException(e);
            }
        }
        return null;
    }

    @Cacheable(value = "ImpactReseau")
    public ImpactReseauDTO getImpactReseau(String refReseau, String critere, String etape) {
        try {
            return interneNumEcoEvalApi.getImpactReseau(refReseau, critere, etape).block();
        } catch (WebClientResponseException e) {
            if (e.getStatusCode() != HttpStatusCode.valueOf(404)) {
                throw new ExternalApiException(e);
            }
        }
        return null;
    }

    @Cacheable(value = "MixElectrique")
    public MixElectriqueDTO getMixElectrique(String pays, String critere) {
        if (pays == null || critere == null) return null;
        try {
            return interneNumEcoEvalApi.getMixElectrique(pays, critere).block();
        } catch (WebClientResponseException e) {
            if (e.getStatusCode() != HttpStatusCode.valueOf(404)) {
                throw new ExternalApiException(e);
            }
        }
        return null;
    }

    @Cacheable(value = "FacteurCaracterisationMixElec")
    public FacteurCaracterisationDTO getMixElectriqueFromFacteurCaracterisation(String critere, String localisation) {
        try {
            return interneNumEcoEvalApi.getFacteurCaracterisation(critere, null, null, localisation, Constants.ELECTRICITY_MIX_CATEGORY).blockFirst();
        } catch (WebClientResponseException e) {
            if (e.getStatusCode() != HttpStatusCode.valueOf(404)) {
                throw new ExternalApiException(e);
            }
        }
        return null;
    }

    @Cacheable(value = "FacteurCaracterisation")
    public FacteurCaracterisationDTO getFacteurCaracterisationByCritereAndEtapeAndNom(String critere, String etape, String nom) {
        try {
            return interneNumEcoEvalApi.getFacteurCaracterisation(critere, etape, nom, null, null).blockFirst();
        } catch (WebClientResponseException e) {
            if (e.getStatusCode() != HttpStatusCode.valueOf(404)) {
                throw new ExternalApiException(e);
            }
        }
        return null;
    }

    @Cacheable(value = "ImpactMessagerie")
    public ImpactMessagerieDTO getMessagerie(String critere) {
        try {
            return interneNumEcoEvalApi.getImpactMessagerie(critere).block();
        } catch (WebClientResponseException e) {
            if (e.getStatusCode() != HttpStatusCode.valueOf(404)) {
                throw new ExternalApiException(e);
            }
        }
        return null;
    }
}
