package it.integry.integrywmsnative.gest.ordini_uscita_elenco.filters;

import androidx.databinding.ObservableField;
import androidx.lifecycle.MutableLiveData;

import com.annimon.stream.Stream;
import com.annimon.stream.function.Predicate;

import org.apache.commons.lang3.time.DateUtils;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;

import it.integry.integrywmsnative.core.model.MtbDepo;
import it.integry.integrywmsnative.core.model.MtbGrup;
import it.integry.integrywmsnative.core.model.OrdineInevasoDTO;
import it.integry.integrywmsnative.core.rest.model.OrdineUscitaInevasoDTO;
import it.integry.integrywmsnative.core.utility.UtilityString;
import it.integry.integrywmsnative.gest.ordini_uscita_elenco.OrdiniUscitaElencoDTO;

public class VenditaFiltroOrdiniViewModel {

    private final ObservableField<Predicate<OrdiniUscitaElencoDTO>> currentDepositoPredicate = new ObservableField<>();
    private final ObservableField<Predicate<OrdiniUscitaElencoDTO>> currentIdViaggioPredicate = new ObservableField<>();
    private final ObservableField<Predicate<OrdiniUscitaElencoDTO>> currentNumOrdsPredicate = new ObservableField<>();
    private final ObservableField<Predicate<OrdiniUscitaElencoDTO>> currentClientePredicate = new ObservableField<>();
    private final ObservableField<Predicate<OrdiniUscitaElencoDTO>> currentDataConsPredicate = new ObservableField<>();
    private final ObservableField<Predicate<OrdiniUscitaElencoDTO>> currentTermConsPredicate = new ObservableField<>();
    private final ObservableField<Predicate<OrdiniUscitaElencoDTO>> currentVettorePredicate = new ObservableField<>();
    private final ObservableField<Predicate<OrdiniUscitaElencoDTO>> currentAgentePredicate = new ObservableField<>();
    private final ObservableField<Predicate<OrdiniUscitaElencoDTO>> currentAutomezzoPredicate = new ObservableField<>();
    private final ObservableField<Predicate<OrdiniUscitaElencoDTO>> currentPaesePredicate = new ObservableField<>();
    private final ObservableField<Predicate<OrdiniUscitaElencoDTO>> currentGruppoMercPredicate = new ObservableField<>();

    private Date selectedDataCons = null;
    private List<MtbGrup> selectedMtbGrup = new ArrayList<>();

    private List<OrdiniUscitaElencoDTO> initialOrderList;
    private final MutableLiveData<List<OrdiniUscitaElencoDTO>> currentFilteredOrderList = new MutableLiveData<>();

    public void init(List<OrdiniUscitaElencoDTO> initialList) {
        this.initialOrderList = initialList;
        this.currentFilteredOrderList.setValue(this.initialOrderList);
    }

    public MutableLiveData<List<OrdiniUscitaElencoDTO>> getMutableFilteredOrderList() {
        return this.currentFilteredOrderList;
    }

    public void setIDViaggioFilter(List<Integer> idViaggio) {
        if (idViaggio == null || idViaggio.isEmpty()) currentIdViaggioPredicate.set(null);
        else {
            currentIdViaggioPredicate.set(o -> idViaggio.contains(o.getIdViaggio()));
        }
    }

    public void setDepositoFilter(List<MtbDepo> mtbDepoList) {
        if (mtbDepoList == null || mtbDepoList.isEmpty()) currentDepositoPredicate.set(null);
        else {
            List<String> codMdeps = Stream.of(mtbDepoList).map(MtbDepo::getCodMdep).toList();
            currentDepositoPredicate.set(o -> codMdeps.contains(o.getCodMdep()));
        }
    }

    public void setNumOrdFilter(List<Integer> numOrds) {
        if (numOrds == null || numOrds.isEmpty()) currentNumOrdsPredicate.set(null);
        else {
            currentNumOrdsPredicate.set(o -> numOrds.contains(o.getNumOrd()));
        }
    }

    public void setClienteFilter(List<String> clienti) {
        if (clienti == null || clienti.isEmpty()) currentClientePredicate.set(null);
        else {
            currentClientePredicate.set(o -> clienti.contains(o.getRagSocOrd()));
        }
    }

