package su.reya.coop

import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.app.Service
import android.content.Intent
import android.content.pm.ServiceInfo
import android.os.Build
import android.os.IBinder
import android.util.Log
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import androidx.core.net.toUri
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.ProcessLifecycleOwner
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.cancel
import kotlinx.coroutines.launch
import su.reya.coop.nostr.NostrManager
import java.io.File

private const val GROUP_KEY_MESSAGES = "su.reya.coop.MESSAGES"

class NostrForegroundService : Service() {
    private val serviceScope = CoroutineScope(Dispatchers.IO + SupervisorJob())
    private val nostr by lazy { NostrManager.instance }
    private var notificationJob: Job? = null

    override fun onBind(intent: Intent?): IBinder? = null

    override fun onCreate() {
        super.onCreate()
        createNotificationChannel()
        startAsForeground()
    }

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        if (intent?.action == "STOP_SERVICE") {
            stopForeground(STOP_FOREGROUND_REMOVE)
            stopSelf()
            return START_NOT_STICKY
        }

        // Start the nostr service in the foreground
        startAsForeground()

        // Check if the service is already running
        if (notificationJob?.isActive == true) return START_STICKY

        // Start the Nostr client
        notificationJob = serviceScope.launch {
            try {
                Log.d("Coop", "Starting Nostr in background")

                // Create a database directory
                val dbDir = File(filesDir, "nostr")
                dbDir.mkdirs()

                // Initialize Nostr client
                try {
                    nostr.init(dbDir.absolutePath)
                } catch (e: Exception) {
                    throw IllegalStateException("Failed to initialize Nostr Client", e)
                }

                // Connect to bootstrap relays
                nostr.connectBootstrapRelays()

                // Handle notifications
                nostr.handleNotifications(
                    onMetadataUpdate = { pubkey, metadata ->
                        serviceScope.launch { nostr.profiles.emitMetadataUpdate(pubkey, metadata) }
                    },
                    onContactListUpdate = { contacts ->
                        serviceScope.launch { nostr.profiles.emitContactListUpdate(contacts) }
                    },
                    onNewMessage = { event ->
                        serviceScope.launch {
                            if (!isUserInApp()) {
                                showNewMessageNotification(event.roomId(), event.content())
                            }
                            nostr.emitNewEvent(event)
                        }
                    }
                )
            } catch (e: Exception) {
                Log.e("Coop", "Failed to start Nostr", e)
            }
        }

        return START_STICKY
    }

    private fun isUserInApp(): Boolean {
        return ProcessLifecycleOwner.get().lifecycle.currentState.isAtLeast(Lifecycle.State.STARTED)
    }

    private fun startAsForeground() {
        val notification = createNotification()
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
            startForeground(1, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_REMOTE_MESSAGING)
        } else {
            startForeground(1, notification)
        }
    }

    private fun getStopServicePendingIntent(): PendingIntent {
        val intent = Intent(this, NostrForegroundService::class.java).apply {
            action = "STOP_SERVICE"
        }
        return PendingIntent.getService(this, 0, intent, PendingIntent.FLAG_IMMUTABLE)
    }

    private fun createNotificationChannel() {
        val manager = getSystemService(NotificationManager::class.java)

        val serviceChannel = NotificationChannel(
            "nostr_service",
            "Nostr Background Status",
            NotificationManager.IMPORTANCE_MIN
        ).apply {
            setShowBadge(false)
        }
        manager?.createNotificationChannel(serviceChannel)

        val messageChannel = NotificationChannel(
            "nostr_messages",
            "New Messages",
            NotificationManager.IMPORTANCE_HIGH
        )
        manager?.createNotificationChannel(messageChannel)
    }

    private fun createNotification(content: String? = null): Notification {
        val builder = NotificationCompat.Builder(this, "nostr_service")
            .setGroup(GROUP_KEY_MESSAGES)
            .setSmallIcon(R.drawable.ic_notification)
            .setOngoing(true)
            .setPriority(NotificationCompat.PRIORITY_MIN)
            .setCategory(Notification.CATEGORY_SERVICE)
            .addAction(R.drawable.ic_notification, "Stop", getStopServicePendingIntent())

        if (content != null) {
            builder.setContentTitle("Coop")
            builder.setContentText(content)
        } else {
            builder.setContentTitle("Coop is active")
        }

        return builder.build()
    }

    private fun showNewMessageNotification(roomId: Long, message: String) {
        val deepLinkUri = "coop://chat/$roomId".toUri()

        val intent = Intent(
            Intent.ACTION_VIEW,
            deepLinkUri,
            this,
            MainActivity::class.java
        )

        val pendingIntent = PendingIntent.getActivity(
            this,
            roomId.toInt(),
            intent,
            PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
        )

        val notification = NotificationCompat.Builder(this, "nostr_messages")
            .setSmallIcon(R.drawable.ic_notification)
            .setContentTitle("You received a new message")
            .setContentText(message)
            .setAutoCancel(true)
            .setContentIntent(pendingIntent)
            .setCategory(Notification.CATEGORY_MESSAGE)
            .build()

        val manager = getSystemService(NotificationManager::class.java)
        manager?.notify(System.currentTimeMillis().toInt(), notification)
    }

    override fun onDestroy() {
        super.onDestroy()
        serviceScope.cancel()
    }

    override fun onTaskRemoved(rootIntent: Intent?) {
        super.onTaskRemoved(rootIntent)
        if (!NotificationManagerCompat.from(this).areNotificationsEnabled()) {
            Log.d("Coop", "Stopping service on task removed because notifications are disabled")
            stopForeground(STOP_FOREGROUND_REMOVE)
            stopSelf()
        }
    }
}
