package com.pixelized.headache.ui.page.summary.monthly

import android.icu.util.Calendar
import androidx.compose.foundation.gestures.FlingBehavior
import androidx.compose.foundation.gestures.snapping.SnapPosition
import androidx.compose.foundation.gestures.snapping.rememberSnapFlingBehavior
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Surface
import androidx.compose.material3.minimumInteractiveComponentSize
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Stable
import androidx.compose.runtime.State
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.keepScreenOn
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.pixelized.headache.ui.navigation.destination.navigateToEventPage
import com.pixelized.headache.ui.navigation.main.LocalMainNavigator
import com.pixelized.headache.ui.page.summary.monthly.item.MonthSummaryItem
import com.pixelized.headache.ui.page.summary.monthly.item.MonthSummaryItemUio
import com.pixelized.headache.ui.page.summary.monthly.item.MonthSummaryPillItemUio
import com.pixelized.headache.ui.page.summary.monthly.item.MonthSummaryTitle
import com.pixelized.headache.ui.page.summary.monthly.item.MonthSummaryTitleUio
import com.pixelized.headache.ui.theme.HeadacheTheme
import com.pixelized.headache.ui.theme.color.HeadacheColorPalette

@Stable
data object MonthSummaryPageDefault {
    @Stable
    val listPadding: PaddingValues = PaddingValues(
        bottom = 16.dp + 16.dp + 56.dp,
    )

    @Stable
    val spacing: Dp = 0.dp
}

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun MonthSummaryPage(
    viewModel: MonthSummaryViewModel = hiltViewModel(),
) {
    val navigation = LocalMainNavigator.current
    val events = viewModel.events.collectAsStateWithLifecycle()

    MonthSummaryContent(
        modifier = Modifier
            .keepScreenOn()
            .fillMaxSize(),
        events = events,
        onItem = {
            navigation.navigateToEventPage(date = it.date)
        },
    )
}

@Composable
@OptIn(ExperimentalMaterial3Api::class)
private fun MonthSummaryContent(
    modifier: Modifier = Modifier,
    state: LazyListState = rememberLazyListState(),
    flingBehavior: FlingBehavior = rememberSnapFlingBehavior(
        lazyListState = state,
        snapPosition = SnapPosition.Start,
    ),
    spacing: Dp = MonthSummaryPageDefault.spacing,
    listPadding: PaddingValues = MonthSummaryPageDefault.listPadding,
    events: State<Map<MonthSummaryTitleUio, List<MonthSummaryItemUio>>>,
    onItem: (MonthSummaryItemUio) -> Unit,
) {
    LazyColumn(
        modifier = modifier,
        state = state,
        flingBehavior = flingBehavior,
        contentPadding = listPadding,
        verticalArrangement = Arrangement.spacedBy(space = spacing),
        reverseLayout = true,
    ) {
        events.value.forEach { entry ->
            items(
                items = entry.value,
                key = { item -> item.date },
            ) { item ->
                MonthSummaryItem(
                    item = item,
                    onItem = onItem,
                )
            }
            item {
                MonthSummaryTitle(
                    item = entry.key,
                )
            }
        }
    }
}

@Composable
@Preview
private fun MonthSummaryPreview(
    @PreviewParameter(MonthSummaryPreviewProvider::class) preview: Map<MonthSummaryTitleUio, List<MonthSummaryItemUio>>,
) {
    HeadacheTheme {
        Surface {
            val events = remember { mutableStateOf(preview) }
            MonthSummaryContent(
                modifier = Modifier.fillMaxSize(),
                events = events,
                onItem = { },
            )
        }
    }
}

private class MonthSummaryPreviewProvider :
    PreviewParameterProvider<Map<MonthSummaryTitleUio, List<MonthSummaryItemUio>>> {

    private fun date(
        year: Int,
    ) = Calendar.getInstance().also {
        it.set(Calendar.YEAR, year)
        it.set(Calendar.MONTH, Calendar.JANUARY)
        it.set(Calendar.DAY_OF_MONTH, 1)
        it.set(Calendar.MILLISECONDS_IN_DAY, 1)
    }

    private fun Calendar.year(
        vararg month: MonthSummaryItemUio,
    ): Pair<MonthSummaryTitleUio, List<MonthSummaryItemUio>> {
        this.add(Calendar.YEAR, -1)
        return MonthSummaryTitleUio(
            date = this.time
        ) to month.toList()
    }

    private fun Calendar.month(
        headache: Int = 0,
        eletriptan: Int = 0,
        ibuprofen: Int = 0,
        paracetamol: Int = 0,
        spifen: Int = 0,
    ): MonthSummaryItemUio {
        val date = this.time
        this.add(Calendar.MONTH, 1)
        return MonthSummaryItemUio(
            date = date,
            days = headache,
            pills = listOfNotNull(
                eletriptan.takeIf { it > 0 }?.let {
                    MonthSummaryPillItemUio(
                        label = "Élétriptan 40",
                        amount = it,
                        color = HeadacheColorPalette.Pill.Eletriptan40,
                    )
                },
                ibuprofen.takeIf { it > 0 }?.let {
                    MonthSummaryPillItemUio(
                        label = "Ibuprofène 400",
                        amount = it,
                        color = HeadacheColorPalette.Pill.Ibuprofene400,
                    )
                },
                paracetamol.takeIf { it > 0 }?.let {
                    MonthSummaryPillItemUio(
                        label = "Paracetamol 1000",
                        amount = it,
                        color = HeadacheColorPalette.Pill.Paracetamol1000,
                    )
                },
                spifen.takeIf { it > 0 }?.let {
                    MonthSummaryPillItemUio(
                        label = "Spifen 400",
                        amount = it,
                        color = HeadacheColorPalette.Pill.Spifen400,
                    )
                },
            ),
        )
    }

    override val values: Sequence<Map<MonthSummaryTitleUio, List<MonthSummaryItemUio>>>
        get() = sequenceOf(
            mapOf(
                with(date(year = 2025)) {
                    year(
                        month(headache = 6, eletriptan = 4, spifen = 6),
                        month(headache = 15, eletriptan = 9, paracetamol = 2, spifen = 14),
                        month(headache = 14, eletriptan = 6, spifen = 10),
                        month(headache = 16, eletriptan = 7, spifen = 11),
                        month(headache = 14, eletriptan = 7, ibuprofen = 1, spifen = 12),
                        month(headache = 12, eletriptan = 3, spifen = 10),
                        month(headache = 7, spifen = 3),
                        month(headache = 8, eletriptan = 1, spifen = 4),
                        month(headache = 8, eletriptan = 1, spifen = 4),
                        month(),
                        month(),
                        month(),
                    )
                },
                with(date(year = 2024)) {
                    year(
                        month(),
                        month(),
                    )
                }
            )
        )
}