@file:OptIn(androidx.compose.ui.ExperimentalComposeUiApi::class)

package com.ponzischeme89.memby.ui.calendar

import androidx.activity.compose.BackHandler
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.BoxWithConstraints
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.fillMaxHeight
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.layout.widthIn
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material.icons.automirrored.filled.ArrowForward
import androidx.compose.material.icons.filled.CalendarMonth
import androidx.compose.material.icons.filled.Event
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.focusProperties
import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.focus.onFocusChanged
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.ContentScale
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.tv.material3.Icon
import androidx.tv.material3.Text
import coil.compose.AsyncImage
import com.ponzischeme89.memby.ServiceLocator
import com.ponzischeme89.memby.data.model.BaseItem
import com.ponzischeme89.memby.ui.FocusScaleContainer
import com.ponzischeme89.memby.ui.distinctItems
import com.ponzischeme89.memby.ui.theme.MembyAccent
import com.ponzischeme89.memby.ui.theme.MembyCardCorner
import com.ponzischeme89.memby.ui.theme.MembyChipCorner
import com.ponzischeme89.memby.ui.theme.MembyMutedText
import com.ponzischeme89.memby.ui.theme.MembyPanelCorner
import com.ponzischeme89.memby.ui.theme.MembyQuietText
import com.ponzischeme89.memby.ui.theme.MembySurface
import com.ponzischeme89.memby.ui.theme.MembySurfaceRaised

/**
 * A television guide rather than a shrunk wall calendar.
 *
 * One week fills the page. The day rail answers when something is on; the programme pane
 * answers what it is with fanart, title logos and episode milestones. Month travel remains
 * server-authored, while week travel only pages through the seven-cell groups the server's
 * month shape already supplied.
 */