    public void setTerminiConsegnaFilter(List<String> terminiConsegna) {
        if (terminiConsegna == null || terminiConsegna.isEmpty())
            currentTermConsPredicate.set(null);
        else {
            currentTermConsPredicate.set(o -> terminiConsegna.contains(o.getTermCons()));
        }
    }

    public void setVettoreFilter(List<String> vettore) {
        if (vettore == null || vettore.isEmpty()) currentVettorePredicate.set(null);
        else {
            currentVettorePredicate.set(o -> vettore.contains(o.getCodVvet() + (!UtilityString.isNullOrEmpty(o.getCodVvet()) ? " - " + o.getDescrizioneVettore() : "")));
        }
    }

    public void setAutomezzoFilter(List<String> automezzi) {
        if (automezzi == null || automezzi.isEmpty()) currentAutomezzoPredicate.set(null);
        else {
            currentAutomezzoPredicate.set(o -> automezzi.contains(o.getDescrizioneAuto()));
        }
    }

    public void setDataConsegnaFilter(Date dataConsegna) {
        this.selectedDataCons = dataConsegna;

        if (dataConsegna == null) currentDataConsPredicate.set(null);
        else {
            currentDataConsPredicate.set(o -> DateUtils.isSameDay(o.getDataConsD(), dataConsegna));
        }
    }

    public void setAgenteFilter(List<String> agenti) {
        if (agenti == null || agenti.isEmpty()) currentAgentePredicate.set(null);
        else {
            currentAgentePredicate.set(o -> agenti.contains(o.getNomeAgente()));
        }
    }

    public void setPaeseFilter(List<String> paesi) {
        if (paesi == null || paesi.isEmpty()) currentPaesePredicate.set(null);
        else {
            currentPaesePredicate.set(o -> paesi.contains(o.getCitta()));
        }
    }

    public void setGruppoMercFilter(List<MtbGrup> mtbGrupList) {
        if (mtbGrupList == null || mtbGrupList.isEmpty()) {
            currentGruppoMercPredicate.set(null);
            this.selectedMtbGrup = new ArrayList<>();
        }
        else {
            this.selectedMtbGrup = mtbGrupList;
            var mtbGrups = Stream.of(mtbGrupList).map(MtbGrup::getCodMgrp).toList();
            currentGruppoMercPredicate.set(o -> Stream.of(o.getAvailableClassMerc())
                    .anyMatch(x -> mtbGrups.contains(x.getCodMgrp())));
        }
    }


    public Date getSelectedDataCons() {
        return selectedDataCons;
    }

    public List<MtbGrup> getSelectedMtbGrup() {
        return selectedMtbGrup;
    }

    public void applyAllTests() {

        List<OrdiniUscitaElencoDTO> returnList = null;

        if (currentNumOrdsPredicate.get() == null &&
                currentClientePredicate.get() == null &&
                currentDataConsPredicate.get() == null &&
                currentTermConsPredicate.get() == null &&
                currentVettorePredicate.get() == null &&
                currentAutomezzoPredicate.get() == null &&
                currentDepositoPredicate.get() == null &&
                currentIdViaggioPredicate.get() == null &&
                currentAgentePredicate.get() == null &&
                currentPaesePredicate.get() == null &&
                currentGruppoMercPredicate.get() == null
        ) {
            returnList = this.initialOrderList;
        } else {
            Stream<OrdiniUscitaElencoDTO> tmpStream = Stream.of(this.initialOrderList)
                    .filter(x ->
                            (currentNumOrdsPredicate.get() == null || (currentNumOrdsPredicate.get().test(x))) &&
                                    (currentClientePredicate.get() == null || (currentClientePredicate.get().test(x))) &&
                                    (currentDataConsPredicate.get() == null || (currentDataConsPredicate.get().test(x))) &&
                                    (currentTermConsPredicate.get() == null || (currentTermConsPredicate.get().test(x))) &&
                                    (currentVettorePredicate.get() == null || (currentVettorePredicate.get().test(x))) &&
                                    (currentAutomezzoPredicate.get() == null || (currentAutomezzoPredicate.get().test(x))) &&
                                    (currentDepositoPredicate.get() == null || (currentDepositoPredicate.get().test(x))) &&
                                    (currentIdViaggioPredicate.get() == null || (currentIdViaggioPredicate.get().test(x))) &&
                                    (currentAgentePredicate.get() == null || (currentAgentePredicate.get().test(x))) &&
                                    (currentPaesePredicate.get() == null || (currentPaesePredicate.get().test(x))) &&
                                    (currentGruppoMercPredicate.get() == null || (currentGruppoMercPredicate.get().test(x)))
                    );

            returnList = tmpStream.toList();
        }

        this.currentFilteredOrderList.setValue(returnList);
    }

