package ru.forbion.f7cloud.feature.f7support

import androidx.compose.foundation.background
import androidx.compose.foundation.border
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.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.layout.widthIn
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.OutlinedTextFieldDefaults
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
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.draw.shadow
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
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 androidx.compose.foundation.layout.heightIn
import androidx.compose.material3.Surface
import androidx.compose.ui.graphics.Brush
import ru.forbion.f7cloud.core.auth.AuthSession
import ru.forbion.f7cloud.core.designsystem.F7Colors
import ru.forbion.f7cloud.core.designsystem.F7PrimaryButton
import java.time.Instant
import java.time.ZoneId
import java.time.format.DateTimeFormatter
import java.util.Locale

private val ColumnNewBg = Color(0xFFDEF9F8)
private val ColumnClosedBg = Color(0xFFF5F5F5)
private val FieldBg = Color(0xFFFDFDFD)

fun formatSupportTicketTime(iso: String): String {
    if (iso.isBlank()) return ""
    val instant = runCatching { Instant.parse(iso) }.getOrNull() ?: return ""
    val zdt = instant.atZone(ZoneId.systemDefault())
    val month = zdt.format(DateTimeFormatter.ofPattern("LLLL", Locale("ru")))
    val hm = zdt.format(DateTimeFormatter.ofPattern("HH:mm"))
    return "${zdt.dayOfMonth} $month, $hm"
}

fun formatSupportMsgTime(iso: String): String {
    if (iso.isBlank()) return ""
    val instant = runCatching { Instant.parse(iso) }.getOrNull() ?: return ""
    return instant.atZone(ZoneId.systemDefault())
        .format(DateTimeFormatter.ofPattern("HH:mm"))
}

private fun formatSupportFileSize(bytes: Long?): String {
    if (bytes == null || bytes < 0) return ""
    return when {
        bytes < 1024 -> "$bytes Б"
        bytes < 1024 * 1024 -> "${bytes / 1024} КБ"
        else -> String.format(Locale.US, "%.1f МБ", bytes / (1024.0 * 1024.0))
    }
}

@Composable
fun SupportHomeContent(
    serverUrl: String,
    isSupportAdmin: Boolean,
    ticketsByBucket: Map<SupportStatusBucket, List<SupportTicket>>,
    hasTickets: Boolean,
    onCreateClick: () -> Unit,
    onTicketClick: (String) -> Unit,
    modifier: Modifier = Modifier,
) {
    val base = serverUrl.trimEnd('/')
    Column(
        modifier = modifier
            .fillMaxSize()
            .verticalScroll(rememberScrollState()),
        horizontalAlignment = if (hasTickets) Alignment.Start else Alignment.CenterHorizontally,
        verticalArrangement = if (hasTickets) Arrangement.Top else Arrangement.Center,
    ) {
        if (!hasTickets) {
            AsyncImage(
                model = "$base/apps/f7support/img/app.svg",
                contentDescription = null,
                modifier = Modifier
                    .width(77.dp)
                    .padding(bottom = 20.dp),
                contentScale = ContentScale.Fit,
            )
        }
        Column(
            modifier = Modifier.fillMaxWidth(),
            horizontalAlignment = if (hasTickets) Alignment.Start else Alignment.CenterHorizontally,
            verticalArrangement = Arrangement.spacedBy(20.dp),
        ) {
            Text(
                text = if (isSupportAdmin) "Все запросы" else "Мои запросы",
                style = MaterialTheme.typography.headlineSmall.copy(
                    fontWeight = FontWeight.Medium,
                    fontSize = 24.sp,
                    lineHeight = 20.sp,
                ),
                color = F7Colors.TextPrimary,
                textAlign = if (hasTickets) TextAlign.Start else TextAlign.Center,
            )
            Text(
                text = if (isSupportAdmin) {
                    "Режим администратора поддержки: видны все обращения с этого F7cloud. Нажмите на запрос, чтобы открыть чат."
                } else {
                    "Нажмите на запрос, чтобы открыть чат. Закройте окно чата, чтобы выбрать другой запрос."
                },
                style = MaterialTheme.typography.bodyLarge.copy(
                    fontWeight = FontWeight.Medium,
                    fontSize = 16.sp,
                    lineHeight = 20.sp,
                ),
                color = Color(0xFF888888),
                textAlign = if (hasTickets) TextAlign.Start else TextAlign.Center,
            )
            F7PrimaryButton(
                text = "Создать",
                onClick = onCreateClick,
                modifier = Modifier.align(
                    if (hasTickets) Alignment.Start else Alignment.CenterHorizontally,
                ),
            )
        }
        if (hasTickets) {
            Spacer(Modifier.height(16.dp))
            SupportKanbanBoard(
                ticketsByBucket = ticketsByBucket,
                isSupportAdmin = isSupportAdmin,
                onTicketClick = onTicketClick,
            )
        }
    }
}

