package ru.forbion.f7cloud.core.designsystem

import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.clickable
import androidx.compose.foundation.horizontalScroll
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.widthIn
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ColumnScope
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.TextButton
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.OutlinedTextFieldDefaults
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.ui.input.key.Key
import androidx.compose.ui.input.key.KeyEventType
import androidx.compose.ui.input.key.key
import androidx.compose.ui.input.key.onKeyEvent
import androidx.compose.ui.input.key.onPreviewKeyEvent
import androidx.compose.ui.input.key.type
import androidx.compose.ui.text.input.KeyboardCapitalization
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.input.VisualTransformation
import androidx.compose.ui.draw.clip
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.draw.shadow
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
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

/**
 * Кнопки forbion (mobile):
 * - [F7PrimaryButton] — градиент, CTA («Создать», «Войти», «Отправить»)
 * - [F7SolidPrimaryButton] — сплошной зелёный, диалоги NC
 * - [F7SecondaryButton] — outline, «Обновить», «Назад», «Отмена»
 * - [F7TextButton] — tertiary, текст без фона
 */

@Composable
fun F7ScreenBackground(modifier: Modifier = Modifier, content: @Composable () -> Unit) {
    Box(
        modifier = modifier
            .fillMaxSize()
            .background(F7Colors.Background),
    ) {
        content()
    }
}

/**
 * Единый экран ошибки (по центру): иконка + сообщение + кнопка «Повторить».
 * Используется везде, где загрузка упала и данных нет — вместо россыпи красного текста.
 */
@Composable
fun F7ErrorState(
    message: String,
    modifier: Modifier = Modifier,
    onRetry: (() -> Unit)? = null,
) {
    Column(
        modifier = modifier
            .fillMaxSize()
            .padding(24.dp),
        horizontalAlignment = Alignment.CenterHorizontally,
        verticalArrangement = Arrangement.Center,
    ) {
        Box(
            modifier = Modifier
                .size(56.dp)
                .clip(CircleShape)
                .background(F7Colors.Error.copy(alpha = 0.12f)),
            contentAlignment = Alignment.Center,
        ) {
            Text("!", color = F7Colors.Error, fontSize = 30.sp, fontWeight = FontWeight.Bold)
        }
        Spacer(Modifier.height(12.dp))
        Text(
            text = message,
            style = MaterialTheme.typography.bodyMedium,
            color = F7Colors.TextSecondary,
            textAlign = TextAlign.Center,
        )
        if (onRetry != null) {
            Spacer(Modifier.height(16.dp))
            F7SecondaryButton(text = "Повторить", onClick = onRetry)
        }
    }
}

@Composable
fun F7ModuleScreen(
    title: String? = null,
    modifier: Modifier = Modifier,
    loading: Boolean = false,
    error: String? = null,
    onRefresh: (() -> Unit)? = null,
    // Действие «Повторить» в экране ошибки; по умолчанию — как onRefresh.
    // Позволяет дать retry, не показывая хедер-кнопку ↻ (когда onRefresh не задан).
    onErrorRetry: (() -> Unit)? = onRefresh,
    headerActions: @Composable RowScope.() -> Unit = {},
    content: @Composable ColumnScope.() -> Unit,
) {
    val showTitle = !title.isNullOrBlank()
    val showHeader = showTitle || onRefresh != null
    Column(
        modifier = modifier
            .fillMaxSize()
            .padding(horizontal = 16.dp, vertical = 12.dp),
        verticalArrangement = Arrangement.spacedBy(12.dp),
    ) {
        if (showHeader) {
            Row(
                modifier = Modifier.fillMaxWidth(),
                verticalAlignment = Alignment.CenterVertically,
            ) {
                if (showTitle) {
                    Text(
                        text = title.orEmpty(),
                        style = MaterialTheme.typography.titleLarge,
                        color = F7Colors.TextPrimary,
                        modifier = Modifier
                            .weight(1f)
                            .padding(end = 8.dp),
                        maxLines = 1,
                        overflow = TextOverflow.Ellipsis,
                    )
                } else {
                    Spacer(modifier = Modifier.weight(1f))
                }
                Row(
                    modifier = Modifier.horizontalScroll(rememberScrollState()),
                    horizontalArrangement = Arrangement.spacedBy(6.dp),
                    verticalAlignment = Alignment.CenterVertically,
                ) {
                    headerActions()
                    if (onRefresh != null) {
                        F7HeaderActionButton(
                            text = "↻",
                            onClick = onRefresh,
                            enabled = !loading,
                        )
                    }
                }
            }
        }
        if (loading) {
            CircularProgressIndicator(color = F7Colors.Primary)
        }
        if (!error.isNullOrBlank()) {
            // Ошибка без данных → центрированный экран с «Повторить»
            F7ErrorState(
                message = error,
                onRetry = onErrorRetry,
                modifier = Modifier
                    .fillMaxWidth()
                    .weight(1f),
            )
        } else {
            Column(
                modifier = Modifier
                    .fillMaxWidth()
                    .weight(1f),
                content = content,
            )
        }
    }
}

