package solutions.tretter.mindmachine.session

import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Slider
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import kotlin.math.max
import kotlin.math.roundToInt

@Composable
fun SetupTimelineEditor(
    state: TimelineEditorState,
    onStateChanged: (TimelineEditorState) -> Unit,
    onCurveGranularityChanged: (Int) -> Unit,
    modifier: Modifier = Modifier,
) {
    var local by remember(state) { mutableStateOf(state) }
    val allowedGranularity = remember(local.durationSec) { TimelineEditorState.allowedGranularitySteps(local.durationSec) }
    val sliderMin = allowedGranularity.first().toFloat()
    val sliderMax = allowedGranularity.last().toFloat()

    Column(
        modifier = modifier.fillMaxWidth(),
        verticalArrangement = Arrangement.spacedBy(10.dp),
    ) {
        Text(
            "Program curves",
            style = MaterialTheme.typography.titleMedium,
            color = MaterialTheme.colorScheme.onBackground,
        )
        Text(
            "Adjust curve granularity, then drag dots up/down to shape the session. Granularity always divides the full duration evenly.",
            style = MaterialTheme.typography.bodySmall,
            color = MaterialTheme.colorScheme.onBackground.copy(alpha = 0.75f),
        )

        val granularitySec = local.curveGranularitySec
        Text(
            "Curve granularity: ${granularitySec}s per dot",
            style = MaterialTheme.typography.bodyMedium,
            color = MaterialTheme.colorScheme.onBackground,
        )
        var granularitySliderValue by remember(state.curveGranularitySec, state.durationSec) {
            mutableFloatStateOf(state.curveGranularitySec.toFloat())
        }
        Slider(
            value = granularitySliderValue.coerceIn(sliderMin, sliderMax),
            onValueChange = { granularitySliderValue = it },
            onValueChangeFinished = {
                val snapped = TimelineEditorState.normalizeGranularitySec(granularitySliderValue.roundToInt(), local.durationSec)
                if (snapped != local.curveGranularitySec) {
                    local = local.setCurveGranularitySec(snapped).also(onStateChanged)
                    onCurveGranularityChanged(snapped)
                }
                granularitySliderValue = local.curveGranularitySec.toFloat()
            },
            valueRange = sliderMin..sliderMax,
            steps = max(0, allowedGranularity.size - 2),
        )

        TimelineGraph(
            title = "Visual",
            leftLabel = "Flash Interval",
            rightLabel = "Blank Interval",
            curveLeft = local.visualLeft,
            curveRight = local.visualRight,
            activeCurve = local.activeCurve,
            viewport = local.viewport,
            selection = local.selection,
            playheadSec = local.playheadSec,
            onViewportChanged = { vp -> local = local.copy(viewport = vp).also(onStateChanged) },
            onSelectionChanged = { sel -> local = local.copy(selection = sel).clampSelection().also(onStateChanged) },
            onUpdateCurve = { curveId, newCurve ->
                val candidate = local.withCurve(curveId, newCurve)
                val maxT = newCurve.points.maxOfOrNull { it.tSec } ?: 0
                local = candidate.extendDurationTo(maxT)
                    .copy(selection = candidate.selection.copy(endSec = max(candidate.selection.endSec, candidate.durationSec)))
                    .also(onStateChanged)
            },
            onTapSideSelect = { side ->
                local = local.copy(activeCurve = if (side == Side.LEFT) TimelineEditorState.ActiveCurve.VISUAL_LEFT else TimelineEditorState.ActiveCurve.VISUAL_RIGHT)
                    .also(onStateChanged)
            }
        )

        Spacer(Modifier.height(6.dp))

        TimelineGraph(
            title = "Audio",
            leftLabel = "Carrier",
            rightLabel = "Binaural",
            curveLeft = local.audioLeft,
            curveRight = local.audioRight,
            activeCurve = local.activeCurve,
            viewport = local.viewport,
            selection = local.selection,
            playheadSec = local.playheadSec,
            onViewportChanged = { vp -> local = local.copy(viewport = vp).also(onStateChanged) },
            onSelectionChanged = { sel -> local = local.copy(selection = sel).clampSelection().also(onStateChanged) },
            onUpdateCurve = { curveId, newCurve ->
                val candidate = local.withCurve(curveId, newCurve)
                val maxT = newCurve.points.maxOfOrNull { it.tSec } ?: 0
                local = candidate.extendDurationTo(maxT).also(onStateChanged)
            },
            onTapSideSelect = { side ->
                local = local.copy(activeCurve = if (side == Side.LEFT) TimelineEditorState.ActiveCurve.AUDIO_LEFT else TimelineEditorState.ActiveCurve.AUDIO_RIGHT)
                    .also(onStateChanged)
            }
        )
    }
}
