package top.yeij.cyrene.ui.components

import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
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.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.widthIn
import androidx.compose.foundation.shape.RoundedCornerShape

import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Close
import androidx.compose.material.icons.filled.ContentCopy
import androidx.compose.material.icons.filled.ExpandLess
import androidx.compose.material.icons.filled.ExpandMore
import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text

import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalClipboardManager
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextDecoration
import androidx.compose.ui.text.withStyle
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.compose.ui.window.Dialog
import androidx.compose.ui.window.DialogProperties
import coil.compose.AsyncImage
import coil.request.ImageRequest
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale

// --- Markdown block model ---

private sealed class MdBlock {
    data class Heading(val level: Int, val text: String) : MdBlock()
    data class Paragraph(val text: String) : MdBlock()
    data class CodeBlock(val language: String?, val code: String) : MdBlock()
    data class ListItem(val ordered: Boolean, val index: Int, val text: String) : MdBlock()
    data class Quote(val text: String) : MdBlock()
    class ThematicBreak : MdBlock()
}

private fun parseMarkdownBlocks(text: String): List<MdBlock> {
    val lines = text.lines()
    val blocks = mutableListOf<MdBlock>()
    var i = 0

    while (i < lines.size) {
        val line = lines[i]
        val trimmed = line.trimStart()

        when {
            // Fenced code block
            trimmed.startsWith("```") -> {
                val lang = trimmed.removePrefix("```").trim().ifBlank { null }
                val codeLines = mutableListOf<String>()
                i++
                while (i < lines.size && !lines[i].trimStart().startsWith("```")) {
                    codeLines.add(lines[i])
                    i++
                }
                if (i < lines.size) i++ // skip closing ```
                blocks.add(MdBlock.CodeBlock(lang, codeLines.joinToString("\n")))
            }
            // Heading
            trimmed.startsWith("#") -> {
                val match = Regex("^(#{1,6})\\s+(.+)$").find(trimmed)
                if (match != null) {
                    val level = match.groupValues[1].length
                    blocks.add(MdBlock.Heading(level, match.groupValues[2]))
                }
                i++
            }
            // Thematic break
            trimmed.matches(Regex("^[-*_]{3,}$")) -> {
                blocks.add(MdBlock.ThematicBreak())
                i++
            }
            // Blockquote
            line.startsWith(">") || trimmed.startsWith(">") -> {
                val quoteLines = mutableListOf<String>()
                while (i < lines.size) {
                    val cur = lines[i]
                    if (cur.trimStart().startsWith(">")) {
                        quoteLines.add(cur.trimStart().removePrefix(">").trimStart())
                        i++
                    } else if (cur.isBlank()) {
                        i++
                        break
                    } else {
                        break
                    }
                }
                if (quoteLines.isNotEmpty()) {
                    blocks.add(MdBlock.Quote(quoteLines.joinToString("\n")))
                }
            }
            // Unordered list
            trimmed.matches(Regex("^[-*+]\\s+.*$")) -> {
                while (i < lines.size && lines[i].trimStart().matches(Regex("^[-*+]\\s+.*$"))) {
                    val itemText = lines[i].trimStart().replaceFirst(Regex("^[-*+]\\s+"), "")
                    blocks.add(MdBlock.ListItem(false, blocks.size + 1, itemText))
                    i++
                }
            }
            // Ordered list
            trimmed.matches(Regex("^\\d+\\.\\s+.*$")) -> {
                var idx = 1
                while (i < lines.size && lines[i].trimStart().matches(Regex("^\\d+\\.\\s+.*$"))) {
                    val itemText = lines[i].trimStart().replaceFirst(Regex("^\\d+\\.\\s+"), "")
                    blocks.add(MdBlock.ListItem(true, idx, itemText))
                    idx++
                    i++
                }
            }
            // Blank line — skip
            line.isBlank() -> { i++ }
            // Paragraph
            else -> {
                val paraLines = mutableListOf<String>()
                while (i < lines.size &&
                    lines[i].isNotBlank() &&
                    !lines[i].trimStart().startsWith("```") &&
                    !lines[i].trimStart().startsWith("#") &&
                    !lines[i].trimStart().matches(Regex("^[-*_]{3,}$")) &&
                    !lines[i].trimStart().startsWith(">") &&
                    !lines[i].trimStart().matches(Regex("^[-*+]\\s+.*$")) &&
                    !lines[i].trimStart().matches(Regex("^\\d+\\.\\s+.*$"))
                ) {
                    paraLines.add(lines[i])
                    i++
                }
                if (paraLines.isNotEmpty()) {
                    blocks.add(MdBlock.Paragraph(paraLines.joinToString(" ")))
                }
            }
        }
    }
    return blocks
}

