package ru.forbion.f7cloud.feature.mail

import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Locale

enum class MailListFilter {
    ALL,
    UNREAD,
    STARRED,
}

data class MailSearchParams(
    val subject: String = "",
    val body: String = "",
    val dateStart: String = "",
    val dateEnd: String = "",
    val from: String = "",
    val to: String = "",
    val cc: String = "",
    val bcc: String = "",
    val tags: String = "",
    val important: Boolean = false,
    val starred: Boolean = false,
    val unread: Boolean = false,
    val hasAttachments: Boolean = false,
    val mentionsMe: Boolean = false,
) {
    fun isActive(): Boolean = subject.isNotBlank() ||
        body.isNotBlank() ||
        dateStart.isNotBlank() ||
        dateEnd.isNotBlank() ||
        from.isNotBlank() ||
        to.isNotBlank() ||
        cc.isNotBlank() ||
        bcc.isNotBlank() ||
        tags.isNotBlank() ||
        important ||
        starred ||
        unread ||
        hasAttachments ||
        mentionsMe

    fun toFilterString(): String {
        val parts = mutableListOf<String>()
        fun addToken(prefix: String, value: String) {
            val trimmed = value.trim()
            if (trimmed.isNotBlank()) parts += "$prefix$trimmed"
        }
        addToken("subject:", subject)
        addToken("body:", body)
        addToken("start:", dateStart)
        addToken("end:", dateEnd)
        addToken("from:", from)
        addToken("to:", to)
        addToken("cc:", cc)
        addToken("bcc:", bcc)
        addToken("tags:", tags)
        if (important) parts += "is:important"
        if (starred) parts += "is:starred"
        if (unread) parts += "is:unread"
        if (hasAttachments) parts += "flags:attachments"
        if (mentionsMe) parts += "mentions:true"
        return parts.joinToString(" ")
    }
}

enum class MailQuickFilter(val label: String) {
    MENTIONS_ME("Мои"),
    HAS_ATTACHMENTS("Имеет вложения"),
    LAST_7_DAYS("Последние 7 дней"),
}

fun mailLast7DaysStartDate(): String {
    val calendar = Calendar.getInstance()
    calendar.add(Calendar.DAY_OF_YEAR, -7)
    return SimpleDateFormat("yyyy-MM-dd", Locale.US).format(calendar.time)
}

fun MailSearchParams.isLast7DaysActive(): Boolean =
    dateStart == mailLast7DaysStartDate() && dateEnd.isBlank()

fun MailSearchParams.isQuickFilterActive(filter: MailQuickFilter): Boolean = when (filter) {
    MailQuickFilter.MENTIONS_ME -> mentionsMe
    MailQuickFilter.HAS_ATTACHMENTS -> hasAttachments
    MailQuickFilter.LAST_7_DAYS -> isLast7DaysActive()
}

fun MailSearchParams.toggleQuickFilter(filter: MailQuickFilter): MailSearchParams = when (filter) {
    MailQuickFilter.MENTIONS_ME -> copy(mentionsMe = !mentionsMe)
    MailQuickFilter.HAS_ATTACHMENTS -> copy(hasAttachments = !hasAttachments)
    MailQuickFilter.LAST_7_DAYS -> if (isLast7DaysActive()) {
        copy(dateStart = "", dateEnd = "")
    } else {
        copy(dateStart = mailLast7DaysStartDate(), dateEnd = "")
    }
}

sealed interface MailInboxListItem {
    data class YearHeader(val year: Int) : MailInboxListItem
    data class MessageItem(val message: MailMessage) : MailInboxListItem
}

fun messageYear(dateInt: Long): Int? {
    if (dateInt <= 0) return null
    val calendar = Calendar.getInstance()
    calendar.timeInMillis = dateInt * 1000L
    return calendar.get(Calendar.YEAR)
}

fun buildMailInboxListItems(messages: List<MailMessage>): List<MailInboxListItem> {
    if (messages.isEmpty()) return emptyList()
    val out = mutableListOf<MailInboxListItem>()
    var lastYear: Int? = null
    for (message in messages) {
        val year = messageYear(message.dateInt)
        if (year != null && year != lastYear) {
            out += MailInboxListItem.YearHeader(year)
            lastYear = year
        }
        out += MailInboxListItem.MessageItem(message)
    }
    return out
}

fun mailFolderListTitle(
    folder: MailFolderEntry?,
    searchQuery: String,
    searchParams: MailSearchParams,
): String? {
    if (folder?.specialRole == "outbox") return null
    if (searchQuery.isNotBlank() || searchParams.isActive()) return "Результаты поиска"
    if (folder?.specialRole == "inbox" && folder.filter == MailListFilter.ALL) return null
    return folder?.title
}

data class MailAccount(
    val id: Int,
    val email: String,
    val name: String,
    val draftsMailboxId: Int?,
    val sentMailboxId: Int?,
    val trashMailboxId: Int?,
    val archiveMailboxId: Int?,
    val junkMailboxId: Int?,
    val snoozeMailboxId: Int? = null,
)

data class MailMailbox(
    val id: Int,
    val accountId: Int,
    val displayName: String,
    val name: String,
    val specialRole: String?,
    val unread: Int,
    val isInbox: Boolean,
)

