package ru.forbion.f7cloud.feature.calendar

import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.clickable
import androidx.compose.foundation.horizontalScroll
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
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.heightIn
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.rememberScrollState
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.DatePicker
import androidx.compose.material3.DatePickerDialog
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.ModalBottomSheet
import androidx.compose.material3.RadioButton
import androidx.compose.material3.Switch
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.material3.rememberDatePickerState
import androidx.compose.material3.rememberModalBottomSheetState
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.offset
import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.sp
import java.time.LocalTime
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.draw.shadow
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext
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 coil.compose.AsyncImage
import coil.request.ImageRequest
import ru.forbion.f7cloud.core.auth.AuthSession
import ru.forbion.f7cloud.core.designsystem.F7Colors
import ru.forbion.f7cloud.core.designsystem.F7ListCard
import ru.forbion.f7cloud.core.designsystem.F7OutlinedField
import ru.forbion.f7cloud.core.designsystem.F7PrimaryButton
import ru.forbion.f7cloud.core.designsystem.F7SecondaryButton
import ru.forbion.f7cloud.core.designsystem.F7TextButton
import java.time.Instant
import java.time.LocalDate
import java.time.YearMonth
import java.time.ZoneId
import java.time.format.DateTimeFormatter
import java.util.Locale

private val weekDayLabels = listOf("Пн", "Вт", "Ср", "Чт", "Пт", "Сб", "Вс")
private val dayTitleFormatter = DateTimeFormatter.ofPattern("d MMMM yyyy", Locale.forLanguageTag("ru"))
private val listDayFormatter = DateTimeFormatter.ofPattern("EEEE, d MMMM", Locale.forLanguageTag("ru"))
private val toolbarDateFormatter = DateTimeFormatter.ofPattern("MMM d, yyyy", Locale.ENGLISH)
private val dayHeaderFormatter = DateTimeFormatter.ofPattern("EE dd.M.yyyy", Locale.forLanguageTag("ru"))

private fun viewModeIconUrl(base: String, mode: CalendarViewMode): String = when (mode) {
    CalendarViewMode.DAY -> "$base/themes/forbion/images/calendar/day-grid-black.svg"
    CalendarViewMode.WEEK -> "$base/themes/forbion/images/calendar/week-grid-black.svg"
    CalendarViewMode.MONTH -> "$base/themes/forbion/images/calendar/mounth-grid-black.svg"
    CalendarViewMode.YEAR -> "$base/themes/forbion/images/calendar/year-grid-black.svg"
    CalendarViewMode.LIST -> "$base/themes/forbion/images/calendar/list-grid-black.svg"
}

private val calendarFallbackColors = listOf(
    Color(0xFF70B62B),
    Color(0xFF2B9AB6),
    Color(0xFF7C5CFF),
    Color(0xFFE67C22),
    Color(0xFFD74642),
    Color(0xFF9B59B6),
)

private fun calendarAccentColor(cal: CalendarBookItem): Color {
    val raw = cal.color?.trim().orEmpty()
    if (raw.isNotBlank()) {
        val hex = raw.removePrefix("#").take(6)
        runCatching {
            return Color(0xFF000000L or hex.toLong(16))
        }
    }
    val index = kotlin.math.abs(cal.href.hashCode()) % calendarFallbackColors.size
    return calendarFallbackColors[index]
}

@Composable
fun CalendarSidebarHeader(
    session: AuthSession,
    periodTitle: String,
    viewMode: CalendarViewMode,
    onPrevious: () -> Unit,
    onNext: () -> Unit,
    onPeriodClick: () -> Unit,
    onCreate: () -> Unit,
    onToday: () -> Unit,
    onViewMode: (CalendarViewMode) -> Unit,
) {
    val base = session.serverUrl.trimEnd('/')
    Column(verticalArrangement = Arrangement.spacedBy(12.dp)) {
        Row(
            modifier = Modifier
                .fillMaxWidth()
                .shadow(1.dp, RoundedCornerShape(8.dp))
                .clip(RoundedCornerShape(8.dp))
                .background(F7Colors.Background)
                .border(1.dp, F7Colors.Border.copy(alpha = 0.6f), RoundedCornerShape(8.dp)),
            verticalAlignment = Alignment.CenterVertically,
        ) {
            CalendarSidebarNavButton(
                iconUrl = "$base/themes/forbion/images/left-arrow-black.svg",
                onClick = onPrevious,
            )
            Box(
                modifier = Modifier
                    .weight(1f)
                    .border(
                        width = 1.dp,
                        color = F7Colors.Border,
                    ),
                contentAlignment = Alignment.Center,
            ) {
                Text(
                    text = periodTitle,
                    modifier = Modifier
                        .fillMaxWidth()
                        .clickable(onClick = onPeriodClick)
                        .padding(vertical = 10.dp, horizontal = 8.dp),
                    style = MaterialTheme.typography.bodyMedium,
                    fontWeight = FontWeight.Medium,
                    color = F7Colors.TextPrimary,
                    textAlign = TextAlign.Center,
                    maxLines = 1,
                    overflow = TextOverflow.Ellipsis,
                )
            }
            CalendarSidebarNavButton(
                iconUrl = "$base/themes/forbion/images/right-arrow-black.svg",
                onClick = onNext,
            )
        }
        Row(
            modifier = Modifier.fillMaxWidth(),
            horizontalArrangement = Arrangement.spacedBy(4.dp),
            verticalAlignment = Alignment.CenterVertically,
        ) {
            Row(
                modifier = Modifier
                    .weight(1f)
                    .height(40.dp)
                    .clip(RoundedCornerShape(20.dp))
                    .background(
                        brush = Brush.linearGradient(
                            listOf(F7Colors.PrimaryGradientStart, F7Colors.PrimaryGradientEnd),
                        ),
                    )
                    .clickable(onClick = onCreate)
                    .padding(horizontal = 14.dp),
                verticalAlignment = Alignment.CenterVertically,
                horizontalArrangement = Arrangement.Center,
            ) {
                AsyncImage(
                    model = "$base/themes/forbion/images/calendar/plus-icon-black.svg",
                    contentDescription = null,
                    modifier = Modifier.size(20.dp),
                )
                Spacer(Modifier.width(8.dp))
                Text(
                    "Событие",
                    style = MaterialTheme.typography.labelLarge,
                    color = F7Colors.TextOnPrimary,
                    fontWeight = FontWeight.SemiBold,
                )
            }
            Box(
                modifier = Modifier
                    .weight(1f)
                    .height(40.dp)
                    .clip(RoundedCornerShape(8.dp))
                    .background(F7Colors.PrimaryLight)
                    .border(1.dp, F7Colors.Border, RoundedCornerShape(8.dp))
                    .clickable(onClick = onToday),
                contentAlignment = Alignment.Center,
            ) {
                Text(
                    "Сегодня",
                    style = MaterialTheme.typography.labelLarge,
                    color = F7Colors.TextPrimary,
                    fontWeight = FontWeight.Medium,
                )
            }
            CalendarViewModeMenuButton(
                session = session,
                selected = viewMode,
                onSelect = onViewMode,
                circular = true,
            )
        }
    }
}

