package com.stand.standapp

import android.content.Intent
import android.os.Bundle
import android.view.KeyEvent
import androidx.appcompat.app.AppCompatActivity
import android.widget.FrameLayout
import org.mozilla.geckoview.GeckoResult
import org.mozilla.geckoview.GeckoRuntime
import org.mozilla.geckoview.GeckoSession
import org.mozilla.geckoview.GeckoSessionSettings
import org.mozilla.geckoview.GeckoView
import org.mozilla.geckoview.StorageController.ClearFlags
import org.mozilla.geckoview.WebRequestError
import timber.log.Timber

class MainActivity : AppCompatActivity() {

    companion object {
        private var instance: MainActivity? = null

        // 防止对话框堆叠
        @Volatile
        private var isConflictDialogShowing = false

        // 待显示的弹窗（instance 为 null 时暂存）
        @Volatile
        private var pendingDialog: Pair<String, String>? = null

        // 待执行的 JS 代码（由 bridge.js 轮询获取）
        @Volatile
        private var pendingJsCode: String? = null

        @JvmStatic
        fun executeJs(script: String) {
            Timber.tag("ExecuteJs").d(script)
            synchronized(pendingJsCode ?: Any()) {
                // 合并多次调用（用换行分隔）
                pendingJsCode = if (pendingJsCode != null) "$pendingJsCode;$script" else script
            }
        }

        @JvmStatic
        fun onPttLoginSuccess() {
            Timber.tag("MainActivity").d("onPttLoginSuccess called from Native")
            executeJs("onPttLoginSuccess()")
        }

        // 硬件按键触发
        @JvmStatic
        fun onHardwarePttDown() {
            Timber.tag("MainActivity").d("onHardwarePttDown triggered")
            instance?.runOnUiThread {
                instance?.pttInterface?.pttSpeakPlay()
                executeJs("onHardwarePttDown()")
            }
        }

        @JvmStatic
        fun onHardwarePttUp() {
            Timber.tag("MainActivity").d("onHardwarePttUp triggered")
            instance?.runOnUiThread {
                instance?.pttInterface?.pttSpeakRelease()
                executeJs("onHardwarePttUp()")
            }
        }

        @JvmStatic
        fun showPttConflictDialog() {
            Timber.tag("PTT").w("showPttConflictDialog: account conflict detected")
            if (isConflictDialogShowing) return
            isConflictDialogShowing = true
            instance?.runOnUiThread {
                val ctx = instance ?: return@runOnUiThread
                androidx.appcompat.app.AlertDialog.Builder(ctx)
                    .setTitle("账号冲突")
                    .setMessage("您的 PTT 账号已在其他设备登录，当前设备已被迫下线。\n请点击确认重启应用。")
                    .setCancelable(false)
                    .setPositiveButton("确认") { _, _ ->
                        com.stand.standapp.utils.AppKiller.killApp(ctx, restart = true)
                    }
                    .setOnDismissListener { isConflictDialogShowing = false }
                    .show()
            }
        }

        @JvmStatic
        fun showPttUpdateDialog(msg: String, title: String) {
            Timber.tag("PTT").w("showPttUpdateDialog: title=%s msg=%s", title, msg)
            if (isConflictDialogShowing) return
            val ctx = instance
            if (ctx == null) {
                pendingDialog = title to msg
                Timber.tag("PTT").d("Pending dialog stored (instance null): title=%s", title)
                return
            }
            isConflictDialogShowing = true
            ctx.runOnUiThread {
                androidx.appcompat.app.AlertDialog.Builder(ctx)
                    .setTitle(title)
                    .setMessage(msg)
                    .setCancelable(false)
                    .setPositiveButton("确认") { _, _ ->
                        com.stand.standapp.utils.AppKiller.killApp(ctx, restart = true)
                    }
                    .setOnDismissListener { isConflictDialogShowing = false }
                    .show()
            }
        }

        @JvmStatic
        fun showPendingDialogIfNeeded() {
            val pending = pendingDialog ?: return
            Timber.tag("PTT").d("Flushing pending dialog: %s", pending.second)
            pendingDialog = null
            showPttUpdateDialog(pending.second, pending.first)
        }

        // 获取并清除待执行的 JS 代码（由 bridge.js 轮询）
        @JvmStatic
        fun pollPendingJs(): String {
            synchronized(pendingJsCode ?: Any()) {
                val code = pendingJsCode ?: ""
                pendingJsCode = null
                return code
            }
        }
    }