@Composable
fun F7PrimaryButton(
    text: String,
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
) {
    val shape = RoundedCornerShape(100.dp)
    val gradient = Brush.linearGradient(
        colors = listOf(F7Colors.PrimaryGradientStart, F7Colors.PrimaryGradientEnd),
    )
    Button(
        onClick = onClick,
        enabled = enabled,
        modifier = modifier
            .heightIn(min = 44.dp)
            .shadow(
                elevation = 4.dp,
                shape = shape,
                spotColor = F7Colors.Primary.copy(alpha = 0.18f),
                ambientColor = F7Colors.Primary.copy(alpha = 0.10f),
            ),
        shape = shape,
        colors = ButtonDefaults.buttonColors(
            containerColor = Color.Transparent,
            disabledContainerColor = Color.Transparent,
        ),
        contentPadding = androidx.compose.foundation.layout.PaddingValues(0.dp),
    ) {
        Box(
            modifier = Modifier
                .fillMaxWidth()
                .border(1.dp, F7Colors.Primary.copy(alpha = 0.22f), shape)
                .background(brush = gradient, shape = shape)
                .padding(horizontal = 18.dp, vertical = 10.dp),
            contentAlignment = Alignment.Center,
        ) {
            Text(
                text = text,
                color = F7Colors.TextOnPrimary,
                style = MaterialTheme.typography.labelLarge,
            )
        }
    }
}

@Composable
fun F7SolidPrimaryButton(
    text: String,
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
) {
    Button(
        onClick = onClick,
        enabled = enabled,
        modifier = modifier.heightIn(min = 40.dp),
        shape = RoundedCornerShape(100.dp),
        colors = ButtonDefaults.buttonColors(
            containerColor = F7Colors.Primary,
            contentColor = F7Colors.TextOnPrimary,
            disabledContainerColor = F7Colors.Border,
            disabledContentColor = F7Colors.TextSecondary,
        ),
    ) {
        Text(text = text, style = MaterialTheme.typography.labelLarge)
    }
}

@Composable
fun F7HeaderActionButton(
    text: String,
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
) {
    OutlinedButton(
        onClick = onClick,
        enabled = enabled,
        modifier = modifier
            .heightIn(min = 36.dp)
            .widthIn(min = 36.dp, max = 52.dp),
        shape = RoundedCornerShape(100.dp),
        border = BorderStroke(1.dp, F7Colors.SecondaryButtonBorder),
        colors = ButtonDefaults.outlinedButtonColors(
            containerColor = F7Colors.SecondaryButtonBg,
            contentColor = F7Colors.TextPrimary,
        ),
        contentPadding = androidx.compose.foundation.layout.PaddingValues(horizontal = 8.dp, vertical = 4.dp),
    ) {
        Text(
            text = text,
            style = MaterialTheme.typography.labelLarge,
            maxLines = 1,
        )
    }
}

@Composable
fun F7SecondaryButton(
    text: String,
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
) {
    OutlinedButton(
        onClick = onClick,
        enabled = enabled,
        modifier = modifier.heightIn(min = 40.dp),
        shape = RoundedCornerShape(100.dp),
        border = BorderStroke(1.dp, F7Colors.SecondaryButtonBorder),
        colors = ButtonDefaults.outlinedButtonColors(
            containerColor = F7Colors.SecondaryButtonBg,
            contentColor = F7Colors.TextPrimary,
        ),
    ) {
        Text(text = text, style = MaterialTheme.typography.labelLarge)
    }
}

@Composable
fun F7TextButton(
    text: String,
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
) {
    TextButton(
        onClick = onClick,
        enabled = enabled,
        modifier = modifier,
        colors = ButtonDefaults.textButtonColors(
            contentColor = F7Colors.TextPrimary,
            disabledContentColor = F7Colors.TextSecondary,
        ),
    ) {
        Text(text = text, style = MaterialTheme.typography.labelLarge)
    }
}