@Composable
private fun renderInlineMarkdown(text: String): AnnotatedString {
    return buildAnnotatedString {
        var remaining = text
        while (remaining.isNotEmpty()) {
            // Bold + Italic ***
            val boldItalic = Regex("""\*\*\*(.+?)\*\*\*""").find(remaining)
            // Bold **
            val bold = Regex("""\*\*(.+?)\*\*""").find(remaining)
            // Italic *
            val italic = Regex("""(?<!\*)\*(?!\*)(.+?)(?<!\*)\*(?!\*)""").find(remaining)
            // Inline code `
            val code = Regex("""`([^`]+)`""").find(remaining)
            // Link [text](url)
            val link = Regex("""\[([^\]]+)\]\(([^)]+)\)""").find(remaining)

            val matches = listOfNotNull(
                boldItalic?.let { "bi" to it },
                bold?.let { "b" to it },
                italic?.let { "i" to it },
                code?.let { "c" to it },
                link?.let { "l" to it },
            ).sortedBy { it.second.range.first }

            if (matches.isEmpty()) {
                append(remaining)
                remaining = ""
            } else {
                val (kind, match) = matches.first()
                // Append text before the match
                if (match.range.first > 0) {
                    append(remaining.substring(0, match.range.first))
                }
                when (kind) {
                    "bi" -> withStyle(SpanStyle(fontWeight = FontWeight.Bold, fontStyle = FontStyle.Italic)) {
                        append(match.groupValues[1])
                    }
                    "b" -> withStyle(SpanStyle(fontWeight = FontWeight.Bold)) {
                        append(match.groupValues[1])
                    }
                    "i" -> withStyle(SpanStyle(fontStyle = FontStyle.Italic)) {
                        append(match.groupValues[1])
                    }
                    "c" -> withStyle(SpanStyle(fontFamily = FontFamily.Monospace, background = Color.Gray.copy(alpha = 0.2f))) {
                        append(match.groupValues[1])
                    }
                    "l" -> {
                        val label = match.groupValues[1]
                        val url = match.groupValues[2]
                        pushStringAnnotation("url", url)
                        withStyle(SpanStyle(color = MaterialTheme.colorScheme.primary, textDecoration = TextDecoration.Underline)) {
                            append(label)
                        }
                        pop()
                    }
                }
                remaining = remaining.substring(match.range.last + 1)
            }
        }
    }
}

// --- Markdown bubble ---