@Composable
private fun SupportKanbanBoard(
    ticketsByBucket: Map<SupportStatusBucket, List<SupportTicket>>,
    isSupportAdmin: Boolean,
    onTicketClick: (String) -> Unit,
) {
    Column(
        modifier = Modifier.fillMaxWidth(),
        verticalArrangement = Arrangement.spacedBy(16.dp),
    ) {
        SupportStatusBucket.entries.forEach { bucket ->
            val tickets = ticketsByBucket[bucket].orEmpty()
            SupportKanbanColumn(
                bucket = bucket,
                tickets = tickets,
                isSupportAdmin = isSupportAdmin,
                onTicketClick = onTicketClick,
            )
        }
    }
}

@Composable
private fun SupportKanbanColumn(
    bucket: SupportStatusBucket,
    tickets: List<SupportTicket>,
    isSupportAdmin: Boolean,
    onTicketClick: (String) -> Unit,
) {
    val headerBg = when (bucket) {
        SupportStatusBucket.New -> ColumnNewBg
        SupportStatusBucket.Progress -> F7Colors.PrimaryLight
        SupportStatusBucket.Closed -> ColumnClosedBg
    }
    Column(
        modifier = Modifier
            .fillMaxWidth()
            .clip(RoundedCornerShape(12.dp)),
    ) {
        Box(
            modifier = Modifier
                .fillMaxWidth()
                .background(headerBg)
                .padding(horizontal = 14.dp, vertical = 8.dp),
            contentAlignment = Alignment.Center,
        ) {
            Text(
                text = bucket.title,
                style = MaterialTheme.typography.bodyMedium.copy(
                    fontWeight = FontWeight.Medium,
                    fontSize = 14.sp,
                ),
                color = F7Colors.TextPrimary,
            )
        }
        if (tickets.isEmpty()) {
            Text(
                text = "Нет обращений",
                modifier = Modifier.padding(16.dp),
                style = MaterialTheme.typography.bodyMedium,
                color = F7Colors.TextSecondary,
            )
        } else {
            LazyRow(
                modifier = Modifier
                    .fillMaxWidth()
                    .padding(top = 12.dp, bottom = 4.dp),
                horizontalArrangement = Arrangement.spacedBy(8.dp),
            ) {
                items(tickets, key = { it.ticketNumber }) { ticket ->
                    SupportTicketBoardCard(
                        ticket = ticket,
                        isSupportAdmin = isSupportAdmin,
                        onClick = { onTicketClick(ticket.ticketNumber) },
                        modifier = Modifier.fillParentMaxWidth(0.92f),
                    )
                }
            }
        }
    }
}

