package de.hackernet.wireguardtv.web

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.Binder
import android.os.Build
import android.os.IBinder
import android.util.Log
import android.widget.Toast
import androidx.core.app.NotificationCompat
import de.hackernet.wireguardtv.R
import de.hackernet.wireguardtv.data.SettingsRepository
import de.hackernet.wireguardtv.ui.MainActivity
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.cancel
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking

/**
 * Foreground Service für den WebServer
 * Ermöglicht den Betrieb des Config-Upload Servers auch im Hintergrund
 * und beim System-Boot
 */
class WebServerService : Service() {

    private val binder = LocalBinder()
    private var webServer: ConfigWebServer? = null
    private val scope = CoroutineScope(SupervisorJob() + Dispatchers.IO)

    // Callbacks für UI-Updates
    var onConfigReceived: ((String, String) -> Unit)? = null
    var onStatusChanged: ((Boolean, String?, Int) -> Unit)? = null
    var onConnectTunnel: ((String) -> Unit)? = null
    var onDisconnectTunnel: (() -> Unit)? = null

    companion object {
        private const val TAG = "WebServerService"
        private const val NOTIFICATION_ID = 1338
        private const val CHANNEL_ID = "webserver_channel"

        const val ACTION_START = "de.hackernet.wireguardtv.WEBSERVER_START"
        const val ACTION_STOP = "de.hackernet.wireguardtv.WEBSERVER_STOP"

        @Volatile
        private var INSTANCE: WebServerService? = null

        fun getInstance(): WebServerService? = INSTANCE

        fun isRunning(): Boolean = INSTANCE?.webServer?.isRunning() == true

        fun getServerUrl(): String? {
            val instance = INSTANCE ?: return null
            val server = instance.webServer ?: return null
            return if (server.isRunning()) {
                "http://${server.getDeviceIpAddress()}:${server.getPort()}"
            } else null
        }
    }

    inner class LocalBinder : Binder() {
        fun getService(): WebServerService = this@WebServerService
    }

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

    override fun onCreate() {
        super.onCreate()
        INSTANCE = this
        createNotificationChannel()
        initWebServer()
        Log.i(TAG, "WebServerService created")
    }

    override fun onDestroy() {
        super.onDestroy()
        INSTANCE = null
        stopServer()
        scope.cancel()
        Log.i(TAG, "WebServerService destroyed")
    }

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        Log.i(TAG, "onStartCommand: action=${intent?.action}")

        when (intent?.action) {
            ACTION_START -> {
                scope.launch {
                    startServer()
                }
            }
            ACTION_STOP -> {
                stopServer()
                stopForeground(STOP_FOREGROUND_REMOVE)
                stopSelf()
            }
            else -> {
                // Default: Server starten (z.B. beim Boot)
                scope.launch {
                    startServer()
                }
            }
        }
        return START_STICKY
    }

    private fun initWebServer() {
        webServer = ConfigWebServer(this).apply {
            onConfigReceived = { name, content ->
                this@WebServerService.onConfigReceived?.invoke(name, content)
            }
            onStatusChanged = { running, ip, port ->
                this@WebServerService.onStatusChanged?.invoke(running, ip, port)
                if (running) {
                    updateNotification(ip, port)
                }
            }
            onConnectTunnel = { tunnelId ->
                this@WebServerService.onConnectTunnel?.invoke(tunnelId)
            }
            onDisconnectTunnel = {
                this@WebServerService.onDisconnectTunnel?.invoke()
            }
        }
    }

    private suspend fun startServer() {
        try {
            val settingsRepository = SettingsRepository.getInstance(this)
            val settings = settingsRepository.getSettings()

            webServer?.updateConfig(
                settings.webServerPort,
                settings.webServerPasswordEnabled,
                settings.webServerPassword
            )

            // Foreground Notification starten bevor der Server läuft
            val ip = webServer?.getDeviceIpAddress() ?: "?"
            startForeground(NOTIFICATION_ID, createNotification(ip, settings.webServerPort))

            webServer?.start()

            Log.i(TAG, "WebServer started on http://$ip:${settings.webServerPort}")
        } catch (e: Exception) {
            Log.e(TAG, "Failed to start WebServer: ${e.message}", e)
        }
    }

    private fun stopServer() {
        webServer?.stop()
        onStatusChanged?.invoke(false, null, 8080)
        Log.i(TAG, "WebServer stopped")
    }

    fun isServerRunning(): Boolean = webServer?.isRunning() == true

    fun getServerIpAddress(): String? = webServer?.getDeviceIpAddress()

    fun getServerPort(): Int = webServer?.getPort() ?: 8080

    fun restartServer() {
        scope.launch {
            stopServer()
            startServer()
        }
    }

    private fun createNotificationChannel() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val channel = NotificationChannel(
                CHANNEL_ID,
                "WebServer",
                NotificationManager.IMPORTANCE_LOW
            ).apply {
                description = "Web-Upload Server Status"
                setShowBadge(false)
            }

            val manager = getSystemService(NotificationManager::class.java)
            manager.createNotificationChannel(channel)
        }
    }

    private fun createNotification(ip: String?, port: Int): Notification {
        val intent = Intent(this, MainActivity::class.java)
        val pendingIntent = PendingIntent.getActivity(
            this, 0, intent,
            PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
        )

        val stopIntent = Intent(this, WebServerService::class.java).apply {
            action = ACTION_STOP
        }
        val stopPendingIntent = PendingIntent.getService(
            this, 1, stopIntent,
            PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
        )

        return NotificationCompat.Builder(this, CHANNEL_ID)
            .setContentTitle("Web-Upload Server")
            .setContentText("Aktiv auf http://$ip:$port")
            .setSmallIcon(R.drawable.ic_web)
            .setOngoing(true)
            .setContentIntent(pendingIntent)
            .addAction(
                R.drawable.ic_disconnect,
                "Stoppen",
                stopPendingIntent
            )
            .build()
    }

    private fun updateNotification(ip: String?, port: Int) {
        val manager = getSystemService(NotificationManager::class.java)
        manager.notify(NOTIFICATION_ID, createNotification(ip, port))
    }
}