    public ObservableField<Predicate<OrdiniUscitaElencoDTO>> getCurrentDepositoPredicate() {
        return currentDepositoPredicate;
    }

    public ObservableField<Predicate<OrdiniUscitaElencoDTO>> getCurrentIdViaggioPredicate() {
        return currentIdViaggioPredicate;
    }

    public ObservableField<Predicate<OrdiniUscitaElencoDTO>> getCurrentNumOrdsPredicate() {
        return currentNumOrdsPredicate;
    }

    public ObservableField<Predicate<OrdiniUscitaElencoDTO>> getCurrentClientePredicate() {
        return currentClientePredicate;
    }

    public ObservableField<Predicate<OrdiniUscitaElencoDTO>> getCurrentDataConsPredicate() {
        return currentDataConsPredicate;
    }

    public ObservableField<Predicate<OrdiniUscitaElencoDTO>> getCurrentTermConsPredicate() {
        return currentTermConsPredicate;
    }

    public ObservableField<Predicate<OrdiniUscitaElencoDTO>> getCurrentVettorePredicate() {
        return currentVettorePredicate;
    }

    public ObservableField<Predicate<OrdiniUscitaElencoDTO>> getCurrentAgentePredicate() {
        return currentAgentePredicate;
    }

    public ObservableField<Predicate<OrdiniUscitaElencoDTO>> getCurrentAutomezzoPredicate() {
        return currentAutomezzoPredicate;
    }

    public ObservableField<Predicate<OrdiniUscitaElencoDTO>> getCurrentPaesePredicate() {
        return currentPaesePredicate;
    }

    public ObservableField<Predicate<OrdiniUscitaElencoDTO>> getCurrentGruppoMercPredicate() {
        return currentGruppoMercPredicate;
    }

    public List<MtbDepo> getAllCodMdeps(List<MtbDepo> mtbDepoFullList) {
        List<String> codMdeps = Stream.of(initialOrderList)
                .map(OrdineInevasoDTO::getCodMdep)
                .distinct()
                .toList();

        return Stream.of(Objects.requireNonNull(mtbDepoFullList))
                .filter(x -> codMdeps.contains(x.getCodMdep()))
                .distinct()
                .withoutNulls()
                .sortBy(MtbDepo::getCodMdep)
                .toList();
    }

    public List<MtbDepo> getAvailableCodMdeps(List<MtbDepo> mtbDepoFullList) {

        if (currentNumOrdsPredicate.get() == null &&
                currentClientePredicate.get() == null &&
                currentDataConsPredicate.get() == null &&
                currentTermConsPredicate.get() == null &&
                currentVettorePredicate.get() == null &&
                currentAutomezzoPredicate.get() == null &&
                currentIdViaggioPredicate.get() == null &&
                currentAgentePredicate.get() == null &&
                currentPaesePredicate.get() == null &&
                currentGruppoMercPredicate.get() == null
        ) {
            return getAllCodMdeps(mtbDepoFullList);
        } else {
            List<String> availableCodMdeps = Stream.of(this.initialOrderList)
                    .filter(x ->
                            (currentNumOrdsPredicate.get() == null || (currentNumOrdsPredicate.get().test(x))) &&
                                    (currentClientePredicate.get() == null || (currentClientePredicate.get().test(x))) &&
                                    (currentDataConsPredicate.get() == null || (currentDataConsPredicate.get().test(x))) &&
                                    (currentTermConsPredicate.get() == null || (currentTermConsPredicate.get().test(x))) &&
                                    (currentVettorePredicate.get() == null || (currentVettorePredicate.get().test(x))) &&
                                    (currentAutomezzoPredicate.get() == null || (currentAutomezzoPredicate.get().test(x))) &&
                                    (currentIdViaggioPredicate.get() == null || (currentIdViaggioPredicate.get().test(x))) &&
                                    (currentAgentePredicate.get() == null || (currentAgentePredicate.get().test(x))) &&
                                    (currentPaesePredicate.get() == null || (currentPaesePredicate.get().test(x))) &&
                                    (currentGruppoMercPredicate.get() == null || (currentGruppoMercPredicate.get().test(x)))
                    )
                    .map(OrdineInevasoDTO::getCodMdep)
                    .distinct()
                    .toList();

            return Stream.of(Objects.requireNonNull(mtbDepoFullList))
                    .filter(x -> availableCodMdeps.contains(x.getCodMdep()))
                    .distinct()
                    .withoutNulls()
                    .sortBy(MtbDepo::getCodMdep)
                    .toList();
        }
    }