@Composable
internal fun CalendarContent(
    state: CalendarUiState,
    navigationFocusRequester: FocusRequester,
    contentFocusRequester: FocusRequester,
    onShowMonth: (String) -> Unit,
    onSelectDate: (String) -> Unit,
    onRetry: () -> Unit,
    onItemFocused: (BaseItem) -> Unit,
    onItemSelected: (BaseItem) -> Unit,
    onExit: () -> Unit,
    modifier: Modifier = Modifier,
    posterUrlFor: (BaseItem) -> String? = { ServiceLocator.repository.primaryUrl(it, 360) },
    backdropUrlFor: (BaseItem) -> String? = { ServiceLocator.repository.backdropUrl(it, 720) },
    logoUrlFor: (BaseItem) -> String? = { ServiceLocator.repository.logoUrl(it, 420) },
) {
    val weeks = remember(state.calendar) { calendarAgendaWeeks(state.calendar) }
    val weekIndex = remember(weeks, state.selectedDate) {
        calendarAgendaWeekIndex(weeks, state.selectedDate)
    }
    val week = weeks.getOrNull(weekIndex)
    val selectedDay = week?.cells?.firstOrNull { it.date == state.selectedDate }
        ?: week?.cells?.firstOrNull { !it.isPad }
    val selectedItems = remember(selectedDay) { selectedDay?.items.orEmpty().distinctItems() }
    val monthFocusAnchor = calendarMonthFocusAnchor(
        previousMonth = state.calendar.previous,
        nextMonth = state.calendar.next,
    )

    val monthFocusRequester = remember { FocusRequester() }
    val weekFocusRequester = remember { FocusRequester() }
    val selectedDayFocusRequester = remember { FocusRequester() }
    val programmeFocusRequester = remember { FocusRequester() }
    var programmeFocused by remember { mutableStateOf(false) }
    var pageHasFocus by remember { mutableStateOf(true) }

    LaunchedEffect(state.calendar.month, state.isLoading) {
        if (state.isLoading || !pageHasFocus) return@LaunchedEffect
        kotlinx.coroutines.delay(32L)
        runCatching { selectedDayFocusRequester.requestFocus() }
    }
    LaunchedEffect(Unit) {
        kotlinx.coroutines.delay(32L)
        runCatching { contentFocusRequester.requestFocus() }
    }
    BackHandler(enabled = programmeFocused) {
        programmeFocused = false
        runCatching { selectedDayFocusRequester.requestFocus() }
    }
    BackHandler(enabled = !programmeFocused, onBack = onExit)

    BoxWithConstraints(
        modifier
            .fillMaxSize()
            .onFocusChanged { pageHasFocus = it.hasFocus }
            .background(
                Brush.linearGradient(
                    listOf(Color(0xFF070B0D), MembySurface, Color(0xFF07110D)),
                ),
            ),
    ) {
        val dayRailWidth = if (maxWidth >= 1100.dp) 270.dp else 224.dp
        Column(
            Modifier.fillMaxSize().padding(start = 38.dp, end = 30.dp, top = 22.dp, bottom = 22.dp),
        ) {
            AgendaHeader(
                monthLabel = state.calendar.label.ifEmpty { "TV calendar" },
                episodeCount = calendarEpisodeCount(state.calendar),
                previousMonth = state.calendar.previous,
                nextMonth = state.calendar.next,
                monthFocusRequester = monthFocusRequester,
                weekFocusRequester = weekFocusRequester,
                onShowMonth = onShowMonth,
            )
            Spacer(Modifier.height(12.dp))

            when {
                state.isLoading && weeks.isEmpty() -> AgendaNotice("Loading the schedule…")
                state.errorMessage != null && weeks.isEmpty() -> AgendaNotice(
                    state.errorMessage.orEmpty(), "Try again", onRetry,
                )
                !state.calendar.available -> AgendaNotice(
                    "The TV calendar is not available. It needs the Memby gateway with Sonarr configured.",
                )
                week == null -> AgendaNotice("Nothing scheduled.")
                else -> {
                    WeekSwitcher(
                        week = week,
                        weekIndex = weekIndex,
                        weekCount = weeks.size,
                        focusRequester = weekFocusRequester,
                        monthFocusRequester = monthFocusRequester,
                        hasMonthControl = monthFocusAnchor != CalendarMonthFocusAnchor.NONE,
                        onPrevious = {
                            weeks.getOrNull(weekIndex - 1)?.let {
                                onSelectDate(calendarAgendaWeekDate(it))
                            }
                        },
                        onNext = {
                            weeks.getOrNull(weekIndex + 1)?.let {
                                onSelectDate(calendarAgendaWeekDate(it))
                            }
                        },
                    )
                    Spacer(Modifier.height(12.dp))
                    Row(Modifier.fillMaxSize()) {
                        WeekDayRail(
                            week = week,
                            selectedDate = selectedDay?.date.orEmpty(),
                            navigationFocusRequester = navigationFocusRequester,
                            weekFocusRequester = weekFocusRequester,
                            contentFocusRequester = contentFocusRequester,
                            selectedDayFocusRequester = selectedDayFocusRequester,
                            programmeFocusRequester = programmeFocusRequester,
                            onSelectDate = {
                                programmeFocused = false
                                onSelectDate(it)
                            },
                            modifier = Modifier.width(dayRailWidth).fillMaxHeight(),
                        )
                        Spacer(Modifier.width(20.dp))
                        ProgrammePane(
                            heading = calendarDayHeading(state.calendar, selectedDay?.date.orEmpty()),
                            items = selectedItems,
                            programmeFocusRequester = programmeFocusRequester,
                            selectedDayFocusRequester = selectedDayFocusRequester,
                            artworkUrlFor = { backdropUrlFor(it) ?: posterUrlFor(it) },
                            logoUrlFor = logoUrlFor,
                            onFocused = {
                                programmeFocused = true
                                onItemFocused(it)
                            },
                            onSelected = onItemSelected,
                            modifier = Modifier.weight(1f).fillMaxHeight(),
                        )
                    }
                }
            }
        }
    }
}

