package it.integry.integrywmsnative.gest.prod_recupero_materiale.rest;

import com.annimon.stream.Stream;
import com.google.gson.reflect.TypeToken;

import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import javax.inject.Singleton;

import it.integry.integrywmsnative.core.expansion.RunnableArgs;
import it.integry.integrywmsnative.core.model.MtbAart;
import it.integry.integrywmsnative.core.rest.consumers.ArticoloRESTConsumer;
import it.integry.integrywmsnative.core.rest.consumers.SystemRESTConsumer;
import it.integry.integrywmsnative.core.rest.consumers._BaseRESTConsumer;
import it.integry.integrywmsnative.gest.prod_recupero_materiale.dto.HistoryVersamentoProdULDTO;
import it.integry.integrywmsnative.gest.prod_recupero_materiale.dto.HistoryVersamentoProdULRestDTO;

@Singleton
public class ProdRecuperMaterialeRESTConsumer extends _BaseRESTConsumer {

    private final SystemRESTConsumer mSystemRESTConsumer;
    private final ArticoloRESTConsumer mArticoloRESTConsumer;

    public ProdRecuperMaterialeRESTConsumer(SystemRESTConsumer systemRESTConsumer, ArticoloRESTConsumer articoloRESTConsumer) {
        this.mSystemRESTConsumer = systemRESTConsumer;
        this.mArticoloRESTConsumer = articoloRESTConsumer;
    }


