package com.feelpay.app;

import com.getcapacitor.JSObject;
import com.getcapacitor.Plugin;
import com.getcapacitor.PluginCall;
import com.getcapacitor.PluginMethod;
import com.getcapacitor.annotation.CapacitorPlugin;
import com.google.android.gms.nearby.connection.ConnectionLifecycleCallback;
import com.google.android.gms.nearby.connection.ConnectionResolution;
import com.google.android.gms.nearby.connection.ConnectionsClient;
import com.google.android.gms.nearby.connection.Payload;
import com.google.android.gms.nearby.connection.PayloadCallback;
import com.google.android.gms.nearby.connection.PayloadTransferUpdate;
import com.google.android.gms.nearby.connection.Strategy;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.provider.Telephony;
import android.telephony.SmsMessage;
import android.util.Log;

import androidx.annotation.NonNull;

import com.google.android.gms.nearby.Nearby;

import java.nio.charset.StandardCharsets;


@CapacitorPlugin(name = "FeelNative")
public class FeelNativePlugin extends Plugin {

    private static final String TAG = "FeelNativePlugin";

    private final FeelNative implementation = new FeelNative();
    private BroadcastReceiver smsReceiver;
    private static final Strategy STRATEGY = Strategy.P2P_CLUSTER; // Use P2P_CLUSTER for M-N connections

    private static final String SERVICE_ID = "com.feelpay.io";
    private ConnectionsClient connectionsClient;
    private String advertisingData; // Store JSON string