@Composable
fun F7AlertDialog(
    title: String,
    onDismiss: () -> Unit,
    confirmText: String,
    onConfirm: () -> Unit,
    modifier: Modifier = Modifier,
    dismissText: String = "Отмена",
    confirmEnabled: Boolean = true,
    content: @Composable ColumnScope.() -> Unit,
) {
    Dialog(onDismissRequest = onDismiss) {
        Surface(
            modifier = modifier.widthIn(max = 400.dp),
            shape = RoundedCornerShape(12.dp),
            color = F7Colors.Surface,
        ) {
            Column(
                modifier = Modifier.padding(20.dp),
                verticalArrangement = Arrangement.spacedBy(16.dp),
            ) {
                Text(text = title, style = MaterialTheme.typography.titleMedium, color = F7Colors.TextPrimary)
                content()
                Row(
                    modifier = Modifier.fillMaxWidth(),
                    horizontalArrangement = Arrangement.spacedBy(8.dp, Alignment.End),
                ) {
                    F7SecondaryButton(text = dismissText, onClick = onDismiss)
                    F7SolidPrimaryButton(
                        text = confirmText,
                        onClick = onConfirm,
                        enabled = confirmEnabled,
                    )
                }
            }
        }
    }
}

@Composable
fun F7MessageComposer(
    value: String,
    onValueChange: (String) -> Unit,
    onSend: () -> Unit,
    modifier: Modifier = Modifier,
    sending: Boolean = false,
    label: String = "Сообщение",
) {
    Row(
        modifier = modifier.fillMaxWidth(),
        horizontalArrangement = Arrangement.spacedBy(8.dp),
        verticalAlignment = Alignment.Bottom,
    ) {
        F7OutlinedField(
            value = value,
            onValueChange = onValueChange,
            label = label,
            modifier = Modifier.weight(1f),
        )
        F7PrimaryButton(
            text = if (sending) "…" else "Отправить",
            onClick = onSend,
            enabled = value.isNotBlank() && !sending,
        )
    }
}

private val LINE_BREAK_CHARS = Regex("[\\r\\n\\u000B\\u000C\\u2028\\u2029\\u0085]")

private fun stripLineBreaks(text: String): String = text.replace(LINE_BREAK_CHARS, "")

private fun Modifier.consumeEnterKey(onEnter: () -> Unit): Modifier = this
    .onPreviewKeyEvent { event ->
        if (event.type == KeyEventType.KeyDown && event.isEnterKey()) {
            onEnter()
            true
        } else {
            false
        }
    }
    .onKeyEvent { event ->
        if (event.type == KeyEventType.KeyDown && event.isEnterKey()) {
            onEnter()
            true
        } else {
            false
        }
    }

private fun androidx.compose.ui.input.key.KeyEvent.isEnterKey(): Boolean =
    key == Key.Enter || key == Key.NumPadEnter

@Composable
fun F7OutlinedField(
    value: String,
    onValueChange: (String) -> Unit,
    label: String,
    modifier: Modifier = Modifier,
    minLines: Int = 1,
    visualTransformation: VisualTransformation = VisualTransformation.None,
    keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
    keyboardActions: KeyboardActions = KeyboardActions.Default,
    onEnter: (() -> Unit)? = null,
) {
    val singleLine = minLines <= 1
    val mergedKeyboardOptions = if (singleLine) {
        keyboardOptions.copy(
            capitalization = KeyboardCapitalization.None,
            autoCorrectEnabled = false,
        )
    } else {
        keyboardOptions
    }
    OutlinedTextField(
        value = value,
        onValueChange = { newValue ->
            if (!singleLine) {
                onValueChange(newValue)
                return@OutlinedTextField
            }
            val hadLineBreak = LINE_BREAK_CHARS.containsMatchIn(newValue)
            val stripped = stripLineBreaks(newValue)
            if (stripped != value) {
                onValueChange(stripped)
            } else if (stripped != newValue) {
                onValueChange(stripped)
            }
            if (hadLineBreak) {
                onEnter?.invoke()
            }
        },
        modifier = modifier
            .fillMaxWidth()
            .then(if (onEnter != null && singleLine) Modifier.consumeEnterKey(onEnter) else Modifier),
        label = { Text(label) },
        minLines = if (singleLine) 1 else minLines,
        visualTransformation = visualTransformation,
        keyboardOptions = mergedKeyboardOptions,
        keyboardActions = keyboardActions,
        singleLine = singleLine,
        maxLines = if (singleLine) 1 else minLines,
        shape = RoundedCornerShape(100.dp),
        colors = OutlinedTextFieldDefaults.colors(
            focusedBorderColor = F7Colors.Primary,
            unfocusedBorderColor = F7Colors.Border,
            focusedContainerColor = Color(0xFFFDFDFD),
            unfocusedContainerColor = Color(0xFFFDFDFD),
            cursorColor = F7Colors.Primary,
        ),
    )
}