@Composable
private fun AgendaHeader(
    monthLabel: String,
    episodeCount: Int,
    previousMonth: String,
    nextMonth: String,
    monthFocusRequester: FocusRequester,
    weekFocusRequester: FocusRequester,
    onShowMonth: (String) -> Unit,
) {
    val monthFocusAnchor = calendarMonthFocusAnchor(previousMonth, nextMonth)
    Row(verticalAlignment = Alignment.CenterVertically) {
        Box(
            Modifier.size(38.dp).background(MembyAccent.copy(alpha = 0.14f), CircleShape),
            contentAlignment = Alignment.Center,
        ) {
            Icon(Icons.Default.CalendarMonth, null, tint = MembyAccent, modifier = Modifier.size(21.dp))
        }
        Spacer(Modifier.width(12.dp))
        Column(Modifier.weight(1f)) {
            Text("TV GUIDE", color = MembyAccent, fontSize = 11.sp, fontWeight = FontWeight.Bold)
            Text(monthLabel, color = Color.White, fontSize = 26.sp, fontWeight = FontWeight.SemiBold)
        }
        Text(
            calendarEpisodeCountLabel(episodeCount),
            color = MembyMutedText,
            fontSize = 13.sp,
            modifier = Modifier.padding(end = 14.dp),
        )
        AgendaIconButton(
            icon = Icons.AutoMirrored.Filled.ArrowBack,
            description = "Previous month",
            enabled = previousMonth.isNotEmpty(),
            onClick = { onShowMonth(previousMonth) },
            modifier = Modifier
                .then(
                    if (monthFocusAnchor == CalendarMonthFocusAnchor.PREVIOUS) {
                        Modifier.focusRequester(monthFocusRequester)
                    } else {
                        Modifier
                    },
                )
                .focusProperties { down = weekFocusRequester },
        )
        Spacer(Modifier.width(8.dp))
        AgendaIconButton(
            icon = Icons.AutoMirrored.Filled.ArrowForward,
            description = "Next month",
            enabled = nextMonth.isNotEmpty(),
            onClick = { onShowMonth(nextMonth) },
            modifier = Modifier
                .then(
                    if (monthFocusAnchor == CalendarMonthFocusAnchor.NEXT) {
                        Modifier.focusRequester(monthFocusRequester)
                    } else {
                        Modifier
                    },
                )
                .focusProperties { down = weekFocusRequester },
        )
    }
}

internal enum class CalendarMonthFocusAnchor { PREVIOUS, NEXT, NONE }

internal fun calendarMonthFocusAnchor(
    previousMonth: String,
    nextMonth: String,
): CalendarMonthFocusAnchor = when {
    nextMonth.isNotEmpty() -> CalendarMonthFocusAnchor.NEXT
    previousMonth.isNotEmpty() -> CalendarMonthFocusAnchor.PREVIOUS
    else -> CalendarMonthFocusAnchor.NONE
}

@Composable
private fun WeekSwitcher(
    week: CalendarAgendaWeek,
    weekIndex: Int,
    weekCount: Int,
    focusRequester: FocusRequester,
    monthFocusRequester: FocusRequester,
    hasMonthControl: Boolean,
    onPrevious: () -> Unit,
    onNext: () -> Unit,
) {
    Row(verticalAlignment = Alignment.CenterVertically) {
        AgendaIconButton(
            Icons.AutoMirrored.Filled.ArrowBack,
            "Previous week",
            weekIndex > 0,
            onPrevious,
        )
        Spacer(Modifier.width(10.dp))
        FocusScaleContainer(
            onFocused = {},
            onClick = {},
            contentDescription = "Week ${week.label}",
            modifier = Modifier
                .focusRequester(focusRequester)
                .focusProperties {
                    up = if (hasMonthControl) monthFocusRequester else FocusRequester.Default
                }
                .background(MembySurfaceRaised.copy(alpha = 0.62f), RoundedCornerShape(MembyChipCorner)),
        ) { focused ->
            Row(
                Modifier
                    .background(if (focused) Color.White else Color.Transparent, RoundedCornerShape(MembyChipCorner))
                    .padding(horizontal = 18.dp, vertical = 8.dp),
                verticalAlignment = Alignment.CenterVertically,
            ) {
                Icon(Icons.Default.Event, null, tint = if (focused) MembySurface else MembyAccent, modifier = Modifier.size(16.dp))
                Spacer(Modifier.width(8.dp))
                Text(
                    week.label,
                    color = if (focused) MembySurface else Color.White,
                    fontSize = 14.sp,
                    fontWeight = FontWeight.SemiBold,
                )
                Spacer(Modifier.width(10.dp))
                Text(
                    calendarEpisodeCountLabel(week.episodeCount),
                    color = if (focused) MembySurface.copy(alpha = 0.65f) else MembyQuietText,
                    fontSize = 12.sp,
                )
            }
        }
        Spacer(Modifier.width(10.dp))
        AgendaIconButton(
            Icons.AutoMirrored.Filled.ArrowForward,
            "Next week",
            weekIndex < weekCount - 1,
            onNext,
        )
        Spacer(Modifier.weight(1f))
        Text("WEEK ${weekIndex + 1} OF $weekCount", color = MembyQuietText, fontSize = 11.sp)
    }
}