    public List<Integer> getAllIDViaggio() {
        return Stream
                .of(Objects.requireNonNull(initialOrderList))
                .filter(x -> x.getIdViaggio() != null)
                .sortBy(x -> -x.getIdViaggio())
                .map(x -> x.getIdViaggio() != null ? x.getIdViaggio() : null)
                .distinct()
                .toList();
    }

    public List<Integer> getAvailableIDViaggio() {

        if (currentNumOrdsPredicate.get() == null &&
                currentClientePredicate.get() == null &&
                currentDataConsPredicate.get() == null &&
                currentTermConsPredicate.get() == null &&
                currentVettorePredicate.get() == null &&
                currentAutomezzoPredicate.get() == null &&
                currentDepositoPredicate.get() == null &&
                currentAgentePredicate.get() == null &&
                currentPaesePredicate.get() == null &&
                currentGruppoMercPredicate.get() == null
        ) {
            return getAllIDViaggio();
        } else {
            return Stream.of(this.initialOrderList)
                    .filter(x ->
                            (currentNumOrdsPredicate.get() == null || (currentNumOrdsPredicate.get().test(x))) &&
                                    (currentClientePredicate.get() == null || (currentClientePredicate.get().test(x))) &&
                                    (currentDataConsPredicate.get() == null || (currentDataConsPredicate.get().test(x))) &&
                                    (currentTermConsPredicate.get() == null || (currentTermConsPredicate.get().test(x))) &&
                                    (currentVettorePredicate.get() == null || (currentVettorePredicate.get().test(x))) &&
                                    (currentAutomezzoPredicate.get() == null || (currentAutomezzoPredicate.get().test(x))) &&
                                    (currentDepositoPredicate.get() == null || (currentDepositoPredicate.get().test(x))) &&
                                    (currentAgentePredicate.get() == null || (currentAgentePredicate.get().test(x))) &&
                                    (currentPaesePredicate.get() == null || (currentPaesePredicate.get().test(x))) &&
                                    (currentGruppoMercPredicate.get() == null || (currentGruppoMercPredicate.get().test(x)))
                    )
                    .map(OrdineUscitaInevasoDTO::getIdViaggio)
                    .distinct()
                    .toList();
        }
    }


    public List<Integer> getAllNumOrds() {
        return Stream
                .of(Objects.requireNonNull(initialOrderList))
                .filter(x -> x.getNumOrd() != null)
                .sortBy(x -> -x.getNumOrd())
                .map(x -> x.getNumOrd() != null ? x.getNumOrd() : null)
                .distinct()
                .toList();
    }

    public List<Integer> getAvailableNumOrds() {

        if (currentIdViaggioPredicate.get() == null &&
                currentClientePredicate.get() == null &&
                currentDataConsPredicate.get() == null &&
                currentTermConsPredicate.get() == null &&
                currentVettorePredicate.get() == null &&
                currentAutomezzoPredicate.get() == null &&
                currentDepositoPredicate.get() == null &&
                currentAgentePredicate.get() == null &&
                currentPaesePredicate.get() == null &&
                currentGruppoMercPredicate.get() == null
        ) {
            return getAllNumOrds();
        } else {
            return Stream.of(this.initialOrderList)
                    .filter(x ->
                            (currentIdViaggioPredicate.get() == null || (currentIdViaggioPredicate.get().test(x))) &&
                                    (currentClientePredicate.get() == null || (currentClientePredicate.get().test(x))) &&
                                    (currentDataConsPredicate.get() == null || (currentDataConsPredicate.get().test(x))) &&
                                    (currentTermConsPredicate.get() == null || (currentTermConsPredicate.get().test(x))) &&
                                    (currentVettorePredicate.get() == null || (currentVettorePredicate.get().test(x))) &&
                                    (currentAutomezzoPredicate.get() == null || (currentAutomezzoPredicate.get().test(x))) &&
                                    (currentDepositoPredicate.get() == null || (currentDepositoPredicate.get().test(x))) &&
                                    (currentAgentePredicate.get() == null || (currentAgentePredicate.get().test(x))) &&
                                    (currentPaesePredicate.get() == null || (currentPaesePredicate.get().test(x))) &&
                                    (currentGruppoMercPredicate.get() == null || (currentGruppoMercPredicate.get().test(x)))
                    )
                    .map(OrdineUscitaInevasoDTO::getNumOrd)
                    .distinct()
                    .toList();
        }
    }