@Composable
fun F7ListCard(
    modifier: Modifier = Modifier,
    selected: Boolean = false,
    onClick: (() -> Unit)? = null,
    content: @Composable ColumnScope.() -> Unit,
) {
    val shape = RoundedCornerShape(8.dp)
    Column(
        modifier = modifier
            .fillMaxWidth()
            .clip(shape)
            .background(F7Colors.Surface)
            .border(
                width = if (selected) 2.dp else 1.dp,
                color = if (selected) F7Colors.PrimaryGradientEnd else F7Colors.Border,
                shape = shape,
            )
            .then(if (onClick != null) Modifier.clickable(onClick = onClick) else Modifier)
            .padding(12.dp),
        content = content,
    )
}

@Composable
fun F7ChatBubble(
    text: String,
    outgoing: Boolean,
    subtitle: String? = null,
    modifier: Modifier = Modifier,
) {
    val bg = if (outgoing) F7Colors.ChatBubbleOut else F7Colors.ChatBubbleIn
    val align = if (outgoing) Alignment.CenterEnd else Alignment.CenterStart
    Box(modifier = modifier.fillMaxWidth(), contentAlignment = align) {
        Column(
            modifier = Modifier
                .fillMaxWidth(0.88f)
                .clip(RoundedCornerShape(8.dp))
                .background(bg)
                .border(1.dp, F7Colors.Border.copy(alpha = 0.5f), RoundedCornerShape(8.dp))
                .padding(horizontal = 12.dp, vertical = 8.dp),
        ) {
            if (!subtitle.isNullOrBlank()) {
                Text(
                    text = subtitle,
                    style = MaterialTheme.typography.labelSmall,
                    color = F7Colors.TextSecondary,
                )
            }
            Text(text = text, style = MaterialTheme.typography.bodyMedium, color = F7Colors.ChatText)
        }
    }
}

@Composable
fun F7TicketCard(
    ticketNumber: String,
    subject: String,
    status: String,
    preview: String,
    hasUnread: Boolean,
    selected: Boolean,
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
) {
    val statusColor = when {
        status.equals("Новый", ignoreCase = true) -> F7Colors.StatusNew
        status.equals("В работе", ignoreCase = true) -> F7Colors.StatusProgress
        else -> F7Colors.StatusClosed
    }
    F7ListCard(modifier = modifier, selected = selected, onClick = onClick) {
        Row(
            modifier = Modifier
                .fillMaxWidth()
                .clip(RoundedCornerShape(4.dp))
                .background(F7Colors.SurfaceMuted)
                .padding(8.dp),
            horizontalArrangement = Arrangement.SpaceBetween,
            verticalAlignment = Alignment.CenterVertically,
        ) {
            Text(
                text = subject,
                style = MaterialTheme.typography.titleSmall,
                color = F7Colors.TextPrimary,
                maxLines = 2,
                overflow = TextOverflow.Ellipsis,
                modifier = Modifier.weight(1f),
            )
            F7StatusChip(text = status, color = statusColor)
        }
        Text(
            text = "#$ticketNumber",
            style = MaterialTheme.typography.labelSmall,
            color = F7Colors.TextSecondary,
            modifier = Modifier.padding(top = 6.dp),
        )
        if (preview.isNotBlank()) {
            Text(
                text = preview,
                style = MaterialTheme.typography.bodyMedium,
                color = F7Colors.TextSecondary,
                maxLines = 3,
                overflow = TextOverflow.Ellipsis,
                modifier = Modifier.padding(top = 8.dp),
            )
        }
        if (hasUnread) {
            Text(
                text = "Новое",
                color = F7Colors.Primary,
                style = MaterialTheme.typography.labelMedium,
                modifier = Modifier.padding(top = 6.dp),
            )
        }
    }
}

@Composable
fun F7StatusChip(text: String, color: Color) {
    Text(
        text = text,
        modifier = Modifier
            .clip(RoundedCornerShape(100.dp))
            .background(color)
            .padding(horizontal = 12.dp, vertical = 4.dp),
        color = F7Colors.TextOnPrimary,
        style = MaterialTheme.typography.labelSmall,
    )
}

@Composable
fun F7AppScaffold(
    modifier: Modifier = Modifier,
    bottomBar: @Composable () -> Unit = {},
    content: @Composable (Modifier) -> Unit,
) {
    Box(modifier = modifier.fillMaxSize()) {
        F7ScreenBackground(modifier = Modifier.fillMaxSize()) {
            content(
                Modifier
                    .fillMaxSize()
                    // Отступы под статус-бар (сверху) И системную навигацию (снизу),
                    // иначе на edge-to-edge (targetSdk 36) контент залезает под панели.
                    .f7SafeTopInsets()
                    .f7SafeBottomInsets(),
            )
        }
        Box(
            modifier = Modifier
                .align(Alignment.BottomCenter)
                .fillMaxWidth(),
            contentAlignment = Alignment.BottomCenter,
        ) {
            bottomBar()
        }
    }
}
