package com.syncflow.ui.home

import androidx.compose.animation.core.LinearEasing
import androidx.compose.animation.core.animateFloat
import androidx.compose.animation.core.infiniteRepeatable
import androidx.compose.animation.core.rememberInfiniteTransition
import androidx.compose.animation.core.tween
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
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.*
import androidx.compose.material.icons.outlined.*
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import com.syncflow.data.db.entities.SyncPairEntity
import com.syncflow.domain.model.SyncStatus
import com.syncflow.ui.shared.SyncProgress
import java.time.Duration
import java.time.Instant
import java.time.ZoneId
import java.time.format.DateTimeFormatter
import java.time.format.FormatStyle

@Composable
fun HomeScreen(
    onAddPair: () -> Unit,
    onPairClick: (Long) -> Unit,
    modifier: Modifier = Modifier,
    vm: HomeViewModel = hiltViewModel(),
) {
    val pairs by vm.syncPairs.collectAsState()
    val progressMap by vm.syncProgressMap.collectAsState()

    if (pairs.isEmpty()) {
        EmptyState(modifier = modifier.fillMaxSize(), onAdd = onAddPair)
    } else {
        LazyColumn(
            modifier = modifier.fillMaxSize(),
            contentPadding = PaddingValues(horizontal = 16.dp, vertical = 8.dp),
            verticalArrangement = Arrangement.spacedBy(10.dp),
        ) {
            items(pairs, key = { it.id }) { pair ->
                SyncPairCard(
                    pair = pair,
                    progress = progressMap[pair.id],
                    onClick = { onPairClick(pair.id) },
                    onSync = { vm.triggerSync(pair) },
                    onToggle = { vm.toggleEnabled(pair) },
                    onPause = { vm.pauseSync(pair) },
                )
            }
            item { Spacer(Modifier.height(80.dp)) }
        }
    }
}

