package it.integry.integrywmsnative.core.rest.consumers;

import android.util.Log;

import com.annimon.stream.Stream;

import java.util.HashMap;
import java.util.List;

import javax.inject.Singleton;

import it.integry.integrywmsnative.BuildConfig;
import it.integry.integrywmsnative.core.exception.NoPrintersFoundException;
import it.integry.integrywmsnative.core.expansion.RunnableArgs;
import it.integry.integrywmsnative.core.model.MtbColt;
import it.integry.integrywmsnative.core.report.ReportType;
import it.integry.integrywmsnative.core.rest.RESTBuilder;
import it.integry.integrywmsnative.core.rest.model.JasperDTO;
import it.integry.integrywmsnative.core.rest.model.JasperPairDTO;
import it.integry.integrywmsnative.core.rest.model.ReportTypeDTO;
import it.integry.integrywmsnative.core.rest.model.ServiceRESTResponse;
import it.integry.integrywmsnative.core.utility.UtilityLogger;
import it.integry.integrywmsnative.core.utility.UtilityString;
import it.integry.integrywmsnative.gest.spedizione.model.PrintOrderCloseDTO;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

@Singleton
public class PrinterRESTConsumer extends _BaseRESTConsumer {

    public enum Type {
        PRIMARIA,
        SECONDARIA
    }


    public void getAvailablePrinters(String codMdep, Type printerType, RunnableArgs<List<String>> onComplete, RunnableArgs<Exception> onFailed) {

        String printerTypeStr = printerType != null ? printerType.toString() : null;

        PrinterRESTConsumerService printerService = RESTBuilder.getService(PrinterRESTConsumerService.class);
        printerService.getAvailablePrinters(codMdep, printerTypeStr).enqueue(new Callback<>() {
            @Override
            public void onResponse(Call<ServiceRESTResponse<List<String>>> call, Response<ServiceRESTResponse<List<String>>> response) {
                analyzeAnswer(response, "GetAvailablePrinters", printerList -> {
                    printerList = Stream.of(printerList).filter(x -> !UtilityString.isNullOrEmpty(x)).toList();
                    onComplete.run(printerList);
                }, onFailed);
            }

            @Override
            public void onFailure(Call<ServiceRESTResponse<List<String>>> call, Throwable t) {
                Log.e("GetAvailablePrinters", t.toString());
                UtilityLogger.error(new Exception(t));
                onFailed.run(new Exception(t));
            }
        });
    }

    public void printCollo(MtbColt testataColloToPrint, Runnable onComplete, RunnableArgs<Exception> onFailed) {

        if (BuildConfig.DEBUG) {
            onComplete.run();
            return;
        }

        PrinterRESTConsumerService printerService = RESTBuilder.getService(PrinterRESTConsumerService.class);
        printerService
                .printCollo(testataColloToPrint)
                .enqueue(new Callback<>() {
                    @Override
                    public void onResponse(Call<ServiceRESTResponse<Object>> call, Response<ServiceRESTResponse<Object>> response) {
                        analyzeAnswer(response, "printCollo", data -> {
                            onComplete.run();
                        }, onFailed);
                    }

                    @Override
                    public void onFailure(Call<ServiceRESTResponse<Object>> call, Throwable t) {
                        if (t.getMessage().contains("Printer not found")) {
                            onFailed.run(new NoPrintersFoundException());
                        } else onFailed.run(new Exception(t));
                    }
                });
    }


    public void printReport(String printerName, String reportName, HashMap<String, Object> params, int quantity, Runnable onComplete, RunnableArgs<Exception> onFailed) {
        if (BuildConfig.DEBUG) {
            onComplete.run();
            return;
        }

        JasperDTO jasperDTO = new JasperDTO();
        jasperDTO.setReportName(reportName);

        Stream.of(params)
                .forEach(x -> jasperDTO.getParams().add(new JasperPairDTO(x.getKey(), x.getValue())));

        PrinterRESTConsumerService printerService = RESTBuilder.getService(PrinterRESTConsumerService.class);
        printerService
                .processPrintReport(printerName, quantity, jasperDTO)
                .enqueue(new Callback<>() {
                    @Override
                    public void onResponse(Call<ServiceRESTResponse<Object>> call, Response<ServiceRESTResponse<Object>> response) {
                        analyzeAnswer(response, "printReport", data -> {
                            onComplete.run();
                        }, onFailed);
                    }

                    @Override
                    public void onFailure(Call<ServiceRESTResponse<Object>> call, Throwable t) {
                        if (t.getMessage().contains("Printer not found")) {
                            onFailed.run(new NoPrintersFoundException());
                        } else onFailed.run(new Exception(t));
                    }
                });
    }

    public void printReportType(ReportType reportType, String codMdep, String codAnag, HashMap<String, Object> params, Runnable onComplete, RunnableArgs<Exception> onFailed) {

        ReportTypeDTO reportTypeDTO = new ReportTypeDTO();
        reportTypeDTO.setReportType(reportType);
        reportTypeDTO.setCodAnag(codAnag);
        reportTypeDTO.setCodMdep(codMdep);

        Stream.of(params)
                .forEach(x -> reportTypeDTO.getParams().add(new JasperPairDTO(x.getKey(), x.getValue())));

        PrinterRESTConsumerService printerService = RESTBuilder.getService(PrinterRESTConsumerService.class);
        printerService
                .printReportType(reportTypeDTO)
                .enqueue(new Callback<>() {
                    @Override
                    public void onResponse(Call<ServiceRESTResponse<Object>> call, Response<ServiceRESTResponse<Object>> response) {
                        analyzeAnswer(response, "printReportType", data -> {
                            onComplete.run();
                        }, onFailed);
                    }

                    @Override
                    public void onFailure(Call<ServiceRESTResponse<Object>> call, Throwable t) {
                        if (t.getMessage().contains("Printer not found")) {
                            onFailed.run(new NoPrintersFoundException());
                        } else onFailed.run(new Exception(t));
                    }
                });
    }

    public void printReportType(ReportType reportType, HashMap<String, Object> params, Runnable onComplete, RunnableArgs<Exception> onFailed) {
        printReportType(reportType, null, null, params, onComplete, onFailed);
    }

    public void printReportType(ReportType reportType, String codMdep, HashMap<String, Object> params, Runnable onComplete, RunnableArgs<Exception> onFailed) {
        printReportType(reportType, codMdep, null, params, onComplete, onFailed);
    }

    public void printClosedOrders(PrintOrderCloseDTO dto, String codMdep, Runnable onComplete, RunnableArgs<Exception> onFailed) {

        PrinterRESTConsumerService printerService = RESTBuilder.getService(PrinterRESTConsumerService.class, 240);
        Call<ServiceRESTResponse<Object>> callable = printerService.printClosedOrders(codMdep, dto);
        callable.enqueue(new Callback<>() {
            @Override
            public void onResponse(Call<ServiceRESTResponse<Object>> call, Response<ServiceRESTResponse<Object>> response) {
                analyzeAnswer(response, "printCollo", data -> {
                    onComplete.run();
                }, onFailed);
            }

            @Override
            public void onFailure(Call<ServiceRESTResponse<Object>> call, Throwable t) {
                if (t.getMessage().contains("Printer not found")) {
                    onFailed.run(new NoPrintersFoundException());
                } else onFailed.run(new Exception(t));
            }
        });
    }


}