@Composable
fun CalendarToolbar(
    session: AuthSession,
    periodTitle: String,
    viewMode: CalendarViewMode,
    onPrevious: () -> Unit,
    onNext: () -> Unit,
    onPeriodClick: () -> Unit,
    onCreate: () -> Unit,
    onToday: () -> Unit,
    onViewMode: (CalendarViewMode) -> Unit,
) {
    CalendarSidebarHeader(
        session = session,
        periodTitle = periodTitle,
        viewMode = viewMode,
        onPrevious = onPrevious,
        onNext = onNext,
        onPeriodClick = onPeriodClick,
        onCreate = onCreate,
        onToday = onToday,
        onViewMode = onViewMode,
    )
}

@Composable
fun CalendarDayHeader(
    day: LocalDate,
    session: AuthSession,
    viewMode: CalendarViewMode,
    onViewMode: (CalendarViewMode) -> Unit,
) {
    Row(
        modifier = Modifier
            .fillMaxWidth()
            .clip(RoundedCornerShape(100.dp))
            .background(F7Colors.PrimaryLight)
            .border(1.dp, F7Colors.Primary.copy(alpha = 0.25f), RoundedCornerShape(100.dp))
            .padding(horizontal = 16.dp, vertical = 10.dp),
        verticalAlignment = Alignment.CenterVertically,
        horizontalArrangement = Arrangement.SpaceBetween,
    ) {
        Text(
            day.format(dayHeaderFormatter).replaceFirstChar {
                if (it.isLowerCase()) it.titlecase(Locale.forLanguageTag("ru")) else it.toString()
            },
            style = MaterialTheme.typography.titleSmall,
            fontWeight = FontWeight.SemiBold,
            color = F7Colors.TextPrimary,
        )
        CalendarViewModeMenuButton(session = session, selected = viewMode, onSelect = onViewMode)
    }
}

@Composable
private fun CalendarViewModeMenuButton(
    session: AuthSession,
    selected: CalendarViewMode,
    onSelect: (CalendarViewMode) -> Unit,
    circular: Boolean = false,
) {
    var expanded by remember { mutableStateOf(false) }
    val base = session.serverUrl.trimEnd('/')
    val shape = if (circular) CircleShape else RoundedCornerShape(10.dp)
    Box {
        Box(
            modifier = Modifier
                .size(40.dp)
                .clip(shape)
                .background(if (circular) F7Colors.Background else F7Colors.Surface)
                .border(1.dp, F7Colors.Border, shape)
                .clickable { expanded = true },
            contentAlignment = Alignment.Center,
        ) {
            AsyncImage(
                model = viewModeIconUrl(base, selected),
                contentDescription = selected.label,
                modifier = Modifier.size(18.dp),
            )
        }
        DropdownMenu(expanded = expanded, onDismissRequest = { expanded = false }) {
            CalendarViewMode.entries.forEach { mode ->
                DropdownMenuItem(
                    text = {
                        Row(
                            verticalAlignment = Alignment.CenterVertically,
                            horizontalArrangement = Arrangement.spacedBy(10.dp),
                        ) {
                            AsyncImage(
                                model = viewModeIconUrl(base, mode),
                                contentDescription = null,
                                modifier = Modifier.size(18.dp),
                            )
                            Text(mode.label)
                        }
                    },
                    onClick = {
                        onSelect(mode)
                        expanded = false
                    },
                )
            }
        }
    }
}

@Composable
private fun CalendarSidebarNavButton(iconUrl: String, onClick: () -> Unit) {
    Box(
        modifier = Modifier
            .size(40.dp)
            .clickable(onClick = onClick),
        contentAlignment = Alignment.Center,
    ) {
        AsyncImage(
            model = iconUrl,
            contentDescription = null,
            modifier = Modifier.size(16.dp),
        )
    }
}

@Composable
private fun CalendarNavButton(text: String, onClick: () -> Unit) {
    Box(
        modifier = Modifier
            .size(36.dp)
            .clip(RoundedCornerShape(8.dp))
            .border(2.dp, F7Colors.Border, RoundedCornerShape(8.dp))
            .clickable(onClick = onClick),
        contentAlignment = Alignment.Center,
    ) {
        Text(text, style = MaterialTheme.typography.titleMedium, color = F7Colors.TextPrimary)
    }
}

@Composable
private fun CalendarIconButton(
    iconUrl: String,
    contentDescription: String?,
    onClick: () -> Unit,
) {
    Box(
        modifier = Modifier
            .size(40.dp)
            .clip(RoundedCornerShape(8.dp))
            .background(F7Colors.Primary)
            .clickable(onClick = onClick),
        contentAlignment = Alignment.Center,
    ) {
        AsyncImage(
            model = iconUrl,
            contentDescription = contentDescription,
            modifier = Modifier.size(20.dp),
            contentScale = ContentScale.Fit,
        )
    }
}