    private var geckoSession: GeckoSession? = null
    private var geckoRuntime: GeckoRuntime? = null
    private var pttInterface: AndroidInterface? = null
    private var canGoBack = false
    private lateinit var geckoView: GeckoView

    private var officialMode = false
    private var loginData = ""

    private val mHandler = android.os.Handler(android.os.Looper.getMainLooper())
    private val TIMEOUT_MS = 10000L

    private val timeoutRunnable = Runnable {
        showErrorPage()
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        instance = this
        showPendingDialogIfNeeded()

        // 读取登录模式和数据
        officialMode = intent.getBooleanExtra("official_mode", false)
        loginData = intent.getStringExtra("login_data") ?: ""

        try {
            setContentView(R.layout.activity_main)

            geckoView = findViewById<GeckoView>(R.id.geckoView)
                    ?: return

            findViewById<android.widget.Button>(R.id.btn_retry)?.setOnClickListener {
                hideErrorPage()
                geckoSession?.reload()
                startTimeoutTimer()
            }

            // 创建 GeckoRuntime
            geckoRuntime = createGeckoRuntime()

            // 创建 AndroidInterface
            pttInterface = AndroidInterface(this)

            // 创建 GeckoSession 并配置（但不加载页面）
            val session = createSession()
            geckoSession = session
            geckoView.setSession(session)

            startTimeoutTimer()

            // 安装桥接扩展，等安装完成后再加载页面
            geckoRuntime?.webExtensionController?.installBuiltIn(
                "resource://android/assets/extensions/bridge/"
            )?.accept { extension ->
                Timber.tag("MainActivity").d("WebExtension installed: ${extension?.metaData?.name}")
                runOnUiThread {
                    val serverUrl = AppConfig.getServerUrl(this)
                    val finalUrl = if (officialMode) {
                        "$serverUrl/sysdispatch/home?t=${System.currentTimeMillis()}"
                    } else {
                        "$serverUrl/example/print_demo.html?t=${System.currentTimeMillis()}"
                    }
                    Timber.tag("MainActivity").d("Loading URL: $finalUrl (officialMode=$officialMode)")
                    session.loadUri(finalUrl)
                }
            }

            // 启动时检查更新
            UpdateManager(this).checkUpdate()

            // 👈 动态注入 Compose 容器，让 FloatingChatWidget 呈现在最上层！
            val composeView = androidx.compose.ui.platform.ComposeView(this).apply {
                setContent {
                    com.stand.standapp.ui.chat.FloatingChatWidget()
                }
            }
            findViewById<FrameLayout>(android.R.id.content)?.addView(
                composeView,
                FrameLayout.LayoutParams(
                    FrameLayout.LayoutParams.MATCH_PARENT,
                    FrameLayout.LayoutParams.MATCH_PARENT
                )
            )

        } catch (e: Exception) {
            Timber.tag("MainActivity").e(e, "Fatal Crash")
        }
    }

    private fun createGeckoRuntime(): GeckoRuntime {
        val runtime = GeckoRuntime.getDefault(this)
        runtime.settings.aboutConfigEnabled = true
        runtime.settings.consoleOutputEnabled = true
        // 强制清缓存，确保 JS/CSS 等资源获取最新版本
        try {
//            runtime.storageController.clearData(ClearFlags.ALL)
            Timber.tag("MainActivity").i("GeckoView cache cleared")
        } catch (e: Exception) {
            Timber.tag("MainActivity").w(e, "Failed to clear GeckoView cache")
        }
        return runtime
    }

    private fun createSession(): GeckoSession {
        val session = GeckoSession()
        val sessionSettings = session.settings

        // 配置 GeckoSession 设置（对应原 WebView settings）
        sessionSettings.allowJavascript = true
        sessionSettings.userAgentMode = GeckoSessionSettings.USER_AGENT_MODE_MOBILE

        val runtime = geckoRuntime ?: return session

        // 设置各种代理
        setupDelegates(session)

        // 打开会话
        session.open(runtime)

        return session
    }

