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.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.ServiceRESTResponse;
import it.integry.integrywmsnative.core.expansion.RunnableArgs;
import it.integry.integrywmsnative.core.model.MtbColt;
import it.integry.integrywmsnative.core.utility.UtilityLogger;
import it.integry.integrywmsnative.core.utility.UtilityString;
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, final RunnableArgs<List<String>> onComplete, final RunnableArgs<Exception> onFailed) {
        PrinterRESTConsumerService printerService = RESTBuilder.getService(PrinterRESTConsumerService.class);
        printerService.getAvailablePrinters(codMdep).enqueue(new Callback<>() {
            @Override
            public void onResponse(Call<ServiceRESTResponse<List<String>>> call, Response<ServiceRESTResponse<List<String>>> response) {
                analyzeAnswer(response, "GetAvailablePrinters", printers -> {
                    onComplete.run(printers != null ? Stream.of(printers).withoutNulls().toList() : null);
                }, onFailed);
            }

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


    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.errorMe(new Exception(t));
                onFailed.run(new Exception(t));
            }
        });
    }

    public void printCollo(String printerName, MtbColt testataColloToPrint, int quantity, String reportName, Runnable onComplete, RunnableArgs<Exception> onFailed) {

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

        if (UtilityString.isNullOrEmpty(printerName)) {
            onFailed.run(new Exception("Nessuna stampante configurata: valore null"));
            return;
        }

        PrinterRESTConsumerService printerService = RESTBuilder.getService(PrinterRESTConsumerService.class);
        printerService.printCollo(
                printerName,
                testataColloToPrint.getDataColloS(),
                testataColloToPrint.getGestione(),
                testataColloToPrint.getSerCollo(),
                testataColloToPrint.getNumCollo(),
                quantity,
                reportName)

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

}