@Composable
fun CalendarMonthGrid(
    month: YearMonth,
    selectedDay: LocalDate,
    eventsByDay: Map<LocalDate, List<CalendarEventItem>>,
    onSelectDay: (LocalDate) -> Unit,
) {
    val days = CalendarRepository.monthGridDays(month)
    val today = LocalDate.now()
    // Живая тема (_calendar-month-view-mobile.css): месяц — белая карточка r12 с рамкой,
    // внутри дни недели — круги 40 (#F5F5F5, 16/500) и ячейки-карточки #FDFDFD r4
    // с тенью, зазор 4.
    Column(
        modifier = Modifier
            .fillMaxWidth()
            .clip(RoundedCornerShape(12.dp))
            .background(Color.White)
            .border(1.dp, F7Colors.Border, RoundedCornerShape(12.dp))
            .padding(12.dp),
        verticalArrangement = Arrangement.spacedBy(4.dp),
    ) {
        Row(
            modifier = Modifier.fillMaxWidth(),
            horizontalArrangement = Arrangement.spacedBy(4.dp),
        ) {
            weekDayLabels.forEach { label ->
                Box(modifier = Modifier.weight(1f), contentAlignment = Alignment.Center) {
                    Box(
                        modifier = Modifier
                            .size(40.dp)
                            .clip(CircleShape)
                            .background(F7Colors.Grey2),
                        contentAlignment = Alignment.Center,
                    ) {
                        Text(
                            text = label,
                            style = MaterialTheme.typography.bodyLarge,
                            fontWeight = FontWeight.Medium,
                            color = F7Colors.TextPrimary,
                        )
                    }
                }
            }
        }
        days.chunked(7).forEach { week ->
            Row(
                modifier = Modifier.fillMaxWidth(),
                horizontalArrangement = Arrangement.spacedBy(4.dp),
            ) {
                week.forEach { day ->
                    val inMonth = day.month == month.month
                    val dayEvents = eventsByDay[day].orEmpty()
                    CalendarDayCell(
                        day = day.dayOfMonth,
                        inMonth = inMonth,
                        isToday = day == today,
                        selected = day == selectedDay,
                        events = dayEvents,
                        onClick = { onSelectDay(day) },
                        modifier = Modifier.weight(1f),
                    )
                }
            }
        }
    }
}

@Composable
private fun CalendarDayCell(
    day: Int,
    inMonth: Boolean,
    isToday: Boolean,
    selected: Boolean,
    events: List<CalendarEventItem>,
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
) {
    // Живая тема: ячейка — карточка #FDFDFD r4 с тонкой тенью, высота 120, паддинг 4;
    // номер дня 14/500 СПРАВА-сверху (чужой месяц — серый); «сегодня» — зелёная плашка
    // 40×24 r4 с белым числом; выбранный день подсвечиваем #ECF9DE (наша адаптация тапа).
    Column(
        modifier = modifier
            .height(120.dp)
            .shadow(
                elevation = 1.dp,
                shape = RoundedCornerShape(4.dp),
                spotColor = F7Colors.Border,
            )
            .clip(RoundedCornerShape(4.dp))
            .background(if (selected) F7Colors.PrimaryLight else Color(0xFFFDFDFD))
            .clickable(onClick = onClick)
            .padding(4.dp),
        verticalArrangement = Arrangement.spacedBy(2.dp),
    ) {
        Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.End) {
            if (isToday) {
                Box(
                    modifier = Modifier
                        .width(40.dp)
                        .height(24.dp)
                        .clip(RoundedCornerShape(4.dp))
                        .background(F7Colors.Primary),
                    contentAlignment = Alignment.Center,
                ) {
                    Text(
                        text = day.toString(),
                        style = MaterialTheme.typography.bodyMedium,
                        fontWeight = FontWeight.Medium,
                        color = Color.White,
                    )
                }
            } else {
                Text(
                    text = day.toString(),
                    style = MaterialTheme.typography.bodyMedium,
                    fontWeight = FontWeight.Medium,
                    color = if (inMonth) F7Colors.TextPrimary else F7Colors.TextSecondary,
                )
            }
        }
        events.take(3).forEach { event ->
            CalendarDayEventPill(event.summary.ifBlank { "Событие" }, muted = !inMonth)
        }
        if (events.size > 3) {
            Text(
                "+${events.size - 3}",
                style = MaterialTheme.typography.labelSmall,
                color = F7Colors.Primary,
                fontWeight = FontWeight.Medium,
            )
        }
    }
}

@Composable
private fun CalendarDayEventPill(text: String, muted: Boolean = false) {
    // Живая тема: пилюля события — фон #ECF9DE, рамка #70B62B, r4, текст 10/12;
    // вне текущего месяца — серые с белым текстом.
    Text(
        text = text,
        modifier = Modifier
            .fillMaxWidth()
            .clip(RoundedCornerShape(4.dp))
            .background(if (muted) F7Colors.TextSecondary else F7Colors.PrimaryLight)
            .border(1.dp, if (muted) F7Colors.TextSecondary else F7Colors.Primary, RoundedCornerShape(4.dp))
            .padding(horizontal = 4.dp, vertical = 2.dp),
        fontSize = 10.sp,
        lineHeight = 12.sp,
        fontWeight = FontWeight.Medium,
        color = if (muted) Color.White else F7Colors.TextPrimary,
        maxLines = 1,
        overflow = TextOverflow.Ellipsis,
    )
}