    public List<String> getAllClienti() {
        return Stream
                .of(Objects.requireNonNull(initialOrderList))
                .filter(x -> !UtilityString.isNullOrEmpty(x.getRagSocOrd()))
                .sortBy(OrdineUscitaInevasoDTO::getRagSocOrd)
                .map(OrdineUscitaInevasoDTO::getRagSocOrd)
                .distinct()
                .toList();
    }

    public List<String> getAvailableClienti() {

        if (currentIdViaggioPredicate.get() == null &&
                currentNumOrdsPredicate.get() == null &&
                currentDataConsPredicate.get() == null &&
                currentTermConsPredicate.get() == null &&
                currentVettorePredicate.get() == null &&
                currentAutomezzoPredicate.get() == null &&
                currentDepositoPredicate.get() == null &&
                currentAgentePredicate.get() == null &&
                currentPaesePredicate.get() == null &&
                currentGruppoMercPredicate.get() == null
        ) {
            return getAllClienti();
        } else {
            return Stream.of(this.initialOrderList)
                    .filter(x ->
                            (currentIdViaggioPredicate.get() == null || (currentIdViaggioPredicate.get().test(x))) &&
                                    (currentNumOrdsPredicate.get() == null || (currentNumOrdsPredicate.get().test(x))) &&
                                    (currentDataConsPredicate.get() == null || (currentDataConsPredicate.get().test(x))) &&
                                    (currentTermConsPredicate.get() == null || (currentTermConsPredicate.get().test(x))) &&
                                    (currentVettorePredicate.get() == null || (currentVettorePredicate.get().test(x))) &&
                                    (currentAutomezzoPredicate.get() == null || (currentAutomezzoPredicate.get().test(x))) &&
                                    (currentDepositoPredicate.get() == null || (currentDepositoPredicate.get().test(x))) &&
                                    (currentAgentePredicate.get() == null || (currentAgentePredicate.get().test(x))) &&
                                    (currentPaesePredicate.get() == null || (currentPaesePredicate.get().test(x))) &&
                                    (currentGruppoMercPredicate.get() == null || (currentGruppoMercPredicate.get().test(x)))
                    )
                    .map(OrdineUscitaInevasoDTO::getRagSocOrd)
                    .distinct()
                    .toList();
        }
    }


    public List<String> getAllVettori() {
        return Stream
                .of(Objects.requireNonNull(initialOrderList))
                .filter(x -> !UtilityString.isNullOrEmpty(x.getCodVvet()))
                .sortBy(OrdineUscitaInevasoDTO::getCodVvet)
                .map(x -> x.getCodVvet() + (!UtilityString.isNullOrEmpty(x.getCodVvet()) ? " - " + x.getDescrizioneVettore() : ""))
                .distinct()
                .toList();
    }

    public List<String> getAvailableVettori() {

        if (currentIdViaggioPredicate.get() == null &&
                currentNumOrdsPredicate.get() == null &&
                currentDataConsPredicate.get() == null &&
                currentTermConsPredicate.get() == null &&
                currentClientePredicate.get() == null &&
                currentAutomezzoPredicate.get() == null &&
                currentDepositoPredicate.get() == null &&
                currentAgentePredicate.get() == null &&
                currentPaesePredicate.get() == null &&
                currentGruppoMercPredicate.get() == null
        ) {
            return getAllVettori();
        } else {
            return Stream.of(this.initialOrderList)
                    .filter(x ->
                            (currentIdViaggioPredicate.get() == null || (currentIdViaggioPredicate.get().test(x))) &&
                                    (currentNumOrdsPredicate.get() == null || (currentNumOrdsPredicate.get().test(x))) &&
                                    (currentDataConsPredicate.get() == null || (currentDataConsPredicate.get().test(x))) &&
                                    (currentTermConsPredicate.get() == null || (currentTermConsPredicate.get().test(x))) &&
                                    (currentClientePredicate.get() == null || (currentClientePredicate.get().test(x))) &&
                                    (currentAutomezzoPredicate.get() == null || (currentAutomezzoPredicate.get().test(x))) &&
                                    (currentDepositoPredicate.get() == null || (currentDepositoPredicate.get().test(x))) &&
                                    (currentAgentePredicate.get() == null || (currentAgentePredicate.get().test(x))) &&
                                    (currentPaesePredicate.get() == null || (currentPaesePredicate.get().test(x))) &&
                                    (currentGruppoMercPredicate.get() == null || (currentGruppoMercPredicate.get().test(x)))
                    )
                    .map(x -> x.getCodVvet() + (!UtilityString.isNullOrEmpty(x.getCodVvet()) ? " - " + x.getDescrizioneVettore() : ""))
                    .distinct()
                    .toList();
        }
    }


