package com.cloudflare.realtimekit;

import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ServiceInfo;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.IBinder;
import android.util.Log;

import androidx.core.app.NotificationCompat;

/**
 * Foreground service that keeps the app alive in the background during a
 * meeting.  Declares foreground service types CAMERA, MICROPHONE, and
 * MEDIA_PLAYBACK so Android does not kill the process while participants have
 * camera / microphone active or audio is playing.
 *
 * Lifecycle is managed from JS via RTKHelper.startMeetingService() and
 * RTKHelper.stopMeetingService(), which are called by LocalMediaHandler.
 */
public class KeepAliveService extends Service {

    private static final String TAG = "KeepAliveService";
    private static final int NOTIFICATION_ID = 42002;

    static final String ACTION_START =
            "com.cloudflare.realtimekit.KEEP_ALIVE_START";

    // Notification config — set by RTKHelperModule.startMeetingService() before launch().
    static volatile String sTitle       = "In a call";
    static volatile String sText        = "Tap to return to your meeting";
    static volatile String sChannelId   = "rtk_meeting";
    static volatile String sChannelName = "Ongoing Meeting";

    // -----------------------------------------------------------------------

    public static void launch(Context context,
                              String title,
                              String text,
                              String channelId,
                              String channelName) {
        sTitle       = title       != null ? title       : "In a call";
        sText        = text        != null ? text        : "Tap to return to your meeting";
        sChannelId   = channelId   != null ? channelId   : "rtk_meeting";
        sChannelName = channelName != null ? channelName : "Ongoing Meeting";

        Intent intent = new Intent(context, KeepAliveService.class);
        intent.setAction(ACTION_START);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            context.startForegroundService(intent);
        } else {
            context.startService(intent);
        }
    }

    public static void stop(Context context) {
        context.stopService(new Intent(context, KeepAliveService.class));
    }

    // -----------------------------------------------------------------------

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onTaskRemoved(Intent rootIntent) {
        // Stop when the user swipes the app away from recents.
        stopSelf();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if (intent == null) {
            return START_NOT_STICKY;
        }

        String action = intent.getAction();

        if (ACTION_START.equals(action)) {
            createNotificationChannel();
            Notification notification = buildNotification();
            try {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                    startForeground(NOTIFICATION_ID, notification,
                            ServiceInfo.FOREGROUND_SERVICE_TYPE_CAMERA
                            | ServiceInfo.FOREGROUND_SERVICE_TYPE_MICROPHONE
                            | ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK);
                } else {
                    startForeground(NOTIFICATION_ID, notification);
                }
            } catch (RuntimeException e) {
                Log.e(TAG, "startForeground failed, stopping service: " + e.getMessage());
                stopSelf();
            }
        }

        return START_NOT_STICKY;
    }

    // -----------------------------------------------------------------------

    private void createNotificationChannel() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationChannel channel = new NotificationChannel(
                    sChannelId, sChannelName, NotificationManager.IMPORTANCE_DEFAULT);
            channel.enableVibration(false);
            NotificationManager nm =
                    (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
            if (nm != null) {
                nm.createNotificationChannel(channel);
            }
        }
    }

    private Notification buildNotification() {
        Intent launchIntent = getPackageManager().getLaunchIntentForPackage(getPackageName());
        if (launchIntent == null) {
            launchIntent = new Intent();
        }

        PendingIntent pendingIntent;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
            pendingIntent = PendingIntent.getActivity(
                    this, 0, launchIntent, PendingIntent.FLAG_IMMUTABLE);
        } else {
            pendingIntent = PendingIntent.getActivity(
                    this, 0, launchIntent, PendingIntent.FLAG_UPDATE_CURRENT);
        }

        int appIconResId = android.R.mipmap.sym_def_app_icon;
        Bitmap largeIcon = null;
        try {
            PackageManager pm = getPackageManager();
            ApplicationInfo ai = pm.getApplicationInfo(getPackageName(), PackageManager.GET_META_DATA);
            appIconResId = ai.icon;
            Drawable drawable = ai.loadIcon(pm);
            if (drawable instanceof BitmapDrawable) {
                largeIcon = ((BitmapDrawable) drawable).getBitmap();
            }
        } catch (Exception e) {
            Log.w(TAG, "Failed to load app icon: " + e.getMessage());
        }

        NotificationCompat.Builder builder = new NotificationCompat.Builder(this, sChannelId)
                .setCategory(NotificationCompat.CATEGORY_CALL)
                .setContentTitle(sTitle)
                .setContentText(sText)
                .setPriority(NotificationCompat.PRIORITY_DEFAULT)
                .setContentIntent(pendingIntent)
                .setOngoing(true)
                .setAutoCancel(false)
                .setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
                .setOnlyAlertOnce(true)
                .setUsesChronometer(false)
                .setSmallIcon(appIconResId)
                .setForegroundServiceBehavior(NotificationCompat.FOREGROUND_SERVICE_IMMEDIATE);

        if (largeIcon != null) {
            builder.setLargeIcon(largeIcon);
        }

        return builder.build();
    }
}