@Composable
fun CalendarWeekView(
    selectedDay: LocalDate,
    events: List<CalendarEventItem>,
    onSelectDay: (LocalDate) -> Unit,
    onEventClick: (CalendarEventItem) -> Unit,
) {
    val (start, _) = CalendarRepository.weekRange(selectedDay)
    val days = (0..6).map { start.plusDays(it.toLong()) }
    Row(
        modifier = Modifier
            .fillMaxWidth()
            .horizontalScroll(rememberScrollState()),
        horizontalArrangement = Arrangement.spacedBy(8.dp),
    ) {
        days.forEach { day ->
            val dayEvents = events.filter { CalendarRepository.eventOccursOnDay(it, day) }
            Column(
                modifier = Modifier
                    .width(120.dp)
                    .clip(RoundedCornerShape(12.dp))
                    .background(if (day == selectedDay) F7Colors.PrimaryLight else F7Colors.Surface)
                    .border(1.dp, if (day == selectedDay) F7Colors.Primary else F7Colors.Border, RoundedCornerShape(12.dp))
                    .clickable { onSelectDay(day) }
                    .padding(8.dp),
                verticalArrangement = Arrangement.spacedBy(6.dp),
            ) {
                Text(
                    weekDayLabels[day.dayOfWeek.value - 1],
                    style = MaterialTheme.typography.labelSmall,
                    color = F7Colors.TextMuted,
                )
                Text(
                    day.dayOfMonth.toString(),
                    style = MaterialTheme.typography.titleMedium,
                    fontWeight = FontWeight.Bold,
                )
                dayEvents.take(4).forEach { event ->
                    CalendarEventChip(event = event, onClick = { onEventClick(event) })
                }
                if (dayEvents.size > 4) {
                    Text("+${dayEvents.size - 4}", style = MaterialTheme.typography.labelSmall, color = F7Colors.TextMuted)
                }
            }
        }
    }
}

@Composable
fun CalendarDayTimeline(
    session: AuthSession,
    day: LocalDate,
    events: List<CalendarEventItem>,
    viewMode: CalendarViewMode,
    onViewMode: (CalendarViewMode) -> Unit,
    onEventClick: (CalendarEventItem) -> Unit,
    modifier: Modifier = Modifier,
) {
    val zone = ZoneId.systemDefault()
    val scrollState = rememberScrollState()
    val hourHeight = 56.dp
    val timeColumnWidth = 52.dp
    val allDayEvents = events.filter { it.allDay }
    val timedEvents = events.filterNot { it.allDay }.sortedBy { it.startEpochMilli }
    val isToday = day == LocalDate.now()
    val now = LocalTime.now()
    val nowOffset = (now.hour + now.minute / 60f) * hourHeight.value

    Column(modifier = modifier.fillMaxSize()) {
        CalendarDayHeader(day = day, session = session, viewMode = viewMode, onViewMode = onViewMode)
        Row(
            modifier = Modifier
                .weight(1f)
                .fillMaxWidth()
                .padding(top = 8.dp)
                .verticalScroll(scrollState),
        ) {
            Column(modifier = Modifier.width(timeColumnWidth)) {
                Box(
                    modifier = Modifier
                        .fillMaxWidth()
                        .height(44.dp)
                        .padding(end = 4.dp),
                    contentAlignment = Alignment.CenterEnd,
                ) {
                    Text(
                        "Весь день",
                        style = MaterialTheme.typography.labelSmall,
                        color = F7Colors.TextMuted,
                        textAlign = TextAlign.End,
                    )
                }
                (0..23).forEach { hour ->
                    Box(
                        modifier = Modifier
                            .fillMaxWidth()
                            .height(hourHeight)
                            .padding(end = 4.dp),
                        contentAlignment = Alignment.TopEnd,
                    ) {
                        Text(
                            "$hour:00",
                            style = MaterialTheme.typography.labelSmall,
                            color = F7Colors.TextMuted,
                            fontSize = 11.sp,
                        )
                    }
                }
            }
            Box(
                modifier = Modifier
                    .weight(1f)
                    .height(hourHeight * 24 + 44.dp),
            ) {
                Column(Modifier.fillMaxSize()) {
                    Box(
                        modifier = Modifier
                            .fillMaxWidth()
                            .height(44.dp)
                            .border(1.dp, F7Colors.BorderLight)
                            .background(F7Colors.SurfaceMuted)
                            .padding(horizontal = 6.dp, vertical = 4.dp),
                    ) {
                        allDayEvents.forEach { event ->
                            Text(
                                event.summary,
                                modifier = Modifier
                                    .fillMaxWidth()
                                    .clip(RoundedCornerShape(6.dp))
                                    .background(F7Colors.PrimaryLight)
                                    .clickable { onEventClick(event) }
                                    .padding(horizontal = 8.dp, vertical = 4.dp),
                                style = MaterialTheme.typography.labelSmall,
                                color = F7Colors.PrimaryDark,
                                maxLines = 1,
                                overflow = TextOverflow.Ellipsis,
                            )
                        }
                    }
                    Box(Modifier.fillMaxWidth().height(hourHeight * 24)) {
                        (0..24).forEach { hour ->
                            Box(
                                modifier = Modifier
                                    .fillMaxWidth()
                                    .height(1.dp)
                                    .offset(y = hourHeight * hour)
                                    .background(F7Colors.BorderLight),
                            )
                        }
                        timedEvents.forEach { event ->
                            val start = Instant.ofEpochMilli(event.startEpochMilli).atZone(zone)
                            val end = Instant.ofEpochMilli(event.endEpochMilli).atZone(zone)
                            val startMinutes = start.hour * 60 + start.minute
                            val endMinutes = end.hour * 60 + end.minute
                            val top = (startMinutes / 60f) * hourHeight.value
                            val height = ((endMinutes - startMinutes).coerceAtLeast(30) / 60f) * hourHeight.value
                            Box(
                                modifier = Modifier
                                    .fillMaxWidth()
                                    .padding(horizontal = 4.dp)
                                    .offset(y = top.dp)
                                    .height(height.dp.coerceAtLeast(28.dp))
                                    .clip(RoundedCornerShape(8.dp))
                                    .background(F7Colors.PrimaryLight)
                                    .border(1.dp, F7Colors.Primary.copy(alpha = 0.35f), RoundedCornerShape(8.dp))
                                    .clickable { onEventClick(event) }
                                    .padding(horizontal = 8.dp, vertical = 4.dp),
                            ) {
                                Text(
                                    event.summary,
                                    style = MaterialTheme.typography.labelSmall,
                                    fontWeight = FontWeight.SemiBold,
                                    color = F7Colors.PrimaryDark,
                                    maxLines = 2,
                                    overflow = TextOverflow.Ellipsis,
                                )
                            }
                        }
                        if (isToday) {
                            Row(
                                modifier = Modifier
                                    .fillMaxWidth()
                                    .offset(y = nowOffset.dp)
                                    .height(2.dp),
                                verticalAlignment = Alignment.CenterVertically,
                            ) {
                                Box(
                                    modifier = Modifier
                                        .size(8.dp)
                                        .clip(CircleShape)
                                        .background(Color(0xFFE53935)),
                                )
                                Box(
                                    modifier = Modifier
                                        .weight(1f)
                                        .height(2.dp)
                                        .background(Color(0xFFE53935)),
                                )
                            }
                        }
                    }
                }
            }
        }
    }
}

