package it.integry.integrywmsnative.gest.accettazione_ordini_picking.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.utility.UtilityString;
import it.integry.integrywmsnative.gest.accettazione_ordini_picking.dto.PickingObjectDTO;

public class AccettazionePickingFiltroOrdineViewModel {

    private final ObservableField<Predicate<PickingObjectDTO>> currentCodArtPredicate = new ObservableField<>();
    private final ObservableField<Predicate<PickingObjectDTO>> currentDescrPredicate = new ObservableField<>();
    private final ObservableField<Predicate<PickingObjectDTO>> currentPosPredicate = new ObservableField<>();


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

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

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


    public void setCodArtFilter(List<String> codArts) {
        if (codArts == null || codArts.isEmpty()) currentCodArtPredicate.set(null);
        else {
            currentCodArtPredicate.set(o -> codArts.contains(o.getSitArtOrdDTO().getCodMart()));
        }
    }


    public void setDescrFilter(List<String> descrs) {
        if (descrs == null || descrs.isEmpty()) currentDescrPredicate.set(null);
        else {
            currentDescrPredicate.set(o -> descrs.contains(o.getSitArtOrdDTO().getDescrizioneEstesaArt()));
        }
    }


    public void setPosFilter(List<String> pos) {
        if (pos == null || pos.isEmpty()) currentPosPredicate.set(null);
        else {
            currentPosPredicate.set(o -> o.getMtbAart() != null && o.getMtbAart().getPosizione() == null ? pos.contains(null) : pos.contains(o.getMtbAart().getPosizione()));
        }
    }


    public void applyAllTests() {

        List<PickingObjectDTO> returnList = null;

        if (currentCodArtPredicate.get() == null &&
                currentDescrPredicate.get() == null &&
                currentPosPredicate.get() == null) {
            returnList = this.initialOrderList;
        } else {
            Stream<PickingObjectDTO> tmpStream = Stream.of(this.initialOrderList)
                    .filter(x ->
                            (currentCodArtPredicate.get() == null || (currentCodArtPredicate.get().test(x))) &&
                                    (currentDescrPredicate.get() == null || (currentDescrPredicate.get().test(x))) &&
                                    (currentPosPredicate.get() == null || (currentPosPredicate.get().test(x)))
                    );

            returnList = tmpStream.toList();
        }

        this.currentFilteredOrderList.setValue(returnList);
    }

    public ObservableField<Predicate<PickingObjectDTO>> getCurrentCodArtPredicate() {
        return currentCodArtPredicate;
    }

    public ObservableField<Predicate<PickingObjectDTO>> getCurrentDescrPredicate() {
        return currentDescrPredicate;
    }

    public ObservableField<Predicate<PickingObjectDTO>> getCurrentPosPredicate() {
        return currentPosPredicate;
    }

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

    public List<String> getAvailableCodArts() {

        if (currentDescrPredicate.get() == null &&
                currentPosPredicate.get() == null) {
            return getAllCodArts();
        } else {
            return Stream.of(this.initialOrderList)
                    .filter(x ->
                            (currentDescrPredicate.get() == null || (currentDescrPredicate.get().test(x))) &&
                                    (currentPosPredicate.get() == null || (currentPosPredicate.get().test(x)))
                    )
                    .map(x -> x.getSitArtOrdDTO().getCodMart())
                    .distinct()
                    .toList();
        }
    }

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

    public List<String> getAvailableDescrs() {

        if (currentCodArtPredicate.get() == null &&
                currentPosPredicate.get() == null) {
            return getAllDescrs();
        } else {
            return Stream.of(this.initialOrderList)
                    .filter(x ->
                            (currentCodArtPredicate.get() == null || (currentCodArtPredicate.get().test(x))) &&
                                    (currentPosPredicate.get() == null || (currentPosPredicate.get().test(x)))
                    )
                    .map(x -> x.getSitArtOrdDTO().getDescrizioneEstesaArt())
                    .distinct()
                    .toList();
        }
    }

    public List<String> getAllPos() {
        return Stream
                .of(Objects.requireNonNull(initialOrderList))
                .filter(x -> x.getMtbAart() != null && x.getMtbAart().getPosizione() != null)
                .sortBy(x -> UtilityString.isNull(x.getMtbAart().getPosizione(), "000000"))
                .map(x -> x.getMtbAart().getPosizione() != null ? x.getMtbAart().getPosizione() : null)
                .distinct()
                .toList();
    }

    public List<String> getAvailablePos() {

        if (currentCodArtPredicate.get() == null &&
                currentDescrPredicate.get() == null) {
            return getAllPos();
        } else {
            return Stream.of(this.initialOrderList)
                    .filter(x ->
                            (currentCodArtPredicate.get() == null || (currentCodArtPredicate.get().test(x))) &&
                                    (currentDescrPredicate.get() == null || (currentDescrPredicate.get().test(x)))
                    )
                    .map(x -> x.getMtbAart().getPosizione())
                    .distinct()
                    .toList();
        }
    }

}
