package com.rosetta.messenger.ui.chats.calls

import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
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.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Call
import androidx.compose.material.icons.filled.CallMade
import androidx.compose.material.icons.filled.CallReceived
import androidx.compose.material.icons.filled.Close
import androidx.compose.material3.Divider
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.produceState
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
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.platform.LocalContext
import com.airbnb.lottie.compose.LottieAnimation
import com.airbnb.lottie.compose.LottieCompositionSpec
import com.airbnb.lottie.compose.animateLottieCompositionAsState
import com.airbnb.lottie.compose.rememberLottieComposition
import com.rosetta.messenger.R
import com.rosetta.messenger.database.CallHistoryRow
import com.rosetta.messenger.database.RosettaDatabase
import com.rosetta.messenger.network.SearchUser
import com.rosetta.messenger.repository.AvatarRepository
import com.rosetta.messenger.ui.components.AvatarImage
import com.rosetta.messenger.ui.components.VerifiedBadge
import com.rosetta.messenger.data.MessageRepository
import com.rosetta.messenger.ui.onboarding.PrimaryBlue
import compose.icons.TablerIcons
import compose.icons.tablericons.Phone
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Date
import java.util.Locale
import org.json.JSONArray

private data class CallHistoryItem(
    val messageId: String,
    val peerKey: String,
    val peerTitle: String,
    val peerUsername: String,
    val peerVerified: Int,
    val peerOnline: Int,
    val timestamp: Long,
    val isOutgoing: Boolean,
    val durationSec: Int,
    val isMissed: Boolean
) {
    fun toSearchUser(): SearchUser =
        SearchUser(
            publicKey = peerKey,
            title = peerTitle,
            username = peerUsername,
            verified = peerVerified,
            online = peerOnline
        )
}

@Composable
fun CallsHistoryScreen(
    isDarkTheme: Boolean,
    accountPublicKey: String,
    avatarRepository: AvatarRepository?,
    onOpenChat: (SearchUser) -> Unit,
    onStartCall: (SearchUser) -> Unit,
    onStartNewCall: () -> Unit,
    modifier: Modifier = Modifier
) {
    val context = LocalContext.current
    val messageDao = remember(context) { RosettaDatabase.getDatabase(context).messageDao() }

    val rows by produceState(initialValue = emptyList<CallHistoryRow>(), accountPublicKey) {
        if (accountPublicKey.isBlank()) {
            value = emptyList()
            return@produceState
        }
        messageDao.getCallHistoryFlow(accountPublicKey).collect { value = it }
    }

    val items = remember(rows) { rows.map { it.toCallHistoryItem() } }

    val backgroundColor = if (isDarkTheme) Color(0xFF1A1A1A) else Color(0xFFF2F2F7)
    val textColor = if (isDarkTheme) Color.White else Color(0xFF111111)
    val secondaryTextColor = if (isDarkTheme) Color(0xFF9D9DA3) else Color(0xFF7A7A80)
    val dividerColor = if (isDarkTheme) Color(0xFF2D2D2F) else Color(0xFFE7E7EA)

    LazyColumn(
        modifier = modifier.fillMaxSize().background(backgroundColor),
        contentPadding = if (items.isEmpty()) PaddingValues(0.dp) else PaddingValues(bottom = 16.dp)
    ) {
        if (items.isEmpty()) {
            item(key = "empty_calls") {
                Column(
                    modifier = Modifier.fillParentMaxSize(),
                    verticalArrangement = Arrangement.Center
                ) {
                    EmptyCallsState(
                        isDarkTheme = isDarkTheme,
                        title = "No Calls Yet",
                        subtitle = "Your recent voice and video calls will\nappear here.",
                        modifier = Modifier.fillMaxWidth().padding(horizontal = 20.dp)
                    )
                }
            }
        } else {
            items(items, key = { it.messageId }) { item ->
                CallHistoryRowItem(
                    item = item,
                    isDarkTheme = isDarkTheme,
                    avatarRepository = avatarRepository,
                    textColor = textColor,
                    secondaryTextColor = secondaryTextColor,
                    onOpenChat = onOpenChat,
                    onStartCall = onStartCall
                )
                Divider(color = dividerColor, thickness = 0.5.dp)
            }
        }
    }
}

@Composable
private fun StartNewCallRow(
    isDarkTheme: Boolean,
    onClick: () -> Unit
) {
    val rowColor = if (isDarkTheme) Color(0xFF1B2B3A) else Color(0xFFEAF4FF)
    val textColor = if (isDarkTheme) Color(0xFF74B8FF) else Color(0xFF1A73E8)

    Row(
        modifier = Modifier.fillMaxWidth().background(rowColor).clickable(onClick = onClick)
            .padding(horizontal = 16.dp, vertical = 13.dp),
        verticalAlignment = Alignment.CenterVertically
    ) {
        Icon(
            imageVector = TablerIcons.Phone,
            contentDescription = null,
            tint = textColor,
            modifier = Modifier.size(22.dp)
        )
        Spacer(modifier = Modifier.width(12.dp))
        Text(
            text = "Start New Call",
            color = textColor,
            fontSize = 16.sp,
            fontWeight = FontWeight.Medium
        )
    }
}

