package com.syaroful.agrilinkvocpro.commodity_price_prediction_feature.presentation.prediction

import android.graphics.Paint
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.background
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Path
import androidx.compose.ui.graphics.PathEffect
import androidx.compose.ui.graphics.StrokeCap
import androidx.compose.ui.graphics.asAndroidPath
import androidx.compose.ui.graphics.asComposePath
import androidx.compose.ui.graphics.drawscope.Stroke
import androidx.compose.ui.graphics.nativeCanvas
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.syaroful.agrilinkvocpro.presentation.theme.MainGreen
import kotlin.math.round
import kotlin.math.roundToInt

@Composable
fun PriceChart(
    day: List<Int> = emptyList(),
    values: List<Double> = emptyList(),
    horizontalValue: Double? = null,
    modifier: Modifier = Modifier,
    graphColor: Color = MainGreen
) {
    Box(
        modifier = Modifier
            .background(
                color = MaterialTheme.colorScheme.surfaceContainer,
                shape = RoundedCornerShape(8.dp)
            )
            .padding(top = 32.dp, start = 16.dp)
            .padding(8.dp)
    ) {
        val spacing = 100f
        val transparentGraphColor = remember {
            graphColor.copy(alpha = 0.5f)
        }
        val upperValue = remember(values) {
            (values.maxOrNull()?.plus(1))?.roundToInt() ?: 0
        }
        val lowerValue = remember(values) {
            values.minOrNull()?.toInt() ?: 0
        }
        val density = LocalDensity.current
        val isDarkMode = isSystemInDarkTheme()
        val textPaint = remember(density) {
            Paint().apply {
                color =
                    if (isDarkMode) android.graphics.Color.WHITE else android.graphics.Color.BLACK
                textAlign = Paint.Align.CENTER
                textSize = density.run { 12.sp.toPx() }
            }
        }

        Canvas(modifier = modifier) {
            val spacePerDay = (size.width - spacing) / values.size
            day.forEachIndexed { i, day ->
                drawContext.canvas.nativeCanvas.drawText(
                    "h $day",
                    spacing + 40f + i * spacePerDay,
                    size.height - 5,
                    textPaint
                )
            }

            val step = (upperValue - lowerValue) / 5f
            (0..4).forEach { i ->
                drawContext.canvas.nativeCanvas.drawText(
                    "Rp " + round(lowerValue + step * i).toInt().toString(),
                    30f,
                    size.height - spacing - i * size.height / 5f,
                    textPaint
                )
            }

            var lastX = 0f
            val strokePath = Path().apply {
                val height = size.height
                for (i in values.indices) {
                    val value = values[i]
                    val nextValue = values.getOrNull(i + 1) ?: values.last()
                    val leftRatio = (value - lowerValue) / (upperValue - lowerValue)
                    val rightRatio = (nextValue - lowerValue) / (upperValue - lowerValue)

                    val x1 = spacing + 40f + i * spacePerDay
                    val y1 = height - spacing - (leftRatio * height).toFloat()
                    val x2 = spacing + (i + 1) * spacePerDay
                    val y2 = height - spacing - (rightRatio * height).toFloat()
                    if (i == 0) {
                        moveTo(x1, y1)
                    }
                    lastX = (x1 + x2) / 2f
                    quadraticTo(x1, y1, lastX, (y1 + y2) / 2f)
                }
            }
            val fillPath = android.graphics.Path(strokePath.asAndroidPath())
                .asComposePath()
                .apply {
                    lineTo(lastX, size.height - spacing)
                    lineTo(spacing, size.height - spacing)
                    close()
                }
            drawPath(
                path = fillPath,
                brush = Brush.verticalGradient(
                    colors = listOf(
                        transparentGraphColor,
                        Color.Transparent
                    ),
                    endY = size.height - spacing
                )
            )
            drawPath(
                path = strokePath,
                color = graphColor,
                style = Stroke(
                    width = 3.dp.toPx(),
                    cap = StrokeCap.Round
                )
            )
            val labelPadding = 12.dp.toPx()

            drawContext.canvas.nativeCanvas.drawText(
                "Harga",
                spacing / 2f,
                labelPadding - 100,
                textPaint.apply { color = android.graphics.Color.GREEN }
            )

            horizontalValue?.let { value ->
                val ratio = (value - lowerValue) / (upperValue - lowerValue)
                val y = size.height - spacing - (ratio * size.height).toFloat()
                drawLine(
                    color = Color.Red,
                    start = Offset(spacing, y),
                    end = Offset(size.width, y),
                    strokeWidth = 2.dp.toPx(),
                    pathEffect = PathEffect.dashPathEffect(floatArrayOf(10f, 10f))
                )
            }
        }
    }
}