@Composable
private fun SyncPairCard(
    pair: SyncPairEntity,
    progress: SyncProgress? = null,
    onClick: () -> Unit,
    onSync: () -> Unit,
    onToggle: () -> Unit,
    onPause: () -> Unit = {},
) {
    val accentColor = pair.lastSyncResult.accentColor

    Card(
        modifier = Modifier
            .fillMaxWidth()
            .clickable(onClick = onClick),
        shape = RoundedCornerShape(16.dp),
        border = BorderStroke(1.dp, MaterialTheme.colorScheme.outline),
        colors = CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.surface),
    ) {
        Row(modifier = Modifier.fillMaxWidth()) {
            // Colored left accent bar
            Box(
                modifier = Modifier
                    .width(3.dp)
                    .height(IntrinsicSize.Min)
                    .defaultMinSize(minHeight = 80.dp),
            ) {
                Box(
                    modifier = Modifier
                        .fillMaxHeight()
                        .width(3.dp),
                ) {
                    Surface(
                        modifier = Modifier.fillMaxSize(),
                        color = accentColor,
                    ) {}
                }
            }

            Column(modifier = Modifier.padding(start = 12.dp, top = 12.dp, end = 12.dp, bottom = 12.dp)) {
                Row(verticalAlignment = Alignment.CenterVertically) {
                    Column(modifier = Modifier.weight(1f)) {
                        Text(
                            pair.name,
                            style = MaterialTheme.typography.titleMedium,
                        )
                        Spacer(Modifier.height(2.dp))
                        val localShortName = pair.localPath.toDisplayPath()
                        Text(
                            localShortName,
                            style = MaterialTheme.typography.bodySmall,
                            color = MaterialTheme.colorScheme.onSurfaceVariant,
                        )
                        Spacer(Modifier.height(2.dp))
                        Row(verticalAlignment = Alignment.CenterVertically) {
                            Icon(
                                Icons.Default.ArrowForward,
                                contentDescription = null,
                                modifier = Modifier.size(12.dp),
                                tint = MaterialTheme.colorScheme.onSurfaceVariant,
                            )
                            Spacer(Modifier.width(4.dp))
                            Text(
                                pair.remotePath,
                                style = MaterialTheme.typography.bodySmall,
                                color = MaterialTheme.colorScheme.onSurfaceVariant,
                            )
                        }
                    }
                    Switch(
                        checked = pair.isEnabled,
                        onCheckedChange = { onToggle() },
                    )
                }
                Spacer(Modifier.height(8.dp))
                Row(
                    verticalAlignment = Alignment.CenterVertically,
                    horizontalArrangement = Arrangement.spacedBy(8.dp),
                ) {
                    StatusPill(pair.lastSyncResult)
                    if (pair.pendingConflicts > 0) {
                        Surface(
                            shape = RoundedCornerShape(50),
                            color = MaterialTheme.colorScheme.errorContainer,
                        ) {
                            Row(
                                modifier = Modifier.padding(horizontal = 8.dp, vertical = 4.dp),
                                verticalAlignment = Alignment.CenterVertically,
                                horizontalArrangement = Arrangement.spacedBy(4.dp),
                            ) {
                                Icon(Icons.Default.Warning, null, Modifier.size(12.dp), tint = MaterialTheme.colorScheme.error)
                                Text(
                                    "${pair.pendingConflicts} conflicts",
                                    style = MaterialTheme.typography.labelSmall,
                                    color = MaterialTheme.colorScheme.error,
                                )
                            }
                        }
                    }
                    Spacer(Modifier.weight(1f))
                    pair.lastSyncAt?.let { at ->
                        Text(
                            at.toRelativeString(),
                            style = MaterialTheme.typography.labelSmall,
                            color = MaterialTheme.colorScheme.onSurfaceVariant,
                        )
                    }
                    val syncRotation by rememberInfiniteTransition(label = "cardSyncSpin").animateFloat(
                        initialValue = 0f, targetValue = 360f,
                        animationSpec = infiniteRepeatable(tween(900, easing = LinearEasing)),
                        label = "cardRotation",
                    )
                    when (pair.lastSyncResult) {
                        SyncStatus.SYNCING -> FilledTonalIconButton(onClick = onPause, modifier = Modifier.size(36.dp)) {
                            Icon(Icons.Default.Pause, "Pause sync", modifier = Modifier.size(18.dp))
                        }
                        SyncStatus.PAUSED -> FilledTonalIconButton(onClick = onSync, modifier = Modifier.size(36.dp), enabled = pair.isEnabled) {
                            Icon(Icons.Default.PlayArrow, "Resume sync", modifier = Modifier.size(18.dp))
                        }
                        else -> FilledTonalIconButton(onClick = onSync, modifier = Modifier.size(36.dp)) {
                            Icon(Icons.Default.Sync, "Sync now", modifier = Modifier.size(18.dp).graphicsLayer { rotationZ = syncRotation * 0f })
                        }
                    }
                }

                val displayProgress = when {
                    pair.lastSyncResult == SyncStatus.SYNCING -> progress
                    pair.lastSyncUploaded > 0 || pair.lastSyncDownloaded > 0 || pair.lastSyncDeleted > 0 ->
                        SyncProgress(pair.lastSyncUploaded, pair.lastSyncDownloaded, pair.lastSyncDeleted, pair.lastSyncBytesTransferred)
                    else -> null
                }
                if (pair.lastSyncResult == SyncStatus.SYNCING && displayProgress == null) {
                    Text(
                        "Starting…",
                        style = MaterialTheme.typography.labelSmall,
                        color = MaterialTheme.colorScheme.onSurfaceVariant,
                        modifier = Modifier.padding(top = 4.dp),
                    )
                } else if (displayProgress != null) {
                    Row(
                        modifier = Modifier.padding(top = 4.dp),
                        verticalAlignment = Alignment.CenterVertically,
                        horizontalArrangement = Arrangement.spacedBy(4.dp),
                    ) {
                        if (displayProgress.uploaded > 0) {
                            Icon(Icons.Default.ArrowUpward, null, Modifier.size(11.dp), tint = MaterialTheme.colorScheme.primary)
                            Text("${displayProgress.uploaded}", style = MaterialTheme.typography.labelSmall, color = MaterialTheme.colorScheme.primary)
                        }
                        if (displayProgress.downloaded > 0) {
                            Icon(Icons.Default.ArrowDownward, null, Modifier.size(11.dp), tint = MaterialTheme.colorScheme.secondary)
                            Text("${displayProgress.downloaded}", style = MaterialTheme.typography.labelSmall, color = MaterialTheme.colorScheme.secondary)
                        }
                        if (displayProgress.deleted > 0) {
                            Icon(Icons.Default.DeleteOutline, null, Modifier.size(11.dp), tint = MaterialTheme.colorScheme.error)
                            Text("${displayProgress.deleted}", style = MaterialTheme.typography.labelSmall, color = MaterialTheme.colorScheme.error)
                        }
                        if (displayProgress.bytesTransferred > 0) {
                            Text(
                                "· ${displayProgress.bytesTransferred.toDisplaySize()}",
                                style = MaterialTheme.typography.labelSmall,
                                color = MaterialTheme.colorScheme.onSurfaceVariant,
                            )
                        }
                    }
                }
            }
        }
    }
}