@Composable
private fun WeekDayRail(
    week: CalendarAgendaWeek,
    selectedDate: String,
    navigationFocusRequester: FocusRequester,
    weekFocusRequester: FocusRequester,
    contentFocusRequester: FocusRequester,
    selectedDayFocusRequester: FocusRequester,
    programmeFocusRequester: FocusRequester,
    onSelectDate: (String) -> Unit,
    modifier: Modifier = Modifier,
) {
    Column(
        modifier
            .background(MembySurfaceRaised.copy(alpha = 0.30f), RoundedCornerShape(MembyPanelCorner))
            .padding(8.dp),
        verticalArrangement = Arrangement.spacedBy(5.dp),
    ) {
        week.cells.forEachIndexed { index, cell ->
            if (cell.isPad) {
                Spacer(Modifier.weight(1f))
            } else {
                val selected = cell.date == selectedDate
                FocusScaleContainer(
                    onFocused = { onSelectDate(cell.date) },
                    onClick = {
                        if (cell.items.isNotEmpty()) runCatching { programmeFocusRequester.requestFocus() }
                    },
                    contentDescription = "${CALENDAR_WEEKDAYS[index]} ${cell.day}, ${calendarEpisodeCountLabel(cell.items.size)}",
                    modifier = Modifier
                        .weight(1f)
                        .fillMaxWidth()
                        .then(
                            if (selected) {
                                Modifier
                                    .focusRequester(contentFocusRequester)
                                    .focusRequester(selectedDayFocusRequester)
                            } else Modifier,
                        )
                        .focusProperties {
                            left = navigationFocusRequester
                            if (index == 0) up = weekFocusRequester
                            if (cell.items.isNotEmpty()) right = programmeFocusRequester
                        },
                ) { focused ->
                    Row(
                        Modifier
                            .fillMaxSize()
                            .background(
                                when {
                                    focused -> Color.White
                                    selected -> MembyAccent.copy(alpha = 0.16f)
                                    else -> Color.Transparent
                                },
                                RoundedCornerShape(MembyCardCorner),
                            )
                            .then(
                                if (selected && !focused) {
                                    Modifier.border(
                                        1.dp,
                                        MembyAccent.copy(alpha = 0.55f),
                                        RoundedCornerShape(MembyCardCorner),
                                    )
                                } else Modifier,
                            )
                            .padding(horizontal = 12.dp),
                        verticalAlignment = Alignment.CenterVertically,
                    ) {
                        Column(Modifier.width(54.dp)) {
                            Text(
                                CALENDAR_WEEKDAYS[index].uppercase(),
                                color = if (focused) MembySurface.copy(alpha = 0.65f) else if (cell.today) MembyAccent else MembyQuietText,
                                fontSize = 10.sp,
                                fontWeight = FontWeight.Bold,
                            )
                            Text(
                                cell.day.toString(),
                                color = if (focused) MembySurface else Color.White,
                                fontSize = 20.sp,
                                fontWeight = FontWeight.Bold,
                            )
                        }
                        Column(Modifier.weight(1f)) {
                            Text(
                                when {
                                    cell.today -> "TODAY"
                                    cell.items.isEmpty() -> "No programmes"
                                    cell.items.size == 1 -> "1 programme"
                                    else -> "${cell.items.size} programmes"
                                },
                                color = if (focused) MembySurface else if (cell.items.isEmpty()) MembyQuietText else Color.White,
                                fontSize = 12.sp,
                                fontWeight = if (cell.items.isNotEmpty()) FontWeight.SemiBold else FontWeight.Normal,
                                maxLines = 1,
                            )
                            cell.items.firstOrNull()?.name?.let {
                                Text(
                                    it,
                                    color = if (focused) MembySurface.copy(alpha = 0.62f) else MembyMutedText,
                                    fontSize = 10.sp,
                                    maxLines = 1,
                                    overflow = TextOverflow.Ellipsis,
                                )
                            }
                        }
                    }
                }
            }
        }
    }
}