    public List<String> getAllAutomezzi() {
        return Stream
                .of(Objects.requireNonNull(initialOrderList))
                .filter(x -> !UtilityString.isNullOrEmpty(x.getDescrizioneAuto()))
                .sortBy(OrdineUscitaInevasoDTO::getDescrizioneAuto)
                .map(OrdineUscitaInevasoDTO::getDescrizioneAuto)
                .distinct()
                .toList();
    }

    public List<String> getAvailableAutomezzi() {

        if (currentIdViaggioPredicate.get() == null &&
                currentNumOrdsPredicate.get() == null &&
                currentDataConsPredicate.get() == null &&
                currentTermConsPredicate.get() == null &&
                currentClientePredicate.get() == null &&
                currentVettorePredicate.get() == null &&
                currentDepositoPredicate.get() == null &&
                currentAgentePredicate.get() == null &&
                currentPaesePredicate.get() == null &&
                currentGruppoMercPredicate.get() == null
        ) {
            return getAllAutomezzi();
        } else {
            return Stream.of(this.initialOrderList)
                    .filter(x ->
                            (currentIdViaggioPredicate.get() == null || (currentIdViaggioPredicate.get().test(x))) &&
                                    (currentNumOrdsPredicate.get() == null || (currentNumOrdsPredicate.get().test(x))) &&
                                    (currentDataConsPredicate.get() == null || (currentDataConsPredicate.get().test(x))) &&
                                    (currentTermConsPredicate.get() == null || (currentTermConsPredicate.get().test(x))) &&
                                    (currentClientePredicate.get() == null || (currentClientePredicate.get().test(x))) &&
                                    (currentVettorePredicate.get() == null || (currentVettorePredicate.get().test(x))) &&
                                    (currentDepositoPredicate.get() == null || (currentDepositoPredicate.get().test(x))) &&
                                    (currentAgentePredicate.get() == null || (currentAgentePredicate.get().test(x))) &&
                                    (currentPaesePredicate.get() == null || (currentPaesePredicate.get().test(x))) &&
                                    (currentGruppoMercPredicate.get() == null || (currentGruppoMercPredicate.get().test(x)))
                    )
                    .map(OrdineUscitaInevasoDTO::getDescrizioneAuto)
                    .distinct()
                    .toList();
        }
    }


    public List<String> getAllPaesi() {
        return Stream
                .of(Objects.requireNonNull(initialOrderList))
                .filter(x -> !UtilityString.isNullOrEmpty(x.getCitta()))
                .sortBy(OrdineUscitaInevasoDTO::getCitta)
                .map(OrdineUscitaInevasoDTO::getCitta)
                .distinct()
                .toList();
    }

