package dev.ulfrx.recipe.ui.components.calendar

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.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.text.BasicText
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import dev.ulfrx.recipe.ui.theme.RecipeTheme
import kotlinx.datetime.LocalDate

private val DAY_SPACING = 4.dp
private val WEEK_SPACING = 4.dp

/** Weekday-letter header row. */
@Composable
internal fun WeekdayHeader(
    locale: CalendarLocale,
    modifier: Modifier = Modifier,
) {
    Row(
        modifier = modifier.fillMaxWidth().padding(bottom = 4.dp),
        horizontalArrangement = Arrangement.spacedBy(DAY_SPACING),
    ) {
        locale.weekdaysShort.forEach { label ->
            Box(
                modifier = Modifier.weight(1f),
                contentAlignment = Alignment.Center,
            ) {
                BasicText(
                    text = label,
                    style =
                        RecipeTheme.typography.label.copy(
                            color = RecipeTheme.colors.contentMuted,
                            fontWeight = FontWeight.Light,
                        ),
                )
            }
        }
    }
}

/**
 * Seven-day Monday-first strip for [anchor]'s week. All days are in-period so
 * the [DayState.dimmed] flag is never set by this composable itself.
 */
@Composable
internal fun WeekStrip(
    anchor: LocalDate,
    today: LocalDate,
    dayState: (LocalDate) -> DayState,
    isSelected: (LocalDate) -> Boolean,
    onSelect: (LocalDate) -> Unit,
    modifier: Modifier = Modifier,
) {
    val days = weekStripDays(anchor)
    Row(
        modifier = modifier.fillMaxWidth(),
        horizontalArrangement = Arrangement.spacedBy(DAY_SPACING),
    ) {
        days.forEach { day ->
            Box(modifier = Modifier.weight(1f)) {
                CalendarDayCell(
                    date = day,
                    state = dayState(day),
                    isSelected = isSelected(day),
                    isToday = day == today,
                    onClick = { onSelect(day) },
                )
            }
        }
    }
}

/**
 * Fixed 6-week grid for [anchor]'s month. Adjacent-month days are auto-marked
 * dimmed (caller's [dayState] does not need to set that flag for them).
 */
@Composable
internal fun MonthGrid(
    anchor: LocalDate,
    today: LocalDate,
    dayState: (LocalDate) -> DayState,
    isSelected: (LocalDate) -> Boolean,
    onSelect: (LocalDate) -> Unit,
    modifier: Modifier = Modifier,
) {
    val days = monthGridDays(anchor)
    Column(
        modifier = modifier.fillMaxWidth(),
        verticalArrangement = Arrangement.spacedBy(WEEK_SPACING),
    ) {
        for (week in 0 until 6) {
            Row(
                modifier = Modifier.fillMaxWidth(),
                horizontalArrangement = Arrangement.spacedBy(DAY_SPACING),
            ) {
                for (dayIdx in 0 until 7) {
                    val day = days[week * 7 + dayIdx]
                    val inMonth = day.monthNumber == anchor.monthNumber
                    val resolved = dayState(day)
                    val effective =
                        if (!inMonth) resolved.copy(dimmed = true) else resolved
                    Box(modifier = Modifier.weight(1f)) {
                        CalendarDayCell(
                            date = day,
                            state = effective,
                            isSelected = isSelected(day),
                            isToday = day == today,
                            onClick = { onSelect(day) },
                        )
                    }
                }
            }
        }
    }
}
