package com.agentui.desktop

import android.app.PendingIntent
import android.app.PictureInPictureParams
import android.app.RemoteAction
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.res.Configuration
import android.graphics.drawable.Icon
import android.os.Build
import android.os.Bundle
import android.util.Log
import android.util.Rational
import android.webkit.WebView
import androidx.activity.enableEdgeToEdge
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat

class MainActivity : TauriActivity() {

    companion object {
        private const val ACTION_PIP_MIC = "com.agentui.desktop.PIP_MIC"
        private const val ACTION_PIP_EXPAND = "com.agentui.desktop.PIP_EXPAND"
        private const val PIP_REQUEST_CODE_MIC = 2001
        private const val PIP_REQUEST_CODE_EXPAND = 2002
    }

    private var pendingRoute: String? = null
    private var pendingVoiceTerminal: String? = null

    private val pipReceiver = object : BroadcastReceiver() {
        override fun onReceive(context: Context, intent: Intent) {
            when (intent.action) {
                ACTION_PIP_MIC -> {
                    Log.d("AgentUI", "PiP mic button pressed")
                    // Launch voice command from PiP
                    val voiceIntent = Intent(context, VoiceCommandActivity::class.java).apply {
                        action = Intent.ACTION_VOICE_COMMAND
                        addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
                    }
                    startActivity(voiceIntent)
                }
                ACTION_PIP_EXPAND -> {
                    Log.d("AgentUI", "PiP expand button pressed")
                    // Bring app to foreground full-screen
                    val expandIntent = Intent(context, MainActivity::class.java).apply {
                        addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT or Intent.FLAG_ACTIVITY_SINGLE_TOP)
                    }
                    startActivity(expandIntent)
                }
            }
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        enableEdgeToEdge()
        super.onCreate(savedInstanceState)
        syncServerUrlToPrefs()
        injectSafeAreaInsets()
        handleWidgetIntent(intent)
        handleVoiceIntent(intent)
        registerPipReceiver()
    }

    override fun onDestroy() {
        super.onDestroy()
        try { unregisterReceiver(pipReceiver) } catch (_: Exception) {}
    }