@Composable
fun SupportTicketBoardCard(
    ticket: SupportTicket,
    isSupportAdmin: Boolean,
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
) {
    val statusColor = when (ticket.statusBucket()) {
        SupportStatusBucket.New -> F7Colors.StatusNew
        SupportStatusBucket.Progress -> F7Colors.StatusProgress
        SupportStatusBucket.Closed -> F7Colors.StatusClosed
    }
    Column(
        modifier = modifier
            .shadow(0.dp, RoundedCornerShape(8.dp))
            .clip(RoundedCornerShape(8.dp))
            .background(Color.White)
            .border(1.dp, F7Colors.Border, RoundedCornerShape(8.dp))
            .clickable(onClick = onClick)
            .padding(12.dp),
    ) {
        Row(
            modifier = Modifier
                .fillMaxWidth()
                .clip(RoundedCornerShape(4.dp))
                .background(F7Colors.SurfaceMuted)
                .padding(8.dp),
            horizontalArrangement = Arrangement.SpaceBetween,
            verticalAlignment = Alignment.CenterVertically,
        ) {
            Text(
                text = "Тема: ${ticket.subject}",
                style = MaterialTheme.typography.bodyMedium.copy(
                    fontWeight = FontWeight.Medium,
                    fontSize = 14.sp,
                ),
                color = F7Colors.TextPrimary,
                maxLines = 2,
                overflow = TextOverflow.Ellipsis,
                modifier = Modifier.weight(1f),
            )
            Text(
                text = ticket.status.ifBlank { "—" },
                modifier = Modifier
                    .clip(RoundedCornerShape(100.dp))
                    .background(statusColor)
                    .padding(horizontal = 12.dp, vertical = 4.dp),
                color = Color.White,
                style = MaterialTheme.typography.labelSmall,
            )
        }
        Text(
            text = "#${ticket.displayNumber()}",
            modifier = Modifier.padding(top = 6.dp),
            style = MaterialTheme.typography.labelSmall.copy(fontSize = 12.sp),
            color = F7Colors.TextSecondary,
        )
        Row(
            modifier = Modifier
                .fillMaxWidth()
                .padding(top = 8.dp),
            horizontalArrangement = Arrangement.spacedBy(10.dp),
            verticalAlignment = Alignment.Top,
        ) {
            Text(
                text = ticket.preview.ifBlank { "Текст последнего сообщения…" },
                modifier = Modifier.weight(1f),
                style = MaterialTheme.typography.bodyMedium.copy(fontSize = 14.sp),
                color = if (ticket.preview.isBlank()) Color(0xFF999999) else F7Colors.TextSecondary,
                maxLines = 3,
                overflow = TextOverflow.Ellipsis,
            )
            if (ticket.hasUnread) {
                Box(
                    modifier = Modifier
                        .padding(top = 6.dp)
                        .size(8.dp)
                        .clip(CircleShape)
                        .background(F7Colors.Primary),
                )
            }
        }
        Row(
            modifier = Modifier
                .fillMaxWidth()
                .padding(top = 8.dp),
            horizontalArrangement = Arrangement.SpaceBetween,
            verticalAlignment = Alignment.CenterVertically,
        ) {
            if (isSupportAdmin && ticket.clientUsername.isNotBlank()) {
                Text(
                    text = "Клиент: ${ticket.clientUsername}",
                    style = MaterialTheme.typography.labelSmall,
                    color = Color(0xFF606060),
                    maxLines = 1,
                    overflow = TextOverflow.Ellipsis,
                    modifier = Modifier.weight(1f),
                )
            } else {
                Spacer(Modifier.weight(1f))
            }
            val timeLabel = formatSupportTicketTime(ticket.activityAt)
            if (timeLabel.isNotBlank()) {
                Text(
                    text = timeLabel,
                    modifier = Modifier
                        .clip(RoundedCornerShape(100.dp))
                        .background(F7Colors.SurfaceMuted)
                        .padding(horizontal = 10.dp, vertical = 2.dp),
                    style = MaterialTheme.typography.labelSmall,
                    color = F7Colors.TextSecondary,
                )
            }
        }
    }
}