@Composable
private fun MarkdownBubble(content: String, modifier: Modifier = Modifier) {
    val blocks = remember(content) { parseMarkdownBlocks(content) }

    Surface(
        modifier = modifier
            .fillMaxWidth()
            .padding(horizontal = 12.dp, vertical = 2.dp),
        shape = MaterialTheme.shapes.medium,
        color = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.7f),
        shadowElevation = 1.dp,
    ) {
        Column(modifier = Modifier.padding(12.dp)) {
            blocks.forEach { block ->
                when (block) {
                    is MdBlock.Heading -> {
                        val fontSize = when (block.level) {
                            1 -> 22.sp
                            2 -> 19.sp
                            3 -> 17.sp
                            4 -> 15.sp
                            5 -> 14.sp
                            else -> 13.sp
                        }
                        Text(
                            text = renderInlineMarkdown(block.text),
                            fontSize = fontSize,
                            fontWeight = FontWeight.Bold,
                            color = MaterialTheme.colorScheme.onSurfaceVariant,
                            modifier = Modifier.padding(vertical = if (block.level <= 2) 6.dp else 2.dp),
                        )
                    }
                    is MdBlock.Paragraph -> {
                        if (block.text.isNotBlank()) {
                            Text(
                                text = renderInlineMarkdown(block.text),
                                style = MaterialTheme.typography.bodyMedium,
                                color = MaterialTheme.colorScheme.onSurfaceVariant,
                            )
                        }
                    }
                    is MdBlock.CodeBlock -> {
                        Surface(
                            modifier = Modifier
                                .fillMaxWidth()
                                .padding(vertical = 4.dp),
                            shape = MaterialTheme.shapes.small,
                            color = Color(0xFF1E1E1E),
                        ) {
                            Column {
                                if (block.language != null) {
                                    Text(
                                        text = block.language,
                                        modifier = Modifier
                                            .background(Color(0xFF333333))
                                            .padding(horizontal = 10.dp, vertical = 4.dp),
                                        color = Color(0xFFCCCCCC),
                                        fontSize = 12.sp,
                                        fontFamily = FontFamily.Monospace,
                                    )
                                }
                                Text(
                                    text = block.code,
                                    modifier = Modifier.padding(10.dp),
                                    color = Color(0xFFD4D4D4),
                                    fontSize = 13.sp,
                                    fontFamily = FontFamily.Monospace,
                                )
                            }
                        }
                    }
                    is MdBlock.ListItem -> {
                        val prefix = if (block.ordered) "${block.index}. " else "• "
                        Row(modifier = Modifier.padding(start = 8.dp, top = 2.dp)) {
                            Text(
                                text = prefix,
                                style = MaterialTheme.typography.bodyMedium,
                                color = MaterialTheme.colorScheme.onSurfaceVariant,
                            )
                            Text(
                                text = renderInlineMarkdown(block.text),
                                style = MaterialTheme.typography.bodyMedium,
                                color = MaterialTheme.colorScheme.onSurfaceVariant,
                            )
                        }
                    }
                    is MdBlock.Quote -> {
                        Surface(
                            modifier = Modifier
                                .fillMaxWidth()
                                .padding(vertical = 2.dp),
                            color = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.5f),
                            shape = MaterialTheme.shapes.small,
                        ) {
                            Row {
                                Box(
                                    modifier = Modifier
                                        .background(MaterialTheme.colorScheme.primary.copy(alpha = 0.5f))
                                        .weight(0.012f)
                                ) {}
                                Text(
                                    text = renderInlineMarkdown(block.text),
                                    modifier = Modifier
                                        .weight(1f)
                                        .padding(8.dp),
                                    style = MaterialTheme.typography.bodyMedium.copy(fontStyle = FontStyle.Italic),
                                    color = MaterialTheme.colorScheme.onSurfaceVariant,
                                )
                            }
                        }
                    }
                    is MdBlock.ThematicBreak -> {
                        Box(
                            modifier = Modifier
                                .fillMaxWidth()
                                .padding(vertical = 6.dp)
                                .background(
                                    MaterialTheme.colorScheme.outlineVariant.copy(alpha = 0.4f),
                                    shape = MaterialTheme.shapes.extraSmall,
                                )
                                .weight(1f)
                        ) {}
                    }
                }
            }
        }
    }
}

// --- Code bubble (standalone code block message) ---

private val codeDarkBg = Color(0xFF1E1E1E)
private val codeSurface = Color(0xFF333333)

