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

import android.annotation.SuppressLint
import android.icu.text.DateFormat
import android.icu.text.SimpleDateFormat
import android.icu.util.Calendar
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
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.height
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Stable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.text.style.TextOverflow
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 com.pixelized.headache.ui.theme.HeadacheTheme
import com.pixelized.headache.ui.theme.color.HeadacheColorPalette
import com.pixelized.headache.utils.extention.capitalize
import java.util.Date
import java.util.Locale

@Stable
class ReportBoxUio(
    val year: Int,
    val months: List<Month>,
) {
    @Stable
    data class Month(
        val date: Date,
        val stats: List<Bar>,
    )

    @Stable
    data class Bar(
        val color: Color,
        val label: String,
        val ratio: Float,
    )
}

@Stable
object ReportBoxDefault {

    @Stable
    val barSpace: Dp = 4.dp

    @Stable
    val titleSpace: Dp = 8.dp

    @Stable
    val barSize: DpSize = DpSize(
        width = 28.dp,
        height = 240.dp,
    )

    @Stable
    val barShape: Shape = RoundedCornerShape(
        topStart = barSize.width / 4,
        topEnd = barSize.width / 4
    )

    @SuppressLint("ConstantLocale")
    @Stable
    val formatter = SimpleDateFormat("MMM", Locale.getDefault())
}

@Composable
fun ReportBox(
    modifier: Modifier = Modifier,
    formatter: DateFormat = ReportBoxDefault.formatter,
    barSize: DpSize = ReportBoxDefault.barSize,
    barShape: Shape = ReportBoxDefault.barShape,
    barSpace: Dp = ReportBoxDefault.barSpace,
    titleSpace: Dp = ReportBoxDefault.titleSpace,
    item: ReportBoxUio,
    onMonth: (ReportBoxUio.Month) -> Unit,
) {
    Column(
        modifier = modifier,
        verticalArrangement = Arrangement.spacedBy(space = titleSpace),
    ) {
        Text(
            modifier = Modifier.padding(top = 16.dp),
            style = MaterialTheme.typography.displaySmall,
            text = "${item.year}",
        )
        Row(
            horizontalArrangement = Arrangement.spacedBy(space = barSpace),
        ) {
            item.months.forEach {
                Month(
                    formatter = formatter,
                    barSize = barSize,
                    barShape = barShape,
                    item = it,
                    onItem = onMonth,
                )
            }
        }
    }
}

@Composable
private fun Month(
    modifier: Modifier = Modifier,
    formatter: DateFormat = ReportBoxDefault.formatter,
    barSize: DpSize = ReportBoxDefault.barSize,
    barShape: Shape = ReportBoxDefault.barShape,
    item: ReportBoxUio.Month,
    onItem: (ReportBoxUio.Month) -> Unit,
) {
    Column(
        modifier = Modifier
            .width(width = barSize.width)
            .clickable { onItem(item) }
            .then(other = modifier),
        horizontalAlignment = Alignment.CenterHorizontally,
    ) {
        Box(
            modifier = Modifier.height(height = barSize.height),
            contentAlignment = Alignment.BottomStart,
        ) {
            item.stats.forEachIndexed { index, stat ->
                Box(
                    modifier = Modifier
                        .size(
                            width = barSize.width,
                            height = barSize.height * stat.ratio
                        )
                        .background(
                            color = stat.color,
                            shape = barShape,
                        ),
                    contentAlignment = Alignment.TopCenter,
                ) {
                    when (index == 0 && item.stats.size >= 2) {
                        true -> Text(
                            modifier = Modifier.offset(y = (-14).dp),
                            style = MaterialTheme.typography.labelSmall,
                            overflow = TextOverflow.Ellipsis,
                            maxLines = 1,
                            color = MaterialTheme.colorScheme.onSurface,
                            text = stat.label,
                        )

                        else -> Text(
                            style = MaterialTheme.typography.labelSmall,
                            overflow = TextOverflow.Ellipsis,
                            maxLines = 1,
                            color = Color.White,
                            text = stat.label,
                        )
                    }
                }
            }
        }
        Text(
            style = MaterialTheme.typography.labelSmall,
            overflow = TextOverflow.Ellipsis,
            maxLines = 1,
            text = formatter.format(item.date).capitalize(),
        )
    }
}

@Composable
@Preview
private fun ReportBoxPreview(
    @PreviewParameter(ReportBoxPreviewProvider::class) preview: ReportBoxUio,
) {
    HeadacheTheme {
        Surface {
            ReportBox(
                item = preview,
                onMonth = { },
            )
        }
    }
}

object ReportBoxPreviewHelper {
    fun month(
        month: Int,
        headache: Int = 0,
        pills: Int = 0,
    ) = ReportBoxUio.Month(
        date = Calendar.getInstance().apply {
            set(Calendar.MONTH, month)
        }.time,
        stats = listOf(
            ReportBoxUio.Bar(
                color = HeadacheColorPalette.Calendar.Headache,
                label = "$headache",
                ratio = (headache.toFloat() / 30).coerceIn(0f, 1f),
            ),
            ReportBoxUio.Bar(
                color = HeadacheColorPalette.Calendar.Pill,
                label = "$pills",
                ratio = (pills.toFloat() / 24).coerceIn(0f, 1f),
            ),
        ).sortedByDescending { it.ratio },
    )
}

private class ReportBoxPreviewProvider : PreviewParameterProvider<ReportBoxUio> {
    override val values: Sequence<ReportBoxUio>
        get() = with(ReportBoxPreviewHelper) {
            sequenceOf(
                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 = 8, pills = 5),
                        month(month = Calendar.OCTOBER, headache = 15, pills = 15),
                        month(month = Calendar.NOVEMBER, headache = 9, pills = 7),
                        month(month = Calendar.DECEMBER),
                    )
                )
            )
        }
}