    public List<String> getAvailablePaesi() {

        if (currentIdViaggioPredicate.get() == null &&
                currentNumOrdsPredicate.get() == null &&
                currentDataConsPredicate.get() == null &&
                currentTermConsPredicate.get() == null &&
                currentClientePredicate.get() == null &&
                currentVettorePredicate.get() == null &&
                currentDepositoPredicate.get() == null &&
                currentAgentePredicate.get() == null &&
                currentAutomezzoPredicate.get() == null &&
                currentGruppoMercPredicate.get() == null
        ) {
            List<String> all = getAllPaesi();
            return all;
        } else {
            return Stream.of(this.initialOrderList)
                    .filter(x ->
                            (currentIdViaggioPredicate.get() == null || (currentIdViaggioPredicate.get().test(x))) &&
                                    (currentNumOrdsPredicate.get() == null || (currentNumOrdsPredicate.get().test(x))) &&
                                    (currentDataConsPredicate.get() == null || (currentDataConsPredicate.get().test(x))) &&
                                    (currentTermConsPredicate.get() == null || (currentTermConsPredicate.get().test(x))) &&
                                    (currentClientePredicate.get() == null || (currentClientePredicate.get().test(x))) &&
                                    (currentVettorePredicate.get() == null || (currentVettorePredicate.get().test(x))) &&
                                    (currentDepositoPredicate.get() == null || (currentDepositoPredicate.get().test(x))) &&
                                    (currentAgentePredicate.get() == null || (currentAgentePredicate.get().test(x))) &&
                                    (currentAutomezzoPredicate.get() == null || (currentAutomezzoPredicate.get().test(x))) &&
                                    (currentGruppoMercPredicate.get() == null || (currentGruppoMercPredicate.get().test(x)))
                    )
                    .map(OrdineUscitaInevasoDTO::getCitta)
                    .distinct()
                    .toList();
        }
    }


    public List<String> getAllAgenti() {
        return Stream
                .of(Objects.requireNonNull(initialOrderList))
                .filter(x -> !UtilityString.isNullOrEmpty(x.getNomeAgente()))
                .sortBy(OrdineUscitaInevasoDTO::getNomeAgente)
                .map(OrdineUscitaInevasoDTO::getNomeAgente)
                .distinct()
                .toList();
    }

    public List<String> getAvailableAgenti() {

        if (currentIdViaggioPredicate.get() == null &&
                currentNumOrdsPredicate.get() == null &&
                currentDataConsPredicate.get() == null &&
                currentTermConsPredicate.get() == null &&
                currentClientePredicate.get() == null &&
                currentVettorePredicate.get() == null &&
                currentDepositoPredicate.get() == null &&
                currentPaesePredicate.get() == null &&
                currentAutomezzoPredicate.get() == null &&
                currentGruppoMercPredicate.get() == null
        ) {
            List<String> all = getAllAgenti();
            return all;
        } else {
            return Stream.of(this.initialOrderList)
                    .filter(x ->
                            (currentIdViaggioPredicate.get() == null || (currentIdViaggioPredicate.get().test(x))) &&
                                    (currentNumOrdsPredicate.get() == null || (currentNumOrdsPredicate.get().test(x))) &&
                                    (currentDataConsPredicate.get() == null || (currentDataConsPredicate.get().test(x))) &&
                                    (currentTermConsPredicate.get() == null || (currentTermConsPredicate.get().test(x))) &&
                                    (currentClientePredicate.get() == null || (currentClientePredicate.get().test(x))) &&
                                    (currentVettorePredicate.get() == null || (currentVettorePredicate.get().test(x))) &&
                                    (currentDepositoPredicate.get() == null || (currentDepositoPredicate.get().test(x))) &&
                                    (currentPaesePredicate.get() == null || (currentPaesePredicate.get().test(x))) &&
                                    (currentAutomezzoPredicate.get() == null || (currentAutomezzoPredicate.get().test(x))) &&
                                    (currentGruppoMercPredicate.get() == null || (currentGruppoMercPredicate.get().test(x)))
                    )
                    .map(OrdineUscitaInevasoDTO::getNomeAgente)
                    .distinct()
                    .toList();
        }
    }


    public List<String> getAllTermCons() {
        return Stream
                .of(Objects.requireNonNull(initialOrderList))
                .filter(x -> !UtilityString.isNullOrEmpty(x.getTermCons()))
                .sortBy(OrdineUscitaInevasoDTO::getTermCons)
                .map(OrdineUscitaInevasoDTO::getTermCons)
                .distinct()
                .toList();
    }