    private fun registerPipReceiver() {
        val filter = IntentFilter().apply {
            addAction(ACTION_PIP_MIC)
            addAction(ACTION_PIP_EXPAND)
        }
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
            registerReceiver(pipReceiver, filter, RECEIVER_NOT_EXPORTED)
        } else {
            registerReceiver(pipReceiver, filter)
        }
    }

    /**
     * Enter PiP when user leaves the app (home button / swipe).
     */
    override fun onUserLeaveHint() {
        super.onUserLeaveHint()
        // Only enter PiP via voice command flow, not on regular minimize
    }

    override fun onPictureInPictureModeChanged(
        isInPictureInPictureMode: Boolean,
        newConfig: Configuration
    ) {
        super.onPictureInPictureModeChanged(isInPictureInPictureMode, newConfig)
        Log.d("AgentUI", "PiP mode changed: $isInPictureInPictureMode")
    }

    private fun enterPipIfSupported() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            try {
                val actions = buildPipActions()
                val builder = PictureInPictureParams.Builder()
                    .setAspectRatio(Rational(9, 16))
                    .setActions(actions)
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
                    builder.setAutoEnterEnabled(false)
                    builder.setSeamlessResizeEnabled(true)
                }
                enterPictureInPictureMode(builder.build())
            } catch (e: Exception) {
                Log.w("AgentUI", "Failed to enter PiP: $e")
            }
        }
    }

    private fun buildPipActions(): List<RemoteAction> {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) return emptyList()

        val actions = mutableListOf<RemoteAction>()

        // Mic button — launch voice command
        val micIntent = PendingIntent.getBroadcast(
            this, PIP_REQUEST_CODE_MIC,
            Intent(ACTION_PIP_MIC).setPackage(packageName),
            PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
        )
        actions.add(RemoteAction(
            Icon.createWithResource(this, android.R.drawable.ic_btn_speak_now),
            "Voice", "Send voice command",
            micIntent
        ))

        // Expand button — bring app to foreground
        val expandIntent = PendingIntent.getBroadcast(
            this, PIP_REQUEST_CODE_EXPAND,
            Intent(ACTION_PIP_EXPAND).setPackage(packageName),
            PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
        )
        actions.add(RemoteAction(
            Icon.createWithResource(this, android.R.drawable.ic_menu_view),
            "Open", "Open full app",
            expandIntent
        ))

        return actions
    }

    override fun onNewIntent(intent: android.content.Intent) {
        super.onNewIntent(intent)
        handleWidgetIntent(intent)
        handleVoiceIntent(intent)
    }

    override fun onResume() {
        super.onResume()
        syncServerUrlToPrefs()
        pendingRoute?.let { route ->
            pendingRoute = null
            navigateWebView(route)
        }
    }

    private fun handleWidgetIntent(intent: android.content.Intent?) {
        val terminalIndex = intent?.getIntExtra("terminalIndex", -1) ?: -1
        if (terminalIndex > 0) {
            val route = "/transcript-debug/$terminalIndex"
            Log.d("AgentUI", "Widget click → navigate to $route")
            pendingRoute = route
            navigateWebView(route)
        }
    }

    private fun handleVoiceIntent(intent: android.content.Intent?) {
        if (intent?.action == "com.agentui.desktop.VOICE_TERMINAL") {
            val sessionId = intent.getStringExtra("ephemeralSessionId") ?: return
            if (sessionId.isNotEmpty()) {
                Log.d("AgentUI", "Voice intent → open terminal $sessionId")
                pendingVoiceTerminal = sessionId
                // Don't call openVoiceTerminal here — WebView may not exist yet.
                // Instead, poll until the WebView is ready.
                pollForWebViewAndOpenTerminal(sessionId, 0)
            }
        }
    }

    /**
     * Retry finding the WebView up to ~3 seconds (15 attempts x 200ms).
     * Once found, inject JS to open floating transcript and enter PiP.
     */
    private fun pollForWebViewAndOpenTerminal(ephemeralSessionId: String, attempt: Int) {
        if (attempt > 15) {
            Log.w("AgentUI", "Gave up waiting for WebView after ${attempt} attempts")
            pendingVoiceTerminal = null
            return
        }

        val webView = try { findWebView(window.decorView) } catch (_: Exception) { null }

        if (webView != null) {
            val js = "window.__VOICE_OPEN_TERMINAL__ && window.__VOICE_OPEN_TERMINAL__('$ephemeralSessionId')"
            webView.evaluateJavascript(js, null)
            pendingVoiceTerminal = null
            Log.d("AgentUI", "Voice terminal JS dispatched (attempt $attempt): $ephemeralSessionId")

            // Enter PiP after the WebView has time to render
            webView.postDelayed({ enterPipIfSupported() }, 500)
        } else {
            Log.d("AgentUI", "WebView not ready (attempt $attempt), retrying in 200ms")
            window.decorView.postDelayed({
                pollForWebViewAndOpenTerminal(ephemeralSessionId, attempt + 1)
            }, 200)
        }
    }

    private fun navigateWebView(route: String) {
        try {
            val decorView = window.decorView
            val webView = findWebView(decorView)
            if (webView != null) {
                val js = "window.__WIDGET_NAVIGATE__ && window.__WIDGET_NAVIGATE__('$route') || (window.location.href = '$route')"
                webView.evaluateJavascript(js, null)
                pendingRoute = null
            }
        } catch (e: Exception) {
            Log.w("AgentUI", "Failed to navigate WebView: $e")
        }
    }

    private fun injectSafeAreaInsets() {
        val decorView = window.decorView
        ViewCompat.setOnApplyWindowInsetsListener(decorView) { view, insets ->
            val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
            val density = resources.displayMetrics.density
            val topPx = systemBars.top
            val bottomPx = systemBars.bottom
            val leftPx = systemBars.left
            val rightPx = systemBars.right
            val topDp = topPx / density
            val bottomDp = bottomPx / density
            val leftDp = leftPx / density
            val rightDp = rightPx / density
            val js = """
                document.documentElement.style.setProperty('--sat', '${topDp}px');
                document.documentElement.style.setProperty('--sab', '${bottomDp}px');
                document.documentElement.style.setProperty('--sal', '${leftDp}px');
                document.documentElement.style.setProperty('--sar', '${rightDp}px');
            """.trimIndent()
            try {
                val webView = view.findViewWithTag<WebView>("tauri_webview")
                    ?: view.findViewById<WebView>(android.R.id.content)?.let {
                        findWebView(it)
                    }
                webView?.evaluateJavascript(js, null)
                Log.d("AgentUI", "Injected safe-area: top=${topDp}dp bottom=${bottomDp}dp")
            } catch (e: Exception) {
                Log.w("AgentUI", "Failed to inject safe-area insets: $e")
            }
            ViewCompat.onApplyWindowInsets(view, insets)
        }
    }

    private fun findWebView(view: android.view.View): WebView? {
        if (view is WebView) return view
        if (view is android.view.ViewGroup) {
            for (i in 0 until view.childCount) {
                val found = findWebView(view.getChildAt(i))
                if (found != null) return found
            }
        }
        return null
    }

    private fun syncServerUrlToPrefs() {
        val url = ServerConfig.getServerUrl(this)
        Log.d("AgentUI", "syncServerUrlToPrefs: resolved url=$url")
    }
}
