package com.aiosman.riderpro

import androidx.compose.animation.core.Animatable
import androidx.compose.foundation.gestures.Orientation
import androidx.compose.foundation.gestures.draggable
import androidx.compose.foundation.gestures.rememberDraggableState
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.Layout
import androidx.compose.ui.layout.Measurable
import androidx.compose.ui.layout.ParentDataModifier
import androidx.compose.ui.unit.Density
import kotlinx.coroutines.launch
import kotlin.math.abs
import kotlin.math.roundToInt

class PagerState(
    currentPage: Int = 0,
    minPage: Int = 0,
    maxPage: Int = 0
) {
    private var _minPage by mutableStateOf(minPage)
    var minPage: Int
        get() = _minPage
        set(value) {
            _minPage = value.coerceAtMost(_maxPage)
            _currentPage = _currentPage.coerceIn(_minPage, _maxPage)
        }

    private var _maxPage by mutableStateOf(maxPage, structuralEqualityPolicy())
    var maxPage: Int
        get() = _maxPage
        set(value) {
            _maxPage = value.coerceAtLeast(_minPage)
            _currentPage = _currentPage.coerceIn(_minPage, maxPage)
        }

    private var _currentPage by mutableStateOf(currentPage.coerceIn(minPage, maxPage))
    var currentPage: Int
        get() = _currentPage
        set(value) {
            _currentPage = value.coerceIn(minPage, maxPage)
        }

    enum class SelectionState { Selected, Undecided }

    var selectionState by mutableStateOf(SelectionState.Selected)

    suspend inline fun <R> selectPage(block: PagerState.() -> R): R = try {
        selectionState = SelectionState.Undecided
        block()
    } finally {
        selectPage()
    }

    suspend fun selectPage() {
        currentPage -= currentPageOffset.roundToInt()
        snapToOffset(0f)
        selectionState = SelectionState.Selected
    }

    private var _currentPageOffset = Animatable(0f).apply {
        updateBounds(-1f, 1f)
    }
    val currentPageOffset: Float
        get() = _currentPageOffset.value

    suspend fun snapToOffset(offset: Float) {
        val max = if (currentPage == minPage) 0f else 1f
        val min = if (currentPage == maxPage) 0f else -1f
        _currentPageOffset.snapTo(offset.coerceIn(min, max))
    }

    suspend fun fling(velocity: Float) {
        if (velocity < 0 && currentPage == maxPage) return
        if (velocity > 0 && currentPage == minPage) return

        // 根据 fling 的方向滑动到下一页或上一页
        _currentPageOffset.animateTo(velocity)
        selectPage()
    }

    override fun toString(): String = "PagerState{minPage=$minPage, maxPage=$maxPage, " +
            "currentPage=$currentPage, currentPageOffset=$currentPageOffset}"
}

@Immutable
private data class PageData(val page: Int) : ParentDataModifier {
    override fun Density.modifyParentData(parentData: Any?): Any? = this@PageData
}

private val Measurable.page: Int
    get() = (parentData as? PageData)?.page ?: error("no PageData for measurable $this")

@Composable
fun Pager(
    modifier: Modifier = Modifier,
    state: PagerState,
    orientation: Orientation = Orientation.Horizontal,
    offscreenLimit: Int = 2,
    horizontalAlignment: Alignment.Horizontal = Alignment.CenterHorizontally,  // 新增水平对齐参数
    verticalAlignment: Alignment.Vertical = Alignment.CenterVertically,  // 新增垂直对齐参数
    content: @Composable PagerScope.() -> Unit
) {
    var pageSize by remember { mutableStateOf(0) }
    val coroutineScope = rememberCoroutineScope()

    Layout(
        content = {
            // 根据 offscreenLimit 计算页面范围
            val minPage = maxOf(state.currentPage - offscreenLimit, state.minPage)
            val maxPage = minOf(state.currentPage + offscreenLimit, state.maxPage)

            for (page in minPage..maxPage) {
                val pageData = PageData(page)
                val scope = PagerScope(state, page)
                key(pageData) {
                    Column(modifier = pageData) {
                        scope.content()
                    }
                }
            }
        },
        modifier = modifier.draggable(
            orientation = orientation,
            onDragStarted = {
                state.selectionState = PagerState.SelectionState.Undecided
            },
            onDragStopped = { velocity ->
                coroutineScope.launch {
                    // 根据速度判断是否滑动到下一页
                    val threshold = 1000f // 速度阈值，可调整
                    if (velocity > threshold) {
                        state.fling(1f) // 向右滑动
                    } else if (velocity < -threshold) {
                        state.fling(-1f) // 向左滑动
                    } else {
                        state.fling(0f) // 保持当前页
                    }
                }
            },
            state = rememberDraggableState { dy ->
                coroutineScope.launch {
                    with(state) {
                        val pos = pageSize * currentPageOffset
                        val max = if (currentPage == minPage) 0 else pageSize
                        val min = if (currentPage == maxPage) 0 else -pageSize

                        // 直接将手指的位移应用到 currentPageOffset
                        val newPos = (pos + dy).coerceIn(min.toFloat(), max.toFloat())
                        snapToOffset(newPos / pageSize)
                    }
                }
            },
        )
    ) { measurables, constraints ->
        layout(constraints.maxWidth, constraints.maxHeight) {
            val currentPage = state.currentPage
            val offset = state.currentPageOffset
            val childConstraints = constraints.copy(minWidth = 0, minHeight = 0)

            measurables.forEach { measurable ->
                val placeable = measurable.measure(childConstraints)
                val page = measurable.page

                // 根据对齐参数计算 x 和 y 位置
                val xPosition = when (horizontalAlignment) {
                    Alignment.Start -> 0
                    Alignment.CenterHorizontally -> (constraints.maxWidth - placeable.width) / 2
                    Alignment.End -> constraints.maxWidth - placeable.width
                    else -> 0
                }

                val yPosition = when (verticalAlignment) {
                    Alignment.Top -> 0
                    Alignment.CenterVertically -> (constraints.maxHeight - placeable.height) / 2
                    Alignment.Bottom -> constraints.maxHeight - placeable.height
                    else -> 0
                }

                if (currentPage == page) { // 只在当前页面设置 pageSize，避免不必要的设置
                    pageSize = if (orientation == Orientation.Horizontal) {
                        placeable.width
                    } else {
                        placeable.height
                    }
                }

                val isVisible = abs(page - (currentPage - offset)) <= 1

                if (isVisible) {
                    // 修正 x 的计算
                    val xOffset = if (orientation == Orientation.Horizontal) {
                        ((page - currentPage) * pageSize + offset * pageSize).roundToInt()
                    } else {
                        0
                    }

                    // 使用 placeRelative 进行放置
                    placeable.placeRelative(
                        x = xPosition + xOffset,
                        y = yPosition + if (orientation == Orientation.Vertical) ((page - (currentPage - offset)) * placeable.height).roundToInt() else 0
                    )
                }
            }

        }
    }
}

class PagerScope(
    private val state: PagerState,
    val page: Int
) {
    val currentPage: Int
        get() = state.currentPage

    val currentPageOffset: Float
        get() = state.currentPageOffset

    val selectionState: PagerState.SelectionState
        get() = state.selectionState
}