@Composable
fun SupportCreateDialog(
    loading: Boolean,
    pendingFiles: List<SupportPendingFile>,
    onDismiss: () -> Unit,
    onPickFiles: () -> Unit,
    onRemoveFile: (String) -> Unit,
    onSubmit: (subject: String, body: String) -> Unit,
) {
    var subject by remember { mutableStateOf("") }
    var body by remember { mutableStateOf("") }
    Dialog(
        onDismissRequest = { if (!loading) onDismiss() },
        properties = DialogProperties(usePlatformDefaultWidth = false),
    ) {
        Column(
            modifier = Modifier
                .fillMaxSize()
                .background(Color.White)
                .padding(16.dp),
        ) {
            Row(
                modifier = Modifier.fillMaxWidth(),
                horizontalArrangement = Arrangement.SpaceBetween,
                verticalAlignment = Alignment.CenterVertically,
            ) {
                Text(
                    text = "Создание запроса",
                    style = MaterialTheme.typography.titleMedium.copy(fontWeight = FontWeight.SemiBold),
                    color = F7Colors.TextPrimary,
                )
                TextButton(onClick = onDismiss, enabled = !loading) {
                    Text("✕", fontSize = 20.sp, color = F7Colors.TextSecondary)
                }
            }
            SupportStyledField(
                value = subject,
                onValueChange = { if (it.length <= 255) subject = it },
                placeholder = "Тема",
                singleLine = true,
                modifier = Modifier.padding(top = 24.dp),
            )
            SupportComposerField(
                value = body,
                onValueChange = { if (it.length <= 4000) body = it },
                placeholder = "Опишите проблему (до 4000 символов)",
                minLines = 6,
                onAttachClick = onPickFiles,
                modifier = Modifier
                    .padding(top = 12.dp)
                    .weight(1f),
            )
            SupportFileChipsRow(
                files = pendingFiles,
                onRemove = onRemoveFile,
                modifier = Modifier.padding(top = 12.dp),
            )
            Row(
                modifier = Modifier
                    .fillMaxWidth()
                    .padding(top = 24.dp),
                horizontalArrangement = Arrangement.End,
            ) {
                F7PrimaryButton(
                    text = if (loading) "…" else "Отправить",
                    onClick = { onSubmit(subject, body) },
                    enabled = subject.isNotBlank() && body.isNotBlank() && !loading,
                )
            }
        }
    }
}

@Composable
fun SupportChatDialog(
    session: AuthSession,
    ticket: SupportTicket,
    messages: List<SupportMessage>,
    loading: Boolean,
    sending: Boolean,
    pendingFiles: List<SupportPendingFile>,
    downloadingAttachmentId: Long?,
    onDismiss: () -> Unit,
    onSend: (String) -> Unit,
    onPickFiles: () -> Unit,
    onRemoveFile: (String) -> Unit,
    onAttachmentClick: (SupportAttachment) -> Unit,
    onComplaintClick: () -> Unit,
) {
    var draft by remember(ticket.ticketNumber) { mutableStateOf("") }
    val listState = rememberLazyListState()
    LaunchedEffect(messages.size) {
        if (messages.isNotEmpty()) {
            listState.animateScrollToItem(messages.lastIndex)
        }
    }
    val assignee = if (ticket.status == "Новый") {
        ""
    } else {
        ticket.assignedEmployee.trim()
    }
    Dialog(
        onDismissRequest = onDismiss,
        properties = DialogProperties(usePlatformDefaultWidth = false),
    ) {
        Column(
            modifier = Modifier
                .fillMaxSize()
                .background(Color.White)
                .padding(16.dp),
        ) {
            Row(
                modifier = Modifier.fillMaxWidth(),
                horizontalArrangement = Arrangement.SpaceBetween,
                verticalAlignment = Alignment.Top,
            ) {
                Column(modifier = Modifier.weight(1f).padding(end = 8.dp)) {
                    Text(
                        text = "Тикет № ${ticket.displayNumber()}",
                        style = MaterialTheme.typography.titleMedium.copy(fontWeight = FontWeight.SemiBold),
                        color = F7Colors.TextPrimary,
                    )
                    Text(
                        text = "Дата создания задачи: ${formatSupportTicketTime(ticket.createdAt).ifBlank { "—" }}",
                        style = MaterialTheme.typography.bodyMedium,
                        color = Color(0xFF606060),
                        modifier = Modifier.padding(top = 4.dp),
                    )
                    Text(
                        text = "Назначенный сотрудник: ${assignee.ifBlank { "—" }}",
                        style = MaterialTheme.typography.bodyMedium,
                        color = Color(0xFF606060),
                        modifier = Modifier.padding(top = 4.dp),
                    )
                }
                TextButton(onClick = onDismiss) {
                    Text("✕", fontSize = 20.sp, color = F7Colors.TextSecondary)
                }
            }
            HorizontalDivider(
                modifier = Modifier.padding(vertical = 8.dp),
                color = F7Colors.BorderLight,
            )
            Box(
                modifier = Modifier
                    .weight(1f)
                    .fillMaxWidth(),
            ) {
                if (loading && messages.isEmpty()) {
                    CircularProgressIndicator(
                        modifier = Modifier.align(Alignment.Center),
                        color = F7Colors.Primary,
                    )
                } else {
                    LazyColumn(
                        state = listState,
                        modifier = Modifier.fillMaxSize(),
                        verticalArrangement = Arrangement.spacedBy(2.dp),
                    ) {
                        items(messages, key = { it.id }) { msg ->
                            SupportMessageRow(
                                message = msg,
                                downloadingAttachmentId = downloadingAttachmentId,
                                onAttachmentClick = onAttachmentClick,
                            )
                        }
                    }
                }
            }
            SupportChatComposerBar(
                session = session,
                value = draft,
                onValueChange = { if (it.length <= 4000) draft = it },
                placeholder = "Напишите сообщение…",
                sending = sending,
                canSend = draft.isNotBlank() || pendingFiles.isNotEmpty(),
                onAttachClick = onPickFiles,
                onSendClick = {
                    onSend(draft)
                    draft = ""
                },
                modifier = Modifier.padding(top = 8.dp),
            )
            SupportFileChipsRow(
                files = pendingFiles,
                onRemove = onRemoveFile,
                modifier = Modifier.padding(top = 8.dp),
            )
            TextButton(
                onClick = onComplaintClick,
                modifier = Modifier.padding(top = 4.dp),
            ) {
                Text(
                    text = "Пожаловаться",
                    color = Color(0xFF808080),
                    style = MaterialTheme.typography.bodyMedium,
                    textDecoration = androidx.compose.ui.text.style.TextDecoration.Underline,
                )
            }
        }
    }
}