@Composable
fun CalendarListView(
    events: List<CalendarEventItem>,
    onEventClick: (CalendarEventItem) -> Unit,
    modifier: Modifier = Modifier,
) {
    val grouped = events.groupBy { event ->
        Instant.ofEpochMilli(event.startEpochMilli).atZone(ZoneId.systemDefault()).toLocalDate()
    }.toSortedMap()
    LazyColumn(
        modifier = modifier.fillMaxWidth(),
        verticalArrangement = Arrangement.spacedBy(8.dp),
    ) {
        grouped.forEach { (day, dayEvents) ->
            item(key = "header-$day") {
                Text(
                    day.format(listDayFormatter).replaceFirstChar {
                        if (it.isLowerCase()) it.titlecase(Locale.forLanguageTag("ru")) else it.toString()
                    },
                    style = MaterialTheme.typography.titleSmall,
                    fontWeight = FontWeight.SemiBold,
                    modifier = Modifier.padding(top = 4.dp),
                )
            }
            items(dayEvents, key = { "${it.uid}|${it.startEpochMilli}" }) { event ->
                CalendarEventRow(event = event, onClick = { onEventClick(event) })
            }
        }
    }
}

@Composable
fun CalendarEventRow(
    event: CalendarEventItem,
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
    highlighted: Boolean = false,
) {
    F7ListCard(
        modifier = modifier
            .fillMaxWidth()
            .then(
                if (highlighted) {
                    Modifier.border(2.dp, F7Colors.Primary, RoundedCornerShape(12.dp))
                } else {
                    Modifier
                },
            )
            .clickable(onClick = onClick),
    ) {
        Row(
            modifier = Modifier.fillMaxWidth(),
            horizontalArrangement = Arrangement.spacedBy(10.dp),
            verticalAlignment = Alignment.Top,
        ) {
            Box(
                modifier = Modifier
                    .width(4.dp)
                    .height(42.dp)
                    .clip(RoundedCornerShape(100.dp))
                    .background(F7Colors.Primary),
            )
            Column(modifier = Modifier.weight(1f)) {
                Text(event.summary, style = MaterialTheme.typography.titleSmall, fontWeight = FontWeight.SemiBold)
                Text(
                    CalendarRepository.formatEventTime(event),
                    style = MaterialTheme.typography.labelSmall,
                    color = F7Colors.TextSecondary,
                )
                if (event.location.isNotBlank()) {
                    Text(event.location, style = MaterialTheme.typography.labelSmall, color = F7Colors.TextMuted, maxLines = 1)
                }
                Text(
                    event.calendarName,
                    style = MaterialTheme.typography.labelSmall,
                    color = F7Colors.TextMuted,
                )
            }
        }
    }
}

@Composable
private fun CalendarEventChip(event: CalendarEventItem, onClick: () -> Unit) {
    // Живая тема: пилюля события — #ECF9DE с рамкой #70B62B, r4, текст 12/16
    Text(
        event.summary,
        modifier = Modifier
            .fillMaxWidth()
            .clip(RoundedCornerShape(4.dp))
            .background(F7Colors.PrimaryLight)
            .border(1.dp, F7Colors.Primary, RoundedCornerShape(4.dp))
            .clickable(onClick = onClick)
            .padding(horizontal = 6.dp, vertical = 4.dp),
        style = MaterialTheme.typography.labelSmall,
        color = F7Colors.PrimaryDark,
        maxLines = 2,
        overflow = TextOverflow.Ellipsis,
    )
}