    public List<String> getAvailableTermCons() {

        if (currentIdViaggioPredicate.get() == null &&
                currentNumOrdsPredicate.get() == null &&
                currentDataConsPredicate.get() == null &&
                currentAgentePredicate.get() == null &&
                currentClientePredicate.get() == null &&
                currentVettorePredicate.get() == null &&
                currentDepositoPredicate.get() == null &&
                currentPaesePredicate.get() == null &&
                currentAutomezzoPredicate.get() == null &&
                currentGruppoMercPredicate.get() == null
        ) {
            return getAllTermCons();
        } else {
            return Stream.of(this.initialOrderList)
                    .filter(x ->
                            (currentIdViaggioPredicate.get() == null || (currentIdViaggioPredicate.get().test(x))) &&
                                    (currentNumOrdsPredicate.get() == null || (currentNumOrdsPredicate.get().test(x))) &&
                                    (currentDataConsPredicate.get() == null || (currentDataConsPredicate.get().test(x))) &&
                                    (currentAgentePredicate.get() == null || (currentAgentePredicate.get().test(x))) &&
                                    (currentClientePredicate.get() == null || (currentClientePredicate.get().test(x))) &&
                                    (currentVettorePredicate.get() == null || (currentVettorePredicate.get().test(x))) &&
                                    (currentDepositoPredicate.get() == null || (currentDepositoPredicate.get().test(x))) &&
                                    (currentPaesePredicate.get() == null || (currentPaesePredicate.get().test(x))) &&
                                    (currentAutomezzoPredicate.get() == null || (currentAutomezzoPredicate.get().test(x))) &&
                                    (currentGruppoMercPredicate.get() == null || (currentGruppoMercPredicate.get().test(x)))
                    )
                    .map(OrdineUscitaInevasoDTO::getTermCons)
                    .distinct()
                    .toList();
        }
    }


    public List<MtbGrup> getAllGruppoMerc(List<MtbGrup> mtbGrupFullList) {
        var codMgrp = Stream.of(initialOrderList)
                .flatMap(ordiniUscitaElencoDTO ->
                        Stream.of(ordiniUscitaElencoDTO.getAvailableClassMerc() != null ?
                                ordiniUscitaElencoDTO.getAvailableClassMerc() :
                                new ArrayList<>()))
                .map(OrdineUscitaInevasoDTO.AvailableClassMerc::getCodMgrp)
                .withoutNulls()
                .distinct()
                .toList();

        return Stream.of(Objects.requireNonNull(mtbGrupFullList))
                .filter(x -> codMgrp.contains(x.getCodMgrp()))
                .distinct()
                .withoutNulls()
                .sortBy(MtbGrup::getDescrizione)
                .toList();
    }

    public List<MtbGrup> getAvailableGruppoMerc(List<MtbGrup> mtbGrupFullList) {

        if (currentNumOrdsPredicate.get() == null &&
                currentClientePredicate.get() == null &&
                currentDataConsPredicate.get() == null &&
                currentTermConsPredicate.get() == null &&
                currentVettorePredicate.get() == null &&
                currentAutomezzoPredicate.get() == null &&
                currentIdViaggioPredicate.get() == null &&
                currentAgentePredicate.get() == null &&
                currentPaesePredicate.get() == null &&
                currentDepositoPredicate.get() == null
        ) {
            return getAllGruppoMerc(mtbGrupFullList);
        } else {
            List<String> availableCodMgrups = Stream.of(this.initialOrderList)
                    .filter(x ->
                            (currentNumOrdsPredicate.get() == null || (currentNumOrdsPredicate.get().test(x))) &&
                                    (currentClientePredicate.get() == null || (currentClientePredicate.get().test(x))) &&
                                    (currentDataConsPredicate.get() == null || (currentDataConsPredicate.get().test(x))) &&
                                    (currentTermConsPredicate.get() == null || (currentTermConsPredicate.get().test(x))) &&
                                    (currentVettorePredicate.get() == null || (currentVettorePredicate.get().test(x))) &&
                                    (currentAutomezzoPredicate.get() == null || (currentAutomezzoPredicate.get().test(x))) &&
                                    (currentIdViaggioPredicate.get() == null || (currentIdViaggioPredicate.get().test(x))) &&
                                    (currentAgentePredicate.get() == null || (currentAgentePredicate.get().test(x))) &&
                                    (currentPaesePredicate.get() == null || (currentPaesePredicate.get().test(x))) &&
                                    (currentDepositoPredicate.get() == null || (currentDepositoPredicate.get().test(x)))
                    )
                    .flatMap(x -> Stream.of(x.getAvailableClassMerc()))
                    .map(OrdineUscitaInevasoDTO.AvailableClassMerc::getCodMgrp)
                    .distinct()
                    .toList();

            return Stream.of(Objects.requireNonNull(mtbGrupFullList))
                    .filter(x -> availableCodMgrups.contains(x.getCodMgrp()))
                    .distinct()
                    .withoutNulls()
                    .sortBy(MtbGrup::getDescrizione)
                    .toList();
        }
    }


}
