package de.hackernet.wireguardtv.ui

import android.app.Activity
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.ServiceConnection
import android.net.VpnService
import android.os.Bundle
import android.os.IBinder
import android.view.KeyEvent
import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContracts
import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.lifecycleScope
import de.hackernet.wireguardtv.R
import de.hackernet.wireguardtv.data.SettingsRepository
import de.hackernet.wireguardtv.data.TunnelRepository
import de.hackernet.wireguardtv.vpn.WireGuardTunnelService
import de.hackernet.wireguardtv.web.WebServerService
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch

/**
 * Haupt-Activity für WireGuard TV
 * Nutzt Leanback Fragments für TV-optimierte Navigation
 */
class MainActivity : FragmentActivity() {

    private lateinit var repository: TunnelRepository
    private lateinit var settingsRepository: SettingsRepository

    private var vpnService: WireGuardTunnelService? = null
    private var vpnBound = false

    // WebServer Service
    private var webServerService: WebServerService? = null
    private var webServerBound = false

    // VPN Permission Request
    private val vpnPermissionLauncher = registerForActivityResult(
        ActivityResultContracts.StartActivityForResult()
    ) { result ->
        if (result.resultCode == Activity.RESULT_OK) {
            // VPN Permission granted, try to connect again
            pendingTunnelId?.let { connectTunnel(it) }
        } else {
            Toast.makeText(this, "VPN-Berechtigung erforderlich", Toast.LENGTH_SHORT).show()
        }
        pendingTunnelId = null
    }

    private var pendingTunnelId: String? = null

    // VPN Service Connection
    private val vpnConnection = object : ServiceConnection {
        override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
            val binder = service as WireGuardTunnelService.LocalBinder
            vpnService = binder.getService()
            vpnBound = true
            observeVpnStatus()
        }