@Composable
fun CalendarNavigationSidebar(
    session: AuthSession,
    state: CalendarUiState,
    periodTitle: String,
    onPrevious: () -> Unit,
    onNext: () -> Unit,
    onPeriodClick: () -> Unit,
    onCreate: () -> Unit,
    onToday: () -> Unit,
    onViewMode: (CalendarViewMode) -> Unit,
    onDismiss: () -> Unit,
    onToggleCalendar: (String) -> Unit,
    onOpenSettings: () -> Unit,
    onOpenAppSettings: () -> Unit,
    onOpenTrash: () -> Unit,
    onOpenTasks: () -> Unit,
    onCreateBook: () -> Unit,
    onSyncNow: () -> Unit,
) {
    val base = session.serverUrl.trimEnd('/')
    val (myCalendars, deckCalendars) = remember(state.calendars) {
        val cards = state.calendars.filter {
            it.isSubscription || it.displayName.contains("deck", ignoreCase = true)
        }
        val mine = state.calendars.filter { it !in cards }
        mine to cards
    }
    Column(
        modifier = Modifier
            .fillMaxHeight()
            .fillMaxWidth()
            .background(F7Colors.Background)
            .padding(horizontal = 16.dp, vertical = 12.dp),
    ) {
        CalendarSidebarHeader(
            session = session,
            periodTitle = periodTitle,
            viewMode = state.viewMode,
            onPrevious = onPrevious,
            onNext = onNext,
            onPeriodClick = onPeriodClick,
            onCreate = {
                onDismiss()
                onCreate()
            },
            onToday = onToday,
            onViewMode = onViewMode,
        )
        Spacer(Modifier.height(16.dp))
        Column(
            modifier = Modifier
                .weight(1f)
                .fillMaxWidth()
                .verticalScroll(rememberScrollState()),
        ) {
            Column(
                modifier = Modifier
                    .fillMaxWidth()
                    .clip(RoundedCornerShape(8.dp))
                    .background(F7Colors.Surface)
                    .border(1.dp, F7Colors.Border.copy(alpha = 0.5f), RoundedCornerShape(8.dp)),
            ) {
                Column(modifier = Modifier.padding(horizontal = 12.dp, vertical = 8.dp)) {
                    CalendarSidebarCaption(
                        title = "Мои календари",
                        plusIconUrl = "$base/themes/forbion/images/calendar/plus-icon-black.svg",
                        onAdd = onCreateBook,
                    )
                    myCalendars.forEach { cal ->
                        CalendarSidebarCalendarRow(cal, onToggleCalendar)
                    }
                    if (deckCalendars.isNotEmpty()) {
                        Spacer(Modifier.height(8.dp))
                        CalendarSidebarCaption(
                            title = "Карточки",
                            plusIconUrl = null,
                            onAdd = null,
                        )
                        deckCalendars.forEach { cal ->
                            CalendarSidebarCalendarRow(cal, onToggleCalendar)
                        }
                    }
                }
                HorizontalDivider(color = F7Colors.Border.copy(alpha = 0.6f))
                Column(modifier = Modifier.padding(horizontal = 12.dp, vertical = 4.dp)) {
                    SidebarActionRow("$base/themes/forbion/images/calendar/basket-black.svg", "Корзина") {
                        onDismiss()
                        onOpenTrash()
                    }
                    if (state.userSettings.showTasks) {
                        SidebarActionRow("$base/themes/forbion/images/calendar/blank-box-gray.svg", "Незапланированные задачи") {
                            onDismiss()
                            onOpenTasks()
                        }
                    }
                    SidebarActionRow("$base/themes/forbion/images/calendar/settings-gray.svg", "Параметры календаря") {
                        onDismiss()
                        onOpenAppSettings()
                    }
                    SidebarActionRow("$base/themes/forbion/images/calendar/calendar-edit-export-white.svg", "Синхронизация с телефоном") {
                        onDismiss()
                        onOpenSettings()
                    }
                    if (state.syncEnabled) {
                        F7SecondaryButton(
                            text = if (state.syncing) "Синхронизация…" else "Синхронизировать сейчас",
                            onClick = onSyncNow,
                            modifier = Modifier
                                .fillMaxWidth()
                                .padding(vertical = 8.dp),
                            enabled = !state.syncing,
                        )
                    }
                }
            }
        }
    }
}

@Composable
private fun CalendarSidebarCaption(
    title: String,
    plusIconUrl: String?,
    onAdd: (() -> Unit)?,
) {
    Row(
        modifier = Modifier
            .fillMaxWidth()
            .padding(vertical = 8.dp),
        horizontalArrangement = Arrangement.SpaceBetween,
        verticalAlignment = Alignment.CenterVertically,
    ) {
        Text(
            title,
            style = MaterialTheme.typography.bodyLarge,
            fontWeight = FontWeight.Medium,
            color = F7Colors.TextPrimary,
        )
        if (plusIconUrl != null && onAdd != null) {
            Box(
                modifier = Modifier
                    .size(28.dp)
                    .clickable(onClick = onAdd),
                contentAlignment = Alignment.Center,
            ) {
                AsyncImage(
                    model = plusIconUrl,
                    contentDescription = "Добавить",
                    modifier = Modifier.size(16.dp),
                )
            }
        }
    }
}

@Composable
private fun CalendarSidebarCalendarRow(
    cal: CalendarBookItem,
    onToggleCalendar: (String) -> Unit,
) {
    val accent = calendarAccentColor(cal)
    Row(
        modifier = Modifier
            .fillMaxWidth()
            .clip(RoundedCornerShape(8.dp))
            .clickable { onToggleCalendar(cal.href) }
            .padding(vertical = 6.dp),
        verticalAlignment = Alignment.CenterVertically,
        horizontalArrangement = Arrangement.spacedBy(12.dp),
    ) {
        CalendarColorCheckbox(
            color = accent,
            checked = cal.visible,
            onToggle = { onToggleCalendar(cal.href) },
        )
        Text(
            cal.displayName,
            style = MaterialTheme.typography.bodyLarge,
            fontWeight = FontWeight.Medium,
            color = F7Colors.TextPrimary,
            maxLines = 2,
            overflow = TextOverflow.Ellipsis,
        )
    }
}