data class MailFolderEntry(
    val mailboxId: Int,
    val accountId: Int,
    val title: String,
    val specialRole: String?,
    val filter: MailListFilter,
    val unread: Int = 0,
) {
    fun cacheKey(): String = "${mailboxId}_${filter.name}"
}

data class MailMessageFlags(
    val seen: Boolean,
    val flagged: Boolean,
    val hasAttachments: Boolean,
    val answered: Boolean,
    val important: Boolean = false,
)

data class MailTag(
    val id: Long = 0,
    val displayName: String,
    val colorHex: String = "",
    val imapLabel: String = "",
)

data class MailMessage(
    val id: Int,
    val subject: String,
    val from: String,
    val fromEmail: String,
    val preview: String,
    val dateInt: Long,
    val flags: MailMessageFlags,
    val tags: List<MailTag> = emptyList(),
)

data class MailAttachment(
    val id: String,
    val fileName: String,
    val mime: String,
    val size: Long,
    val cid: String? = null,
    val downloadUrl: String? = null,
)

data class MailMessageDetail(
    val id: Int,
    val subject: String,
    val from: String,
    val fromEmail: String,
    val to: String,
    val cc: String,
    val dateInt: Long,
    val bodyHtml: String,
    val bodyPlain: String,
    val hasHtmlBody: Boolean,
    val flags: MailMessageFlags,
    val attachments: List<MailAttachment>,
    val tags: List<MailTag> = emptyList(),
)

fun MailMessage.toDetailStub(): MailMessageDetail =
    MailMessageDetail(
        id = id,
        subject = subject,
        from = from,
        fromEmail = fromEmail,
        to = "",
        cc = "",
        dateInt = dateInt,
        bodyHtml = "",
        bodyPlain = "",
        hasHtmlBody = false,
        flags = flags,
        attachments = emptyList(),
        tags = tags,
    )

fun MailMessageDetail.hasBodyContent(): Boolean =
    bodyHtml.isNotBlank() || bodyPlain.isNotBlank()

private val HTML_BODY_HINT = Regex("""^\s*<(?:!DOCTYPE|html|head|body|table|div|p|span|br|meta)\b""", RegexOption.IGNORE_CASE)

fun MailMessageDetail.looksLikeHtml(): Boolean =
    hasHtmlBody ||
        HTML_BODY_HINT.containsMatchIn(bodyHtml) ||
        HTML_BODY_HINT.containsMatchIn(bodyPlain)

fun MailMessageDetail.htmlBodyForDisplay(): String = when {
    bodyHtml.isNotBlank() -> bodyHtml
    bodyPlain.isNotBlank() && HTML_BODY_HINT.containsMatchIn(bodyPlain) -> bodyPlain
    else -> ""
}

fun MailMessageDetail.plainBodyForDisplay(): String {
    if (bodyPlain.isNotBlank() && !HTML_BODY_HINT.containsMatchIn(bodyPlain)) return bodyPlain
    if (bodyHtml.isNotBlank() && !HTML_BODY_HINT.containsMatchIn(bodyHtml)) return bodyHtml
    return ""
}

data class MailBootstrap(
    val accounts: List<MailAccount>,
    val mailboxes: List<MailMailbox>,
    val folders: List<MailFolderEntry>,
    val selectedFolder: MailFolderEntry?,
)

data class MailMessagesPage(
    val messages: List<MailMessage>,
    // Long: курсор = dateInt (Unix-секунды); Int резал бы значение (баг, ломается ~2038).
    val nextCursor: Long?,
)

data class MailAppSettings(
    val showThreaded: Boolean = true,
    val highlightExternalAddresses: Boolean = false,
    val allowNewAccounts: Boolean = true,
    val trustedSenders: List<MailTrustedSender> = emptyList(),
    val textBlocks: List<MailTextBlock> = emptyList(),
)

data class MailTrustedSender(
    val id: Int,
    val email: String,
    val type: String,
)

data class MailTextBlock(
    val id: Int,
    val title: String,
    val content: String,
    val preview: String = "",
)

data class MailAccountSettings(
    val id: Int,
    val email: String,
    val name: String,
    val signature: String,
    val draftsMailboxId: Int?,
    val sentMailboxId: Int?,
    val trashMailboxId: Int?,
    val archiveMailboxId: Int?,
    val junkMailboxId: Int?,
    val searchBody: Boolean,
    val classificationEnabled: Boolean,
    val signatureAboveQuote: Boolean,
    val imipCreate: Boolean,
    val quotaPercentage: Int?,
    val imapHost: String?,
    val smtpHost: String?,
)

data class MailOutboxMessage(
    val id: Int,
    val accountId: Int,
    val subject: String,
    val toRecipients: String,
    val preview: String,
    val updatedAt: Long,
    val sendAt: Long?,
    val failed: Boolean,
    val status: Int,
)

object MailVirtualFolders {
    val OUTBOX = MailFolderEntry(
        mailboxId = 0,
        accountId = 0,
        title = "Исходящие",
        specialRole = "outbox",
        filter = MailListFilter.ALL,
    )
}