@Composable
private fun CodeBubble(content: String, modifier: Modifier = Modifier) {
    val (language, code) = remember(content) {
        if (content.startsWith("[lang:")) {
            val endBracket = content.indexOf("]\n")
            if (endBracket > 0) {
                content.substring(6, endBracket) to content.substring(endBracket + 2)
            } else "Code" to content
        } else "Code" to content
    }

    Column(
        modifier = modifier
            .fillMaxWidth()
            .padding(horizontal = 12.dp, vertical = 2.dp),
    ) {
        Surface(
            shape = MaterialTheme.shapes.medium,
            color = codeDarkBg,
            shadowElevation = 2.dp,
        ) {
            Column {
                // Language header
                Box(
                    modifier = Modifier
                        .background(codeSurface, MaterialTheme.shapes.medium)
                        .padding(horizontal = 12.dp, vertical = 6.dp),
                ) {
                    Row(
                        verticalAlignment = Alignment.CenterVertically,
                        horizontalArrangement = Arrangement.SpaceBetween,
                    ) {
                        Text(
                            text = language,
                            color = Color(0xFFAAAAAA),
                            fontSize = 12.sp,
                            fontFamily = FontFamily.Monospace,
                        )
                    }
                }
                // Code content
                Text(
                    text = code,
                    modifier = Modifier.padding(12.dp),
                    color = Color(0xFFD4D4D4),
                    fontSize = 13.sp,
                    fontFamily = FontFamily.Monospace,
                )
            }
        }
    }
}

// --- Collapsible wrapper for non-chat content ---

private const val COLLAPSE_THRESHOLD = 300

@Composable
private fun CollapsibleBubble(
    content: String,
    modifier: Modifier = Modifier,
    bubble: @Composable (String, Modifier) -> Unit,
) {
    var expanded by remember { mutableStateOf(false) }
    val lines = content.lines()
    val isLong = content.length > COLLAPSE_THRESHOLD || lines.size > 8

    if (!isLong) {
        bubble(content, modifier)
        return
    }

    Column(modifier = modifier) {
        Row(
            verticalAlignment = Alignment.Top,
            modifier = Modifier.fillMaxWidth(),
        ) {
            Box(modifier = Modifier.weight(1f)) {
                if (expanded) {
                    bubble(content, Modifier)
                } else {
                    val truncated = lines.take(5).joinToString("\n").let {
                        if (it.length >= content.length) it else it + "\n…"
                    }
                    bubble(truncated, Modifier)
                }
            }
            IconButton(
                onClick = { expanded = !expanded },
                modifier = Modifier
                    .padding(top = 4.dp)
                    .size(32.dp),
            ) {
                Icon(
                    imageVector = if (expanded) Icons.Filled.ExpandLess else Icons.Filled.ExpandMore,
                    contentDescription = if (expanded) "折叠" else "展开",
                    tint = MaterialTheme.colorScheme.onSurfaceVariant,
                    modifier = Modifier.size(20.dp),
                )
            }
        }
    }
}

// --- Main ChatBubble dispatcher ---

@Composable
fun ChatBubble(
    content: String,
    role: String,
    msgType: String,
    timestamp: Long,
    modifier: Modifier = Modifier,
    imageDataUris: List<String> = emptyList(),
) {
    val isUser = role == "user"
    val formattedTime = SimpleDateFormat("HH:mm", Locale.getDefault()).format(Date(timestamp))

    when (msgType) {
        "chat" -> ChatMessageBubble(content, isUser, formattedTime, modifier, imageDataUris)
        "action" -> ActionMessage(content, modifier)
        "markdown" -> CollapsibleBubble(content, modifier) { text, mod ->
            MarkdownBubble(text, mod)
        }
        "code" -> CollapsibleBubble(content, modifier) { text, mod ->
            CodeBubble(text, mod)
        }
        "thinking" -> CollapsibleBubble(content, modifier) { text, mod ->
            ThinkingBubble(text, mod)
        }
        "tool_progress" -> CollapsibleBubble(content, modifier) { text, mod ->
            ToolProgressBubble(text, mod)
        }
        "system_info" -> SystemInfoBubble(content, modifier)
        else -> ChatMessageBubble(content, isUser, formattedTime, modifier, imageDataUris)
    }
}

// --- Full-screen image preview dialog ---