@Composable
private fun CalendarColorCheckbox(
    color: Color,
    checked: Boolean,
    onToggle: () -> Unit,
) {
    Box(
        modifier = Modifier
            .size(20.dp)
            .clip(RoundedCornerShape(4.dp))
            .then(
                if (checked) {
                    Modifier.background(color)
                } else {
                    Modifier
                        .background(F7Colors.Surface)
                        .border(2.dp, color, RoundedCornerShape(4.dp))
                },
            )
            .clickable(onClick = onToggle),
        contentAlignment = Alignment.Center,
    ) {
        if (checked) {
            Text(
                "✓",
                color = Color.White,
                fontSize = 12.sp,
                fontWeight = FontWeight.Bold,
                lineHeight = 12.sp,
            )
        }
    }
}

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun CalendarEventDetailSheet(
    session: AuthSession,
    event: CalendarEventItem,
    onDismiss: () -> Unit,
    onEdit: () -> Unit,
    onDelete: () -> Unit,
    onDuplicate: () -> Unit = {},
    onAccept: () -> Unit = {},
    onDecline: () -> Unit = {},
    onTentative: () -> Unit = {},
    deleting: Boolean,
) {
    val sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true)
    val base = session.serverUrl.trimEnd('/')
    ModalBottomSheet(
        onDismissRequest = onDismiss,
        sheetState = sheetState,
        containerColor = F7Colors.Surface,
    ) {
        Column(
            modifier = Modifier
                .fillMaxWidth()
                .padding(horizontal = 20.dp)
                .padding(bottom = 28.dp),
            verticalArrangement = Arrangement.spacedBy(12.dp),
        ) {
            // Живая тема: заголовки модалок 18/600
            Text(
                event.summary,
                style = MaterialTheme.typography.titleMedium.copy(fontSize = 18.sp),
                fontWeight = FontWeight.SemiBold,
                color = F7Colors.TextPrimary,
            )
            CalendarDetailRow(
                iconUrl = "$base/themes/forbion/images/calendar/event-clock.svg",
                label = "Время",
                value = CalendarRepository.formatEventTime(event),
            )
            CalendarDetailRow(
                iconUrl = "$base/themes/forbion/images/calendar/calendar-black.svg",
                label = "Календарь",
                value = event.calendarName,
            )
            if (event.location.isNotBlank()) {
                CalendarDetailRow(
                    iconUrl = "$base/themes/forbion/images/calendar/event-location-gray.svg",
                    label = "Место",
                    value = event.location,
                )
            }
            if (event.description.isNotBlank()) {
                CalendarDetailRow(
                    iconUrl = "$base/themes/forbion/images/calendar/event-add-description-gray.svg",
                    label = "Описание",
                    value = event.description,
                )
            }
            if (event.talkRoomUrl.isNotBlank()) {
                CalendarDetailRow(
                    iconUrl = "$base/themes/forbion/images/calendar/event-video-gray.svg",
                    label = "Talk",
                    value = event.talkRoomUrl,
                )
            }
            if (event.rrule.isNotBlank()) {
                CalendarDetailRow(
                    iconUrl = "$base/themes/forbion/images/calendar/event-repeat-gray.svg",
                    label = "Повторение",
                    value = event.rrule,
                )
            }
            if (event.categories.isNotEmpty()) {
                CalendarDetailRow(
                    iconUrl = "$base/themes/forbion/images/calendar/event-tag-gray.svg",
                    label = "Категории",
                    value = event.categories.joinToString(", "),
                )
            }
            if (event.attendees.isNotEmpty()) {
                CalendarDetailRow(
                    iconUrl = "$base/themes/forbion/images/calendar/event-participants-gray.svg",
                    label = "Участники",
                    value = event.attendees.joinToString("\n") { "• ${it.displayName.ifBlank { it.email }} (${it.partStat})" },
                )
            }
            Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
                F7PrimaryButton(text = "Изменить", onClick = onEdit, modifier = Modifier.weight(1f))
                F7SecondaryButton(text = "Копия", onClick = onDuplicate, modifier = Modifier.weight(1f))
            }
            if (event.attendees.isNotEmpty()) {
                Row(horizontalArrangement = Arrangement.spacedBy(6.dp)) {
                    F7SecondaryButton(text = "Принять", onClick = onAccept, modifier = Modifier.weight(1f))
                    F7SecondaryButton(text = "Может быть", onClick = onTentative, modifier = Modifier.weight(1f))
                    F7SecondaryButton(text = "Отклонить", onClick = onDecline, modifier = Modifier.weight(1f))
                }
            }
            F7SecondaryButton(
                text = if (deleting) "Удаление…" else "Удалить",
                onClick = onDelete,
                enabled = !deleting,
            )
        }
    }
}

@Composable
private fun SidebarActionRow(iconUrl: String, label: String, onClick: () -> Unit) {
    Row(
        modifier = Modifier
            .fillMaxWidth()
            .clip(RoundedCornerShape(8.dp))
            .clickable(onClick = onClick)
            .padding(vertical = 12.dp),
        verticalAlignment = Alignment.CenterVertically,
        horizontalArrangement = Arrangement.spacedBy(12.dp),
    ) {
        AsyncImage(model = iconUrl, contentDescription = null, modifier = Modifier.size(20.dp))
        Text(
            label,
            style = MaterialTheme.typography.bodyLarge,
            fontWeight = FontWeight.Medium,
            color = F7Colors.TextPrimary,
        )
    }
}

@Composable
private fun CalendarDetailRow(iconUrl: String, label: String, value: String) {
    Row(
        modifier = Modifier.fillMaxWidth(),
        horizontalArrangement = Arrangement.spacedBy(10.dp),
        verticalAlignment = Alignment.Top,
    ) {
        AsyncImage(model = iconUrl, contentDescription = null, modifier = Modifier.size(20.dp))
        Column {
            Text(label, style = MaterialTheme.typography.labelMedium, color = F7Colors.TextSecondary)
            Text(value, style = MaterialTheme.typography.bodyMedium)
        }
    }
}

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun CalendarDatePickerDialog(
    selectedDay: LocalDate,
    onDismiss: () -> Unit,
    onConfirm: (LocalDate) -> Unit,
) {
    val state = rememberDatePickerState(
        initialSelectedDateMillis = selectedDay.atStartOfDay(ZoneId.systemDefault()).toInstant().toEpochMilli(),
    )
    DatePickerDialog(
        onDismissRequest = onDismiss,
        confirmButton = {
            TextButton(onClick = {
                val millis = state.selectedDateMillis ?: return@TextButton
                val day = Instant.ofEpochMilli(millis).atZone(ZoneId.systemDefault()).toLocalDate()
                onConfirm(day)
            }) { Text("OK") }
        },
        dismissButton = {
            TextButton(onClick = onDismiss) { Text("Отмена") }
        },
    ) {
        DatePicker(state = state)
    }
}