@Composable
private fun ProgrammePane(
    heading: String,
    items: List<BaseItem>,
    programmeFocusRequester: FocusRequester,
    selectedDayFocusRequester: FocusRequester,
    artworkUrlFor: (BaseItem) -> String?,
    logoUrlFor: (BaseItem) -> String?,
    onFocused: (BaseItem) -> Unit,
    onSelected: (BaseItem) -> Unit,
    modifier: Modifier = Modifier,
) {
    Column(modifier) {
        Row(verticalAlignment = Alignment.Bottom) {
            Column(Modifier.weight(1f)) {
                Text("AIRING", color = MembyAccent, fontSize = 10.sp, fontWeight = FontWeight.Bold)
                Text(heading.ifEmpty { "Select a day" }, color = Color.White, fontSize = 20.sp, fontWeight = FontWeight.SemiBold)
            }
            if (items.isNotEmpty()) {
                Text(calendarEpisodeCountLabel(items.size), color = MembyQuietText, fontSize = 12.sp)
            }
        }
        Spacer(Modifier.height(9.dp))
        if (items.isEmpty()) {
            Box(
                Modifier
                    .fillMaxSize()
                    .background(MembySurfaceRaised.copy(alpha = 0.22f), RoundedCornerShape(MembyPanelCorner))
                    .border(1.dp, Color.White.copy(alpha = 0.05f), RoundedCornerShape(MembyPanelCorner)),
                contentAlignment = Alignment.Center,
            ) {
                Column(horizontalAlignment = Alignment.CenterHorizontally) {
                    Icon(Icons.Default.Event, null, tint = MembyQuietText, modifier = Modifier.size(30.dp))
                    Spacer(Modifier.height(8.dp))
                    Text("Nothing airing", color = MembyMutedText, fontSize = 15.sp)
                    Text("Choose another day or week", color = MembyQuietText, fontSize = 12.sp)
                }
            }
            return@Column
        }
        val listState = rememberLazyListState()
        LazyColumn(
            state = listState,
            contentPadding = PaddingValues(bottom = 12.dp),
            verticalArrangement = Arrangement.spacedBy(10.dp),
        ) {
            itemsIndexed(items, key = { _, item -> item.id }) { index, item ->
                ProgrammeCard(
                    item = item,
                    artworkUrl = artworkUrlFor(item),
                    logoUrl = logoUrlFor(item),
                    onFocused = { onFocused(item) },
                    onClick = { onSelected(item) },
                    modifier = Modifier
                        .then(if (index == 0) Modifier.focusRequester(programmeFocusRequester) else Modifier)
                        .focusProperties { left = selectedDayFocusRequester },
                )
            }
        }
    }
}

@Composable
private fun ProgrammeCard(
    item: BaseItem,
    artworkUrl: String?,
    logoUrl: String?,
    onFocused: () -> Unit,
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
) {
    val shape = RoundedCornerShape(MembyCardCorner)
    FocusScaleContainer(
        onFocused = onFocused,
        onClick = onClick,
        contentDescription = "${item.name} ${item.membyEpisodeCode.orEmpty()}",
        modifier = modifier.fillMaxWidth(),
    ) { focused ->
        Row(
            Modifier
                .fillMaxWidth()
                .height(118.dp)
                .clip(shape)
                .background(MembySurfaceRaised.copy(alpha = 0.72f))
                .border(if (focused) 2.dp else 1.dp, if (focused) Color.White else Color.White.copy(alpha = 0.07f), shape),
        ) {
            Box(Modifier.width(214.dp).fillMaxHeight().background(MembySurface)) {
                Box(
                    Modifier.fillMaxSize().background(
                        Brush.linearGradient(
                            listOf(MembyAccent.copy(alpha = 0.30f), Color(0xFF102523), MembySurfaceRaised),
                        ),
                    ),
                    contentAlignment = Alignment.Center,
                ) {
                    Text(
                        item.name.trim().firstOrNull()?.uppercase().orEmpty(),
                        color = Color.White.copy(alpha = 0.16f),
                        fontSize = 52.sp,
                        fontWeight = FontWeight.Black,
                    )
                }
                if (artworkUrl != null) {
                    AsyncImage(
                        model = artworkUrl,
                        contentDescription = null,
                        contentScale = ContentScale.Crop,
                        modifier = Modifier.fillMaxSize(),
                    )
                }
                Box(
                    Modifier.fillMaxSize().background(
                        Brush.horizontalGradient(
                            listOf(Color.Transparent, MembySurfaceRaised.copy(alpha = 0.12f), MembySurfaceRaised),
                        ),
                    ),
                )
                item.membyEpisodeEvent?.takeIf(String::isNotBlank)?.let { event ->
                    EventBadge(event, Modifier.align(Alignment.TopStart).padding(9.dp))
                }
            }
            Column(
                Modifier.weight(1f).fillMaxHeight().padding(start = 14.dp, end = 14.dp, top = 11.dp, bottom = 10.dp),
                verticalArrangement = Arrangement.Center,
            ) {
                if (logoUrl != null) {
                    AsyncImage(
                        model = logoUrl,
                        contentDescription = item.name,
                        contentScale = ContentScale.Fit,
                        modifier = Modifier.widthIn(max = 190.dp).height(34.dp),
                    )
                } else {
                    Text(
                        item.name,
                        color = Color.White,
                        fontSize = 17.sp,
                        fontWeight = FontWeight.Bold,
                        maxLines = 1,
                        overflow = TextOverflow.Ellipsis,
                    )
                }
                Spacer(Modifier.height(5.dp))
                Text(
                    listOfNotNull(
                        item.membyEpisodeCode?.takeIf(String::isNotBlank),
                        item.membyEpisodeTitle?.takeIf(String::isNotBlank),
                    ).joinToString("  ·  "),
                    color = Color.White.copy(alpha = 0.82f),
                    fontSize = 13.sp,
                    fontWeight = FontWeight.Medium,
                    maxLines = 1,
                    overflow = TextOverflow.Ellipsis,
                )
                Spacer(Modifier.height(4.dp))
                Row(verticalAlignment = Alignment.CenterVertically) {
                    Text(
                        item.membyAirLabel.orEmpty(),
                        color = MembyAccent,
                        fontSize = 11.sp,
                        fontWeight = FontWeight.SemiBold,
                        maxLines = 1,
                    )
                    item.membyAvailabilityText?.takeIf(String::isNotBlank)?.let {
                        Text("  ·  $it", color = MembyQuietText, fontSize = 11.sp, maxLines = 1)
                    }
                }
            }
        }
    }
}

