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

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

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

import javax.inject.Singleton;

import it.integry.integrywmsnative.core.model.GtbAnag;
import it.integry.integrywmsnative.core.rest.consumers.ArticoloRESTConsumer;
import it.integry.integrywmsnative.core.rest.consumers.ISimpleOperationCallback;
import it.integry.integrywmsnative.core.rest.consumers.SystemRESTConsumer;
import it.integry.integrywmsnative.core.expansion.RunnableArgs;
import it.integry.integrywmsnative.core.model.DtbDocr;
import it.integry.integrywmsnative.core.model.MtbAart;
import it.integry.integrywmsnative.core.utility.UtilityDB;
import it.integry.integrywmsnative.core.utility.UtilityQuery;
import it.integry.integrywmsnative.gest.picking_resi.rest.WithdrawableDtbDocr;
import it.integry.integrywmsnative.core.rest.model.DocumentoResoDTO;

@Singleton
public class UltimeConsegneClienteRESTConsumer {

    private final SystemRESTConsumer systemRESTConsumer;

    public UltimeConsegneClienteRESTConsumer(SystemRESTConsumer systemRESTConsumer) {
        this.systemRESTConsumer = systemRESTConsumer;
    }

    public void getAvailableCodAnagClienti(RunnableArgs<List<GtbAnag>> onComplete, RunnableArgs<Exception> onFailed) {
        String sql = "SELECT DISTINCT gtb_anag.cod_anag, gtb_anag.rag_soc " +
                "FROM gtb_anag " +
                "INNER JOIN vtb_clie ON vtb_clie.cod_anag = gtb_anag.cod_anag " +
                "WHERE flag_stato = 'A'";

        Type typeOfObjectsList = new TypeToken<ArrayList<GtbAnag>>() {
        }.getType();
        systemRESTConsumer.<ArrayList<GtbAnag>>processSql(sql, typeOfObjectsList, value -> {
            if (onComplete != null) onComplete.run(value);
        }, ex -> {
            if (onFailed != null) onFailed.run(ex);
        });
    }

    public void getUltimeConsegneClienti(String codMdep, String codAnag, String codMart, Integer limitConsegnePerCli, int limitDays, RunnableArgs<ArrayList<DocumentoResoDTO>> onComplete, RunnableArgs<Exception> onFailed) {

        String sql = "SELECT consegne.*, " +
                "       rag_soc," +
                "       dtb_doct.gestione  " +
                "FROM WMS_GetUltimeConsegneClienti(" +
                UtilityDB.valueToString(limitConsegnePerCli >= 0 ? limitConsegnePerCli : null) + ", " +
                UtilityDB.valueToString(codAnag) + ", " +
                UtilityDB.valueToString(codMart) + ", " +
                UtilityDB.valueToString(codMdep) + ", " +
                UtilityDB.valueToString(limitDays) + ") consegne " +
                "INNER JOIN dtb_doct ON consegne.num_doc = dtb_doct.num_doc AND consegne.data_doc = dtb_doct.data_doc AND consegne.cod_anag = dtb_doct.cod_anag AND consegne.cod_dtip = dtb_doct.cod_dtip AND consegne.ser_doc = dtb_doct.ser_doc " +
                "LEFT OUTER JOIN gtb_anag ON consegne.cod_anag = gtb_anag.cod_anag " +
                "ORDER BY rag_soc, " +
                "         counter_consegna ";


        Type typeOfObjectsList = new TypeToken<ArrayList<DocumentoResoDTO>>() {
        }.getType();
        systemRESTConsumer.<ArrayList<DocumentoResoDTO>>processSql(sql, typeOfObjectsList, value -> {
            if (onComplete != null) onComplete.run(value);
        }, ex -> {
            if (onFailed != null) onFailed.run(ex);
        });
    }