@Composable
private fun CallHistoryRowItem(
    item: CallHistoryItem,
    isDarkTheme: Boolean,
    avatarRepository: AvatarRepository?,
    textColor: Color,
    secondaryTextColor: Color,
    onOpenChat: (SearchUser) -> Unit,
    onStartCall: (SearchUser) -> Unit
) {
    val subtitleColor =
        when {
            item.isMissed -> Color(0xFFE55A5A)
            isDarkTheme -> Color(0xFF56D97A)
            else -> Color(0xFF1EA75E)
        }
    val directionIconColor =
        if (item.durationSec == 0) Color(0xFFE55A5A) else subtitleColor
    val directionIcon =
        when {
            item.durationSec == 0 -> Icons.Default.Close
            item.isOutgoing -> Icons.Default.CallMade
            else -> Icons.Default.CallReceived
        }
    val subtitleText =
        when {
            item.durationSec > 0 -> "${item.directionLabel()}  ${formatCallTimestamp(item.timestamp)}"
            else -> item.directionLabel() + "  " + formatCallTimestamp(item.timestamp)
        }

    Row(
        modifier =
            Modifier.fillMaxWidth()
                .clickable { onOpenChat(item.toSearchUser()) }
                .padding(horizontal = 14.dp, vertical = 10.dp),
        verticalAlignment = Alignment.CenterVertically
    ) {
        AvatarImage(
            publicKey = item.peerKey,
            avatarRepository = avatarRepository,
            size = 52.dp,
            isDarkTheme = isDarkTheme,
            displayName = item.peerTitle
        )

        Spacer(modifier = Modifier.width(12.dp))

        Column(
            modifier = Modifier.weight(1f)
        ) {
            Row(verticalAlignment = Alignment.CenterVertically) {
                Text(
                    text = item.peerTitle,
                    color = textColor,
                    fontSize = 16.sp,
                    fontWeight = FontWeight.SemiBold,
                    maxLines = 1,
                    overflow = TextOverflow.Ellipsis,
                    modifier = Modifier.weight(1f, fill = false)
                )
                val isOfficialByKey = MessageRepository.isSystemAccount(item.peerKey)
                if (item.peerVerified > 0 || isOfficialByKey) {
                    Spacer(modifier = Modifier.width(4.dp))
                    VerifiedBadge(
                        verified = if (item.peerVerified > 0) item.peerVerified else 1,
                        size = 16,
                        isDarkTheme = isDarkTheme
                    )
                }
            }
            Spacer(modifier = Modifier.height(3.dp))
            Row(
                verticalAlignment = Alignment.CenterVertically
            ) {
                Icon(
                    imageVector = directionIcon,
                    contentDescription = null,
                    tint = directionIconColor,
                    modifier = Modifier.size(14.dp)
                )
                Spacer(modifier = Modifier.width(4.dp))
                Text(
                    text = subtitleText,
                    color = if (item.isMissed) Color(0xFFE55A5A) else secondaryTextColor,
                    fontSize = 13.sp,
                    maxLines = 1,
                    overflow = TextOverflow.Ellipsis
                )
            }
        }

        IconButton(
            onClick = { onStartCall(item.toSearchUser()) }
        ) {
            Icon(
                imageVector = Icons.Default.Call,
                contentDescription = "Call",
                tint = PrimaryBlue
            )
        }
    }
}

@Composable
private fun EmptyCallsState(
    isDarkTheme: Boolean,
    title: String,
    subtitle: String,
    modifier: Modifier = Modifier
) {
    val titleColor = if (isDarkTheme) Color(0xFFEDEDF2) else Color(0xFF1C1C1E)
    val subtitleColor = if (isDarkTheme) Color(0xFF9D9DA3) else Color(0xFF8E8E93)
    val cardColor = if (isDarkTheme) Color(0xFF242529) else Color(0xFFF6F6FA)
    val lottieComposition by rememberLottieComposition(
        LottieCompositionSpec.RawRes(R.raw.phone_duck)
    )
    val lottieProgress by animateLottieCompositionAsState(
        composition = lottieComposition,
        iterations = 1
    )

    Column(
        modifier = modifier,
        horizontalAlignment = Alignment.CenterHorizontally,
        verticalArrangement = Arrangement.Center
    ) {
        Column(
            modifier = Modifier
                .fillMaxWidth()
                .background(cardColor, RoundedCornerShape(28.dp))
                .padding(horizontal = 20.dp, vertical = 24.dp),
            horizontalAlignment = Alignment.CenterHorizontally
        ) {
            if (lottieComposition != null) {
                LottieAnimation(
                    composition = lottieComposition,
                    progress = { lottieProgress },
                    modifier = Modifier.size(184.dp)
                )
            } else {
                Icon(
                    imageVector = Icons.Default.Call,
                    contentDescription = null,
                    tint = subtitleColor,
                    modifier = Modifier.size(52.dp)
                )
            }
            Spacer(modifier = Modifier.height(18.dp))
            if (title.isNotBlank()) {
                Text(
                    text = title,
                    color = titleColor,
                    fontSize = 22.sp,
                    lineHeight = 24.sp,
                    fontWeight = FontWeight.SemiBold,
                    textAlign = TextAlign.Center
                )
                Spacer(modifier = Modifier.height(8.dp))
            }
            Text(
                text = subtitle,
                color = subtitleColor,
                fontSize = 15.sp,
                lineHeight = 20.sp,
                textAlign = TextAlign.Center
            )
        }
    }
}

