package com.ponzischeme89.memby.ui.alerts

import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.clickable
import androidx.compose.foundation.focusGroup
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
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.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.NotificationsActive
import androidx.compose.material.icons.filled.Tv
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.focus.onFocusChanged
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.compose.ui.zIndex
import androidx.tv.material3.Icon
import androidx.tv.material3.Text
import com.ponzischeme89.memby.data.model.NotificationPreferences
import com.ponzischeme89.memby.data.model.UserNotification
import com.ponzischeme89.memby.ui.MembyChoiceChip
import com.ponzischeme89.memby.ui.formatMyShowDate
import com.ponzischeme89.memby.ui.theme.MembyAccent
import com.ponzischeme89.memby.ui.theme.MembyCardCorner
import com.ponzischeme89.memby.ui.theme.MembyHairline
import com.ponzischeme89.memby.ui.theme.MembyMutedText
import com.ponzischeme89.memby.ui.theme.MembyQuietText
import com.ponzischeme89.memby.ui.theme.MembySurface
import kotlinx.coroutines.delay

/**
 * My Alerts — a full page rather than the panel it used to be, reached from the user menu in
 * the user picker.
 *
 * It moved there because these alerts belong to a *person*, not to a television: they follow
 * whoever is signed in, so the place that already answers "who is watching" is where somebody
 * looks for their own news. The bell it replaced sat in the corner of the launcher, was only
 * drawn on Home, and cost a focus target on every set in the house whether or not there was
 * anything behind it.
 *
 * It reads like Settings on purpose — black canvas, flat rows on a shared 16dp inset with
 * hairlines between them, and the row under focus the only lit surface on the page.
 *
 * Two things are worth preserving. **A press dismisses**, with the focused row saying so, and
 * the hint is what makes that safe: this is the only page whose whole job is emptying itself,
 * and a second confirmation press on every alert is what made the old panel not worth
 * opening. And **focus marks read** — a row can only be read by being looked at, so nothing
 * has to be pressed to clear the "new" flag on it.
 *
 * Stateless by design: the caller owns the list and the requests, so this can be previewed
 * and screenshotted with no server.
 */
@Composable
fun MyAlertsPage(
    notifications: List<UserNotification>,
    preferences: NotificationPreferences,
    onToggleEnabled: () -> Unit,
    onToggleShowReturns: () -> Unit,
    onRead: (UserNotification) -> Unit,
    onDismiss: (UserNotification) -> Unit,
    onDismissAll: () -> Unit,
    onClose: () -> Unit,
    modifier: Modifier = Modifier,
) {
    val listFocusRequester = remember { FocusRequester() }
    val actionsFocusRequester = remember { FocusRequester() }
    val hasAlerts = notifications.isNotEmpty()
    LaunchedEffect(hasAlerts) {
        // One frame for the list to place its first row; an empty page has nothing below
        // the actions to land on, so the chips take the remote instead.
        delay(16)
        runCatching {
            if (hasAlerts) listFocusRequester.requestFocus() else actionsFocusRequester.requestFocus()
        }
    }

    Box(modifier.fillMaxSize().zIndex(9f).background(MembySurface)) {
        Column(
            modifier = Modifier
                .fillMaxSize()
                .padding(horizontal = 56.dp)
                .padding(top = 40.dp, bottom = 28.dp),
        ) {
            AlertsHeader(
                total = notifications.size,
                unread = notifications.count(UserNotification::unread),
            )
            Spacer(Modifier.height(20.dp))
            Row(
                modifier = Modifier.fillMaxWidth().focusGroup(),
                horizontalArrangement = Arrangement.spacedBy(10.dp),
                verticalAlignment = Alignment.CenterVertically,
            ) {
                MembyChoiceChip(
                    label = if (preferences.enabled) "Alerts on" else "Alerts off",
                    selected = preferences.enabled,
                    onClick = onToggleEnabled,
                    modifier = Modifier.focusRequester(actionsFocusRequester),
                )
                MembyChoiceChip(
                    label = if (preferences.showReturnAlerts) "Show returns on" else "Show returns off",
                    selected = preferences.enabled && preferences.showReturnAlerts,
                    onClick = { if (preferences.enabled) onToggleShowReturns() },
                )
                Spacer(Modifier.width(1.dp))
                if (hasAlerts) {
                    MembyChoiceChip(
                        label = "Dismiss all",
                        selected = false,
                        onClick = onDismissAll,
                    )
                }
                Spacer(Modifier.weight(1f))
                MembyChoiceChip(label = "Close", selected = false, onClick = onClose)
            }
            Spacer(Modifier.height(18.dp))
            Box(Modifier.fillMaxWidth().height(1.dp).background(MembyHairline))
            if (!hasAlerts) {
                AlertsEmptyState(enabled = preferences.enabled)
            } else {
                LazyColumn(
                    modifier = Modifier.fillMaxWidth().weight(1f),
                    contentPadding = PaddingValues(vertical = 6.dp),
                ) {
                    items(notifications, key = UserNotification::id) { notification ->
                        AlertRow(
                            notification = notification,
                            modifier = if (notification.id == notifications.first().id) {
                                Modifier.focusRequester(listFocusRequester)
                            } else {
                                Modifier
                            },
                            onFocused = { if (notification.unread) onRead(notification) },
                            onClick = { onDismiss(notification) },
                        )
                        if (notification.id != notifications.last().id) {
                            Box(
                                Modifier
                                    .fillMaxWidth()
                                    .padding(horizontal = 16.dp)
                                    .height(1.dp)
                                    .background(MembyHairline),
                            )
                        }
                    }
                }
            }
        }
    }
}

