package com.gametime.watch.bridge

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.ServiceInfo
import android.os.Build
import android.os.IBinder
import androidx.core.app.NotificationCompat
import androidx.core.app.ServiceCompat
import androidx.core.content.ContextCompat
import com.gametime.watch.R

internal class WatchHeartRateForegroundService : Service() {
    companion object {
        const val CHANNEL_ID = "gametime_watch_heart_rate"
        const val CHANNEL_NAME = "Collecte cardio GameTime"
        const val NOTIFICATION_ID = 9102
        const val EXTRA_EXERCISE_NAME = "exerciseName"
        private var lastCommandKey: String? = null
        private var serviceRequested = false

        fun start(context: Context, projection: Map<String, Any?>) {
            val sessionId = projection["deviceSessionId"] as? String ?: ""
            val phase = projection["phase"] as? String ?: "noActiveSession"
            if (sessionId.isBlank() || phase != "running") {
                stop(context, force = phase == "noActiveSession")
                return
            }
            val exerciseName = (projection["exerciseName"] as? String)
                ?.takeIf { it.isNotBlank() }
                ?: "Séance en cours"
            val key = "$sessionId|$phase|$exerciseName"
            if (serviceRequested && key == lastCommandKey) {
                return
            }
            serviceRequested = true
            lastCommandKey = key
            ContextCompat.startForegroundService(
                context,
                Intent(context, WatchHeartRateForegroundService::class.java)
                    .putExtra(EXTRA_EXERCISE_NAME, exerciseName),
            )
        }

        fun stop(context: Context, force: Boolean = false) {
            if (!force && !serviceRequested) {
                return
            }
            serviceRequested = false
            lastCommandKey = null
            context.stopService(Intent(context, WatchHeartRateForegroundService::class.java))
        }
    }

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

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        WatchBridgePlugin.attachApplicationContext(applicationContext)
        val exerciseName = intent
            ?.getStringExtra(EXTRA_EXERCISE_NAME)
            ?.takeIf { it.isNotBlank() }
            ?: "Séance en cours"
        ServiceCompat.startForeground(
            this,
            NOTIFICATION_ID,
            buildNotification(exerciseName),
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
                ServiceInfo.FOREGROUND_SERVICE_TYPE_HEALTH
            } else {
                0
            },
        )
        return START_STICKY
    }

    private fun buildNotification(exerciseName: String): Notification {
        ensureNotificationChannel()
        val touchIntent = PendingIntent.getActivity(
            this,
            0,
            WatchBridgePlugin.openActiveSessionIntent(this),
            PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE,
        )
        return NotificationCompat.Builder(this, CHANNEL_ID)
            .setSmallIcon(R.drawable.ic_ongoing_gt)
            .setContentTitle("GameTime")
            .setContentText(exerciseName)
            .setContentIntent(touchIntent)
            .setCategory(NotificationCompat.CATEGORY_STATUS)
            .setPriority(NotificationCompat.PRIORITY_LOW)
            .setOngoing(true)
            .setOnlyAlertOnce(true)
            .setShowWhen(false)
            .build()
    }

    private fun ensureNotificationChannel() {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
            return
        }
        val manager = getSystemService(NotificationManager::class.java)
        if (manager.getNotificationChannel(CHANNEL_ID) != null) {
            return
        }
        manager.createNotificationChannel(
            NotificationChannel(
                CHANNEL_ID,
                CHANNEL_NAME,
                NotificationManager.IMPORTANCE_LOW,
            ),
        )
    }
}