private fun CallHistoryRow.toCallHistoryItem(): CallHistoryItem {
    val displayName = resolveDisplayName(peerTitle.orEmpty(), peerUsername.orEmpty(), peerKey)
    val username = peerUsername.orEmpty().trim().trimStart('@')
    val durationSec = parseCallDurationFromAttachments(message.attachments)
    val isOutgoing = message.fromMe == 1
    val isMissed = !isOutgoing && durationSec == 0

    return CallHistoryItem(
        messageId = message.messageId,
        peerKey = peerKey,
        peerTitle = displayName,
        peerUsername = username,
        peerVerified = peerVerified ?: 0,
        peerOnline = peerOnline ?: 0,
        timestamp = message.timestamp,
        isOutgoing = isOutgoing,
        durationSec = durationSec,
        isMissed = isMissed
    )
}

private fun resolveDisplayName(title: String, username: String, publicKey: String): String {
    val normalizedTitle = title.trim()
    if (normalizedTitle.isNotEmpty() &&
        normalizedTitle != publicKey &&
        normalizedTitle != publicKey.take(7) &&
        normalizedTitle != publicKey.take(8)
    ) {
        return normalizedTitle
    }

    val normalizedUsername = username.trim().trimStart('@')
    if (normalizedUsername.isNotEmpty()) return normalizedUsername

    return publicKey.take(8)
}

private fun parseCallDurationFromAttachments(attachmentsJson: String): Int {
    if (attachmentsJson.isBlank() || attachmentsJson == "[]") return 0
    return runCatching {
        val attachments = JSONArray(attachmentsJson)
        for (i in 0 until attachments.length()) {
            val attachment = attachments.optJSONObject(i) ?: continue
            if (attachment.optInt("type", -1) != 4) continue
            return parseCallDurationSeconds(attachment.optString("preview", ""))
        }
        0
    }.getOrDefault(0)
}

private fun parseCallDurationSeconds(preview: String): Int {
    if (preview.isBlank()) return 0

    preview.substringAfterLast("::").trim().toIntOrNull()?.let {
        return it.coerceAtLeast(0)
    }

    val durationRegex =
        Regex("duration(?:Sec|Seconds)?\\s*[:=]\\s*(\\d+)", RegexOption.IGNORE_CASE)
    durationRegex.find(preview)?.groupValues?.getOrNull(1)?.toIntOrNull()?.let {
        return it.coerceAtLeast(0)
    }

    return preview.trim().toIntOrNull()?.coerceAtLeast(0) ?: 0
}

private fun CallHistoryItem.directionLabel(): String {
    return when {
        durationSec == 0 && isOutgoing -> "Rejected call"
        durationSec == 0 && !isOutgoing -> "Missed call"
        isOutgoing -> "Outgoing call"
        else -> "Incoming call"
    }
}

private fun formatCallTimestamp(timestamp: Long): String {
    if (timestamp <= 0L) return ""
    val now = Calendar.getInstance()
    val callTime = Calendar.getInstance().apply { timeInMillis = timestamp }

    val sameYear = now.get(Calendar.YEAR) == callTime.get(Calendar.YEAR)
    val sameDay =
        sameYear && now.get(Calendar.DAY_OF_YEAR) == callTime.get(Calendar.DAY_OF_YEAR)

    val yesterday = now.clone() as Calendar
    yesterday.add(Calendar.DAY_OF_YEAR, -1)
    val isYesterday =
        sameYear && yesterday.get(Calendar.DAY_OF_YEAR) == callTime.get(Calendar.DAY_OF_YEAR)

    return when {
        sameDay -> SimpleDateFormat("HH:mm", Locale.getDefault()).format(Date(timestamp))
        isYesterday -> "Yesterday"
        else -> SimpleDateFormat("dd MMM", Locale.getDefault()).format(Date(timestamp))
    }
}