@Composable
fun SupportComplaintDialog(
    sending: Boolean,
    onDismiss: () -> Unit,
    onSubmit: (String) -> Unit,
) {
    var body by remember { mutableStateOf("") }
    Dialog(
        onDismissRequest = { if (!sending) onDismiss() },
        properties = DialogProperties(usePlatformDefaultWidth = false),
    ) {
        Column(
            modifier = Modifier
                .fillMaxSize()
                .background(Color.White)
                .padding(16.dp),
        ) {
            Row(
                modifier = Modifier.fillMaxWidth(),
                horizontalArrangement = Arrangement.SpaceBetween,
                verticalAlignment = Alignment.CenterVertically,
            ) {
                Text(
                    text = "Жалоба",
                    style = MaterialTheme.typography.titleMedium.copy(fontWeight = FontWeight.SemiBold),
                )
                TextButton(onClick = onDismiss, enabled = !sending) {
                    Text("✕", fontSize = 20.sp)
                }
            }
            SupportStyledField(
                value = body,
                onValueChange = { if (it.length <= 4000) body = it },
                placeholder = "Опишите жалобу (до 4000 символов)",
                minLines = 8,
                modifier = Modifier
                    .padding(top = 16.dp)
                    .weight(1f),
            )
            Row(
                modifier = Modifier.fillMaxWidth(),
                horizontalArrangement = Arrangement.End,
            ) {
                F7PrimaryButton(
                    text = if (sending) "…" else "Отправить",
                    onClick = { onSubmit(body) },
                    enabled = body.isNotBlank() && !sending,
                )
            }
        }
    }
}