@Composable
fun CalendarEventEditorDialog(
    state: CalendarUiState,
    onDismiss: () -> Unit,
    onDraftChange: (CalendarEventDraft) -> Unit,
    onSave: () -> Unit,
    onDelete: () -> Unit,
) {
    val draft = state.eventDraft
    val isEdit = state.editorMode == CalendarEditorMode.EDIT
    AlertDialog(
        onDismissRequest = { if (!state.saving && !state.deleting) onDismiss() },
        title = { Text(if (isEdit) "Редактировать событие" else "Создать событие") },
        text = {
            Column(
                modifier = Modifier
                    .fillMaxWidth()
                    .heightIn(max = 420.dp)
                    .verticalScroll(rememberScrollState()),
                verticalArrangement = Arrangement.spacedBy(10.dp),
            ) {
                F7OutlinedField(
                    value = draft.title,
                    onValueChange = { onDraftChange(draft.copy(title = it)) },
                    label = "Название",
                )
                Text(
                    draft.date.format(dayTitleFormatter),
                    style = MaterialTheme.typography.bodySmall,
                    color = F7Colors.TextSecondary,
                )
                Row(horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically) {
                    Text("Весь день")
                    Switch(
                        checked = draft.allDay,
                        onCheckedChange = { onDraftChange(draft.copy(allDay = it)) },
                    )
                }
                if (!draft.allDay) {
                    F7OutlinedField(
                        value = draft.startTime,
                        onValueChange = { onDraftChange(draft.copy(startTime = it)) },
                        label = "Начало (ЧЧ:ММ)",
                    )
                    F7OutlinedField(
                        value = draft.endTime,
                        onValueChange = { onDraftChange(draft.copy(endTime = it)) },
                        label = "Окончание (ЧЧ:ММ)",
                    )
                }
                F7OutlinedField(
                    value = draft.location,
                    onValueChange = { onDraftChange(draft.copy(location = it)) },
                    label = "Место",
                )
                F7OutlinedField(
                    value = draft.description,
                    onValueChange = { onDraftChange(draft.copy(description = it)) },
                    label = "Описание",
                )
                if (state.calendars.isNotEmpty()) {
                    Text("Календарь", style = MaterialTheme.typography.labelMedium)
                    state.calendars.filter { it.visible }.forEach { cal ->
                        Row(
                            modifier = Modifier
                                .fillMaxWidth()
                                .clickable { onDraftChange(draft.copy(calendarHref = cal.href)) },
                            verticalAlignment = Alignment.CenterVertically,
                        ) {
                            RadioButton(
                                selected = draft.calendarHref == cal.href,
                                onClick = { onDraftChange(draft.copy(calendarHref = cal.href)) },
                            )
                            Text(cal.displayName, modifier = Modifier.padding(start = 4.dp))
                        }
                    }
                }
            }
        },
        confirmButton = {
            F7PrimaryButton(
                text = if (state.saving) "Сохранение…" else "Сохранить",
                onClick = onSave,
                enabled = !state.saving,
            )
        },
        dismissButton = {
            Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
                if (isEdit) {
                    TextButton(onClick = onDelete, enabled = !state.deleting) {
                        Text(if (state.deleting) "Удаление…" else "Удалить", color = F7Colors.Error)
                    }
                }
                TextButton(onClick = onDismiss, enabled = !state.saving) { Text("Отмена") }
            }
        },
    )
}

@Composable
fun CalendarSyncSettingsDialog(
    state: CalendarUiState,
    onDismiss: () -> Unit,
    onSyncEnabledChange: (Boolean) -> Unit,
    onSelectCalendar: (Long) -> Unit,
    onSyncNow: () -> Unit,
) {
    AlertDialog(
        onDismissRequest = onDismiss,
        title = { Text("Параметры календаря") },
        text = {
            Column(verticalArrangement = Arrangement.spacedBy(12.dp)) {
                Text(
                    "Синхронизация F7cloud с календарём телефона (Google и др.).",
                    style = MaterialTheme.typography.bodySmall,
                    color = F7Colors.TextSecondary,
                )
                Row(
                    modifier = Modifier.fillMaxWidth(),
                    horizontalArrangement = Arrangement.SpaceBetween,
                    verticalAlignment = Alignment.CenterVertically,
                ) {
                    Text("Синхронизация с телефоном")
                    Switch(checked = state.syncEnabled, onCheckedChange = onSyncEnabledChange)
                }
                if (state.deviceCalendars.isEmpty()) {
                    Text(
                        "Календари телефона не найдены",
                        style = MaterialTheme.typography.bodySmall,
                        color = F7Colors.TextSecondary,
                    )
                } else if (state.syncEnabled) {
                    Text("Календарь на телефоне", style = MaterialTheme.typography.labelMedium)
                    state.deviceCalendars.take(8).forEach { cal ->
                        Row(
                            modifier = Modifier
                                .fillMaxWidth()
                                .clickable { onSelectCalendar(cal.id) },
                            verticalAlignment = Alignment.CenterVertically,
                        ) {
                            RadioButton(
                                selected = state.selectedDeviceCalendarId == cal.id,
                                onClick = { onSelectCalendar(cal.id) },
                            )
                            Column(modifier = Modifier.padding(start = 4.dp)) {
                                Text(cal.displayName)
                                if (cal.accountName.isNotBlank()) {
                                    Text(cal.accountName, style = MaterialTheme.typography.labelSmall, color = F7Colors.TextMuted)
                                }
                            }
                        }
                    }
                }
            }
        },
        confirmButton = {
            F7PrimaryButton(
                text = if (state.syncing) "Синхронизация…" else "Синхронизировать",
                onClick = onSyncNow,
                enabled = state.syncEnabled && !state.syncing && state.selectedDeviceCalendarId > 0,
            )
        },
        dismissButton = {
            TextButton(onClick = onDismiss) { Text("Закрыть") }
        },
    )
}
