package cordova.plugin.netcontroll.integration.ifood;

import static android.app.Activity.RESULT_CANCELED;
import static android.app.Activity.RESULT_OK;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.Application;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Color;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Base64;
import android.util.Log;
import android.util.Printer;

import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaInterface;
import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.CordovaWebView;
import org.apache.cordova.PluginResult;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;

import cordova.plugin.netcontroll.integration.util.NetControllPrinter;

public class IfoodPOS {
    private Activity mActivity;
    private Context mContext;
    private CordovaInterface mCordova;
    private CordovaWebView mWebView;

    public void initialize(CordovaInterface cordova, CordovaWebView webView) {
        mActivity = cordova.getActivity();
        mContext = cordova.getActivity().getApplicationContext();
        mCordova = cordova;
        mWebView = webView;
    }

    public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
        String callbackContextMessageBase = "Result Ifood POS - " + action + ": ";
        if (action.equals("IniciarTransacao")) {
            JSONObject params = args.getJSONObject(0);
            try {
                JSONObject paymentParams = args.getJSONObject(0);
                paymentParams.put("sendResultInSameIntent", true);
                startPayment(paymentParams, callbackContext);
                return true;
            } catch (Exception error) {
                callbackContext.error(callbackContextMessageBase + "Error Detail: " + error);
            }
        } else if (action.equals("CancelarTransacao")) {
                JSONObject params = args.getJSONObject(0);
                try {
                    JSONObject paymentParams = args.getJSONObject(0);
                    paymentParams.put("sendResultInSameIntent", true);
                    startPaymentCancel(paymentParams, callbackContext);
                    return true;
                } catch (Exception error) {
                    callbackContext.error(callbackContextMessageBase + "Error Detail: " + error);
                }
        } else if (action.equals("ObterTokenImpressao")) {
            JSONObject params = args.getJSONObject(0);
            try {
                JSONObject paymentParams = args.getJSONObject(0);
                paymentParams.put("sendResultInSameIntent", true);
                getPrintToken(paymentParams, callbackContext);
                return true;
            } catch (Exception error) {
                callbackContext.error(callbackContextMessageBase + "Error Detail: " + error);
            }
        } else if (action.equals("ImpressaoTextoNetPrint")) {
            JSONObject params = args.getJSONObject(0);
            try {
                printBase64(params, callbackContext);
            } catch (Exception e) {
                callbackContext.error("ImpressaoTextoNetPrintImg error: " + e);
            }
            return true;
        }
        return false;
    }



    /**
     * Inicia o processo de pagamento com o Ifood
     */
    private void startPayment(JSONObject params, CallbackContext callbackContext) throws JSONException {
        // Extrair parâmetros
        String paymentMethod = params.optString("tipoPagamento", "");
        int value = params.optInt("valor", 0);
        String transactionId = params.optString("transactionId", "trans_" + System.currentTimeMillis());
        String tableId = params.optString("tableId", "");
        boolean printReceipt = params.optBoolean("imprimirComprovante", true);
        boolean sendResultInSameIntent = params.optBoolean("sendResultInSameIntent", true);

        // Verificar valor mínimo
        if (value <= 0) {
            callbackContext.error("Valor de pagamento inválido");
            return;
        }

        // Verificar tipo transação
        if (paymentMethod.isEmpty()) {
            callbackContext.error("Tipo de pagamento inválido");
            return;
        }

        // Criar objeto de pagamento
        JSONObject paymentObject = new JSONObject();
        paymentObject.put("paymentMethod", paymentMethod);
        paymentObject.put("value", value);
        paymentObject.put("tableId", tableId);
        paymentObject.put("transactionId", transactionId);
        paymentObject.put("printReceipt", printReceipt);

        // Definir URL de retorno para o próprio app
        String packageName = this.mActivity.getPackageName();
        String urlToReturn = "https://netcontroll.pdv.com/make-payment?content=";
        paymentObject.put("urlToReturn", urlToReturn);
        paymentObject.put("sendResultInSameIntent", sendResultInSameIntent);

        // Converter para Base64
        String paymentBase64 = Base64.encodeToString(
                paymentObject.toString().getBytes(StandardCharsets.UTF_8),
                Base64.NO_WRAP
        );

        // Construir a URL do deeplink
        String deeplinkUrl = "https://portal.ifood.com.br/make-payment?content=" + paymentBase64;

        // Abrir o deeplink
        Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(deeplinkUrl));
        
        CordovaPlugin transacao = new CordovaPlugin() {
            @Override
            public void onActivityResult(int requestCode, int resultCode, Intent data) {
                if (requestCode == 1234) {
                    if (resultCode == RESULT_OK && data != null) {
                        String mensagem = data.getExtras().getString("RESULT");
                        callbackContext.success(mensagem);
                    } else if (resultCode == RESULT_CANCELED) {
                        callbackContext.error("Operação cancelada pelo usuário");
                    }
                } else {
                    callbackContext.error("Resultado da transação não encontrado");
                }
            }
        };
        mCordova.startActivityForResult(transacao, intent, 1234);
    }

    /**
     * Inicia o processo de cancelamento com o Ifood
     */
    private void startPaymentCancel(JSONObject params, CallbackContext callbackContext) throws JSONException {
        // Extrair parâmetros

        String transactionIdAdyen = params.optString("transactionIdAdyen", "");
        boolean printReceipt = params.optBoolean("imprimirComprovante", true);
        boolean sendResultInSameIntent = params.optBoolean("sendResultInSameIntent", true);

        // Criar objeto de pagamento
        JSONObject paymentObject = new JSONObject();
        paymentObject.put("transactionIdAdyen", transactionIdAdyen);
        paymentObject.put("printReceipt", printReceipt);

        // Definir URL de retorno para o próprio app
        String packageName = this.mActivity.getPackageName();
        String urlToReturn = "https://netcontroll.pdv.com/make-refund?content=";
        paymentObject.put("urlToReturn", urlToReturn);
        paymentObject.put("sendResultInSameIntent", sendResultInSameIntent);

        // Converter para Base64
        String paymentBase64 = Base64.encodeToString(
                paymentObject.toString().getBytes(StandardCharsets.UTF_8),
                Base64.NO_WRAP
        );

        // Construir a URL do deeplink
        String deeplinkUrl = "https://portal.ifood.com.br/make-refund?content=" + paymentBase64;

        // Abrir o deeplink
        Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(deeplinkUrl));

        CordovaPlugin transacaoCancelar = new CordovaPlugin() {
            @Override
            public void onActivityResult(int requestCode, int resultCode, Intent data) {
                if (requestCode == 1234) {
                    if (resultCode == RESULT_OK && data != null) {
                        String mensagem = data.getExtras().getString("RESULT");
                        callbackContext.success(mensagem);
                    } else if (resultCode == RESULT_CANCELED) {
                        callbackContext.error("Operação cancelada pelo usuário");
                    }
                } else {
                    callbackContext.error("Resultado da transação não encontrado");
                }
            }
        };
        mCordova.startActivityForResult(transacaoCancelar, intent, 1234);
    }


    /**
     * Obtem o token de impressão com o Ifood
     */
    private void getPrintToken(JSONObject params, CallbackContext callbackContext) throws JSONException {
        // Extrair parâmetros

        String integrationApp = params.optString("integrationApp", "Xmenu");
        boolean sendResultInSameIntent = params.optBoolean("sendResultInSameIntent", true);

        // Criar objeto de pagamento
        JSONObject paymentObject = new JSONObject();
        paymentObject.put("integrationApp", integrationApp);

        // Definir URL de retorno para o próprio app
        String packageName = this.mActivity.getPackageName();
        String urlToReturn = "https://netcontroll.pdv.com/print-file?content=";
        paymentObject.put("urlToReturn", urlToReturn);
        paymentObject.put("sendResultInSameIntent", sendResultInSameIntent);

        // Converter para Base64
        String paymentBase64 = Base64.encodeToString(
                paymentObject.toString().getBytes(StandardCharsets.UTF_8),
                Base64.NO_WRAP
        );

        // Construir a URL do deeplink
        String deeplinkUrl = "https://portal.ifood.com.br/print-file?content=" + paymentBase64;

        // Abrir o deeplink
        Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(deeplinkUrl));

        CordovaPlugin transacaoCancelar = new CordovaPlugin() {
            @Override
            public void onActivityResult(int requestCode, int resultCode, Intent data) {
                if (requestCode == 1234) {
                    if (resultCode == RESULT_OK && data != null) {
                        String mensagem = data.getExtras().getString("RESULT");
                        callbackContext.success(mensagem);
                    } else if (resultCode == RESULT_CANCELED) {
                        callbackContext.error("Operação cancelada pelo usuário");
                    }
                } else {
                    callbackContext.error("Resultado da transação não encontrado");
                }
            }
        };
        mCordova.startActivityForResult(transacaoCancelar, intent, 1234);
    }

    /**
     * Imprimir img Base64 Ifood
     */
    private void printBase64(JSONObject params, CallbackContext callbackContext) throws JSONException {
        //Extrair Parâmetros
        try {

            String dados = params.getString("dados");
            Boolean negrito = false;
            try {
                negrito = false;
            }catch (Exception ex){
            }

            String html = cordova.plugin.netcontroll.integration.util.NetControllPrinter.ConverterTextoImpressoToHtmlIfood(dados, negrito);
            cordova.plugin.netcontroll.integration.util.NetControllPrinter.ConverterHtmlToBitmap(html, mContext, bitmapResult -> {
                String dadosImg = "";
                String authorizationHash = params.optString("authorizationHash", "");

                bitmapResult = convertTo1Bit(bitmapResult);
                dadosImg = cordova.plugin.netcontroll.integration.util.NetControllPrinter.ConverterBitmapToBase64(bitmapResult);

                // Verificar hash
                if (authorizationHash.isEmpty()) {
                    callbackContext.error("Token de autorização não informado!");
                    return;
                }

                // Verificar code64
                if (dadosImg.isEmpty()) {
                    callbackContext.error("Impresso não informado!");
                    return;
                }

                // Criar objeto de pagamento
                JSONObject paymentObject = new JSONObject();
                try {
                    paymentObject.put("authorizationHash", authorizationHash);
                    paymentObject.put("contentBase64", dadosImg);
                } catch (JSONException e) {
                    throw new RuntimeException(e);
                }

                try {
                    // URL da API
                    URL url = new URL("https://movilepay-api.ifood.com.br/ifoodpay/mobile/api/v1/print/file");

                    // Conexão HTTP
                    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                    conn.setRequestMethod("POST");
                    conn.setDoOutput(true);
                    conn.setRequestProperty("Content-Type", "application/json; charset=UTF-8");

                    // Corpo da requisição
                    String jsonInputString = paymentObject.toString();

                    // Enviar o body
                    try (OutputStream os = conn.getOutputStream()) {
                        byte[] input = jsonInputString.getBytes("utf-8");
                        os.write(input, 0, input.length);
                    }

                    // Verificar a resposta
                    int responseCode = conn.getResponseCode();
                    if (responseCode == HttpURLConnection.HTTP_OK) {
                        callbackContext.success("Impressão enviada com sucesso.");
                    } else {
                        callbackContext.error("Erro ao enviar para impressão.");
                    }

                    conn.disconnect();

                } catch (Exception e) {
                    callbackContext.error("Erro ao enviar para impressão.");
                }
            });
        } catch (Exception e) {
            callbackContext.error("Erro ao enviar para impressão.");
        }
    }

    /**
     * Converte bitmap para 1-bit (preto e branco puro)
     */
    private static Bitmap convertTo1Bit(Bitmap original) {
        int width = original.getWidth();
        int height = original.getHeight();
        
        // Cria bitmap monocromático
        Bitmap bitmap1Bit = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        
        int[] pixels = new int[width * height];
        original.getPixels(pixels, 0, width, 0, 0, width, height);
        
        // Threshold otimizado para texto
        int threshold = 128;
        
        for (int i = 0; i < pixels.length; i++) {
            int pixel = pixels[i];
            
            // Calcula luminância
            int r = Color.red(pixel);
            int g = Color.green(pixel);
            int b = Color.blue(pixel);
            int gray = (int)(0.299 * r + 0.587 * g + 0.114 * b);
            
            // Converte para preto ou branco puro
            pixels[i] = gray > threshold ? Color.WHITE : Color.BLACK;
        }
        
        bitmap1Bit.setPixels(pixels, 0, width, 0, 0, width, height);
        return bitmap1Bit;
    }
}