package it.integry.integrywmsnative.core.data_store.db.repository.implementations;

import com.annimon.stream.Stream;

import org.apache.commons.lang3.StringUtils;

import java.util.ArrayList;
import java.util.List;

import javax.inject.Inject;

import it.integry.integrywmsnative.core.data_store.db.dao.ArticoloGrigliaDao;
import it.integry.integrywmsnative.core.data_store.db.entity.ArticoloGriglia;
import it.integry.integrywmsnative.core.data_store.db.entity.Griglia;
import it.integry.integrywmsnative.core.data_store.db.repository.ArticoloGrigliaRepository;
import it.integry.integrywmsnative.core.expansion.RunnableArgs;

public class ArticoliGrigliaDataSource extends Repository implements ArticoloGrigliaRepository {

    private final ArticoloGrigliaDao mArticoloGrigliaDao;

    @Inject
    public ArticoliGrigliaDataSource(ArticoloGrigliaDao articoloGrigliaDao) {
        this.mArticoloGrigliaDao = articoloGrigliaDao;
    }

    public void saveArticoliToGriglia(List<ArticoloGriglia> articoli, Griglia griglia, Runnable onSuccess, RunnableArgs<Exception> onFail) {
        execute(() -> {
            try {
                List<ArticoloGriglia> toUpdate = new ArrayList<>();
                List<ArticoloGriglia> toInsert = new ArrayList<>();
                List<String> codMarts = new ArrayList<>();
                for (ArticoloGriglia art : articoli) {
                    Integer id = mArticoloGrigliaDao.getIdArticoloByGrigliaAndBarcodeAndCodMart(griglia.getGrigliaId(), art.getBarCode(), art.getCodMart());
                    codMarts.add(art.getCodMart());
                    if (id != null) {
                        art.setArticoloGrigliaId(id);
                        toUpdate.add(art);
                    } else {
                        toInsert.add(art);
                    }
                }
                mArticoloGrigliaDao.insertAll(toInsert);
                mArticoloGrigliaDao.updateAll(toUpdate);
                List<ArticoloGriglia> articoliGriglia = mArticoloGrigliaDao.getArticoliFromGriglia(griglia.getGrigliaId());
                List<ArticoloGriglia> toDelete = Stream.of(articoliGriglia).filter(articolo -> !codMarts.contains(articolo.getCodMart())).toList();
                mArticoloGrigliaDao.deleteList(toDelete);
                onSuccess.run();
            } catch (Exception e) {
                onFail.run(e);
            }
        });
    }

    public void findArticoloByBarcodeAndGriglia(String barcode, int idGriglia, RunnableArgs<ArticoloGriglia> onSuccess, RunnableArgs<Exception> onFail) {
        execute(() -> {
            try {
                onSuccess.run(mArticoloGrigliaDao.findArticoloByBarcodeAndGriglia(barcode, idGriglia));
            } catch (Exception e) {
                onFail.run(e);
            }
        });
    }

    public void findArticoloByCodMartAndGriglia(String codMart, int idGriglia, RunnableArgs<ArticoloGriglia> onSuccess, RunnableArgs<Exception> onFail) {
        execute(() -> {
            try {
                onSuccess.run(mArticoloGrigliaDao.findArticoloByCodMartAndGriglia(codMart, idGriglia));
            } catch (Exception e) {
                onFail.run(e);
            }
        });
    }

    public void findArticoloByScanAndGriglia(String scan, int idGriglia, RunnableArgs<ArticoloGriglia> onSuccess, RunnableArgs<Exception> onFail) {
        execute(() -> {
            try {
                ArticoloGriglia articolo = mArticoloGrigliaDao.findArticoloByCodMartAndGriglia(scan, idGriglia);
                if (articolo == null) {
                    articolo = mArticoloGrigliaDao.findArticoloByBarcodeAndGriglia(scan, idGriglia);
                    if (articolo == null) {
                        String barcode = StringUtils.leftPad(scan, 13, "0");
                        articolo = mArticoloGrigliaDao.findArticoloByBarcodeAndGriglia(barcode, idGriglia);
                    }
                }
                onSuccess.run(articolo);
            } catch (Exception e) {
                onFail.run(e);
            }
        });
    }
}
