package com.gametime.watch.bridge

import android.Manifest
import android.app.Activity
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.content.Context
import android.content.pm.PackageManager
import android.os.Build
import android.util.Log
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import androidx.wear.ongoing.OngoingActivity
import androidx.wear.ongoing.Status
import com.gametime.watch.R

object WatchOngoingActivityController {
    private const val TAG = "GTWatchOngoing"
    private const val CHANNEL_ID = "gametime_watch_session"
    private const val CHANNEL_NAME = "Séance GameTime"
    private const val NOTIFICATION_ID = 9101
    private const val ONGOING_ACTIVITY_ID = 9101
    private const val REPUBLISH_INTERVAL_MS = 60000L
    private var lastAppliedKey: String? = null
    private var lastAppliedAtEpochMs = 0L

    fun update(context: Context, projection: Map<String, Any?>, activity: Activity?) {
        val phase = projection["phase"] as? String ?: "noActiveSession"
        val sessionId = projection["deviceSessionId"] as? String ?: ""
        if (phase == "noActiveSession" || sessionId.isBlank()) {
            cancel(context, force = phase == "noActiveSession")
            return
        }
        val key = ongoingKey(projection)
        val now = System.currentTimeMillis()
        if (key == lastAppliedKey && now - lastAppliedAtEpochMs < REPUBLISH_INTERVAL_MS) {
            return
        }
        if (!hasPostNotificationsPermission(context)) {
            Log.d(TAG, "skip ongoing activity: POST_NOTIFICATIONS not granted")
            return
        }
        lastAppliedKey = key
        lastAppliedAtEpochMs = now
        post(context, projection)
    }

    fun cancel(context: Context, force: Boolean = true) {
        if (!force && lastAppliedKey == null) {
            return
        }
        lastAppliedKey = null
        lastAppliedAtEpochMs = 0L
        NotificationManagerCompat.from(context).cancel(NOTIFICATION_ID)
    }

    private fun ongoingKey(projection: Map<String, Any?>): String {
        val phase = projection["phase"] as? String ?: "noActiveSession"
        val sessionId = projection["deviceSessionId"] as? String ?: ""
        val exerciseName = projection["exerciseName"] as? String ?: ""
        return "$sessionId|$phase|$exerciseName"
    }

    private fun post(context: Context, projection: Map<String, Any?>) {
        ensureNotificationChannel(context)
        val touchIntent = PendingIntent.getActivity(
            context,
            0,
            WatchBridgePlugin.openActiveSessionIntent(context),
            PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE,
        )
        val exerciseName = (projection["exerciseName"] as? String)
            ?.takeIf { it.isNotBlank() }
            ?: "Séance en cours"
        val status = Status.Builder()
            .addPart("activity", Status.TextPart(exerciseName))
            .addTemplate("#activity#")
            .build()
        val notificationBuilder = NotificationCompat.Builder(context, 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)

        OngoingActivity.Builder(context, NOTIFICATION_ID, notificationBuilder)
            .setOngoingActivityId(ONGOING_ACTIVITY_ID)
            .setStaticIcon(R.drawable.ic_ongoing_gt)
            .setTouchIntent(touchIntent)
            .setTitle("GameTime")
            .setStatus(status)
            .build()
            .apply(context)

        NotificationManagerCompat.from(context).notify(
            NOTIFICATION_ID,
            notificationBuilder.build(),
        )
    }

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

    private fun hasPostNotificationsPermission(context: Context): Boolean {
        return Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU ||
            context.checkSelfPermission(Manifest.permission.POST_NOTIFICATIONS) ==
            PackageManager.PERMISSION_GRANTED
    }
}