    private fun setupDelegates(session: GeckoSession) {
        // NavigationDelegate - 处理页面加载错误
        session.navigationDelegate = object : GeckoSession.NavigationDelegate {
            override fun onLoadError(
                session: GeckoSession,
                uri: String?,
                error: WebRequestError
            ): GeckoResult<String>? {
                Timber.tag("MainActivity").e("Page load error: ${error.code} - ${error.category}")
                runOnUiThread { showErrorPage() }
                return null
            }

            override fun onCanGoBack(session: GeckoSession, canGoBack: Boolean) {
                this@MainActivity.canGoBack = canGoBack
            }

            override fun onCanGoForward(session: GeckoSession, canGoForward: Boolean) {
            }
        }

        // ProgressDelegate - 页面加载进度
        session.progressDelegate = object : GeckoSession.ProgressDelegate {
            override fun onPageStart(session: GeckoSession, url: String) {
                Timber.tag("MainActivity").d("Page started: $url")
            }

            override fun onPageStop(session: GeckoSession, success: Boolean) {
                Timber.tag("MainActivity").d("Page stopped, success: $success")
                // 正式界面模式下，页面加载完成后传递登录数据给前端
//                if (success && officialMode && loginData.isNotEmpty()) {
//                    // 延迟 500ms 确保 JS 上下文就绪
//                    mHandler.postDelayed({
//                        val escaped = loginData.replace("'", "\\'").replace("\n", "\\n")
//                        executeJs("if(window.appLogin){window.appLogin('$escaped');}")
//                        Timber.tag("MainActivity").d("Called appLogin with loginData")
//                    }, 500)
//                }
            }
        }

        // PromptDelegate - 处理 JS bridge 和 console 消息
        session.promptDelegate = object : GeckoSession.PromptDelegate {
            override fun onTextPrompt(
                session: GeckoSession,
                prompt: GeckoSession.PromptDelegate.TextPrompt
            ): GeckoResult<GeckoSession.PromptDelegate.PromptResponse>? {
                val message = prompt.message ?: ""

                if (message.startsWith("bridge:")) {
                    // JS bridge 消息
                    val payload = message.substring(7)
                    if (payload == "_poll") {
                        // 轮询待执行的 JS 代码
                        val code = pollPendingJs()
                        return GeckoResult.fromValue(prompt.confirm(code))
                    }
                    val result = handleBridgeCall(payload, prompt.defaultValue ?: "")
                    return GeckoResult.fromValue(prompt.confirm(result))
                }
                
                // 默认处理（显示对话框）
                val res = GeckoResult<GeckoSession.PromptDelegate.PromptResponse>()
                runOnUiThread {
                    val input = android.widget.EditText(this@MainActivity)
                    input.setText(prompt.defaultValue)
                    androidx.appcompat.app.AlertDialog.Builder(this@MainActivity)
                        .setTitle(prompt.title ?: "")
                        .setMessage(prompt.message)
                        .setView(input)
                        .setPositiveButton("确定") { _, _ -> res.complete(prompt.confirm(input.text.toString())) }
                        .setNegativeButton("取消") { _, _ -> res.complete(prompt.dismiss()) }
                        .setOnCancelListener { res.complete(prompt.dismiss()) }
                        .show()
                }
                return res
            }

            override fun onAlertPrompt(
                session: GeckoSession,
                prompt: GeckoSession.PromptDelegate.AlertPrompt
            ): GeckoResult<GeckoSession.PromptDelegate.PromptResponse>? {
                val res = GeckoResult<GeckoSession.PromptDelegate.PromptResponse>()
                runOnUiThread {
                    androidx.appcompat.app.AlertDialog.Builder(this@MainActivity)
                        .setMessage(prompt.message)
                        .setPositiveButton("确定") { _, _ -> res.complete(prompt.dismiss()) }
                        .setOnCancelListener { res.complete(prompt.dismiss()) }
                        .show()
                }
                return res
            }

            override fun onAuthPrompt(
                session: GeckoSession,
                prompt: GeckoSession.PromptDelegate.AuthPrompt
            ): GeckoResult<GeckoSession.PromptDelegate.PromptResponse>? {
                return null
            }

            override fun onChoicePrompt(
                session: GeckoSession,
                prompt: GeckoSession.PromptDelegate.ChoicePrompt
            ): GeckoResult<GeckoSession.PromptDelegate.PromptResponse>? {
                val res = GeckoResult<GeckoSession.PromptDelegate.PromptResponse>()
                runOnUiThread {
                    val choices = prompt.choices.map { it.label }.toTypedArray()
                    androidx.appcompat.app.AlertDialog.Builder(this@MainActivity)
                        .setTitle(prompt.title)
                        .setSingleChoiceItems(choices, -1) { dialog, which ->
                            dialog.dismiss()
                            res.complete(prompt.confirm(prompt.choices[which]))
                        }
                        .setOnCancelListener { res.complete(prompt.dismiss()) }
                        .show()
                }
                return res
            }

            override fun onButtonPrompt(
                session: GeckoSession,
                prompt: GeckoSession.PromptDelegate.ButtonPrompt
            ): GeckoResult<GeckoSession.PromptDelegate.PromptResponse>? {
                val res = GeckoResult<GeckoSession.PromptDelegate.PromptResponse>()
                runOnUiThread {
                    androidx.appcompat.app.AlertDialog.Builder(this@MainActivity)
                        .setTitle(prompt.title ?: "提示")
                        .setMessage(prompt.message)
                        .setPositiveButton("确定") { _, _ -> res.complete(prompt.confirm(GeckoSession.PromptDelegate.ButtonPrompt.Type.POSITIVE)) }
                        .setNegativeButton("取消") { _, _ -> res.complete(prompt.dismiss()) }
                        .setOnCancelListener { res.complete(prompt.dismiss()) }
                        .show()
                }
                return res
            }
        }
    }