@Composable
private fun EventBadge(event: String, modifier: Modifier = Modifier) {
    val colour = when {
        event.equals("Series finale", true) -> Color(0xFFE66D65)
        event.contains("finale", true) -> Color(0xFFF1A34F)
        else -> MembyAccent
    }
    Text(
        event.uppercase(),
        color = Color.White,
        fontSize = 9.sp,
        fontWeight = FontWeight.Bold,
        modifier = modifier
            .background(colour.copy(alpha = 0.92f), RoundedCornerShape(MembyChipCorner))
            .padding(horizontal = 8.dp, vertical = 4.dp),
    )
}

@Composable
private fun AgendaIconButton(
    icon: androidx.compose.ui.graphics.vector.ImageVector,
    description: String,
    enabled: Boolean,
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
) {
    if (!enabled) {
        Spacer(Modifier.size(36.dp))
        return
    }
    FocusScaleContainer(
        onFocused = {},
        onClick = onClick,
        contentDescription = description,
        modifier = modifier.size(36.dp),
    ) { focused ->
        Box(
            Modifier.fillMaxSize().background(if (focused) Color.White else MembySurfaceRaised, CircleShape),
            contentAlignment = Alignment.Center,
        ) {
            Icon(icon, description, tint = if (focused) MembySurface else Color.White, modifier = Modifier.size(18.dp))
        }
    }
}

@Composable
private fun AgendaNotice(message: String, action: String? = null, onAction: () -> Unit = {}) {
    Column(
        Modifier
            .fillMaxSize()
            .background(MembySurfaceRaised.copy(alpha = 0.22f), RoundedCornerShape(MembyPanelCorner))
            .padding(28.dp),
        horizontalAlignment = Alignment.Start,
        verticalArrangement = Arrangement.Center,
    ) {
        Text(message, color = MembyMutedText, fontSize = 16.sp)
        if (action != null) {
            Spacer(Modifier.height(14.dp))
            FocusScaleContainer(
                onFocused = {},
                onClick = onAction,
                contentDescription = action,
                modifier = Modifier.background(MembySurfaceRaised, RoundedCornerShape(MembyChipCorner)),
            ) { focused ->
                Text(
                    action,
                    color = if (focused) MembySurface else Color.White,
                    fontWeight = FontWeight.SemiBold,
                    modifier = Modifier
                        .background(if (focused) Color.White else Color.Transparent, RoundedCornerShape(MembyChipCorner))
                        .padding(horizontal = 18.dp, vertical = 10.dp),
                )
            }
        }
    }
}
