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


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.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.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.Modifier
import androidx.compose.ui.keepScreenOn
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.platform.LocalWindowInfo
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.DpSize
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.theme.HeadacheTheme
import com.pixelized.headache.utils.extention.calculate

@Stable
data object ReportPageDefault {
    @Stable
    val paddingValues = PaddingValues(
        start = 16.dp,
        end = 16.dp,
        bottom = 16.dp + 16.dp + 56.dp,
    )

    @Stable
    val contentSpace: Dp = 8.dp

    @Stable
    val barSpace: Dp = ReportBoxDefault.barSpace
}

@Composable
fun ReportPage(
    viewModel: ReportViewModel = hiltViewModel(),
) {
    val navigator = LocalMainNavigator.current
    val events = viewModel.events.collectAsStateWithLifecycle()

    ReportContent(
        modifier = Modifier
            .keepScreenOn()
            .fillMaxSize(),
        events = events,
        onMonth = {
            navigator.navigateToEventPage(date = it.date)
        },
    )
}

@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun ReportContent(
    modifier: Modifier = Modifier,
    state: LazyListState = rememberLazyListState(),
    flingBehavior: FlingBehavior = rememberSnapFlingBehavior(
        lazyListState = state,
        snapPosition = SnapPosition.Start,
    ),
    paddingValues: PaddingValues = ReportPageDefault.paddingValues,
    contentSpace: Dp = ReportPageDefault.contentSpace,
    barSpace: Dp = ReportPageDefault.barSpace,
    barSize: DpSize = rememberBarSize(column = 12, paddingValues = paddingValues, space = barSpace),
    events: State<List<ReportBoxUio>>,
    onMonth: (ReportBoxUio.Month) -> Unit,
) {
    LazyColumn(
        modifier = modifier,
        state = state,
        flingBehavior = flingBehavior,
        contentPadding = paddingValues,
        reverseLayout = true,
        verticalArrangement = Arrangement.spacedBy(space = contentSpace),
    ) {
        items(
            items = events.value
        ) { item ->
            ReportBox(
                barSize = barSize,
                barSpace = barSpace,
                item = item,
                onMonth = onMonth,
            )
        }
    }
}

@Composable
private fun rememberBarSize(
    column: Int,
    paddingValues: PaddingValues,
    space: Dp,
): DpSize {
    val density = LocalDensity.current
    val windowInfo = LocalWindowInfo.current
    val screenWidth = remember(density, windowInfo) {
        with(density) { windowInfo.containerSize.width.toDp() }
    }
    val (start, _, end, _) = paddingValues.calculate()
    return remember {
        DpSize(
            width = (screenWidth - space * (column - 1) - start - end) / column,
            height = ReportBoxDefault.barSize.height,
        )
    }
}

@Composable
@Preview
private fun ReportPreview(
    @PreviewParameter(ReportPreviewProvider::class) preview: List<ReportBoxUio>,
) {
    HeadacheTheme {
        Surface {
            ReportContent(
                events = remember { mutableStateOf(preview) },
                onMonth = { },
            )
        }
    }
}

private class ReportPreviewProvider : PreviewParameterProvider<List<ReportBoxUio>> {

    override val values: Sequence<List<ReportBoxUio>>
        get() = with(ReportBoxPreviewHelper) {
            sequenceOf(
                listOf(
                    ReportBoxUio(
                        year = 2025,
                        months = listOf(
                            month(month = Calendar.JANUARY, headache = 6, pills = 10),
                            month(month = Calendar.FEBRUARY, headache = 15, pills = 24),
                            month(month = Calendar.MARCH, headache = 14, pills = 16),
                            month(month = Calendar.APRIL, headache = 16, pills = 18),
                            month(month = Calendar.MARCH, headache = 14, pills = 20),
                            month(month = Calendar.JUNE, headache = 12, pills = 13),
                            month(month = Calendar.JULY, headache = 7, pills = 3),
                            month(month = Calendar.AUGUST, headache = 8, pills = 5),
                            month(month = Calendar.SEPTEMBER, headache = 10, pills = 5),
                            month(month = Calendar.OCTOBER, headache = 15, pills = 15),
                            month(month = Calendar.NOVEMBER, headache = 9, pills = 7),
                            month(month = Calendar.DECEMBER, headache = 0, pills = 0),
                        ),
                    ),
                    ReportBoxUio(
                        year = 2024,
                        months = listOf(
                            month(month = Calendar.JANUARY, headache = 14),
                            month(month = Calendar.FEBRUARY, headache = 15),
                            month(month = Calendar.MARCH, headache = 15),
                            month(month = Calendar.APRIL, headache = 10),
                            month(month = Calendar.MARCH, headache = 7),
                            month(month = Calendar.JUNE, headache = 15),
                            month(month = Calendar.JULY, headache = 7),
                            month(month = Calendar.AUGUST, headache = 11, pills = 12),
                            month(month = Calendar.SEPTEMBER, headache = 12, pills = 15),
                            month(month = Calendar.OCTOBER, headache = 5, pills = 8),
                            month(month = Calendar.NOVEMBER, headache = 17, pills = 22),
                            month(month = Calendar.DECEMBER, headache = 12, pills = 17),
                        ),
                    )
                )
            )
        }
}