package it.integry.integrywmsnative.gest.inventario;

import androidx.lifecycle.LiveData;

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

import it.integry.integrywmsnative.core.data_store.db.entity.InventarioRoomDTO;
import it.integry.integrywmsnative.core.data_store.db.respository_new.InventarioRepository;
import it.integry.integrywmsnative.core.expansion.RunnableArgs;
import it.integry.integrywmsnative.core.expansion.RunnableArgss;
import it.integry.integrywmsnative.core.interfaces.viewmodel_listeners.ILoadingListener;
import it.integry.integrywmsnative.core.rest.consumers.InventarioRESTConsumer;
import it.integry.integrywmsnative.core.rest.model.inventario.InventarioArtDTO;
import it.integry.integrywmsnative.core.settings.SettingsManager;
import it.integry.integrywmsnative.core.utility.UtilityDate;
import it.integry.integrywmsnative.core.utility.UtilityString;

public class ElencoInventariViewModel {

    private final InventarioRepository inventarioRepository;
    private final InventarioRESTConsumer inventarioRESTConsumer;
    private final SettingsManager settingsManager;
    private Listener listener;

    private LiveData<List<InventarioRoomDTO>> inventarioList;

    private final String codMdep;

    public ElencoInventariViewModel(
            InventarioRepository inventarioRepository,
            InventarioRESTConsumer inventarioRESTConsumer,
            SettingsManager settingsManager) {
        this.inventarioRepository = inventarioRepository;
        this.inventarioRESTConsumer = inventarioRESTConsumer;
        this.settingsManager = settingsManager;


        codMdep = settingsManager.getSettings().getUserSession().getDepo().getCodMdep();
    }

    public void loadData() {
        inventarioList = inventarioRepository.retrieve();
    }

    public void destroyData() {
        inventarioList = null;
    }

    public LiveData<List<InventarioRoomDTO>> getInventarioList() {
        return inventarioList;
    }

    public void openInventario() {
        sendOnInventarioInfoRequest((inventoryId, zone) -> {
            this.sendOnLoadingStarted();

            inventarioRESTConsumer.loadInventario(inventoryId, loadedInventario -> {

                if (loadedInventario == null || loadedInventario.getMtbInvent() == null) {
                    this.sendOnLoadingEnded();
                    this.sendCreateInventarioRequest(inventoryId, zone);
                } else {

                    var matchedInventory = getInventarioList().getValue()
                            .stream()
                            .filter(x -> Objects.equals(x.getIdInventario(), inventoryId) && UtilityString.equalsIgnoreCase(x.getZona(), zone) &&
                                    !x.isSyncronized())
                            .findFirst()
                            .orElse(null);

                    if (matchedInventory == null)
                        this.createNewInventario(inventoryId, zone, (inventarioRoom, listaArts) -> {
                            this.sendOnLoadingEnded();
                            this.sendOnInventarioLoaded(inventarioRoom, listaArts);
                        });

                    else
                        loadInventarioData(inventoryId, listaArts -> {
                            this.sendOnLoadingEnded();
                            this.sendOnInventarioLoaded(matchedInventory, listaArts);
                        });

                }
            }, this::sendOnError);
        });
    }


    public void loadInventarioData(long inventoryId, RunnableArgs<List<InventarioArtDTO>> onComplete) {
        this.sendOnLoadingStarted();
        inventarioRESTConsumer.loadInventarioArts(inventoryId, inventarioArts -> {
            this.sendOnLoadingEnded();

            onComplete.run(inventarioArts.getArts());
        }, this::sendOnError);
    }


    public void createNewInventario(long inventoryId, String zone, RunnableArgss<InventarioRoomDTO, List<InventarioArtDTO>> onComplete) {
        this.sendOnLoadingStarted();

        var codMdep = settingsManager.getSettings().getUserSession().getDepo().getCodMdep();

        var createdInventario = new InventarioRoomDTO();
        createdInventario.setIdInventario(inventoryId);
        createdInventario.setZona(zone);
        createdInventario.setCodMdep(codMdep);
        createdInventario.setInseritoDa(settingsManager.getSettings().getUser().getFullname());
        createdInventario.setDataInventario(UtilityDate.getNow());

        loadInventarioData(inventoryId, inventarioArts -> {
            inventarioRepository.insert(createdInventario, () -> {
                this.sendOnLoadingEnded();
                onComplete.run(createdInventario, inventarioArts);
            }, this::sendOnError);
        });
    }

    public void deleteInventario(InventarioRoomDTO inventarioRoomDTO) {
        inventarioRepository.delete(inventarioRoomDTO, null, this::sendOnError);
    }


    public void setListener(Listener listener) {
        this.listener = listener;
    }

    private void sendOnInventarioInfoRequest(RunnableArgss<Long, String> onComplete) {
        if (listener != null) listener.onInventarioInfoRequest(onComplete);
    }

    private void sendOnInventarioLoaded(InventarioRoomDTO inventarioRoomDTO, List<InventarioArtDTO> listaArts) {
        if (listener != null) listener.onInventarioLoaded(inventarioRoomDTO, listaArts);
    }

    private void sendCreateInventarioRequest(long inventoryId, String zone) {
        if (this.listener != null) this.listener.onCreateInventarioRequest(inventoryId, zone);
    }

    private void sendOnLoadingStarted() {
        if (this.listener != null) listener.onLoadingStarted();
    }

    private void sendOnLoadingEnded() {
        if (this.listener != null) listener.onLoadingEnded();
    }

    private void sendOnError(Exception ex) {
        if (this.listener != null) listener.onError(ex);
    }

    public interface Listener extends ILoadingListener {

        void onInventarioInfoRequest(RunnableArgss<Long, String> onComplete);

        void onInventarioLoaded(InventarioRoomDTO inventarioRoomDTO, List<InventarioArtDTO> listaArts);

        void onCreateInventarioRequest(long inventoryId, String zone);

        void onError(Exception ex);

    }

}