        override fun onServiceDisconnected(name: ComponentName?) {
            vpnService = null
            vpnBound = false
        }
    }

    // WebServer Service Connection
    private val webServerConnection = object : ServiceConnection {
        override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
            val binder = service as WebServerService.LocalBinder
            webServerService = binder.getService()
            webServerBound = true
            setupWebServerCallbacks()
            // UI aktualisieren wenn Service bereits läuft
            if (webServerService?.isServerRunning() == true) {
                val ip = webServerService?.getServerIpAddress()
                val port = webServerService?.getServerPort() ?: 8080
                (supportFragmentManager.findFragmentById(R.id.main_container) as? MainFragment)
                    ?.updateWebServerStatus(true, ip, port)
            }
        }

        override fun onServiceDisconnected(name: ComponentName?) {
            webServerService = null
            webServerBound = false
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        repository = TunnelRepository.getInstance(this)
        settingsRepository = SettingsRepository.getInstance(this)

        // Main Fragment laden
        if (savedInstanceState == null) {
            supportFragmentManager.beginTransaction()
                .replace(R.id.main_container, MainFragment())
                .commit()
        }

        // VPN Service binden
        bindVpnService()

        // WebServer Service binden (falls er bereits läuft vom Boot)
        bindWebServerService()

        // Autostart prüfen (nur wenn Service noch nicht läuft)
        checkWebServerAutoStart()
    }

    private fun checkWebServerAutoStart() {
        lifecycleScope.launch {
            val settings = settingsRepository.getSettings()
            if (settings.webServerAutoStart && !WebServerService.isRunning()) {
                startWebServer()
            }
        }
    }

    private fun bindWebServerService() {
        // Versuchen, an bereits laufenden Service zu binden
        Intent(this, WebServerService::class.java).also { intent ->
            bindService(intent, webServerConnection, Context.BIND_AUTO_CREATE)
        }
    }

    private fun setupWebServerCallbacks() {
        webServerService?.apply {
            onConfigReceived = { name, _ ->
                runOnUiThread {
                    Toast.makeText(
                        this@MainActivity,
                        "Config '$name' empfangen!",
                        Toast.LENGTH_LONG
                    ).show()
                    (supportFragmentManager.findFragmentById(R.id.main_container) as? MainFragment)
                        ?.refreshTunnelList()
                }
            }
            onStatusChanged = { running, ip, port ->
                runOnUiThread {
                    (supportFragmentManager.findFragmentById(R.id.main_container) as? MainFragment)
                        ?.updateWebServerStatus(running, ip, port)
                }
            }
            onConnectTunnel = { tunnelId ->
                runOnUiThread {
                    connectTunnel(tunnelId)
                }
            }
            onDisconnectTunnel = {
                runOnUiThread {
                    disconnectTunnel()
                }
            }
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        if (vpnBound) {
            unbindService(vpnConnection)
            vpnBound = false
        }
        if (webServerBound) {
            unbindService(webServerConnection)
            webServerBound = false
        }
        // Service NICHT stoppen - soll im Hintergrund weiterlaufen
    }

    private fun bindVpnService() {
        Intent(this, WireGuardTunnelService::class.java).also { intent ->
            bindService(intent, vpnConnection, Context.BIND_AUTO_CREATE)
        }
    }

    /**
     * Tunnel verbinden mit VPN Permission Check
     */
    fun connectTunnel(tunnelId: String) {
        val vpnIntent = VpnService.prepare(this)
        if (vpnIntent != null) {
            pendingTunnelId = tunnelId
            vpnPermissionLauncher.launch(vpnIntent)
        } else {
            // Permission already granted
            val intent = Intent(this, WireGuardTunnelService::class.java).apply {
                action = WireGuardTunnelService.ACTION_CONNECT
                putExtra(WireGuardTunnelService.EXTRA_TUNNEL_ID, tunnelId)
            }
            startService(intent)
        }
    }

    /**
     * Tunnel trennen
     */
    fun disconnectTunnel() {
        val intent = Intent(this, WireGuardTunnelService::class.java).apply {
            action = WireGuardTunnelService.ACTION_DISCONNECT
        }
        startService(intent)
    }

    /**
     * Webserver starten/stoppen
     */
    fun toggleWebServer() {
        if (isWebServerRunning()) {
            stopWebServer()
        } else {
            startWebServer()
        }
    }

    fun startWebServer() {
        val intent = Intent(this, WebServerService::class.java).apply {
            action = WebServerService.ACTION_START
        }
        startForegroundService(intent)

        // Toast kommt später über den Callback wenn Server gestartet ist
        lifecycleScope.launch {
            val settings = settingsRepository.getSettings()
            // Kurz warten bis Service gestartet ist
            kotlinx.coroutines.delay(500)
            if (webServerService == null) {
                // Falls noch nicht gebunden, neu binden
                bindWebServerService()
            }
        }
    }

    fun stopWebServer() {
        val intent = Intent(this, WebServerService::class.java).apply {
            action = WebServerService.ACTION_STOP
        }
        startService(intent)
        Toast.makeText(this, "Webserver gestoppt", Toast.LENGTH_SHORT).show()
    }

    fun isWebServerRunning(): Boolean = WebServerService.isRunning()

    fun getWebServerUrl(): String? = WebServerService.getServerUrl()

    private fun observeVpnStatus() {
        lifecycleScope.launch {
            vpnService?.status?.collectLatest { status ->
                // UI Update über Fragment
                (supportFragmentManager.findFragmentById(R.id.main_container) as? MainFragment)
                    ?.updateTunnelStatus(status)
            }
        }
    }

    /**
     * D-Pad Navigation Support
     */
    override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
        when (keyCode) {
            KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE -> {
                // Play/Pause als Toggle für aktiven Tunnel
                toggleActiveTunnel()
                return true
            }
            KeyEvent.KEYCODE_MENU -> {
                // Menü-Taste öffnet Einstellungen
                openSettings()
                return true
            }
        }
        return super.onKeyDown(keyCode, event)
    }

    private fun toggleActiveTunnel() {
        lifecycleScope.launch {
            if (vpnService?.isConnected() == true) {
                disconnectTunnel()
            } else {
                val activeTunnelId = repository.getActiveTunnelId()
                    ?: repository.getTunnels().firstOrNull()?.id
                activeTunnelId?.let { connectTunnel(it) }
            }
        }
    }

    private fun openSettings() {
        startActivity(Intent(this, SettingsActivity::class.java))
    }
}