@Composable
private fun AlertsHeader(total: Int, unread: Int) {
    Column(
        modifier = Modifier.padding(start = 16.dp),
        verticalArrangement = Arrangement.spacedBy(4.dp),
    ) {
        Text("My Alerts", color = Color.White, fontSize = 32.sp, fontWeight = FontWeight.Bold)
        Text(alertsSummary(total, unread), color = MembyQuietText, fontSize = 14.sp)
    }
}

@Composable
private fun AlertsEmptyState(enabled: Boolean) {
    Column(
        modifier = Modifier.fillMaxSize(),
        verticalArrangement = Arrangement.Center,
        horizontalAlignment = Alignment.CenterHorizontally,
    ) {
        Text("You’re all caught up.", color = MembyMutedText, fontSize = 20.sp, fontWeight = FontWeight.SemiBold)
        Spacer(Modifier.height(8.dp))
        Text(
            if (enabled) {
                "Alerts about the shows you follow will show up here."
            } else {
                "Alerts are switched off, so nothing new will arrive here."
            },
            color = MembyQuietText,
            fontSize = 14.sp,
        )
    }
}

@Composable
private fun AlertRow(
    notification: UserNotification,
    onFocused: () -> Unit,
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
) {
    var focused by remember { mutableStateOf(false) }
    val shape = RoundedCornerShape(MembyCardCorner)
    Row(
        modifier = modifier
            .fillMaxWidth()
            .onFocusChanged {
                focused = it.isFocused
                if (it.isFocused) onFocused()
            }
            .clip(shape)
            .background(if (focused) Color.White.copy(alpha = 0.11f) else Color.Transparent)
            .border(
                width = if (focused) 2.dp else 1.dp,
                color = if (focused) Color.White.copy(alpha = 0.88f) else Color.Transparent,
                shape = shape,
            )
            .clickable(onClick = onClick)
            .semantics {
                contentDescription = "${notification.title}. ${notification.message}. Press to dismiss."
            }
            .padding(horizontal = 16.dp, vertical = 15.dp),
        verticalAlignment = Alignment.CenterVertically,
        horizontalArrangement = Arrangement.spacedBy(16.dp),
    ) {
        Box(
            Modifier.size(38.dp).clip(CircleShape).background(
                if (notification.unread) MembyAccent.copy(alpha = 0.18f) else Color.White.copy(alpha = 0.05f),
            ),
            contentAlignment = Alignment.Center,
        ) {
            Icon(
                alertIcon(notification.kind),
                contentDescription = null,
                tint = if (notification.unread) MembyAccent else MembyQuietText,
                modifier = Modifier.size(19.dp),
            )
        }
        Column(Modifier.weight(1f), verticalArrangement = Arrangement.spacedBy(3.dp)) {
            Row(verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(9.dp)) {
                Text(
                    notification.title,
                    color = Color.White,
                    fontSize = 17.sp,
                    fontWeight = FontWeight.SemiBold,
                    maxLines = 1,
                    overflow = TextOverflow.Ellipsis,
                )
                if (notification.unread) {
                    Text(
                        "NEW",
                        color = MembyAccent,
                        fontSize = 9.sp,
                        fontWeight = FontWeight.Bold,
                        letterSpacing = 1.sp,
                        modifier = Modifier
                            .clip(RoundedCornerShape(4.dp))
                            .background(MembyAccent.copy(alpha = 0.14f))
                            .padding(horizontal = 5.dp, vertical = 2.dp),
                    )
                }
            }
            Text(
                notification.message,
                color = MembyMutedText,
                fontSize = 14.sp,
                maxLines = 2,
                overflow = TextOverflow.Ellipsis,
            )
            notification.eventAt?.takeIf { it.isNotBlank() }?.let {
                Text(formatMyShowDate(it), color = MembyQuietText, fontSize = 12.sp, maxLines = 1)
            }
        }
        // The hint is the whole reason a single press is allowed to dismiss: it is stated on
        // the row about to go, and only on the row under focus.
        Box(Modifier.width(112.dp), contentAlignment = Alignment.CenterEnd) {
            if (focused) {
                Text(
                    "OK to dismiss",
                    color = Color.White,
                    fontSize = 12.sp,
                    fontWeight = FontWeight.Bold,
                    maxLines = 1,
                )
            }
        }
    }
}

private fun alertIcon(kind: String): ImageVector = when {
    kind.contains("return", ignoreCase = true) -> Icons.Default.Tv
    kind.contains("series", ignoreCase = true) -> Icons.Default.Tv
    else -> Icons.Default.NotificationsActive
}