@Composable
private fun StatusPill(status: SyncStatus) {
    val (icon, label) = when (status) {
        SyncStatus.SUCCESS  -> Pair(Icons.Default.CheckCircle, "Synced")
        SyncStatus.SYNCING  -> Pair(Icons.Default.Sync, "Syncing…")
        SyncStatus.PAUSED   -> Pair(Icons.Default.Pause, "Paused")
        SyncStatus.FAILED   -> Pair(Icons.Default.Error, "Failed")
        SyncStatus.CONFLICT -> Pair(Icons.Default.Warning, "Conflict")
        SyncStatus.PARTIAL  -> Pair(Icons.Default.WarningAmber, "Partial")
        SyncStatus.IDLE     -> Pair(Icons.Outlined.Circle, "Idle")
    }
    val containerColor = status.accentColor
    val rotation by rememberInfiniteTransition(label = "syncSpin").animateFloat(
        initialValue = 0f, targetValue = 360f,
        animationSpec = infiniteRepeatable(tween(1000, easing = LinearEasing)),
        label = "rotation",
    )
    Surface(
        shape = RoundedCornerShape(50),
        color = containerColor.copy(alpha = 0.15f),
    ) {
        Row(
            modifier = Modifier.padding(horizontal = 8.dp, vertical = 4.dp),
            verticalAlignment = Alignment.CenterVertically,
            horizontalArrangement = Arrangement.spacedBy(4.dp),
        ) {
            Icon(
                icon, null,
                Modifier.size(12.dp).graphicsLayer { if (status == SyncStatus.SYNCING) rotationZ = rotation },
                tint = containerColor,
            )
            Text(label, style = MaterialTheme.typography.labelSmall, color = containerColor)
        }
    }
}

@Composable
private fun EmptyState(modifier: Modifier = Modifier, onAdd: () -> Unit) {
    Column(
        modifier = modifier,
        horizontalAlignment = Alignment.CenterHorizontally,
        verticalArrangement = Arrangement.Center,
    ) {
        Icon(
            Icons.Outlined.CloudSync,
            null,
            modifier = Modifier.size(100.dp),
            tint = MaterialTheme.colorScheme.primary.copy(alpha = 0.4f),
        )
        Spacer(Modifier.height(16.dp))
        Text("No sync pairs yet", style = MaterialTheme.typography.titleLarge)
        Spacer(Modifier.height(8.dp))
        Text(
            "Tap + to create your first sync",
            style = MaterialTheme.typography.bodyMedium,
            color = MaterialTheme.colorScheme.onSurfaceVariant,
        )
        Spacer(Modifier.height(24.dp))
        FilledTonalButton(onClick = onAdd) { Text("Add Sync Pair") }
    }
}

private fun Long.toDisplaySize(): String = when {
    this < 1_024 -> "$this B"
    this < 1_048_576 -> "${"%.1f".format(this / 1_024.0)} KB"
    this < 1_073_741_824 -> "${"%.1f".format(this / 1_048_576.0)} MB"
    else -> "${"%.1f".format(this / 1_073_741_824.0)} GB"
}

private val SyncStatus.accentColor: Color
    @Composable get() = when (this) {
        SyncStatus.SUCCESS  -> Color(0xFF2E7D32)
        SyncStatus.SYNCING  -> Color(0xFF1565C0)
        SyncStatus.PAUSED   -> Color(0xFF6A1B9A)
        SyncStatus.FAILED   -> Color(0xFFC62828)
        SyncStatus.PARTIAL  -> Color(0xFFE65100)
        SyncStatus.CONFLICT -> Color(0xFFF9A825)
        SyncStatus.IDLE     -> MaterialTheme.colorScheme.outline
    }

private fun String.toDisplayPath(): String {
    // For SAF content:// URIs, decode the last path segment (e.g. primary%3ASyncFlowTest → SyncFlowTest)
    val decoded = java.net.URLDecoder.decode(this, "UTF-8")
    return decoded.trimEnd('/').substringAfterLast('/').substringAfterLast(':').ifEmpty { decoded }
}

private fun Instant.toRelativeString(): String {
    val diff = Duration.between(this, Instant.now()).abs()
    return when {
        diff.toMinutes() < 1  -> "Just now"
        diff.toMinutes() < 60 -> "${diff.toMinutes()} min ago"
        diff.toHours() < 24   -> "${diff.toHours()} hr ago"
        diff.toDays() == 1L   -> "Yesterday"
        else -> DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT)
            .format(atZone(ZoneId.systemDefault()))
    }
}