@Composable
private fun SupportMessageRow(
    message: SupportMessage,
    downloadingAttachmentId: Long?,
    onAttachmentClick: (SupportAttachment) -> Unit,
) {
    val align = if (message.outgoing) Alignment.CenterEnd else Alignment.CenterStart
    Column(
        modifier = Modifier
            .fillMaxWidth()
            .padding(vertical = 4.dp),
        horizontalAlignment = if (message.outgoing) Alignment.End else Alignment.Start,
    ) {
        if (!message.outgoing) {
            Row(
                verticalAlignment = Alignment.CenterVertically,
                horizontalArrangement = Arrangement.spacedBy(8.dp),
                modifier = Modifier.padding(bottom = 6.dp),
            ) {
                Box(
                    modifier = Modifier
                        .size(20.dp)
                        .clip(CircleShape)
                        .background(F7Colors.PrimaryLight),
                    contentAlignment = Alignment.Center,
                ) {
                    Text("F7", fontSize = 11.sp, fontWeight = FontWeight.Bold, color = F7Colors.Primary)
                }
                Text(
                    text = message.authorLabel,
                    style = MaterialTheme.typography.labelSmall,
                    color = Color(0xFF808080),
                )
            }
        }
        Box(modifier = Modifier.fillMaxWidth(), contentAlignment = align) {
            Column(
                modifier = Modifier
                    .fillMaxWidth(0.88f)
                    .clip(RoundedCornerShape(16.dp))
                    .background(F7Colors.ChatBubbleSupport)
                    .padding(horizontal = 12.dp, vertical = 8.dp),
            ) {
                val text = message.text.trim()
                if (text.isNotBlank() && !isSupportMessagePlaceholder(text)) {
                    Text(
                        text = text,
                        style = MaterialTheme.typography.bodyMedium.copy(
                            fontWeight = FontWeight.Medium,
                            fontSize = 14.sp,
                            lineHeight = 20.sp,
                        ),
                        color = F7Colors.TextPrimary,
                    )
                }
                message.attachments.forEach { att ->
                    SupportAttachmentRow(
                        attachment = att,
                        loading = downloadingAttachmentId == att.id,
                        onClick = { onAttachmentClick(att) },
                    )
                }
                Row(
                    modifier = Modifier
                        .fillMaxWidth()
                        .padding(top = 4.dp),
                    horizontalArrangement = Arrangement.End,
                    verticalAlignment = Alignment.CenterVertically,
                ) {
                    if (message.outgoing) {
                        Text(
                            text = if (message.read) "✓✓" else "✓",
                            style = MaterialTheme.typography.labelSmall,
                            color = F7Colors.TextSecondary,
                            modifier = Modifier.padding(end = 4.dp),
                        )
                    }
                    Text(
                        text = formatSupportMsgTime(message.createdAt),
                        style = MaterialTheme.typography.labelSmall,
                        color = F7Colors.TextSecondary,
                    )
                }
            }
        }
    }
}

@Composable
private fun SupportAttachmentRow(
    attachment: SupportAttachment,
    loading: Boolean = false,
    onClick: () -> Unit = {},
) {
    Row(
        modifier = Modifier
            .fillMaxWidth()
            .padding(top = 6.dp)
            .clip(RoundedCornerShape(100.dp))
            .background(Color.White.copy(alpha = 0.6f))
            .clickable(onClick = onClick)
            .padding(horizontal = 8.dp, vertical = 6.dp),
        verticalAlignment = Alignment.CenterVertically,
        horizontalArrangement = Arrangement.spacedBy(8.dp),
    ) {
        Text(
            text = attachment.filename,
            modifier = Modifier.weight(1f),
            style = MaterialTheme.typography.bodyMedium.copy(fontWeight = FontWeight.Medium),
            maxLines = 1,
            overflow = TextOverflow.Ellipsis,
        )
        if (loading) {
            CircularProgressIndicator(
                modifier = Modifier.size(16.dp),
                strokeWidth = 2.dp,
                color = F7Colors.Primary,
            )
        } else {
            val size = formatSupportFileSize(attachment.sizeBytes)
            if (size.isNotBlank()) {
                Text(text = size, style = MaterialTheme.typography.labelSmall, color = F7Colors.TextSecondary)
            }
        }
    }
}

