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

import android.text.TextUtils;
import android.util.Log;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;

import it.integry.integrywmsnative.BuildConfig;
import it.integry.integrywmsnative.core.CommonConst;
import it.integry.integrywmsnative.core.REST.RESTBuilder;
import it.integry.integrywmsnative.core.REST.model.AvailableCodMdepsDTO;
import it.integry.integrywmsnative.core.REST.model.MailRequestDTO;
import it.integry.integrywmsnative.core.REST.model.NativeSqlRequestDTO;
import it.integry.integrywmsnative.core.REST.model.ServiceRESTResponse;
import it.integry.integrywmsnative.core.expansion.RunnableArgs;
import it.integry.integrywmsnative.core.model.Azienda;
import it.integry.integrywmsnative.core.model.MtbColt;
import it.integry.integrywmsnative.core.settings.SettingsManager;
import it.integry.integrywmsnative.core.utility.UtilityLogger;
import it.integry.integrywmsnative.core.utility.UtilityString;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

public class SystemRESTConsumer extends _BaseRESTConsumer {

    public static <T> void processSql(String nativeSql, final Type clazz, final ISimpleOperationCallback<T> callback) {

        NativeSqlRequestDTO nativeSqlDTO = new NativeSqlRequestDTO();
        nativeSqlDTO.nativeSql = nativeSql;

        SystemRESTConsumerService service = RESTBuilder.getService(SystemRESTConsumerService.class);
        service.processSql(nativeSqlDTO).enqueue(new Callback<ServiceRESTResponse<Object>>() {
            @Override
            public void onResponse(Call<ServiceRESTResponse<Object>> call, Response<ServiceRESTResponse<Object>> response) {
                analyzeAnswer(response, "ProcessSql", new ISimpleOperationCallback<Object>() {
                    @Override
                    public void onSuccess(Object value) {
                        Gson gson = new Gson();
                        String json = gson.toJson(value);

                        InputStream ims  = new ByteArrayInputStream(json.getBytes());
                        Reader reader = new InputStreamReader(ims);
                        T gsonObj = gson.fromJson(reader, clazz);

                        callback.onSuccess(gsonObj);
                    }

                    @Override
                    public void onFailed(Exception ex) {
                        callback.onFailed(ex);
                    }
                });
            }

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

    }


    public static void getAvailableProfiles(final ISimpleOperationCallback<List<String>> callback){

        SystemRESTConsumerService service = RESTBuilder.getService(SystemRESTConsumerService.class);
        service.getAvailableProfiles(SettingsManager.i().user.username, SettingsManager.i().user.password).enqueue(new Callback<ServiceRESTResponse<List<String>>>() {
            @Override
            public void onResponse(Call<ServiceRESTResponse<List<String>>> call, Response<ServiceRESTResponse<List<String>>> response) {
                analyzeAnswer(response, "ProfilesAvailable", callback);
            }

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


    }





    public static void getAvailableCodMdeps(final ISimpleOperationCallback<List<AvailableCodMdepsDTO>> callback){

        SystemRESTConsumerService service = RESTBuilder.getService(SystemRESTConsumerService.class);
        service.getAvailableCodMdeps().enqueue(new Callback<ServiceRESTResponse<List<AvailableCodMdepsDTO>>>() {
            @Override
            public void onResponse(Call<ServiceRESTResponse<List<AvailableCodMdepsDTO>>> call, Response<ServiceRESTResponse<List<AvailableCodMdepsDTO>>> response) {
                analyzeAnswer(response, "CodMdepsAvailable", callback);
            }

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


    public static void sendErrorLogMail(String message) {
        sendErrorLogMail(message, null, null);
    }


    public static void sendErrorLogMail(String message, Runnable onComplete, RunnableArgs<Exception> onFailed) {

        String currentAzienda = UtilityString.isNullOrEmpty(SettingsManager.i().userSession.profileDB) ? "" : " [" + SettingsManager.i().userSession.profileDB + "]";

        String dest = "";
        if(BuildConfig.DEBUG) {
            dest = TextUtils.join(";", CommonConst.Mail.forErrorsDebug);
        } else {
            dest = TextUtils.join(";", CommonConst.Mail.forErrors);
        }


        MailRequestDTO mailDTO = new MailRequestDTO()
                .setFrom("sender@integry.it")
                .setFromName((BuildConfig.DEBUG ? "[DEBUG] " : "") + "WMS Android")
                .setTo(dest)
                .setSubject("Bug notification" + currentAzienda)
                .setMsgText(message)
                .setHtml(true);

        sendMail(mailDTO, () -> {
            if(onComplete != null) onComplete.run();
        }, ex -> {
            Log.e(SystemRESTConsumer.class.getName(), "", ex);
            if(onFailed != null) onFailed.run(ex);
        });
    }


    public static void sendMail(MailRequestDTO mailDTO, Runnable onComplete, RunnableArgs<Exception> onFailed) {

        SystemRESTConsumerService service = RESTBuilder.getService(SystemRESTConsumerService.class);
        service.sendMail(mailDTO).enqueue(new Callback<ServiceRESTResponse<String>>() {
            @Override
            public void onResponse(Call<ServiceRESTResponse<String>> call, Response<ServiceRESTResponse<String>> response) {
                if(onComplete != null) onComplete.run();
            }

            @Override
            public void onFailure(Call<ServiceRESTResponse<String>> call, Throwable t) {
                if(onFailed != null) {
                    onFailed.run(new Exception(t));
                }
            }
        });
    }



    public static void getAzienda(RunnableArgs<Azienda> onComplete, RunnableArgs<Exception> onFailed) {

        String sql = "SELECT TOP 1 * FROM azienda";

        Type typeOfObjectsList = new TypeToken<ArrayList<Azienda>>() {}.getType();
        SystemRESTConsumer.processSql(sql, typeOfObjectsList, new ISimpleOperationCallback<List<Azienda>>() {
            @Override
            public void onSuccess(List<Azienda> value) {
                if(onComplete != null) onComplete.run(value.get(0));
            }

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

    }
}