    public static void loadDocRowFromConsegna(List<DocumentoResoDTO> consegne, RunnableArgs<ArrayList<WithdrawableDtbDocr>> onComplete, RunnableArgs<Exception> onFailed) {
        List<HashMap<String, Object>> filterCond = new ArrayList<>();

        for (int i = 0; i < consegne.size(); i++) {
            HashMap<String, Object> filter = new HashMap<>();

            filter.put("dtb_docr.data_doc", consegne.get(i).getDataDocD());
            filter.put("dtb_docr.num_doc", consegne.get(i).getNumDoc());
            filter.put("dtb_docr.ser_doc", consegne.get(i).getSerDoc());
            filter.put("dtb_docr.cod_anag", consegne.get(i).getCodAnag());
            filter.put("dtb_docr.cod_dtip", consegne.get(i).getCodDtip());

            filterCond.add(filter);
        }

        String sql = "SELECT dtb_docr.[cod_anag]" +
                "      ,dtb_docr.[cod_dtip]" +
                "      ,dtb_docr.[data_doc]" +
                "      ,dtb_docr.[ser_doc]" +
                "      ,dtb_docr.[num_doc]" +
                "      ,dtb_docr.[id_riga]" +
                "      ,dtb_docr.[cod_mart]" +
                "      ,dtb_docr.[descrizione]" +
                "      ,dtb_docr.[unt_doc]" +
                "      ,(dtb_docr.[rap_conv] / dtb_docr.[rap_conv]) as rap_conv" +
                "      ,(dtb_docr.[qta_doc] * dtb_docr.[rap_conv]) - ISNULL(mtb_colr.qta_col, 0) as qta_doc" +
                "      ,dtb_docr.[val_unt]" +
                "      ,dtb_docr.[sconto5]" +
                "      ,dtb_docr.[sconto6]" +
                "      ,dtb_docr.[sconto7]" +
                "      ,dtb_docr.[sconto8]" +
                "      ,dtb_docr.[cod_aliq]" +
                "      ,dtb_docr.[perc_prov]" +
                "      ,dtb_docr.[val_prov]" +
                "      ,dtb_docr.[data_ord]" +
                "      ,dtb_docr.[num_ord]" +
                "      ,dtb_docr.[riga_ord]" +
                "      ,dtb_docr.[importo_riga]" +
                "      ,dtb_docr.[cod_col]" +
                "      ,dtb_docr.[cod_tagl]" +
                "      ,dtb_docr.[cod_jcom]" +
                "      ,dtb_docr.[cod_mdep]" +
                "      ,dtb_docr.[perc_gest]" +
                "      ,dtb_docr.[val_gest]" +
                "      ,dtb_docr.[partita_mag]" +
                "      ,dtb_docr.[val_unt_iva]" +
                "      ,dtb_docr.[qta_cnf]" +
                "      ,dtb_docr.[descrizione_estesa]" +
                "      ,dtb_docr.[costo_unt]" +
                "      ,dtb_docr.[perc_ispe]" +
                "      ,dtb_docr.[val_ispe]" +
                "      ,dtb_docr.[perc_promo]" +
                "      ,dtb_docr.[val_promo]" +
                "      ,dtb_docr.[perc_oneri]" +
                "      ,dtb_docr.[val_oneri]" +
                "      ,dtb_docr.[flag_evaso_forzato]" +
                "      ,dtb_docr.[cod_dtip_comp]" +
                "      ,dtb_docr.[data_doc_comp]" +
                "      ,dtb_docr.[ser_doc_comp]" +
                "      ,dtb_docr.[num_doc_comp]" +
                "      ,dtb_docr.[cod_promo]" +
                "      ,dtb_docr.[perc_prov2]" +
                "      ,dtb_docr.[val_prov2]" +
                "      ,dtb_docr.[cod_art_for]" +
                "      ,dtb_docr.[unt_doc2]" +
                "      ,dtb_docr.[qta_doc2]" +
                "      ,dtb_docr.[unt_doc3]" +
                "      ,dtb_docr.[qta_doc3]" +
                "      ,dtb_docr.[num_cnf]" +
                "      ,dtb_docr.[peso_lordo]" +
                "      ,dtb_docr.[posizione]" +
                "      ,dtb_docr.[cod_anag_comp]" +
                "      ,dtb_docr.[cod_mtip]" +
                "      ,dtb_docr.[matricola]" +
                "      ,dtb_docr.[data_iniz_comp]" +
                "      ,dtb_docr.[data_fine_comp]" +
                "      ,dtb_docr.[cod_kit]" +
                "      ,dtb_docr.[cod_alis]" +
                "      ,dtb_docr.[data_ins_row]" +
                "      ,dtb_docr.[note] " +
                "      ,dtb_doct.[gestione] " +
                "FROM dtb_docr " +
                "INNER JOIN dtb_doct ON dtb_docr.num_doc = dtb_doct.num_doc AND dtb_docr.data_doc = dtb_doct.data_doc AND dtb_docr.cod_anag = dtb_doct.cod_anag AND dtb_docr.cod_dtip = dtb_doct.cod_dtip AND dtb_docr.ser_doc = dtb_doct.ser_doc " +
                "INNER JOIN mtb_aart ON dtb_docr.cod_mart = mtb_aart.cod_mart " +
                "LEFT OUTER JOIN ctb_cont ON mtb_aart.cod_ccon_ricavi = ctb_cont.cod_ccon " +
                "LEFT OUTER JOIN ctb_grup ON ctb_cont.cod_cgrp = ctb_grup.cod_cgrp " +
                "LEFT OUTER JOIN mtb_colr ON " +
                " dtb_docr.cod_anag = mtb_colr.cod_anag_doc AND " +
                " dtb_docr.cod_dtip = mtb_colr.cod_dtip_doc AND " +
                " dtb_docr.ser_doc = mtb_colr.ser_doc AND " +
                " dtb_docr.data_doc = mtb_colr.data_doc AND " +
                " dtb_docr.num_doc = mtb_colr.num_doc AND " +
                " dtb_docr.id_riga = mtb_colr.id_riga_doc " +
                "WHERE " +
                "   (ctb_grup.sezione <> 1 OR ctb_grup.sezione IS NULL) AND " +
                "   dtb_docr.[qta_doc] - ISNULL(mtb_colr.qta_col, 0) > 0 AND" +
                "   ( " +
                UtilityQuery.concatFieldListInWhereCond(filterCond) +
                "   ) " +
                "ORDER BY cod_mart";


        Type typeOfObjectsList = new TypeToken<ArrayList<WithdrawableDtbDocr>>() {
        }.getType();
        SystemRESTConsumer.processSqlStatic(sql, typeOfObjectsList, new ISimpleOperationCallback<ArrayList<WithdrawableDtbDocr>>() {
            @Override
            public void onSuccess(ArrayList<WithdrawableDtbDocr> values) {

                if (values != null && values.size() > 0) {
                    List<String> codMarts = Stream.of(values)
                            .map(DtbDocr::getCodMart)
                            .withoutNulls()
                            .distinct()
                            .toList();

                    ArticoloRESTConsumer.getByCodMartsStatic(codMarts, arts -> {

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

                                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);
                            }


                            if (onComplete != null) onComplete.run(values);
                        }

                    }, onFailed);

                } else {
                    if (onComplete != null) onComplete.run(values);
                }
            }

            @Override
            public void onFailed(Exception ex) {
                if (onFailed != null) onFailed.run(ex);
            }
        });
    }

}