@Composable
private fun ImagePreviewDialog(
    imageUri: String,
    onDismiss: () -> Unit,
) {
    val context = LocalContext.current
    Dialog(
        onDismissRequest = onDismiss,
        properties = DialogProperties(usePlatformDefaultWidth = false),
    ) {
        Box(
            modifier = Modifier
                .fillMaxSize()
                .background(Color.Black.copy(alpha = 0.95f))
                .clickable { onDismiss() },
            contentAlignment = Alignment.Center,
        ) {
            CircularProgressIndicator(
                color = Color.White.copy(alpha = 0.6f),
                modifier = Modifier.size(48.dp),
            )
            AsyncImage(
                model = ImageRequest.Builder(context)
                    .data(imageUri)
                    .crossfade(true)
                    .build(),
                contentDescription = "图片预览",
                modifier = Modifier
                    .fillMaxWidth()
                    .padding(16.dp),
                contentScale = ContentScale.Fit,
            )
            IconButton(
                onClick = onDismiss,
                modifier = Modifier
                    .align(Alignment.TopEnd)
                    .padding(16.dp),
            ) {
                Icon(
                    Icons.Default.Close,
                    contentDescription = "关闭",
                    tint = Color.White,
                )
            }
        }
    }
}

// --- Chat message bubble ---

@OptIn(ExperimentalFoundationApi::class)
@Composable
private fun ChatMessageBubble(
    content: String,
    isUser: Boolean,
    time: String,
    modifier: Modifier = Modifier,
    imageDataUris: List<String> = emptyList(),
) {
    var showMenu by remember { mutableStateOf(false) }
    var previewImageUri by remember { mutableStateOf<String?>(null) }
    val clipboardManager = LocalClipboardManager.current
    val context = LocalContext.current
    val hasImages = imageDataUris.isNotEmpty()

    Row(
        modifier = modifier
            .fillMaxWidth()
            .padding(horizontal = 12.dp, vertical = 4.dp),
        horizontalArrangement = if (isUser) Arrangement.End else Arrangement.Start,
    ) {
        Column(
            horizontalAlignment = if (isUser) Alignment.End else Alignment.Start,
        ) {
            Box {
                Surface(
                    shape = MaterialTheme.shapes.large,
                    color = if (isUser)
                        MaterialTheme.colorScheme.primary
                    else
                        MaterialTheme.colorScheme.surfaceVariant,
                    shadowElevation = 2.dp,
                    modifier = Modifier
                        .widthIn(max = 300.dp)
                        .combinedClickable(
                            onClick = {},
                            onLongClick = { showMenu = true },
                        ),
                ) {
                    Column {
                        if (hasImages) {
                            imageDataUris.forEach { uri ->
                                AsyncImage(
                                    model = ImageRequest.Builder(context)
                                        .data(uri)
                                        .crossfade(true)
                                        .build(),
                                    contentDescription = "图片",
                                    modifier = Modifier
                                        .fillMaxWidth()
                                        .heightIn(min = 120.dp, max = 240.dp)
                                        .padding(top = 6.dp, start = 6.dp, end = 6.dp)
                                        .clip(RoundedCornerShape(8.dp))
                                        .clickable { previewImageUri = uri },
                                    contentScale = ContentScale.FillWidth,
                                )
                            }
                        }
                        if (content.isNotBlank()) {
                            Text(
                                text = renderInlineMarkdown(content),
                                modifier = Modifier.padding(
                                    start = 12.dp, end = 12.dp,
                                    top = if (hasImages) 6.dp else 12.dp,
                                    bottom = 12.dp,
                                ),
                                color = if (isUser)
                                    MaterialTheme.colorScheme.onPrimary
                                else
                                    MaterialTheme.colorScheme.onSurfaceVariant,
                            )
                        }
                    }
                }
                DropdownMenu(
                    expanded = showMenu,
                    onDismissRequest = { showMenu = false },
                ) {
                    DropdownMenuItem(
                        text = { Text("复制") },
                        leadingIcon = {
                            Icon(Icons.Default.ContentCopy, contentDescription = null)
                        },
                        onClick = {
                            showMenu = false
                            clipboardManager.setText(AnnotatedString(content))
                        },
                    )
                }
            }
            Text(
                text = time,
                style = MaterialTheme.typography.labelSmall,
                color = MaterialTheme.colorScheme.onSurfaceVariant,
                modifier = Modifier.padding(top = 2.dp),
            )
        }
    }

    // Full-screen image preview
    if (previewImageUri != null) {
        ImagePreviewDialog(
            imageUri = previewImageUri!!,
            onDismiss = { previewImageUri = null },
        )
    }
}