    private fun handleBridgeCall(method: String, argsJson: String): String {
        return try {
            pttInterface?.dispatch(method, argsJson) ?: ""
        } catch (e: Exception) {
            Timber.tag("Bridge").e(e, "Bridge call failed: $method")
            "{\"error\":\"${e.message}\"}"
        }
    }

    fun getGeckoSession(): GeckoSession? {
        return geckoSession
    }

    fun getAndroidInterface(): AndroidInterface? {
        return pttInterface
    }

    fun showExitDialog() {
        executeJs("addExitText()")

        androidx.appcompat.app.AlertDialog.Builder(this)
            .setTitle("提示")
            .setMessage("确定要退出应用吗？")
            .setPositiveButton("确定") { _, _ ->
                com.stand.standapp.utils.AppKiller.killApp(this)
            }
            .setNegativeButton("取消", null)
            .show()
    }

    private fun pttLogoutAndDestroy() {
        try {
            com.example.kingway.ptt.SendAtUtil.toCancelLogin()
        } catch (e: Exception) {
            Timber.tag("LoginActivity").e(e, "PTT cancel failed")
        }
        try {
            com.example.kingway.ptt.SendAtUtil.toLogout()
            Timber.tag("LoginActivity").i("PTT logout sent")
        } catch (e: Exception) {
            Timber.tag("LoginActivity").e(e, "PTT logout failed")
        }
        try {
            com.stand.standapp.utils.GpioManager.stopListening()
        } catch (e: Exception) {
            Timber.tag("MainActivity").e(e, "GPIO stop failed")
        }
        try {
            com.stand.standapp.utils.GpioManager.stopListening()
        } catch (e: Exception) {
            Timber.tag("LoginActivity").e(e, "GPIO stop failed")
        }
        try {
//            com.example.kingway.ptt.MyApplication.destroy()
            Timber.tag("LoginActivity").i("PTT native destroyed")
        } catch (e: Exception) {
            Timber.tag("LoginActivity").e(e, "PTT destroy failed")
        }
        try {
//            PrinterManager.shutdown()
            Timber.tag("LoginActivity").i("Printer shut down")
        } catch (e: Exception) {
            Timber.tag("LoginActivity").e(e, "Printer shutdown failed")
        }
        try {
            com.stand.standapp.utils.LogManager.shutdown()
            Timber.tag("LoginActivity").i("LogManager shut down")
        } catch (e: Exception) {
            Timber.tag("LoginActivity").e(e, "LogManager shutdown failed")
        }
    }

    override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            val session = geckoSession
            if (canGoBack && session != null) {
                session.goBack()
                return true
            }
            showExitDialog()
            return true
        }
        return super.onKeyDown(keyCode, event)
    }

    override fun onDestroy() {
        cancelTimeoutTimer()
        geckoView.releaseSession()
        geckoSession?.close()
        geckoSession = null
        instance = null
        super.onDestroy()
    }

    private fun startTimeoutTimer() {
        cancelTimeoutTimer()
        mHandler.postDelayed(timeoutRunnable, TIMEOUT_MS)
    }

    fun cancelTimeoutTimer() {
        mHandler.removeCallbacks(timeoutRunnable)
    }

    fun isOfficialMode(): Boolean = officialMode

    fun getLoginData(): String = loginData

    private fun showErrorPage() {
        findViewById<android.view.View>(R.id.loading_layout)?.visibility = android.view.View.GONE
        findViewById<android.view.View>(R.id.error_layout)?.visibility = android.view.View.VISIBLE
    }

    private fun hideErrorPage() {
        findViewById<android.view.View>(R.id.error_layout)?.visibility = android.view.View.GONE
        findViewById<android.view.View>(R.id.loading_layout)?.visibility = android.view.View.VISIBLE
    }
}