@Composable
private fun SupportFileChipsRow(
    files: List<SupportPendingFile>,
    onRemove: (String) -> Unit,
    modifier: Modifier = Modifier,
) {
    if (files.isEmpty()) return
    Row(
        modifier = modifier.fillMaxWidth(),
        horizontalArrangement = Arrangement.spacedBy(8.dp),
    ) {
        files.forEach { file ->
            Row(
                modifier = Modifier
                    .clip(RoundedCornerShape(100.dp))
                    .background(FieldBg)
                    .border(1.dp, F7Colors.Border, RoundedCornerShape(100.dp))
                    .padding(start = 12.dp, end = 4.dp, top = 2.dp, bottom = 2.dp),
                verticalAlignment = Alignment.CenterVertically,
            ) {
                Text(
                    text = file.fileName,
                    style = MaterialTheme.typography.bodyMedium.copy(
                        fontWeight = FontWeight.Medium,
                        fontSize = 14.sp,
                    ),
                    maxLines = 1,
                    overflow = TextOverflow.Ellipsis,
                    modifier = Modifier.widthIn(max = 200.dp),
                )
                TextButton(onClick = { onRemove(file.localId) }) {
                    Text("✕", fontSize = 14.sp, color = F7Colors.TextSecondary)
                }
            }
        }
    }
}

@Composable
private fun SupportChatComposerBar(
    session: AuthSession,
    value: String,
    onValueChange: (String) -> Unit,
    placeholder: String,
    sending: Boolean,
    canSend: Boolean,
    onAttachClick: () -> Unit,
    onSendClick: () -> Unit,
    modifier: Modifier = Modifier,
) {
    var emojiOpen by remember { mutableStateOf(false) }
    val base = session.serverUrl.trimEnd('/')
    val asset = { name: String -> "$base/themes/forbion/images/spreed/$name" }

    Column(modifier = modifier.fillMaxWidth(), verticalArrangement = Arrangement.spacedBy(6.dp)) {
        SupportEmojiPicker(
            visible = emojiOpen,
            onDismiss = { emojiOpen = false },
            onEmojiSelected = { onValueChange(value + it) },
        )
        Row(
            modifier = Modifier.fillMaxWidth(),
            verticalAlignment = Alignment.CenterVertically,
            horizontalArrangement = Arrangement.spacedBy(8.dp),
        ) {
            Row(
                modifier = Modifier
                    .weight(1f)
                    .heightIn(min = 48.dp)
                    .clip(RoundedCornerShape(100.dp))
                    .background(FieldBg)
                    .border(1.dp, F7Colors.TalkComposerBorder, RoundedCornerShape(100.dp))
                    .padding(horizontal = 4.dp),
                verticalAlignment = Alignment.CenterVertically,
            ) {
                Box(
                    modifier = Modifier
                        .size(40.dp)
                        .clip(CircleShape)
                        .clickable(enabled = !sending) { emojiOpen = !emojiOpen },
                    contentAlignment = Alignment.Center,
                ) {
                    AsyncImage(
                        model = asset("smile-icon-black.svg"),
                        contentDescription = "Смайлики",
                        modifier = Modifier.size(20.dp),
                    )
                }
                OutlinedTextField(
                    value = value,
                    onValueChange = onValueChange,
                    modifier = Modifier.weight(1f),
                    enabled = !sending,
                    placeholder = {
                        Text(placeholder, color = F7Colors.TextSecondary, fontSize = 14.sp)
                    },
                    minLines = 1,
                    maxLines = 4,
                    shape = RoundedCornerShape(100.dp),
                    colors = OutlinedTextFieldDefaults.colors(
                        focusedContainerColor = Color.Transparent,
                        unfocusedContainerColor = Color.Transparent,
                        focusedBorderColor = Color.Transparent,
                        unfocusedBorderColor = Color.Transparent,
                        disabledBorderColor = Color.Transparent,
                        cursorColor = F7Colors.Primary,
                    ),
                )
                Box(
                    modifier = Modifier
                        .size(40.dp)
                        .clip(CircleShape)
                        .clickable(enabled = !sending, onClick = onAttachClick),
                    contentAlignment = Alignment.Center,
                ) {
                    AsyncImage(
                        model = asset("paramrts-black.svg"),
                        contentDescription = "Вложение",
                        modifier = Modifier.size(20.dp),
                    )
                }
            }
            Box(
                modifier = Modifier
                    .size(48.dp)
                    .clip(CircleShape)
                    .background(
                        brush = Brush.linearGradient(
                            listOf(F7Colors.PrimaryGradientStart, F7Colors.PrimaryGradientEnd),
                        ),
                        shape = CircleShape,
                    )
                    .clickable(enabled = canSend && !sending, onClick = onSendClick),
                contentAlignment = Alignment.Center,
            ) {
                if (sending) {
                    CircularProgressIndicator(
                        modifier = Modifier.size(20.dp),
                        strokeWidth = 2.dp,
                        color = F7Colors.TextOnPrimary,
                    )
                } else {
                    AsyncImage(
                        model = asset("chevron-up-icon-white.svg"),
                        contentDescription = "Отправить",
                        modifier = Modifier.size(18.dp),
                    )
                }
            }
        }
    }
}

