package com.wisp.app.ui.screen

import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.PickVisualMediaRequest
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
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.Spacer
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.imePadding
import androidx.compose.foundation.layout.navigationBarsPadding
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.wrapContentWidth
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material.icons.automirrored.filled.Reply
import androidx.compose.material.icons.automirrored.filled.Send
import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.filled.KeyboardArrowLeft
import androidx.compose.material.icons.outlined.Close
import androidx.compose.material.icons.outlined.Cloud
import androidx.compose.material.icons.outlined.Image
import androidx.compose.ui.draw.scale
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.layout.onSizeChanged
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedTextField
import androidx.compose.ui.text.input.KeyboardCapitalization
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults
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.mutableLongStateOf
import androidx.compose.runtime.mutableStateMapOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import com.wisp.app.nostr.DmMessage
import com.wisp.app.nostr.toNpub
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Date
import java.util.Locale
import com.wisp.app.nostr.ProfileData
import com.wisp.app.relay.RelayPool
import com.wisp.app.repo.EventRepository
import com.wisp.app.repo.RelayInfoRepository
import androidx.compose.ui.text.TextRange
import androidx.compose.ui.text.input.TextFieldValue
import com.wisp.app.ui.component.DmBubble
import com.wisp.app.ui.component.EmojiShortcodePopup
import com.wisp.app.ui.component.EmojiVisualTransformation
import com.wisp.app.ui.component.detectEmojiAutocomplete
import com.wisp.app.ui.component.insertEmojiShortcode
import com.wisp.app.ui.component.ProfilePicture
import com.wisp.app.ui.component.ZapDialog
import com.wisp.app.nostr.NostrSigner
import com.wisp.app.R
import com.wisp.app.viewmodel.DeliveryRelaySource
import com.wisp.app.viewmodel.DmConversationViewModel
import com.wisp.app.viewmodel.PowStatus
import com.wisp.app.viewmodel.SocialActionManager

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun DmConversationScreen(
    viewModel: DmConversationViewModel,
    relayPool: RelayPool,
    peerProfile: ProfileData?,
    userProfile: ProfileData? = null,
    userPubkey: String?,
    eventRepo: EventRepository? = null,
    relayInfoRepo: RelayInfoRepository? = null,
    onBack: () -> Unit,
    onProfileClick: ((String) -> Unit)? = null,
    onNoteClick: ((String) -> Unit)? = null,
    peerPubkey: String? = null,
    participants: List<String> = emptyList(),
    signer: NostrSigner? = null,
    socialActionManager: SocialActionManager? = null,
    isWalletConnected: Boolean = false,
    onGoToWallet: () -> Unit = {},
    noteActions: com.wisp.app.ui.component.NoteActions? = null,
    resolvedEmojis: Map<String, String> = emptyMap(),
    unicodeEmojis: List<String> = emptyList(),
    onOpenEmojiLibrary: (() -> Unit)? = null,
    onEmojiUsed: ((String) -> Unit)? = null
) {
    val messages by viewModel.messages.collectAsState()
    val messageText by viewModel.messageText.collectAsState()
    val sending by viewModel.sending.collectAsState()
    val sendError by viewModel.sendError.collectAsState()
    val uploadProgress by viewModel.uploadProgress.collectAsState()
    val peerDelivery by viewModel.peerDeliveryRelays.collectAsState()
    val allParticipantRelays by viewModel.allParticipantRelays.collectAsState()
    val userDmRelays by viewModel.userDmRelays.collectAsState()
    val miningStatus by viewModel.miningStatus.collectAsState()
    val replyingTo by viewModel.replyingToMessage.collectAsState()
    val selectedMessageId by viewModel.selectedMessageId.collectAsState()
    val isGroup = participants.size > 1
    val listState = rememberLazyListState()
    var showRelayInfo by remember { mutableStateOf(false) }
    var debugMessage by remember { mutableStateOf<DmMessage?>(null) }
    var zapTargetMessage by remember { mutableStateOf<DmMessage?>(null) }
    var zapPendingSats by remember { mutableLongStateOf(0L) }
    var lastZappedMessage by remember { mutableStateOf<DmMessage?>(null) }
    val zapSatsMap = remember { mutableStateMapOf<String, Long>() }
    val zapInProgress by (socialActionManager?.zapInProgress ?: kotlinx.coroutines.flow.MutableStateFlow(emptySet())).collectAsState()

    // Record sats on the bubble once zap completes (keyed by senderPubkey)
    LaunchedEffect(socialActionManager) {
        socialActionManager?.zapSuccess?.collect { key ->
            val msg = lastZappedMessage
            if (msg != null && key == msg.senderPubkey) {
                zapSatsMap[msg.id] = (zapSatsMap[msg.id] ?: 0L) + zapPendingSats / 1000
                lastZappedMessage = null
                zapPendingSats = 0L
            }
        }
    }
    val totalRelayCount = (allParticipantRelays.values.sumOf { it.urls.size } + userDmRelays.size)
        .coerceAtLeast(peerDelivery.urls.size + userDmRelays.size)
    val context = LocalContext.current

    val photoPickerLauncher = rememberLauncherForActivityResult(
        contract = ActivityResultContracts.PickMultipleVisualMedia()
    ) { uris ->
        if (uris.isNotEmpty()) viewModel.uploadMedia(uris, context.contentResolver, relayPool, signer)
    }

    // Auto-scroll to bottom when new messages arrive
    LaunchedEffect(messages.size) {
        if (messages.isNotEmpty()) {
            listState.animateScrollToItem(0)
        }
    }

    Scaffold(
        contentWindowInsets = WindowInsets(0, 0, 0, 0),
        topBar = {
            Column {
                TopAppBar(
                    title = {
                        if (isGroup) {
                            // Group DM header: stacked avatars + participant names
                            Row(verticalAlignment = Alignment.CenterVertically) {
                                Box {
                                    participants.take(3).forEachIndexed { i, pubkey ->
                                        val profile = remember(pubkey) { eventRepo?.getProfileData(pubkey) }
                                        ProfilePicture(
                                            url = profile?.picture,
                                            size = 28,
                                            modifier = Modifier.offset(x = (i * 12).dp)
                                        )
                                    }
                                }
                                Spacer(Modifier.width((participants.take(3).size * 12 + 4).dp))
                                Column {
                                    val names = participants.take(3).joinToString(", ") { pk ->
                                        eventRepo?.getProfileData(pk)?.displayString
                                            ?: pk.toNpub().let { "${it.take(12)}...${it.takeLast(4)}" }
                                    }
                                    val suffix = if (participants.size > 3) " +${participants.size - 3}" else ""
                                    Text(
                                        names + suffix,
                                        style = MaterialTheme.typography.titleSmall,
                                        maxLines = 1,
                                        overflow = TextOverflow.Ellipsis
                                    )
                                    Text(
                                        "${participants.size + 1} people",
                                        style = MaterialTheme.typography.labelSmall,
                                        color = MaterialTheme.colorScheme.onSurfaceVariant
                                    )
                                }
                            }
                        } else {
                            Row(
                                verticalAlignment = Alignment.CenterVertically,
                                modifier = Modifier.clickable(enabled = peerPubkey != null && onProfileClick != null) {
                                    peerPubkey?.let { onProfileClick?.invoke(it) }
                                }
                            ) {
                                ProfilePicture(url = peerProfile?.picture, size = 40)
                                Spacer(Modifier.width(10.dp))
                                Text(
                                    peerProfile?.displayString ?: stringResource(R.string.title_chat),
                                    style = MaterialTheme.typography.titleMedium,
                                    fontWeight = FontWeight.Medium,
                                    maxLines = 1,
                                    overflow = TextOverflow.Ellipsis
                                )
                            }
                        }
                    },
                    navigationIcon = {
                        IconButton(onClick = onBack, modifier = Modifier.size(36.dp)) {
                            Icon(
                                Icons.Filled.KeyboardArrowLeft,
                                contentDescription = stringResource(R.string.cd_back),
                                tint = MaterialTheme.colorScheme.onSurfaceVariant,
                                modifier = Modifier.size(24.dp)
                            )
                        }
                    },
                    actions = {
                        if (totalRelayCount > 0) {
                            IconButton(onClick = { showRelayInfo = !showRelayInfo }) {
                                Box {
                                    Icon(
                                        Icons.Outlined.Cloud,
                                        contentDescription = "DM relays",
                                        tint = if (showRelayInfo) MaterialTheme.colorScheme.primary
                                        else MaterialTheme.colorScheme.onSurfaceVariant
                                    )
                                    // Badge with relay count
                                    Box(
                                        modifier = Modifier
                                            .align(Alignment.TopEnd)
                                            .offset(x = 2.dp, y = (-2).dp)
                                            .size(16.dp)
                                            .clip(CircleShape)
                                            .background(MaterialTheme.colorScheme.primary),
                                        contentAlignment = Alignment.Center
                                    ) {
                                        Text(
                                            text = "$totalRelayCount",
                                            style = MaterialTheme.typography.labelSmall,
                                            color = MaterialTheme.colorScheme.onPrimary,
                                            fontSize = 10.sp
                                        )
                                    }
                                }
                            }
                        }
                    },
                    colors = TopAppBarDefaults.topAppBarColors(
                        containerColor = MaterialTheme.colorScheme.background
                    )
                )

                // Expandable relay info panel
                AnimatedVisibility(visible = showRelayInfo) {
                    Column(modifier = Modifier.fillMaxWidth()) {
                        Column(
                            modifier = Modifier
                                .fillMaxWidth()
                                .background(MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.4f))
                                .padding(horizontal = 16.dp, vertical = 8.dp)
                        ) {
                            // Show relay info for each participant (works for 1:1 and group)
                            val displayRelays = allParticipantRelays.ifEmpty {
                                if (peerDelivery.urls.isNotEmpty()) mapOf(peerPubkey.orEmpty() to peerDelivery) else emptyMap()
                            }
                            displayRelays.entries.forEachIndexed { index, (pubkey, delivery) ->
                                if (index > 0) Spacer(Modifier.height(6.dp))
                                val participantProfile = eventRepo?.getProfileData(pubkey)
                                Row(verticalAlignment = Alignment.CenterVertically) {
                                    ProfilePicture(url = participantProfile?.picture, size = 20)
                                    Spacer(Modifier.width(8.dp))
                                    Text(
                                        text = participantProfile?.displayString ?: pubkey.toNpub().let { "${it.take(12)}...${it.takeLast(4)}" },
                                        style = MaterialTheme.typography.labelMedium,
                                        color = MaterialTheme.colorScheme.onSurface,
                                        maxLines = 1,
                                        overflow = TextOverflow.Ellipsis
                                    )
                                    val sourceLabel = when (delivery.source) {
                                        DeliveryRelaySource.DM_RELAYS -> null
                                        DeliveryRelaySource.READ_RELAYS -> "inbox"
                                        DeliveryRelaySource.WRITE_RELAYS -> "write"
                                        DeliveryRelaySource.OWN_RELAYS -> "your relays"
                                    }
                                    if (sourceLabel != null) {
                                        Spacer(Modifier.width(6.dp))
                                        Text(
                                            text = "($sourceLabel)",
                                            style = MaterialTheme.typography.labelSmall,
                                            color = MaterialTheme.colorScheme.onSurfaceVariant
                                        )
                                    }
                                }
                                for (url in delivery.urls) {
                                    Text(
                                        text = url.removePrefix("wss://"),
                                        style = MaterialTheme.typography.bodySmall,
                                        color = MaterialTheme.colorScheme.onSurfaceVariant,
                                        modifier = Modifier.padding(start = 28.dp, top = 2.dp)
                                    )
                                }
                            }
                            if (displayRelays.isNotEmpty() && userDmRelays.isNotEmpty()) {
                                Spacer(Modifier.height(6.dp))
                            }
                            if (userDmRelays.isNotEmpty()) {
                                Row(verticalAlignment = Alignment.CenterVertically) {
                                    ProfilePicture(url = userProfile?.picture, size = 20)
                                    Spacer(Modifier.width(8.dp))
                                    Text(
                                        text = stringResource(R.string.dm_you),
                                        style = MaterialTheme.typography.labelMedium,
                                        color = MaterialTheme.colorScheme.onSurface
                                    )
                                }
                                for (url in userDmRelays) {
                                    Text(
                                        text = url.removePrefix("wss://"),
                                        style = MaterialTheme.typography.bodySmall,
                                        color = MaterialTheme.colorScheme.onSurfaceVariant,
                                        modifier = Modifier.padding(start = 28.dp, top = 2.dp)
                                    )
                                }
                            }
                        }
                        HorizontalDivider()
                    }
                }
            }
        }
    ) { padding ->
        val density = LocalDensity.current
        var bottomBarHeightPx by remember { mutableIntStateOf(0) }

        // Emoji autocomplete state — must live at composable scope
        var dmTfv by remember { mutableStateOf(TextFieldValue()) }
        LaunchedEffect(messageText) {
            if (dmTfv.text != messageText) {
                dmTfv = TextFieldValue(messageText, TextRange(messageText.length))
            }
        }
        LaunchedEffect(messageText) {
            if (messageText.isNotBlank()) viewModel.clearSendError()
        }
        val dmEmojiState = remember(dmTfv) { detectEmojiAutocomplete(dmTfv) }
        val dmEmojiVisualTransformation = remember(resolvedEmojis) { EmojiVisualTransformation(resolvedEmojis) }

        Box(
            modifier = Modifier
                .padding(padding)
                .fillMaxSize()
                .imePadding()
        ) {
            LazyColumn(
                state = listState,
                modifier = Modifier
                    .fillMaxSize()
                    .clickable(indication = null, interactionSource = remember { androidx.compose.foundation.interaction.MutableInteractionSource() }) {
                        viewModel.selectMessage(null)
                    },
                reverseLayout = true,
                contentPadding = PaddingValues(bottom = with(density) { bottomBarHeightPx.toDp() })
            ) {
                val ordered = messages.reversed() // newest -> oldest (reverseLayout draws index 0 at bottom)
                for ((i, msg) in ordered.withIndex()) {
                    item(key = msg.id) {
                        val icons = msg.relayUrls.map { url ->
                            url to relayInfoRepo?.getIconUrl(url)
                        }
                        DmBubble(
                            message = msg,
                            isSent = msg.senderPubkey == userPubkey,
                            isSelected = selectedMessageId == msg.id,
                            conversationMessages = messages,
                            eventRepo = eventRepo,
                            relayIcons = icons,
                            onSelect = { viewModel.selectMessage(msg.id) },
                            onReply = { viewModel.setReplyingTo(it) },
                            onReact = { m, emoji -> viewModel.sendReaction(m.rumorId, emoji, relayPool, signer, resolvedEmojis); onEmojiUsed?.invoke(emoji) },
                            onZap = { m -> zapTargetMessage = m },
                            isZapInProgress = msg.senderPubkey in zapInProgress,
                            zapSats = msg.zaps.sumOf { it.sats }.coerceAtLeast(zapSatsMap[msg.id] ?: 0L),
                            onProfileClick = onProfileClick,
                            onNoteClick = onNoteClick,
                            onDebugTap = { debugMessage = it },
                            noteActions = noteActions,
                            resolvedEmojis = resolvedEmojis,
                            unicodeEmojis = unicodeEmojis,
                            onOpenEmojiLibrary = onOpenEmojiLibrary
                        )
                    }
                    // Emit each day's header at the group's older boundary so reverseLayout
                    // renders it on top of the whole group (not above just the newest message).
                    val olderMsg = ordered.getOrNull(i + 1)
                    val dateKey = dayKey(msg.createdAt)
                    if (olderMsg == null || dayKey(olderMsg.createdAt) != dateKey) {
                        item(key = "date-$dateKey") {
                            DateHeader(formatDateHeader(msg.createdAt))
                        }
                    }
                }
            }

            LaunchedEffect(listState.isScrollInProgress) {
                if (listState.isScrollInProgress) viewModel.selectMessage(null)
            }

            // Bottom bar overlay with gradient
            Column(
                modifier = Modifier
                    .align(Alignment.BottomStart)
                    .fillMaxWidth()
                    .onSizeChanged { bottomBarHeightPx = it.height }
                    .background(
                        Brush.verticalGradient(
                            colors = listOf(Color.Transparent, MaterialTheme.colorScheme.background)
                        )
                    )
                    .navigationBarsPadding()
            ) {
                AnimatedVisibility(visible = uploadProgress != null) {
                    Text(
                        text = uploadProgress ?: "",
                        color = MaterialTheme.colorScheme.primary,
                        style = MaterialTheme.typography.bodySmall,
                        modifier = Modifier.fillMaxWidth().padding(horizontal = 12.dp, vertical = 4.dp)
                    )
                }
                AnimatedVisibility(visible = sendError != null) {
                    Text(
                        text = sendError ?: "",
                        color = MaterialTheme.colorScheme.error,
                        style = MaterialTheme.typography.bodySmall,
                        modifier = Modifier.fillMaxWidth().padding(horizontal = 12.dp, vertical = 4.dp)
                    )
                }
                if (dmEmojiState != null) {
                    EmojiShortcodePopup(
                        query = dmEmojiState.query,
                        resolvedEmojis = resolvedEmojis,
                        onSelect = { shortcode ->
                            val newTfv = insertEmojiShortcode(dmTfv, dmEmojiState.triggerIndex, shortcode)
                            dmTfv = newTfv
                            viewModel.updateMessageText(newTfv.text)
                        }
                    )
                }
                Surface(
                    modifier = Modifier
                        .fillMaxWidth()
                        .padding(start = 12.dp, end = 12.dp, top = 0.dp, bottom = 8.dp),
                    shape = RoundedCornerShape(12.dp),
                    color = MaterialTheme.colorScheme.surfaceContainerLow
                ) {
                    Column(modifier = Modifier.padding(8.dp)) {
                        // Reply preview inside the composer surface
                        val replyMsg = replyingTo
                        if (replyMsg != null) {
                            val senderName = remember(replyMsg.senderPubkey) {
                                if (replyMsg.senderPubkey == userPubkey) "You"
                                else eventRepo?.getProfileData(replyMsg.senderPubkey)?.displayString
                                    ?: replyMsg.senderPubkey.toNpub().let { "${it.take(12)}...${it.takeLast(4)}" }
                            }
                            Row(
                                modifier = Modifier.fillMaxWidth(),
                                verticalAlignment = Alignment.CenterVertically
                            ) {
                                Icon(
                                    Icons.AutoMirrored.Filled.Reply,
                                    contentDescription = null,
                                    tint = MaterialTheme.colorScheme.primary,
                                    modifier = Modifier.size(14.dp).scale(scaleX = -1f, scaleY = -1f)
                                )
                                Spacer(Modifier.width(6.dp))
                                Text(
                                    text = senderName,
                                    style = MaterialTheme.typography.labelSmall,
                                    fontWeight = FontWeight.SemiBold,
                                    color = MaterialTheme.colorScheme.primary,
                                    modifier = Modifier.weight(1f),
                                    maxLines = 1,
                                    overflow = TextOverflow.Ellipsis
                                )
                                Icon(
                                    Icons.Outlined.Close,
                                    contentDescription = "Cancel reply",
                                    tint = MaterialTheme.colorScheme.onSurfaceVariant,
                                    modifier = Modifier
                                        .size(14.dp)
                                        .clickable { viewModel.clearReply() }
                                )
                            }
                            Text(
                                text = replyMsg.content,
                                style = MaterialTheme.typography.bodySmall,
                                color = MaterialTheme.colorScheme.onSurfaceVariant,
                                maxLines = 1,
                                overflow = TextOverflow.Ellipsis,
                                modifier = Modifier.padding(start = 20.dp, top = 2.dp, bottom = 4.dp)
                            )
                        }
                        Row(
                            verticalAlignment = Alignment.Bottom,
                            horizontalArrangement = Arrangement.spacedBy(10.dp),
                            modifier = Modifier.fillMaxWidth()
                        ) {
                            Surface(
                                onClick = {
                                    photoPickerLauncher.launch(
                                        PickVisualMediaRequest(ActivityResultContracts.PickVisualMedia.ImageAndVideo)
                                    )
                                },
                                enabled = uploadProgress == null && !sending,
                                shape = RoundedCornerShape(8.dp),
                                color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.08f),
                                modifier = Modifier.size(32.dp)
                            ) {
                                Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
                                    Icon(
                                        Icons.Filled.Add,
                                        contentDescription = stringResource(R.string.cd_attach_media),
                                        tint = if (uploadProgress == null && !sending) MaterialTheme.colorScheme.onSurfaceVariant
                                               else MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.38f),
                                        modifier = Modifier.size(18.dp)
                                    )
                                }
                            }
                            androidx.compose.foundation.text.BasicTextField(
                                value = dmTfv,
                                onValueChange = { new ->
                                    if (!com.wisp.app.ui.component.NsecPasteGuard.blockIfNsec(dmTfv.text, new.text)) {
                                        dmTfv = new
                                        viewModel.updateMessageText(new.text)
                                    }
                                },
                                modifier = Modifier.weight(1f).heightIn(min = 28.dp).padding(top = 4.dp),
                                enabled = uploadProgress == null,
                                keyboardOptions = KeyboardOptions(capitalization = KeyboardCapitalization.Sentences),
                                visualTransformation = dmEmojiVisualTransformation,
                                maxLines = 5,
                                cursorBrush = SolidColor(MaterialTheme.colorScheme.primary),
                                textStyle = MaterialTheme.typography.bodyLarge.copy(
                                    color = MaterialTheme.colorScheme.onSurface
                                ),
                                decorationBox = { innerTextField ->
                                    Box {
                                        if (dmTfv.text.isEmpty()) {
                                            Text(
                                                stringResource(R.string.placeholder_message),
                                                style = MaterialTheme.typography.bodyLarge,
                                                color = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.45f)
                                            )
                                        }
                                        innerTextField()
                                    }
                                }
                            )
                            if (sending && miningStatus is PowStatus.Mining) {
                                Column(
                                    modifier = Modifier.size(32.dp),
                                    horizontalAlignment = Alignment.CenterHorizontally,
                                    verticalArrangement = Arrangement.Center
                                ) {
                                    CircularProgressIndicator(modifier = Modifier.size(16.dp), strokeWidth = 2.dp)
                                    Text("Mining…", style = MaterialTheme.typography.labelSmall, color = MaterialTheme.colorScheme.onSurfaceVariant, fontSize = 7.sp)
                                }
                            } else if (sending) {
                                Box(modifier = Modifier.size(32.dp), contentAlignment = Alignment.Center) {
                                    CircularProgressIndicator(modifier = Modifier.size(18.dp), strokeWidth = 2.dp)
                                }
                            } else {
                                IconButton(
                                    onClick = { viewModel.sendMessage(relayPool, signer, resolvedEmojis) },
                                    enabled = messageText.isNotBlank(),
                                    modifier = Modifier.size(32.dp)
                                ) {
                                    Icon(
                                        Icons.AutoMirrored.Filled.Send,
                                        contentDescription = stringResource(R.string.cd_send),
                                        tint = if (messageText.isNotBlank()) MaterialTheme.colorScheme.primary
                                               else MaterialTheme.colorScheme.onSurface.copy(alpha = 0.38f),
                                        modifier = Modifier.size(20.dp)
                                    )
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    debugMessage?.let { msg ->
        DmDebugDialog(message = msg, onDismiss = { debugMessage = null })
    }

    if (zapTargetMessage != null) {
        ZapDialog(
            isWalletConnected = isWalletConnected,
            onDismiss = { zapTargetMessage = null },
            onZap = { amountMsats, message, isAnonymous, _ ->
                val target = zapTargetMessage ?: return@ZapDialog
                zapPendingSats = amountMsats
                lastZappedMessage = target
                zapTargetMessage = null
                socialActionManager?.sendZapToPubkey(target.senderPubkey, amountMsats, message, isAnonymous, rumorId = target.rumorId.ifEmpty { null })
            },
            onGoToWallet = {
                zapTargetMessage = null
                onGoToWallet()
            },
            recipientPubkey = zapTargetMessage?.senderPubkey,
            profileLookup = { pk -> peerProfile?.takeIf { it.pubkey == pk } }
        )
    }
}

@Composable
private fun DmDebugDialog(message: DmMessage, onDismiss: () -> Unit) {
    val context = androidx.compose.ui.platform.LocalContext.current
    var tab by remember { mutableIntStateOf(0) }
    val json = if (tab == 0) message.debugGiftWrapJson ?: "(not available)" else message.debugRumorJson ?: "(not available)"
    androidx.compose.material3.AlertDialog(
        onDismissRequest = onDismiss,
        title = {
            androidx.compose.material3.TabRow(selectedTabIndex = tab) {
                androidx.compose.material3.Tab(selected = tab == 0, onClick = { tab = 0 }, text = { Text("Gift Wrap") })
                androidx.compose.material3.Tab(selected = tab == 1, onClick = { tab = 1 }, text = { Text("Rumor") })
            }
        },
        text = {
            Text(
                text = json,
                style = MaterialTheme.typography.bodySmall.copy(
                    fontFamily = androidx.compose.ui.text.font.FontFamily.Monospace,
                    fontSize = 10.sp
                ),
                color = MaterialTheme.colorScheme.onSurface,
                modifier = Modifier.verticalScroll(rememberScrollState())
            )
        },
        confirmButton = {
            androidx.compose.material3.TextButton(onClick = {
                val clipboard = context.getSystemService(android.content.Context.CLIPBOARD_SERVICE) as android.content.ClipboardManager
                clipboard.setPrimaryClip(android.content.ClipData.newPlainText("dm_debug", json))
            }) { Text("Copy") }
        },
        dismissButton = {
            androidx.compose.material3.TextButton(onClick = onDismiss) { Text("Close") }
        }
    )
}

@Composable
private fun DateHeader(label: String) {
    Row(
        modifier = Modifier
            .fillMaxWidth()
            .padding(horizontal = 16.dp, vertical = 12.dp),
        verticalAlignment = Alignment.CenterVertically
    ) {
        HorizontalDivider(modifier = Modifier.weight(1f))
        Text(
            text = label,
            style = MaterialTheme.typography.labelSmall,
            color = MaterialTheme.colorScheme.onSurfaceVariant,
            modifier = Modifier.padding(horizontal = 12.dp)
        )
        HorizontalDivider(modifier = Modifier.weight(1f))
    }
}

private val dateHeaderFormat = SimpleDateFormat("EEEE, MMMM d", Locale.US)
private val dateHeaderYearFormat = SimpleDateFormat("EEEE, MMMM d, yyyy", Locale.US)

private fun dayKey(epoch: Long): String {
    val cal = Calendar.getInstance()
    cal.timeInMillis = epoch * 1000
    return "${cal.get(Calendar.YEAR)}-${cal.get(Calendar.DAY_OF_YEAR)}"
}

private fun formatDateHeader(epoch: Long): String {
    val msgDate = Date(epoch * 1000)
    val now = Calendar.getInstance()
    val msg = Calendar.getInstance().apply { time = msgDate }

    val today = Calendar.getInstance()
    val yesterday = Calendar.getInstance().apply { add(Calendar.DAY_OF_YEAR, -1) }

    return when {
        msg.get(Calendar.YEAR) == today.get(Calendar.YEAR) &&
                msg.get(Calendar.DAY_OF_YEAR) == today.get(Calendar.DAY_OF_YEAR) -> "Today"
        msg.get(Calendar.YEAR) == yesterday.get(Calendar.YEAR) &&
                msg.get(Calendar.DAY_OF_YEAR) == yesterday.get(Calendar.DAY_OF_YEAR) -> "Yesterday"
        msg.get(Calendar.YEAR) != now.get(Calendar.YEAR) -> dateHeaderYearFormat.format(msgDate)
        else -> dateHeaderFormat.format(msgDate)
    }
}
