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

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

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

import java.util.List;
import java.util.Objects;

import it.integry.integrywmsnative.core.model.JtbComt;
import it.integry.integrywmsnative.gest.accettazione.dto.OrdineAccettazioneInevasoDTO;

public class OrdineProduzioneFilterViewModel {
    private final ObservableField<Predicate<OrdineAccettazioneInevasoDTO>> currentNumOrdsPredicate = new ObservableField<>();
    private final ObservableField<Predicate<OrdineAccettazioneInevasoDTO>> currentCommPredicate = new ObservableField<>();


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

    public void init(List<OrdineAccettazioneInevasoDTO> initialList) {
        this.initialOrderList = initialList;
        this.currentFilteredOrderList.setValue(this.initialOrderList);
    }
    public MutableLiveData<List<OrdineAccettazioneInevasoDTO>> getMutableFilteredOrderList() {
        return this.currentFilteredOrderList;
    }

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

    public void setCommessaFilter(List<JtbComt> jtbComtList) {
        if (jtbComtList == null || jtbComtList.isEmpty()) currentCommPredicate.set(null);
        else {
            List<String> codMdeps = Stream.of(jtbComtList).map(JtbComt::getCodJcom).toList();
            currentCommPredicate.set(o -> codMdeps.contains(o.getCodJcom()));
        }
    }

    public void applyAllTests() {
        List<OrdineAccettazioneInevasoDTO> returnList = null;

        if (currentNumOrdsPredicate.get() == null &&
                currentCommPredicate.get() == null
        ) {
            returnList = this.initialOrderList;
        } else {
            Stream<OrdineAccettazioneInevasoDTO> tmpStream = Stream.of(this.initialOrderList)
                    .filter(x ->
                            (currentNumOrdsPredicate.get() == null || (currentNumOrdsPredicate.get().test(x))) &&
                                    (currentCommPredicate.get() == null || (currentCommPredicate.get().test(x))));

            returnList = tmpStream.toList();
        }

        this.currentFilteredOrderList.setValue(returnList);
    }

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

    public ObservableField<Predicate<OrdineAccettazioneInevasoDTO>> getCurrentCommPredicate() {
        return currentCommPredicate;
    }


    public List<JtbComt> getAllCommesse(List<JtbComt> commesseFullList) {
        List<String> codJcom = Stream.of(initialOrderList)
                .map(OrdineAccettazioneInevasoDTO::getCodJcom)
                .distinct()
                .toList();

        return Stream.of(Objects.requireNonNull(commesseFullList))
                .filter(x -> codJcom.contains(x.getCodJcom()))
                .distinct()
                .withoutNulls()
                .sortBy(JtbComt::getCodJcom)
                .toList();
    }

    public List<JtbComt> getAvailableCommesse(List<JtbComt> commesseFullList) {

        if (currentNumOrdsPredicate.get() == null) {
            return getAllCommesse(commesseFullList);
        } else {
            List<String> availableCodMdeps = Stream.of(this.initialOrderList)
                    .filter(x ->
                            (currentNumOrdsPredicate.get() == null || (currentNumOrdsPredicate.get().test(x)))
                    )
                    .map(OrdineAccettazioneInevasoDTO::getCodJcom)
                    .distinct()
                    .toList();

            return Stream.of(Objects.requireNonNull(commesseFullList))
                    .filter(x -> availableCodMdeps.contains(x.getCodJcom()))
                    .distinct()
                    .withoutNulls()
                    .sortBy(JtbComt::getCodJcom)
                    .toList();
        }
    }

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

    public List<Integer> getAvailableNumOrds() {

        if (currentCommPredicate.get() == null
        ) {
            return getAllNumOrds();
        } else {
            return Stream.of(this.initialOrderList)
                    .filter(x ->
                            (currentCommPredicate.get() == null || (currentCommPredicate.get().test(x)))
                    )
                    .map(OrdineAccettazioneInevasoDTO::getNumero)
                    .distinct()
                    .toList();
        }
    }

}