private val supportQuickEmojis = listOf(
    "😀", "😂", "😍", "👍", "🙏", "🔥", "❤️", "🎉", "😢", "👏", "✅", "🤔",
)

@Composable
private fun SupportEmojiPicker(
    visible: Boolean,
    onDismiss: () -> Unit,
    onEmojiSelected: (String) -> Unit,
) {
    if (!visible) return
    Surface(
        modifier = Modifier.fillMaxWidth(),
        shape = RoundedCornerShape(12.dp),
        color = F7Colors.Surface,
        shadowElevation = 4.dp,
    ) {
        Column(Modifier.padding(12.dp)) {
            Row(
                modifier = Modifier.fillMaxWidth(),
                horizontalArrangement = Arrangement.SpaceBetween,
                verticalAlignment = Alignment.CenterVertically,
            ) {
                Text("Смайлики", style = MaterialTheme.typography.labelMedium)
                TextButton(onClick = onDismiss) { Text("Закрыть") }
            }
            Row(
                modifier = Modifier
                    .fillMaxWidth()
                    .padding(top = 8.dp),
                horizontalArrangement = Arrangement.spacedBy(4.dp),
            ) {
                supportQuickEmojis.forEach { emoji ->
                    Text(
                        text = emoji,
                        fontSize = 22.sp,
                        modifier = Modifier
                            .clip(RoundedCornerShape(8.dp))
                            .clickable {
                                onEmojiSelected(emoji)
                                onDismiss()
                            }
                            .padding(4.dp),
                    )
                }
            }
        }
    }
}

@Composable
private fun SupportComposerField(
    value: String,
    onValueChange: (String) -> Unit,
    placeholder: String,
    onAttachClick: () -> Unit,
    modifier: Modifier = Modifier,
    minLines: Int = 3,
) {
    Box(modifier = modifier.fillMaxWidth()) {
        SupportStyledField(
            value = value,
            onValueChange = onValueChange,
            placeholder = placeholder,
            minLines = minLines,
            modifier = Modifier
                .fillMaxWidth()
                .padding(end = 44.dp, bottom = 36.dp),
        )
        Box(
            modifier = Modifier
                .align(Alignment.BottomEnd)
                .padding(end = 10.dp, bottom = 10.dp)
                .size(36.dp)
                .clip(RoundedCornerShape(8.dp))
                .clickable(onClick = onAttachClick),
            contentAlignment = Alignment.Center,
        ) {
            Text(
                text = "📎",
                fontSize = 18.sp,
            )
        }
    }
}

private fun isSupportMessagePlaceholder(text: String): Boolean = text == "."

@Composable
private fun SupportStyledField(
    value: String,
    onValueChange: (String) -> Unit,
    placeholder: String,
    modifier: Modifier = Modifier,
    singleLine: Boolean = false,
    minLines: Int = 1,
) {
    OutlinedTextField(
        value = value,
        onValueChange = onValueChange,
        modifier = modifier.fillMaxWidth(),
        placeholder = { Text(placeholder, color = F7Colors.TextSecondary) },
        singleLine = singleLine,
        minLines = if (singleLine) 1 else minLines,
        shape = RoundedCornerShape(8.dp),
        colors = OutlinedTextFieldDefaults.colors(
            focusedContainerColor = FieldBg,
            unfocusedContainerColor = FieldBg,
            focusedBorderColor = F7Colors.Border,
            unfocusedBorderColor = F7Colors.Border,
        ),
    )
}