    public void loadLastULVersate(RunnableArgs<List<HistoryVersamentoProdULDTO>> onComplete, RunnableArgs<Exception> onFailed) {

        String sql = "WITH ul_list AS ( " +
                "    SELECT jtb_fasi.cod_jfas, " +
                "           jtb_fasi.descrizione                                      AS descrizione_fase, " +
                "           mtb_colr.gestione, " +
                "           mtb_colr.data_collo, " +
                "           mtb_colr.num_collo, " +
                "           mtb_colr.ser_collo, " +
                "           mtb_colr.cod_mart, " +
                "           mtb_colr.cod_col, " +
                "           mtb_colr.cod_tagl, " +
                "           SUM(mtb_colr.qta_col)                                     AS qta_col, " +
                "           SUM(mtb_colr.num_cnf)                                     AS num_cnf, " +
                "           mtb_colr.partita_mag, " +
                "           mtb_colr.cod_jcom, " +
                "           mtb_colr.num_collo_rif, " +
                "           mtb_colr.data_collo_rif, " +
                "           mtb_colr.ser_collo_rif, " +
                "           mtb_colr.gestione_rif, " +
                "           mtb_colt.segno, " +
                "           ISNULL(mtb_aart.descrizione_estesa, mtb_aart.descrizione) AS descrizione_art, " +
                "           mtb_aart.unt_mis, " +
                "           MAX(datetime_row)                                         AS datetime_row, " +
                "           dtb_ord_steps.num_ord, " +
                "           dtb_ord_steps.data_ord, " +
                "           dtb_ord_steps.gestione                                    as gestione_ord, " +
                "           dtb_ord_steps.hr_num                                      as hr, " +
                "           mtb_colr.riga_ord, " +
                "           CONVERT(INTEGER, ROUND((CAST(dtb_ord_steps.hr_num AS DECIMAL(20, 5)) / " +
                "                                   SUM(dtb_ord_steps.hr_num) OVER (PARTITION BY mtb_colr.num_collo)) * 100, " +
                "                                  0))                                as percentage_hr " +
                "    FROM mtb_colr " +
                "             INNER JOIN mtb_colt ON mtb_colr.num_collo = mtb_colt.num_collo " +
                "        AND mtb_colr.data_collo = mtb_colt.data_collo " +
                "        AND mtb_colr.ser_collo = mtb_colt.ser_collo " +
                "        AND mtb_colr.gestione = mtb_colt.gestione " +
                "             INNER JOIN dtb_ord_steps ON dtb_ord_steps.data_ord = mtb_colr.data_ord " +
                "        AND dtb_ord_steps.gestione = mtb_colr.gestione " +
                "        AND dtb_ord_steps.num_ord = mtb_colr.num_ord " +
                "        AND dtb_ord_steps.data_iniz is not null " +
                "        AND dtb_ord_steps.data_fine is null " +
                "             INNER JOIN mtb_aart ON mtb_colr.cod_mart = mtb_aart.cod_mart " +
                "             LEFT OUTER JOIN jtb_fasi ON mtb_colt.cod_jfas = jtb_fasi.cod_jfas " +
                "    WHERE jtb_fasi.cod_jfas IS NOT NULL " +
                "      AND segno = -1 " +
                "      AND mtb_colr.data_collo > DATEADD(DAY, -5, GETDATE()) " +
                "    GROUP BY jtb_fasi.cod_jfas, " +
                "             jtb_fasi.descrizione, " +
                "             mtb_colr.gestione, " +
                "             mtb_colr.data_collo, " +
                "             mtb_colr.num_collo, " +
                "             mtb_colr.ser_collo, " +
                "             mtb_colr.cod_mart, " +
                "             mtb_colr.cod_col, " +
                "             mtb_colr.cod_tagl, " +
                "             mtb_colr.ser_collo, " +
                "             mtb_colr.partita_mag, " +
                "             mtb_colr.cod_jcom, " +
                "             mtb_aart.descrizione_estesa, " +
                "             mtb_aart.descrizione, " +
                "             mtb_aart.unt_mis, " +
                "             mtb_colr.num_collo_rif, " +
                "             mtb_colr.data_collo_rif, " +
                "             mtb_colr.ser_collo_rif, " +
                "             mtb_colr.gestione_rif, " +
                "             mtb_colt.segno, " +
                "             dtb_ord_steps.num_ord, " +
                "             dtb_ord_steps.data_ord, " +
                "             dtb_ord_steps.gestione, " +
                "             mtb_colr.riga_ord, " +
                "             dtb_ord_steps.hr_num " +
                "    HAVING SUM(mtb_colr.qta_col) > 0 " +
                "), max_ul AS ( " +
                "    SELECT " +
                "           cod_jfas, " +
                "             descrizione_fase, " +
                "             gestione, " +
                "             cod_mart, " +
                "             cod_col, " +
                "             cod_tagl, " +
                "             ser_collo, " +
                "             partita_mag, " +
                "             cod_jcom, " +
                "             descrizione_art, " +
                "             unt_mis, " +
                "             num_collo_rif, " +
                "             data_collo_rif, " +
                "             ser_collo_rif, " +
                "             gestione_rif, " +
                "             segno, " +
                "             num_ord, " +
                "             data_ord, " +
                "             gestione_ord, " +
                "             riga_ord, " +
                "             hr, " +
                "        MAX (datetime_row) as max_datetime_row " +
                "    FROM ul_list " +
                "    GROUP BY cod_jfas, " +
                "             descrizione_fase, " +
                "             gestione, " +
                "             cod_mart, " +
                "             cod_col, " +
                "             cod_tagl, " +
                "             ser_collo, " +
                "             partita_mag, " +
                "             cod_jcom, " +
                "             descrizione_art, " +
                "             unt_mis, " +
                "             num_collo_rif, " +
                "             data_collo_rif, " +
                "             ser_collo_rif, " +
                "             gestione_rif, " +
                "             segno, " +
                "             num_ord, " +
                "             data_ord, " +
                "             gestione_ord, " +
                "             riga_ord, " +
                "             hr " +
                ") " +
                " " +
                "SELECT qta_col, num_cnf, * FROM max_ul " +
                "LEFT OUTER JOIN ul_list ON " +
                "            ISNULL(max_ul.cod_jfas, '') = ISNULL(ul_list.cod_jfas, '') AND " +
                "            ISNULL(max_ul.descrizione_fase, '') = ISNULL(ul_list.descrizione_fase, '') AND " +
                "            ISNULL(max_ul.gestione, '') = ISNULL(ul_list.gestione, '') AND " +
                "            ISNULL(max_ul.cod_mart, '') = ISNULL(ul_list.cod_mart, '') AND " +
                "            ISNULL(max_ul.cod_col, '') = ISNULL(ul_list.cod_col, '') AND " +
                "            ISNULL(max_ul.cod_tagl, '') = ISNULL(ul_list.cod_tagl, '') AND " +
                "            ISNULL(max_ul.ser_collo, '') = ISNULL(ul_list.ser_collo, '') AND " +
                "            ISNULL(max_ul.partita_mag, '') = ISNULL(ul_list.partita_mag, '') AND " +
                "            ISNULL(max_ul.cod_jcom, '') = ISNULL(ul_list.cod_jcom, '') AND " +
                "            ISNULL(max_ul.descrizione_art, '') = ISNULL(ul_list.descrizione_art, '') AND " +
                "            ISNULL(max_ul.unt_mis, '') = ISNULL(ul_list.unt_mis, '') AND " +
                "            ISNULL(max_ul.num_collo_rif, '') = ISNULL(ul_list.num_collo_rif, '') AND " +
                "            ISNULL(max_ul.data_collo_rif, '') = ISNULL(ul_list.data_collo_rif, '') AND " +
                "            ISNULL(max_ul.ser_collo_rif, '') = ISNULL(ul_list.ser_collo_rif, '') AND " +
                "            ISNULL(max_ul.gestione_rif, '') = ISNULL(ul_list.gestione_rif, '') AND " +
                "            ISNULL(max_ul.segno, '') = ISNULL(ul_list.segno, '') AND " +
                "            ISNULL(max_ul.num_ord, '') = ISNULL(ul_list.num_ord, '') AND " +
                "            ISNULL(max_ul.data_ord, '') = ISNULL(ul_list.data_ord, '') AND " +
                "            ISNULL(max_ul.gestione_ord, '') = ISNULL(ul_list.gestione_ord, '') AND " +
                "            ISNULL(max_ul.riga_ord, '') = ISNULL(ul_list.riga_ord, '') AND " +
                "            ISNULL(max_ul.hr, '') = ISNULL(ul_list.hr, '') AND " +
                "            max_ul.max_datetime_row = ul_list.datetime_row";

        Type typeOfObjectsList = new TypeToken<ArrayList<HistoryVersamentoProdULRestDTO>>() {}.getType();
        this.mSystemRESTConsumer.<ArrayList<HistoryVersamentoProdULRestDTO>>processSql(sql, typeOfObjectsList, ulList -> {

            if (ulList == null) {
                onComplete.run(null);
                return;
            }

            List<HistoryVersamentoProdULDTO> newUlList = new ArrayList<>();

            Stream.of(ulList)
                    .distinctBy(x -> {
                        HashMap<String, Object> hashMap = new HashMap<>();
                        hashMap.put("gestione", x.getGestione());
                        hashMap.put("data_collo", x.getDataCollo());
                        hashMap.put("ser_collo", x.getSerCollo());
                        hashMap.put("num_collo", x.getNumCollo());
                        hashMap.put("cod_mart", x.getCodMart());
                        hashMap.put("gestione_rif", x.getGestioneRif());
                        hashMap.put("data_collo_rif", x.getDataColloRif());
                        hashMap.put("ser_collo_rif", x.getSerColloRif());
                        hashMap.put("num_collo_rif", x.getNumColloRif());

                        return hashMap;
                    })
                    .forEach(restDTO -> {

                        List<HistoryVersamentoProdULDTO.OrdineDto> ordineList = Stream.of(ulList)
                                .filter(x -> x.getNumCollo().equals(restDTO.getNumCollo()) &&
                                        x.getDataCollo().equals(restDTO.getDataCollo()) &&
                                        x.getSerCollo().equals(restDTO.getSerCollo()) &&
                                        x.getGestione().equals(restDTO.getGestione()))
                                .map(x -> new HistoryVersamentoProdULDTO.OrdineDto()
                                        .setData(x.getDataOrdD())
                                        .setNumero(x.getNumOrd())
                                        .setGestione(x.getGestioneOrd())
                                        .setRigaOrd(x.getRigaOrd())
                                        .setQtaCol(x.getQtaCol())
                                        .setNumCnf(x.getNumCnf())
                                        .setPercentageHr(x.getPercentageHr()))
                                .toList();

                        BigDecimal qtaColTot = BigDecimal.ZERO;
                        BigDecimal numCnfColTot = BigDecimal.ZERO;

                        for (HistoryVersamentoProdULDTO.OrdineDto ordine :
                                ordineList) {
                            qtaColTot = qtaColTot.add(ordine.getQtaCol());
                            numCnfColTot = numCnfColTot.add(ordine.getNumCnf());
                        }

                        newUlList.add(new HistoryVersamentoProdULDTO()
                                .setGestione(restDTO.getGestione())
                                .setDataCollo(restDTO.getDataCollo())
                                .setSerCollo(restDTO.getSerCollo())
                                .setNumCollo(restDTO.getNumCollo())
                                .setSegno(restDTO.getSegno())
                                .setCodMart(restDTO.getCodMart())
                                .setCodCol(restDTO.getCodCol())
                                .setCodTagl(restDTO.getCodTagl())
                                .setCodJfas(restDTO.getCodJfas())
                                .setDescrizioneFase(restDTO.getDescrizioneFase())
                                .setQtaCol(qtaColTot)
                                .setNumCnf(numCnfColTot)
                                .setPartitaMag(restDTO.getPartitaMag())
                                .setCodJcom(restDTO.getCodJcom())
                                .setDatetimeRow(restDTO.getDatetimeRow())
                                .setUntMis(restDTO.getUntMis())
                                .setGestioneRif(restDTO.getGestioneRif())
                                .setDataColloRif(restDTO.getDataColloRif())
                                .setSerColloRif(restDTO.getSerColloRif())
                                .setNumColloRif(restDTO.getNumColloRif())
                                .setOrdini(ordineList));

                    });


            if (newUlList.size() > 0) {
                List<String> codMarts = Stream.of(newUlList)
                        .map(HistoryVersamentoProdULDTO::getCodMart)
                        .withoutNulls()
                        .distinct()
                        .toList();

                this.mArticoloRESTConsumer.getByCodMarts(codMarts, arts -> {

                    if (arts != null && arts.size() > 0) {
                        for (HistoryVersamentoProdULDTO value : newUlList) {

                            MtbAart foundMtbAart = null;

                            List<MtbAart> mtbAartStream = Stream.of(arts)
                                    .filter(x -> x.getCodMart().equalsIgnoreCase(value.getCodMart())).toList();

                            if (mtbAartStream != null && mtbAartStream.size() > 0) {
                                foundMtbAart = mtbAartStream.get(0);
                            }

                            value.setMtbAart(foundMtbAart);
                        }
                    }

                    onComplete.run(newUlList);

                }, onFailed);

            } else {
                onComplete.run(newUlList);
            }

        }, onFailed);
    }


}
