package top.yeij.cyrene.ui.screens.settings

import android.os.Build
import android.widget.Toast
import androidx.biometric.BiometricManager
import androidx.biometric.BiometricPrompt
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.clickable
import androidx.compose.foundation.combinedClickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ExperimentalLayoutApi
import androidx.compose.foundation.layout.FlowRow
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material.icons.automirrored.filled.Send
import androidx.compose.material.icons.filled.BatterySaver
import androidx.compose.material.icons.filled.Check
import androidx.compose.material.icons.filled.DarkMode
import androidx.compose.material.icons.filled.DeleteForever
import androidx.compose.material.icons.filled.LightMode
import androidx.compose.material.icons.filled.Palette
import androidx.compose.material.icons.filled.Security
import androidx.compose.material.icons.filled.SettingsBrightness
import androidx.compose.material.icons.filled.Share
import androidx.compose.material.icons.filled.Terminal
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.CenterAlignedTopAppBar
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.FilledTonalIconButton
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.ListItem
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Scaffold
import androidx.compose.material3.ScrollableTabRow
import androidx.compose.material3.Switch
import androidx.compose.material3.Tab
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Brush
import androidx.lifecycle.compose.LocalLifecycleOwner
import androidx.core.content.ContextCompat
import androidx.fragment.app.FragmentActivity
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.unit.dp
import kotlinx.coroutines.launch
import org.koin.compose.koinInject
import top.yeij.cyrene.ui.theme.PresetColorLabels
import top.yeij.cyrene.ui.theme.PresetThemeColors
import top.yeij.cyrene.util.KeepAliveManager
import top.yeij.cyrene.util.LogCategory
import top.yeij.cyrene.util.RootKeepAliveHelper
import top.yeij.cyrene.util.RuntimeLog
import top.yeij.cyrene.viewmodel.SettingsViewModel

