package com.ariacockpit

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.os.Build
import android.os.IBinder
import android.os.PowerManager
import android.util.Log
import androidx.core.app.NotificationCompat

/**
 * Foreground-Service der den App-Prozess waehrend TTS-Wiedergabe am Leben
 * haelt — Android killt sonst den Prozess sobald die App im Hintergrund ist
 * und ARIA verstummt mitten im Satz.
 *
 * Notification ist persistent (ongoing) waehrend der Service laeuft.
 * Tap auf die Notification bringt MainActivity zurueck nach vorne.
 *
 * foregroundServiceType="mediaPlayback" ist Pflicht ab Android 14, sonst
 * wirft startForeground() eine SecurityException.
 */
class AriaPlaybackService : Service() {
    companion object {
        private const val TAG = "AriaPlaybackService"
        private const val CHANNEL_ID = "aria_playback"
        private const val NOTIFICATION_ID = 1042
        const val EXTRA_REASON = "reason"  // "tts" | "wake" | "rec" | ""
    }

    private var currentReason: String = ""

    // PARTIAL_WAKE_LOCK haelt die CPU wach solange der Foreground-Service
    // aktiv ist. Damit bleibt die JS-Bridge im Doze ansprechbar und die
    // gesamte Sprach-Pipeline (Wake → Aufnahme → POST → ARIA → TTS → wieder
    // Wake) laeuft durchgehend im Hintergrund. Ein einziger Lock fuer den
    // ganzen Foreground-Cycle, nicht pro Sub-Modul.
    private var wakeLock: PowerManager.WakeLock? = null

    override fun onCreate() {
        super.onCreate()
        ensureNotificationChannel()
        acquireWakeLock()
    }

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        val reason = intent?.getStringExtra(EXTRA_REASON) ?: ""
        currentReason = reason
        Log.i(TAG, "Foreground-Service start/update (reason=$reason)")
        // Falls der Lock zwischendurch released wurde (z.B. nach onCreate-
        // race oder OS-quirk), hier sicherheits-halber erneut anfordern.
        acquireWakeLock()
        try {
            startForeground(NOTIFICATION_ID, buildNotification(reason))
        } catch (e: Exception) {
            Log.e(TAG, "startForeground fehlgeschlagen", e)
            stopSelf()
        }
        // START_NOT_STICKY: wenn Android den Service killt, NICHT automatisch
        // wieder starten — die App entscheidet wann der Service noetig ist.
        return START_NOT_STICKY
    }

    override fun onDestroy() {
        releaseWakeLock()
        Log.i(TAG, "Foreground-Service gestoppt")
        super.onDestroy()
    }

    private fun acquireWakeLock() {
        if (wakeLock?.isHeld == true) return
        try {
            val pm = getSystemService(Context.POWER_SERVICE) as PowerManager
            wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
                                      "AriaCockpit:Pipeline").apply {
                setReferenceCounted(false)
                acquire(8 * 60 * 60 * 1000L)  // 8h Sicherheits-Cap
            }
            Log.i(TAG, "WakeLock acquired (CPU bleibt wach im Hintergrund)")
        } catch (e: Exception) {
            Log.w(TAG, "WakeLock acquire fehlgeschlagen: ${e.message}")
        }
    }

    private fun releaseWakeLock() {
        try {
            wakeLock?.takeIf { it.isHeld }?.release()
            if (wakeLock != null) Log.i(TAG, "WakeLock released")
        } catch (e: Exception) {
            Log.w(TAG, "WakeLock release fehlgeschlagen: ${e.message}")
        }
        wakeLock = null
    }

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

    private fun ensureNotificationChannel() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val nm = getSystemService(NotificationManager::class.java) ?: return
            if (nm.getNotificationChannel(CHANNEL_ID) == null) {
                val channel = NotificationChannel(
                    CHANNEL_ID,
                    "ARIA Audio-Wiedergabe",
                    NotificationManager.IMPORTANCE_LOW,
                ).apply {
                    description = "Notification waehrend ARIA spricht (haelt die App im Hintergrund am Leben)"
                    setShowBadge(false)
                }
                nm.createNotificationChannel(channel)
            }
        }
    }

    private fun buildNotification(reason: String): Notification {
        val launchIntent = Intent(this, MainActivity::class.java).apply {
            flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP
        }
        val pendingFlags = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
            PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
        else
            PendingIntent.FLAG_UPDATE_CURRENT
        val pendingIntent = PendingIntent.getActivity(this, 0, launchIntent, pendingFlags)

        val (title, body) = when (reason) {
            "tts"  -> "ARIA spricht" to "Antwort wird abgespielt — antippen oeffnet die App"
            "rec"  -> "ARIA hoert zu" to "Sprachaufnahme laeuft — antippen oeffnet die App"
            "wake" -> "ARIA bereit"   to "Wake-Word lauscht passiv — antippen oeffnet die App"
            else   -> "ARIA aktiv"    to "Hintergrund-Modus — antippen oeffnet die App"
        }

        return NotificationCompat.Builder(this, CHANNEL_ID)
            .setContentTitle(title)
            .setContentText(body)
            .setSmallIcon(R.mipmap.ic_launcher)
            .setContentIntent(pendingIntent)
            .setOngoing(true)
            .setShowWhen(false)
            .setPriority(NotificationCompat.PRIORITY_LOW)
            .setCategory(NotificationCompat.CATEGORY_SERVICE)
            .setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
            .build()
    }
}