// --- Action message ---

private val actionTagRegex = Regex("""</?action>""", RegexOption.IGNORE_CASE)

@Composable
private fun ActionMessage(content: String, modifier: Modifier = Modifier) {
    val displayText = remember(content) {
        content.replace(actionTagRegex, "").trim()
    }
    Row(
        modifier = modifier
            .fillMaxWidth()
            .padding(horizontal = 12.dp, vertical = 2.dp),
        horizontalArrangement = Arrangement.Start,
    ) {
        Text(
            text = displayText,
            style = MaterialTheme.typography.bodyMedium.copy(
                fontStyle = FontStyle.Italic,
            ),
            color = MaterialTheme.colorScheme.onSurfaceVariant,
            textAlign = TextAlign.Start,
        )
    }
}

// --- Thinking bubble ---

@Composable
private fun ThinkingBubble(content: String, modifier: Modifier = Modifier) {
    Box(
        modifier = modifier
            .fillMaxWidth()
            .padding(horizontal = 12.dp, vertical = 2.dp)
            .background(
                color = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.5f),
                shape = MaterialTheme.shapes.medium,
            ),
    ) {
        Text(
            text = content,
            modifier = Modifier.padding(10.dp),
            style = MaterialTheme.typography.bodySmall,
            color = MaterialTheme.colorScheme.onSurfaceVariant,
        )
    }
}

// --- Tool progress bubble ---

@Composable
private fun ToolProgressBubble(content: String, modifier: Modifier = Modifier) {
    Row(
        modifier = modifier
            .fillMaxWidth()
            .padding(horizontal = 12.dp, vertical = 2.dp),
        horizontalArrangement = Arrangement.Start,
    ) {
        Surface(
            shape = MaterialTheme.shapes.small,
            color = MaterialTheme.colorScheme.tertiaryContainer.copy(alpha = 0.6f),
        ) {
            Text(
                text = content,
                modifier = Modifier.padding(horizontal = 10.dp, vertical = 6.dp),
                style = MaterialTheme.typography.bodySmall,
                color = MaterialTheme.colorScheme.onTertiaryContainer,
            )
        }
    }
}

// --- System info bubble ---

@OptIn(ExperimentalFoundationApi::class)
@Composable
private fun SystemInfoBubble(content: String, modifier: Modifier = Modifier) {
    var showMenu by remember { mutableStateOf(false) }
    val clipboardManager = LocalClipboardManager.current

    Row(
        modifier = modifier
            .fillMaxWidth()
            .padding(horizontal = 12.dp, vertical = 2.dp),
        horizontalArrangement = Arrangement.Center,
    ) {
        Box {
            Text(
                text = content,
                style = MaterialTheme.typography.bodySmall,
                color = MaterialTheme.colorScheme.error,
                textAlign = TextAlign.Center,
                modifier = Modifier.combinedClickable(
                    onClick = {},
                    onLongClick = { showMenu = true },
                ),
            )
            DropdownMenu(
                expanded = showMenu,
                onDismissRequest = { showMenu = false },
            ) {
                DropdownMenuItem(
                    text = { Text("复制") },
                    leadingIcon = {
                        Icon(Icons.Default.ContentCopy, contentDescription = null)
                    },
                    onClick = {
                        showMenu = false
                        clipboardManager.setText(AnnotatedString(content))
                    },
                )
            }
        }
    }
}
