package com.seven.ikar.kotlin.ui

import androidx.compose.ui.graphics.Color
import com.seven.ikar.kotlin.core.contacts.DiscoverUserItem
import com.seven.ikar.kotlin.core.model.ChatSummaryDto
import com.seven.ikar.kotlin.core.model.ChatType
import com.seven.ikar.kotlin.core.model.UserSummaryDto
import com.seven.ikar.kotlin.ui.theme.TelegramBlue
import com.seven.ikar.kotlin.ui.theme.TelegramInkMuted
import java.time.OffsetDateTime
import java.time.ZoneId
import java.time.format.DateTimeFormatter
import java.util.Locale
import kotlin.math.abs

private val AvatarPalette = listOf(
    Color(0xFF5AA7F0),
    Color(0xFF47BFD8),
    Color(0xFF4F83F1),
    Color(0xFF60C689),
    Color(0xFFD488F5),
    Color(0xFFF2A45A),
    Color(0xFFF06C8E),
    Color(0xFF7E8A98)
)

private val TimeFormatter = DateTimeFormatter.ofPattern("HH:mm", Locale("ru", "RU"))
private val DayMonthFormatter = DateTimeFormatter.ofPattern("d MMM", Locale("ru", "RU"))
private val DayMonthYearFormatter = DateTimeFormatter.ofPattern("d MMM yyyy", Locale("ru", "RU"))

fun ikarAvatarInitials(value: String?): String {
    if (value.isNullOrBlank()) {
        return "M"
    }

    val parts = value
        .split(' ', '-', '_')
        .map { it.trim() }
        .filter { it.isNotEmpty() }
        .take(2)
        .map { it.first().uppercaseChar() }

    return if (parts.isEmpty()) "M" else parts.joinToString("")
}

fun ikarAvatarColor(value: String?): Color {
    if (value.isNullOrBlank()) {
        return AvatarPalette.first()
    }

    var hash = 17
    value.trim().forEach { symbol ->
        hash = (hash * 31) + symbol.uppercaseChar().code
    }

    if (hash == Int.MIN_VALUE) {
        hash = Int.MAX_VALUE
    }

    return AvatarPalette[abs(hash) % AvatarPalette.size]
}

fun formatPresence(user: UserSummaryDto): String {
    if (user.isBot) {
        return "бот"
    }
    if (user.isOnline) {
        return "в сети"
    }

    val lastSeen = parseOffsetDateTime(user.lastSeenAt) ?: return "был давно"
    val now = OffsetDateTime.now()
    val delta = java.time.Duration.between(lastSeen, now)

    return when {
        delta < java.time.Duration.ofDays(7) -> "был недавно"
        else -> "был давно"
    }
}

fun formatDiscoverPresence(item: DiscoverUserItem): String = when {
    item.user.isBot -> "бот · @${item.username}"
    item.secondaryLine.isNotBlank() -> item.secondaryLine
    else -> formatPresence(item.user)
}

fun formatPresenceColor(item: DiscoverUserItem): Color = when {
    item.user.isOnline -> TelegramBlue
    else -> TelegramInkMuted
}

fun chatSubtitle(chat: ChatSummaryDto): String = if (!chat.secondaryText.isNullOrBlank()) {
    chat.secondaryText
} else {
    when (chat.type) {
        ChatType.Direct -> "личный чат"
        ChatType.Group -> "группа"
        ChatType.Channel -> if (chat.canSendMessages) "канал" else "канал только для чтения"
    }
}

fun chatPreview(chat: ChatSummaryDto): String = if (!chat.lastMessagePreview.isNullOrBlank()) {
    chat.lastMessagePreview.stripSenderPrefix()
} else {
    when (chat.type) {
        ChatType.Channel -> "Пока нет публикаций"
        else -> "Пока нет сообщений"
    }
}

private fun String.stripSenderPrefix(): String {
    val delimiter = ": "
    val delimiterIndex = indexOf(delimiter)
    if (delimiterIndex <= 0) {
        return this
    }

    val previewWithoutSender = substring(delimiterIndex + delimiter.length)
    return previewWithoutSender.ifBlank { this }
}

fun chatTypeLabel(chatType: ChatType): String = when (chatType) {
    ChatType.Direct -> "ЛИЧНЫЙ"
    ChatType.Group -> "ГРУППА"
    ChatType.Channel -> "КАНАЛ"
}

fun formatLastActivity(lastActivityAt: String?): String {
    val value = parseOffsetDateTime(lastActivityAt) ?: return ""
    val now = OffsetDateTime.now()
    return when {
        value.toLocalDate() == now.toLocalDate() -> value.format(TimeFormatter)
        value.toLocalDate() == now.minusDays(1).toLocalDate() -> "Вчера"
        value.year == now.year -> value.format(DayMonthFormatter)
        else -> value.format(DayMonthYearFormatter)
    }
}

private fun parseOffsetDateTime(value: String?): OffsetDateTime? =
    value?.takeIf { it.isNotBlank() }?.let {
        runCatching {
            OffsetDateTime.parse(it)
                .atZoneSameInstant(ZoneId.systemDefault())
                .toOffsetDateTime()
        }.getOrNull()
    }