@OptIn(ExperimentalMaterial3Api::class, androidx.compose.foundation.ExperimentalFoundationApi::class, ExperimentalLayoutApi::class)
@Composable
fun SettingsScreen(
    onBack: () -> Unit,
    onNavigateToKeepAlive: () -> Unit = {},
    viewModel: SettingsViewModel = koinInject(),
) {
    val baseUrl by viewModel.baseUrl.collectAsState()
    val themeMode by viewModel.themeMode.collectAsState()
    val wakeWord by viewModel.wakeWord.collectAsState()
    val dashScopeApiKey by viewModel.dashScopeApiKey.collectAsState()
    val dashScopeEndpoint by viewModel.dashScopeEndpoint.collectAsState()
    val dashScopeModel by viewModel.dashScopeModel.collectAsState()
    val autoScreenContext by viewModel.autoScreenContext.collectAsState()
    val typingIndicatorStyle by viewModel.typingIndicatorStyle.collectAsState()
    val themeColor by viewModel.themeColor.collectAsState()
    val enterToSend by viewModel.enterToSend.collectAsState()
    val rootKeepAlive by viewModel.rootKeepAlive.collectAsState()
    val context = LocalContext.current
    val scope = rememberCoroutineScope()

    fun sanitizeUrl(raw: String): String? {
        var url = raw.trim()
        if (url.isEmpty()) return null
        val hasScheme = url.contains("://")
        if (!hasScheme) url = "http://$url"
        return try {
            val parsed = java.net.URL(url)
            val host = parsed.host ?: return null
            if (host.isEmpty()) return null
            val scheme = parsed.protocol
            val port = if (parsed.port > 0) ":${parsed.port}" else ""
            val path = parsed.path?.trimEnd('/') ?: ""
            val query = parsed.query?.let { "?$it" } ?: ""
            "$scheme://$host$port$path$query"
        } catch (_: Exception) {
            null
        }
    }

    Scaffold(
        topBar = {
            CenterAlignedTopAppBar(
                title = { Text("设置") },
                navigationIcon = {
                    IconButton(onClick = onBack) {
                        Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = "返回")
                    }
                },
            )
        },
    ) { padding ->
        Column(
            modifier = Modifier
                .fillMaxSize()
                .padding(padding)
                .verticalScroll(rememberScrollState()),
        ) {
            // Server
            Text(
                text = "服务器",
                style = MaterialTheme.typography.labelLarge,
                color = MaterialTheme.colorScheme.primary,
                modifier = Modifier.padding(16.dp),
            )
            OutlinedTextField(
                value = baseUrl,
                onValueChange = { viewModel.updateBaseUrlInput(it) },
                label = { Text("服务器地址") },
                placeholder = { Text("http://192.168.1.x:8080") },
                singleLine = true,
                shape = MaterialTheme.shapes.medium,
                keyboardOptions = KeyboardOptions(
                    keyboardType = KeyboardType.Uri,
                    imeAction = ImeAction.Done,
                ),
                keyboardActions = KeyboardActions(
                    onDone = {
                        scope.launch {
                            val sanitized = sanitizeUrl(baseUrl)
                            if (sanitized != null) {
                                viewModel.saveBaseUrl(sanitized)
                                Toast.makeText(context, "地址已保存", Toast.LENGTH_SHORT).show()
                            }
                        }
                    },
                ),
                trailingIcon = {
                    FilledTonalIconButton(onClick = {
                        val sanitized = sanitizeUrl(baseUrl)
                        if (sanitized != null) {
                            viewModel.saveBaseUrl(sanitized)
                            Toast.makeText(context, "地址已保存", Toast.LENGTH_SHORT).show()
                        } else {
                            Toast.makeText(context, "地址格式无效", Toast.LENGTH_SHORT).show()
                        }
                    }) {
                        Icon(Icons.Filled.Check, contentDescription = "确认")
                    }
                },
                modifier = Modifier
                    .fillMaxWidth()
                    .padding(horizontal = 16.dp),
            )

            Spacer(modifier = Modifier.height(16.dp))
            HorizontalDivider()
            Spacer(modifier = Modifier.height(16.dp))

            // Appearance
            Text(
                text = "外观",
                style = MaterialTheme.typography.labelLarge,
                color = MaterialTheme.colorScheme.primary,
                modifier = Modifier.padding(16.dp),
            )

            val themeLabel = when (themeMode) {
                "light" -> "浅色模式"
                "dark" -> "深色模式"
                else -> "跟随系统"
            }
            val themeIcon = when (themeMode) {
                "light" -> Icons.Filled.LightMode
                "dark" -> Icons.Filled.DarkMode
                else -> Icons.Filled.SettingsBrightness
            }

            ListItem(
                headlineContent = { Text("主题") },
                supportingContent = { Text(themeLabel) },
                leadingContent = { Icon(themeIcon, contentDescription = null) },
                modifier = Modifier.clickable {
                    val next = when (themeMode) {
                        "light" -> "dark"
                        "dark" -> "auto"
                        else -> "light"
                    }
                    viewModel.saveThemeMode(next)
                },
            )

            var showColorDialog by remember { mutableStateOf(false) }
            val currentColorLabel = PresetColorLabels[themeColor] ?: "昔涟粉"

            ListItem(
                headlineContent = { Text("主题色") },
                supportingContent = { Text(currentColorLabel) },
                leadingContent = {
                    Box(
                        modifier = Modifier
                            .size(24.dp)
                            .background(
                                color = androidx.compose.ui.graphics.Color(
                                    (PresetThemeColors[themeColor]?.seed ?: 0xFFE91E8C).toInt()
                                ),
                                shape = CircleShape,
                            ),
                    )
                },
                modifier = Modifier.clickable { showColorDialog = true },
            )

            if (showColorDialog) {
                AlertDialog(
                    onDismissRequest = { showColorDialog = false },
                    title = { Text("选择主题色") },
                    text = {
                        Column {
                            // Monet option (Android 12+)
                            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) {
                                val isMonet = themeColor == "monet"
                                Row(
                                    modifier = Modifier
                                        .fillMaxWidth()
                                        .clickable {
                                            viewModel.saveThemeColor("monet")
                                            showColorDialog = false
                                        }
                                        .padding(vertical = 6.dp),
                                    verticalAlignment = Alignment.CenterVertically,
                                ) {
                                    Box(
                                        modifier = Modifier
                                            .size(36.dp)
                                            .background(
                                                brush = androidx.compose.ui.graphics.Brush.horizontalGradient(
                                                    listOf(
                                                        androidx.compose.ui.graphics.Color(0xFF4ECDC4),
                                                        androidx.compose.ui.graphics.Color(0xFFFF6B6B),
                                                        androidx.compose.ui.graphics.Color(0xFFFFE66D),
                                                        androidx.compose.ui.graphics.Color(0xFF45B7D1),
                                                    )
                                                ),
                                                shape = CircleShape,
                                            )
                                            .then(
                                                if (isMonet) Modifier.border(
                                                    3.dp,
                                                    MaterialTheme.colorScheme.primary,
                                                    CircleShape,
                                                ) else Modifier
                                            ),
                                    )
                                    Spacer(modifier = Modifier.width(12.dp))
                                    Text(
                                        text = "莫奈取色",
                                        style = MaterialTheme.typography.bodyMedium,
                                    )
                                    Spacer(modifier = Modifier.weight(1f))
                                    Text(
                                        text = "跟随壁纸",
                                        style = MaterialTheme.typography.bodySmall,
                                        color = MaterialTheme.colorScheme.onSurfaceVariant,
                                    )
                                }
                            }

                            // Preset color chips
                            FlowRow(
                                modifier = Modifier.padding(top = 8.dp),
                                horizontalArrangement = Arrangement.spacedBy(12.dp),
                                verticalArrangement = Arrangement.spacedBy(12.dp),
                            ) {
                                PresetThemeColors.keys.forEach { key ->
                                    val isSelected = themeColor == key
                                    val seedColor = androidx.compose.ui.graphics.Color(
                                        (PresetThemeColors[key]?.seed ?: 0xFFE91E8C).toInt()
                                    )
                                    val label = PresetColorLabels[key] ?: key

                                    Column(
                                        horizontalAlignment = Alignment.CenterHorizontally,
                                        modifier = Modifier
                                            .clickable {
                                                viewModel.saveThemeColor(key)
                                                showColorDialog = false
                                            }
                                            .padding(4.dp),
                                    ) {
                                        Box(
                                            modifier = Modifier
                                                .size(36.dp)
                                                .background(seedColor, CircleShape)
                                                .then(
                                                    if (isSelected) Modifier.border(
                                                        3.dp,
                                                        MaterialTheme.colorScheme.primary,
                                                        CircleShape,
                                                    ) else Modifier.border(
                                                        1.dp,
                                                        MaterialTheme.colorScheme.outlineVariant,
                                                        CircleShape,
                                                    )
                                                ),
                                        )
                                        Spacer(modifier = Modifier.height(4.dp))
                                        Text(
                                            text = label,
                                            style = MaterialTheme.typography.labelSmall,
                                            color = if (isSelected) MaterialTheme.colorScheme.primary
                                                    else MaterialTheme.colorScheme.onSurfaceVariant,
                                        )
                                    }
                                }
                            }
                        }
                    },
                    confirmButton = {
                        TextButton(onClick = { showColorDialog = false }) {
                            Text("关闭")
                        }
                    },
                )
            }

            val indicatorStyleLabel = if (typingIndicatorStyle == "text") "文字" else "气泡"
            ListItem(
                headlineContent = { Text("正在输入指示器") },
                supportingContent = { Text(indicatorStyleLabel) },
                leadingContent = { Icon(Icons.Filled.Palette, contentDescription = null) },
                modifier = Modifier.clickable {
                    val next = if (typingIndicatorStyle == "bubble") "text" else "bubble"
                    viewModel.saveTypingIndicatorStyle(next)
                },
            )

            ListItem(
                headlineContent = { Text("回车键发送") },
                supportingContent = { Text(if (enterToSend) "回车直接发送消息" else "回车换行") },
                leadingContent = { Icon(Icons.AutoMirrored.Filled.Send, contentDescription = null) },
                trailingContent = {
                    androidx.compose.material3.Switch(
                        checked = enterToSend,
                        onCheckedChange = { viewModel.saveEnterToSend(it) },
                    )
                },
                modifier = Modifier.clickable { viewModel.saveEnterToSend(!enterToSend) },
            )

            Spacer(modifier = Modifier.height(16.dp))
            HorizontalDivider()
            Spacer(modifier = Modifier.height(16.dp))

            // Background keep-alive
            val keepAliveManager = remember { KeepAliveManager(context) }
            var isBatteryExempt by remember { mutableStateOf(keepAliveManager.isBatteryOptimizationExempt()) }
            val lifecycleOwner = LocalLifecycleOwner.current

            // Re-check battery exemption when returning from system settings
            LaunchedEffect(lifecycleOwner) {
                lifecycleOwner.lifecycle.addObserver(object : androidx.lifecycle.DefaultLifecycleObserver {
                    override fun onResume(owner: androidx.lifecycle.LifecycleOwner) {
                        isBatteryExempt = keepAliveManager.isBatteryOptimizationExempt()
                    }
                })
            }

            // Hidden root toggle: tap section title 5 times to reveal
            var rootTapCount by remember { mutableIntStateOf(0) }
            var rootRevealed by remember { mutableStateOf(false) }

            Text(
                text = "后台保活",
                style = MaterialTheme.typography.labelLarge,
                color = MaterialTheme.colorScheme.primary,
                modifier = Modifier
                    .padding(16.dp)
                    .combinedClickable(
                        onClick = {
                            if (!rootRevealed) {
                                rootTapCount++
                                if (rootTapCount >= 5) {
                                    rootRevealed = true
                                    rootTapCount = 0
                                    Toast.makeText(context, "已解锁 Root 保活选项", Toast.LENGTH_SHORT).show()
                                }
                            }
                        },
                    ),
            )

            ListItem(
                headlineContent = { Text("忽略电池优化") },
                supportingContent = {
                    Text(
                        if (isBatteryExempt) "已允许，后台连接更稳定"
                        else "未允许，建议开启以确保消息推送及时送达"
                    )
                },
                leadingContent = {
                    Icon(
                        Icons.Filled.BatterySaver,
                        contentDescription = null,
                        tint = if (isBatteryExempt) MaterialTheme.colorScheme.primary
                               else MaterialTheme.colorScheme.error,
                    )
                },
                modifier = Modifier.clickable {
                    if (!isBatteryExempt) {
                        try {
                            context.startActivity(keepAliveManager.openBatteryOptimizationSettings())
                        } catch (_: Exception) {
                            Toast.makeText(context, "无法打开电池优化设置", Toast.LENGTH_SHORT).show()
                        }
                    }
                },
            )

            // Root-level keep-alive (hidden by default, revealed after 5 taps)
            if (rootRevealed) {
                val isRootAvailable = remember { RootKeepAliveHelper.isRootAvailable() }

                ListItem(
                    headlineContent = { Text("Root 保活 (隐藏)") },
                    supportingContent = {
                        Text(
                            if (!isRootAvailable) "未检测到 Root 权限"
                            else if (rootKeepAlive) "已启用 — 系统级白名单、Doze豁免、强制后台运行"
                            else "使用 Root 权限将应用加入系统级白名单，对抗任何保活限制"
                        )
                    },
                    leadingContent = {
                        Icon(
                            Icons.Filled.Terminal,
                            contentDescription = null,
                            tint = if (rootKeepAlive && isRootAvailable) MaterialTheme.colorScheme.tertiary
                                   else MaterialTheme.colorScheme.onSurfaceVariant,
                        )
                    },
                    trailingContent = {
                        Switch(
                            checked = rootKeepAlive,
                            enabled = isRootAvailable,
                            onCheckedChange = { enabled ->
                                if (enabled) {
                                    val success = RootKeepAliveHelper.applyRootKeepAlive(context.packageName)
                                    if (success) {
                                        viewModel.saveRootKeepAlive(true)
                                        Toast.makeText(context, "Root 保活已启用", Toast.LENGTH_SHORT).show()
                                    } else {
                                        Toast.makeText(context, "Root 保活应用失败，请检查 Root 权限", Toast.LENGTH_LONG).show()
                                    }
                                } else {
                                    RootKeepAliveHelper.removeRootKeepAlive(context.packageName)
                                    viewModel.saveRootKeepAlive(false)
                                    Toast.makeText(context, "Root 保活已关闭", Toast.LENGTH_SHORT).show()
                                }
                            },
                        )
                    },
                    modifier = Modifier.clickable(enabled = isRootAvailable) {
                        val newState = !rootKeepAlive
                        if (newState) {
                            val success = RootKeepAliveHelper.applyRootKeepAlive(context.packageName)
                            if (success) {
                                viewModel.saveRootKeepAlive(true)
                                Toast.makeText(context, "Root 保活已启用", Toast.LENGTH_SHORT).show()
                            } else {
                                Toast.makeText(context, "Root 保活应用失败", Toast.LENGTH_LONG).show()
                            }
                        } else {
                            RootKeepAliveHelper.removeRootKeepAlive(context.packageName)
                            viewModel.saveRootKeepAlive(false)
                            Toast.makeText(context, "Root 保活已关闭", Toast.LENGTH_SHORT).show()
                        }
                    },
                )

                // System wakelock toggle (held only while app is alive, reapplied on boot)
                var sysWakeLockHeld by remember { mutableStateOf(false) }
                ListItem(
                    headlineContent = { Text("系统级 WakeLock (隐藏)") },
                    supportingContent = {
                        Text(
                            if (!isRootAvailable) "需要 Root 权限"
                            else if (sysWakeLockHeld) "已持有系统级内核锁，CPU永不休眠"
                            else "写入 /sys/power/wake_lock 阻止 CPU 休眠"
                        )
                    },
                    leadingContent = {
                        Icon(
                            Icons.Filled.Security,
                            contentDescription = null,
                            tint = if (sysWakeLockHeld) MaterialTheme.colorScheme.error
                                   else MaterialTheme.colorScheme.onSurfaceVariant,
                        )
                    },
                    trailingContent = {
                        Switch(
                            checked = sysWakeLockHeld,
                            enabled = isRootAvailable,
                            onCheckedChange = { enable ->
                                if (enable) {
                                    val ok = RootKeepAliveHelper.acquireSystemWakeLock("CyreneKA")
                                    if (ok) {
                                        sysWakeLockHeld = true
                                        Toast.makeText(context, "系统 WakeLock 已持有 — 注意：将显著增加耗电", Toast.LENGTH_LONG).show()
                                    } else {
                                        Toast.makeText(context, "WakeLock 获取失败", Toast.LENGTH_SHORT).show()
                                    }
                                } else {
                                    val ok = RootKeepAliveHelper.releaseSystemWakeLock("CyreneKA")
                                    if (ok) {
                                        sysWakeLockHeld = false
                                        Toast.makeText(context, "系统 WakeLock 已释放", Toast.LENGTH_SHORT).show()
                                    } else {
                                        Toast.makeText(context, "WakeLock 释放失败", Toast.LENGTH_SHORT).show()
                                    }
                                }
                            },
                        )
                    },
                )
            }

            ListItem(
                headlineContent = { Text("保活设置") },
                supportingContent = { Text("前台服务、自启动管理、OEM厂商后台白名单") },
                leadingContent = { Icon(Icons.Filled.Security, contentDescription = null) },
                modifier = Modifier.clickable { onNavigateToKeepAlive() },
            )

            Spacer(modifier = Modifier.height(16.dp))
            HorizontalDivider()
            Spacer(modifier = Modifier.height(16.dp))

            // Voice
            Text(
                text = "语音",
                style = MaterialTheme.typography.labelLarge,
                color = MaterialTheme.colorScheme.primary,
                modifier = Modifier.padding(16.dp),
            )

            OutlinedTextField(
                value = wakeWord,
                onValueChange = { viewModel.saveWakeWord(it) },
                label = { Text("唤醒词") },
                modifier = Modifier
                    .fillMaxWidth()
                    .padding(horizontal = 16.dp),
                shape = MaterialTheme.shapes.medium,
            )

            Spacer(modifier = Modifier.height(8.dp))

            ListItem(
                headlineContent = { Text("自动读取屏幕内容") },
                supportingContent = { Text("电源键唤起助手时自动截取当前屏幕内容并加入对话上下文") },
                trailingContent = {
                    androidx.compose.material3.Switch(
                        checked = autoScreenContext,
                        onCheckedChange = { viewModel.saveAutoScreenContext(it) },
                    )
                },
                modifier = Modifier.clickable { viewModel.saveAutoScreenContext(!autoScreenContext) },
            )

            Spacer(modifier = Modifier.height(16.dp))
            HorizontalDivider()
            Spacer(modifier = Modifier.height(16.dp))

            // DashScope STT
            Text(
                text = "语音识别 (DashScope)",
                style = MaterialTheme.typography.labelLarge,
                color = MaterialTheme.colorScheme.primary,
                modifier = Modifier.padding(16.dp),
            )

            OutlinedTextField(
                value = dashScopeApiKey,
                onValueChange = { viewModel.updateDashScopeApiKeyInput(it) },
                label = { Text("API Key") },
                placeholder = { Text("sk-xxxxxxxxxxxxxxxx") },
                singleLine = true,
                shape = MaterialTheme.shapes.medium,
                keyboardOptions = KeyboardOptions(
                    keyboardType = KeyboardType.Password,
                    imeAction = ImeAction.Done,
                ),
                keyboardActions = KeyboardActions(
                    onDone = {
                        scope.launch {
                            viewModel.saveDashScopeApiKey(dashScopeApiKey)
                            Toast.makeText(context, "API Key 已保存", Toast.LENGTH_SHORT).show()
                        }
                    },
                ),
                trailingIcon = {
                    FilledTonalIconButton(onClick = {
                        scope.launch {
                            viewModel.saveDashScopeApiKey(dashScopeApiKey)
                            Toast.makeText(context, "API Key 已保存", Toast.LENGTH_SHORT).show()
                        }
                    }) {
                        Icon(Icons.Filled.Check, contentDescription = "保存")
                    }
                },
                modifier = Modifier
                    .fillMaxWidth()
                    .padding(horizontal = 16.dp),
            )

            Spacer(modifier = Modifier.height(8.dp))

            OutlinedTextField(
                value = dashScopeEndpoint,
                onValueChange = { viewModel.updateDashScopeEndpointInput(it) },
                label = { Text("WebSocket 端点") },
                placeholder = { Text("wss://dashscope.aliyuncs.com/api-ws/v1/inference") },
                singleLine = true,
                shape = MaterialTheme.shapes.medium,
                keyboardOptions = KeyboardOptions(
                    keyboardType = KeyboardType.Uri,
                    imeAction = ImeAction.Done,
                ),
                keyboardActions = KeyboardActions(
                    onDone = {
                        scope.launch {
                            viewModel.saveDashScopeEndpoint(dashScopeEndpoint)
                            Toast.makeText(context, "端点已保存", Toast.LENGTH_SHORT).show()
                        }
                    },
                ),
                trailingIcon = {
                    FilledTonalIconButton(onClick = {
                        scope.launch {
                            viewModel.saveDashScopeEndpoint(dashScopeEndpoint)
                            Toast.makeText(context, "端点已保存", Toast.LENGTH_SHORT).show()
                        }
                    }) {
                        Icon(Icons.Filled.Check, contentDescription = "保存")
                    }
                },
                modifier = Modifier
                    .fillMaxWidth()
                    .padding(horizontal = 16.dp),
            )

            Spacer(modifier = Modifier.height(8.dp))

            OutlinedTextField(
                value = dashScopeModel,
                onValueChange = { viewModel.updateDashScopeModelInput(it) },
                label = { Text("模型") },
                placeholder = { Text("fun-asr-realtime") },
                singleLine = true,
                shape = MaterialTheme.shapes.medium,
                keyboardOptions = KeyboardOptions(
                    imeAction = ImeAction.Done,
                ),
                keyboardActions = KeyboardActions(
                    onDone = {
                        scope.launch {
                            viewModel.saveDashScopeModel(dashScopeModel)
                            Toast.makeText(context, "模型已保存", Toast.LENGTH_SHORT).show()
                        }
                    },
                ),
                trailingIcon = {
                    FilledTonalIconButton(onClick = {
                        scope.launch {
                            viewModel.saveDashScopeModel(dashScopeModel)
                            Toast.makeText(context, "模型已保存", Toast.LENGTH_SHORT).show()
                        }
                    }) {
                        Icon(Icons.Filled.Check, contentDescription = "保存")
                    }
                },
                modifier = Modifier
                    .fillMaxWidth()
                    .padding(horizontal = 16.dp),
            )

            Spacer(modifier = Modifier.height(12.dp))

            Text(
                text = "未配置 API Key 时，语音输入将自动使用后端服务处理。",
                style = MaterialTheme.typography.bodySmall,
                color = MaterialTheme.colorScheme.onSurfaceVariant,
                modifier = Modifier.padding(horizontal = 16.dp),
            )

            Spacer(modifier = Modifier.height(24.dp))
            HorizontalDivider()
            Spacer(modifier = Modifier.height(16.dp))

            // Data management
            Text(
                text = "数据",
                style = MaterialTheme.typography.labelLarge,
                color = MaterialTheme.colorScheme.primary,
                modifier = Modifier.padding(16.dp),
            )

            var showClearDialog by remember { mutableStateOf(false) }
            ListItem(
                headlineContent = { Text("清空本地消息记录") },
                supportingContent = { Text("仅清除本地数据库，服务器消息仍保留。下次加载将只获取清除时间之后的消息。") },
                leadingContent = { Icon(Icons.Filled.DeleteForever, contentDescription = null, tint = MaterialTheme.colorScheme.error) },
                modifier = Modifier.clickable { showClearDialog = true },
            )

            if (showClearDialog) {
                AlertDialog(
                    onDismissRequest = { showClearDialog = false },
                    title = { Text("确认清空") },
                    text = { Text("将清空所有本地消息记录。服务器上的消息不会被删除，但下次加载历史时将只获取本次清除之后的消息。") },
                    confirmButton = {
                        TextButton(
                            onClick = {
                                showClearDialog = false
                                val activity = context as? FragmentActivity
                                if (activity == null) {
                                    viewModel.clearLocalMessages()
                                    Toast.makeText(context, "本地消息已清空", Toast.LENGTH_SHORT).show()
                                    return@TextButton
                                }
                                val biometricManager = BiometricManager.from(context)
                                val canAuth = when (biometricManager.canAuthenticate(
                                    BiometricManager.Authenticators.BIOMETRIC_STRONG or
                                        BiometricManager.Authenticators.DEVICE_CREDENTIAL
                                )) {
                                    BiometricManager.BIOMETRIC_SUCCESS -> true
                                    else -> false
                                }
                                if (!canAuth) {
                                    viewModel.clearLocalMessages()
                                    Toast.makeText(context, "本地消息已清空", Toast.LENGTH_SHORT).show()
                                    return@TextButton
                                }
                                val prompt = BiometricPrompt(
                                    activity,
                                    ContextCompat.getMainExecutor(context),
                                    object : BiometricPrompt.AuthenticationCallback() {
                                        override fun onAuthenticationSucceeded(
                                            result: BiometricPrompt.AuthenticationResult,
                                        ) {
                                            viewModel.clearLocalMessages()
                                            Toast.makeText(context, "本地消息已清空", Toast.LENGTH_SHORT).show()
                                        }

                                        override fun onAuthenticationFailed() {
                                            Toast.makeText(context, "验证失败", Toast.LENGTH_SHORT).show()
                                        }

                                        override fun onAuthenticationError(
                                            errorCode: Int,
                                            errString: CharSequence,
                                        ) {
                                            Toast.makeText(context, "验证取消", Toast.LENGTH_SHORT).show()
                                        }
                                    },
                                )
                                prompt.authenticate(
                                    BiometricPrompt.PromptInfo.Builder()
                                        .setTitle("身份验证")
                                        .setSubtitle("需要验证身份后才能清空消息记录")
                                        .setAllowedAuthenticators(
                                            BiometricManager.Authenticators.BIOMETRIC_STRONG or
                                                BiometricManager.Authenticators.DEVICE_CREDENTIAL
                                        )
                                        .build(),
                                )
                            },
                            colors = ButtonDefaults.textButtonColors(contentColor = MaterialTheme.colorScheme.error),
                        ) {
                            Text("清空")
                        }
                    },
                    dismissButton = {
                        TextButton(onClick = { showClearDialog = false }) {
                            Text("取消")
                        }
                    },
                )
            }

            // Runtime logs
            Text(
                text = "运行日志",
                style = MaterialTheme.typography.labelLarge,
                color = MaterialTheme.colorScheme.primary,
                modifier = Modifier.padding(16.dp),
            )

            val logEntries by RuntimeLog.entries.collectAsState()
            var selectedTab by remember { mutableStateOf(0) }
            val tabs = listOf("全部") + LogCategory.entries.map { it.label }
            val allCategories = LogCategory.entries.toList()

            // Scroll to bottom
            val scrollState = rememberScrollState()
            androidx.compose.runtime.LaunchedEffect(logEntries.size, selectedTab) {
                if (logEntries.isNotEmpty()) {
                    scrollState.animateScrollTo(scrollState.maxValue)
                }
            }

            ScrollableTabRow(
                selectedTabIndex = selectedTab,
                edgePadding = 16.dp,
                divider = {},
            ) {
                tabs.forEachIndexed { index, label ->
                    Tab(
                        selected = selectedTab == index,
                        onClick = { selectedTab = index },
                        text = { Text(label, maxLines = 1, style = MaterialTheme.typography.labelMedium) },
                    )
                }
            }

            val currentCategory = if (selectedTab == 0) null else allCategories.getOrNull(selectedTab - 1)

            Row(
                modifier = Modifier
                    .fillMaxWidth()
                    .padding(horizontal = 16.dp, vertical = 8.dp),
                horizontalArrangement = Arrangement.spacedBy(8.dp),
            ) {
                OutlinedButton(
                    onClick = {
                        val file = RuntimeLog.exportToFile(context, currentCategory)
                        RuntimeLog.shareFile(context, file)
                    },
                ) {
                    Icon(Icons.Filled.Share, contentDescription = null, modifier = Modifier.size(16.dp))
                    Spacer(modifier = Modifier.width(4.dp))
                    Text(if (currentCategory != null) "导出${currentCategory.label}" else "导出全部")
                }
                OutlinedButton(
                    onClick = {
                        val file = RuntimeLog.exportAllAsZip(context)
                        RuntimeLog.shareFile(context, file)
                    },
                ) {
                    Icon(Icons.Filled.Share, contentDescription = null, modifier = Modifier.size(16.dp))
                    Spacer(modifier = Modifier.width(4.dp))
                    Text("打包全部")
                }
                OutlinedButton(
                    onClick = { RuntimeLog.clear() },
                    colors = ButtonDefaults.outlinedButtonColors(contentColor = MaterialTheme.colorScheme.error),
                ) {
                    Text("清空")
                }
            }

            val displayLogs = if (selectedTab == 0) {
                logEntries.takeLast(500)
            } else {
                val cat = allCategories.getOrNull(selectedTab - 1)
                if (cat != null) logEntries.filter { it.category == cat }.takeLast(500) else emptyList()
            }

            if (displayLogs.isEmpty()) {
                Text(
                    text = "暂无${tabs[selectedTab]}日志",
                    style = MaterialTheme.typography.bodySmall,
                    color = MaterialTheme.colorScheme.onSurfaceVariant,
                    modifier = Modifier.padding(horizontal = 16.dp, vertical = 8.dp),
                )
            } else {
                // Log count header
                Text(
                    text = "共 ${displayLogs.size} 条${if (displayLogs.size >= 500) "+" else ""}",
                    style = MaterialTheme.typography.labelSmall,
                    color = MaterialTheme.colorScheme.onSurfaceVariant,
                    modifier = Modifier.padding(horizontal = 16.dp, vertical = 4.dp),
                )
                // Fixed-height scrollable log area
                Box(
                    modifier = Modifier
                        .fillMaxWidth()
                        .padding(horizontal = 12.dp)
                        .height(280.dp)
                        .background(
                            MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.4f),
                            RoundedCornerShape(8.dp),
                        )
                        .padding(8.dp),
                ) {
                    Column(
                        modifier = Modifier.verticalScroll(scrollState),
                    ) {
                        displayLogs.forEach { entry ->
                            Text(
                                text = entry.formatted(),
                                style = MaterialTheme.typography.bodySmall,
                                fontFamily = androidx.compose.ui.text.font.FontFamily.Monospace,
                                color = MaterialTheme.colorScheme.onSurfaceVariant,
                                modifier = Modifier.padding(vertical = 1.dp),
                            )
                        }
                    }
                }
            }

            Spacer(modifier = Modifier.height(80.dp))
        }
    }
}