    @Override
    public void load() {
        super.load();
        connectionsClient = Nearby.getConnectionsClient(getContext());
        // Register an IntentFilter for incoming SMS messages.
        IntentFilter filter = new IntentFilter("android.provider.Telephony.SMS_RECEIVED");
        smsReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                if ("android.provider.Telephony.SMS_RECEIVED".equals(intent.getAction())) {
                    // Retrieve SMS messages from the intent.
                    SmsMessage[] messages = Telephony.Sms.Intents.getMessagesFromIntent(intent);
                    if (messages != null) {
                        for (SmsMessage message : messages) {
                            // Prepare a JSObject with SMS details.
                            JSObject smsData = new JSObject();
                            smsData.put("body", message.getMessageBody());
                            smsData.put("address", message.getOriginatingAddress());
                            // Notify JS listeners of the new SMS event.
                            notifyListeners("smsReceived", smsData);
                        }
                    }
                }
            }
        };

        getContext().registerReceiver(smsReceiver, filter);

    }

    @PluginMethod
    public void print(PluginCall call) {
        String content = call.getString("data");
        String printerName = call.getString("printerName");
        String address = call.getString("address");
        try {
            implementation.print(content, printerName, address);
            call.resolve();
        } catch (Exception e) {
            call.reject("Failed to print", e);
        }
    }

    @PluginMethod
    public void getAllPrinters(PluginCall call) {
        try {
            String printersJson = implementation.getAllPrinters(getContext());  // Pass context
            JSObject result = new JSObject();
            result.put("printers", printersJson);
            call.resolve(result);
        } catch (Exception e) {
            call.reject("Failed to get printers", e);
        }
    }

    /**
     * Start advertising to find other devices
//     */
   @PluginMethod
    public void startAdvertising(PluginCall call) {
        String jsonData = call.getString("data"); // Get JSON string

        if (jsonData == null) {
            call.reject("Missing JSON data");
            return;
        }

        advertisingData = jsonData; // Store JSON data

        connectionsClient.startAdvertising(
                "DeviceName",
                SERVICE_ID,
                connectionLifecycleCallback,
                new com.google.android.gms.nearby.connection.AdvertisingOptions.Builder()
                        .setStrategy(STRATEGY)
                        .build()
        ).addOnSuccessListener(unused -> {
            call.resolve(new JSObject().put("status", "Advertising started"));
        }).addOnFailureListener(e -> {
            call.reject("Failed to start advertising", e);
        });
    }

    /**
     * Start discovering nearby devices
     */
    @PluginMethod
    public void startDiscovery(PluginCall call) {
        connectionsClient.startDiscovery(
                SERVICE_ID,
                endpointDiscoveryCallback,
                new com.google.android.gms.nearby.connection.DiscoveryOptions.Builder()
                        .setStrategy(STRATEGY)
                        .build()
        ).addOnSuccessListener(unused -> {
            JSObject res = new JSObject();
            res.put("status", "Discovery started");
            res.put("data", advertisingData);
            call.resolve(res);
        }).addOnFailureListener(e -> {
            call.reject("Failed to start discovery", e);
        });
    }

    /**
     * Send a message to a connected device
     */
    @PluginMethod
    public void sendMessage(PluginCall call) {
        String endpointId = call.getString("endpointId");
        String message = call.getString("message");

        if (endpointId == null || message == null) {
            call.reject("Missing endpointId or message");
            return;
        }

        Payload payload = Payload.fromBytes(message.getBytes(StandardCharsets.UTF_8));
        connectionsClient.sendPayload(endpointId, payload);
        call.resolve(new JSObject().put("status", "Message sent"));
    }

    /**
     * Disconnect from all devices
     */
    @PluginMethod
    public void stopAllConnections(PluginCall call) {
        connectionsClient.stopAllEndpoints();
        call.resolve(new JSObject().put("status", "All connections stopped"));
    }

    /**
     * Callback for discovering devices
     */
    private final com.google.android.gms.nearby.connection.EndpointDiscoveryCallback endpointDiscoveryCallback =
            new com.google.android.gms.nearby.connection.EndpointDiscoveryCallback() {
                @Override
                public void onEndpointFound(@NonNull String endpointId, @NonNull com.google.android.gms.nearby.connection.DiscoveredEndpointInfo info) {
                    Log.d(TAG, "Found endpoint: " + endpointId);
                    connectionsClient.requestConnection("DeviceName", endpointId, connectionLifecycleCallback);
                }

                @Override
                public void onEndpointLost(@NonNull String endpointId) {
                    Log.d(TAG, "Lost endpoint: " + endpointId);
                }
            };

    /**
     * Callback for handling connections
     */
    private final ConnectionLifecycleCallback connectionLifecycleCallback =
            new ConnectionLifecycleCallback() {
                @Override
                public void onConnectionInitiated(@NonNull String endpointId, @NonNull com.google.android.gms.nearby.connection.ConnectionInfo info) {
                    Log.d(TAG, "Connection initiated with: " + endpointId);
                    connectionsClient.acceptConnection(endpointId, payloadCallback);
                }
                @Override
                public void onConnectionResult(@NonNull String endpointId, @NonNull ConnectionResolution result) {
                    if (result.getStatus().isSuccess()) {
                        Log.d(TAG, "Connected to " + endpointId);

                        // Send the stored JSON data when a connection is established
                        if (advertisingData != null) {
                            Payload payload = Payload.fromBytes(advertisingData.getBytes(StandardCharsets.UTF_8));
                            connectionsClient.sendPayload(endpointId, payload);
                        }
                    } else {
                        Log.d(TAG, "Connection failed with " + endpointId);
                    }
                }


                @Override
                public void onDisconnected(@NonNull String endpointId) {
                    Log.d(TAG, "Disconnected from " + endpointId);
                }
            };

    /**
     * Callback for handling received messages
     */
    private final PayloadCallback payloadCallback = new PayloadCallback() {
        @Override
        public void onPayloadReceived(@NonNull String endpointId, @NonNull Payload payload) {
            if (payload.getType() == Payload.Type.BYTES) {
                String receivedMessage = new String(payload.asBytes(), StandardCharsets.UTF_8);
                Log.d(TAG, "Received message: " + receivedMessage);
            }
        }

        @Override
        public void onPayloadTransferUpdate(@NonNull String endpointId, @NonNull PayloadTransferUpdate update) {
            if (update.getStatus() == PayloadTransferUpdate.Status.SUCCESS) {
                Log.d(TAG, "Payload transfer successful");
            }
        }
    };



    @Override
    public void handleOnDestroy() {
        // Unregister the BroadcastReceiver when the plugin is destroyed.
        if (smsReceiver != null) {
            getContext().unregisterReceiver(smsReceiver);
        }
        connectionsClient.stopAllEndpoints();

        super.handleOnDestroy();
    }


}
