package cl.homelogic.platform.designsystem.components.molecules

import androidx.compose.foundation.background
import androidx.compose.foundation.gestures.detectHorizontalDragGestures
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.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.foundation.pager.HorizontalPager
import androidx.compose.foundation.pager.rememberPagerState
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.pointer.pointerInput
import cl.homelogic.platform.designsystem.components.atoms.BottomSafeZone
import cl.homelogic.platform.designsystem.components.atoms.ButtonStyle
import cl.homelogic.platform.designsystem.components.atoms.SimpleButton
import cl.homelogic.platform.designsystem.foundations.Padding
import cl.homelogic.platform.designsystem.foundations.Sizes
import kotlinx.coroutines.launch

class OnboardingNavigationContext(
    val currentPage: Int,
    val pageCount: Int,
    private val navigateTo: suspend (Int) -> Unit,
    private val restrictNavigation: (Boolean) -> Unit,
) {
    val isFirstPage: Boolean get() = currentPage == 0
    val isLastPage: Boolean get() = currentPage == pageCount - 1

    suspend fun goToNextPage() {
        if (currentPage < pageCount - 1) {
            navigateTo(currentPage + 1)
        }
    }

    suspend fun goToPreviousPage() {
        if (currentPage > 0) {
            navigateTo(currentPage - 1)
        }
    }

    fun enableNavigation() {
        restrictNavigation(false)
    }
}

data class OnboardingSlide(
    val restrictNavigation: Boolean = false,
    val content: @Composable OnboardingNavigationContext.() -> Unit,
)

@Composable
fun OnboardingWindow(
    modifier: Modifier = Modifier,
    slides: List<OnboardingSlide>,
    continueButtonText: String,
    showIndicators: Boolean = true,
    onFinish: () -> Unit = {},
) {
    if (slides.isEmpty()) {
        onFinish()
    }

    val coroutineScope = rememberCoroutineScope()
    val pagerState = rememberPagerState(pageCount = { slides.size })

    val isLastPage = pagerState.currentPage == slides.size - 1
    val currentSlide = slides[pagerState.currentPage]

    var hasRestrictedNavigation by remember(pagerState.currentPage) {
        mutableStateOf(currentSlide.restrictNavigation)
    }

    val navigationContext = remember(pagerState.currentPage, hasRestrictedNavigation) {
        OnboardingNavigationContext(
            currentPage = pagerState.currentPage,
            pageCount = slides.size,
            navigateTo = { page -> pagerState.animateScrollToPage(page) },
            restrictNavigation = { hasRestrictedNavigation = it },
        )
    }

    Box(
        modifier = modifier
            .fillMaxSize()
            .pointerInput(pagerState.currentPage, hasRestrictedNavigation) {
                if (!hasRestrictedNavigation) {
                    detectHorizontalDragGestures(
                        onDragStart = {},
                        onDragEnd = {},
                        onDragCancel = {},
                        onHorizontalDrag = { change, dragAmount ->
                            change.consume()

                            if (dragAmount > 50 && !navigationContext.isFirstPage) {
                                coroutineScope.launch {
                                    navigationContext.goToPreviousPage()
                                }
                            } else if (dragAmount < -50 && !navigationContext.isLastPage) {
                                coroutineScope.launch {
                                    navigationContext.goToNextPage()
                                }
                            }
                        },
                    )
                }
            },
    ) {
        Column(
            modifier = Modifier.fillMaxSize(),
            horizontalAlignment = Alignment.CenterHorizontally,
        ) {
            Box(
                modifier = Modifier
                    .weight(1f)
                    .wrapContentHeight()
                    .fillMaxWidth(),
            ) {
                HorizontalPager(
                    state = pagerState,
                    modifier = Modifier.fillMaxSize(),
                    userScrollEnabled = !hasRestrictedNavigation,
                ) { page ->
                    val slideNavigationContext = remember(page, pagerState.currentPage) {
                        OnboardingNavigationContext(
                            currentPage = page,
                            pageCount = slides.size,
                            navigateTo = { targetPage -> pagerState.animateScrollToPage(targetPage) },
                            restrictNavigation = {
                                if (page == pagerState.currentPage) {
                                    hasRestrictedNavigation = it
                                }
                            },
                        )
                    }

                    slides[page].content(slideNavigationContext)
                }
            }

            if (showIndicators) {
                PageIndicators(
                    pageCount = slides.size,
                    currentPage = pagerState.currentPage,
                    modifier = Modifier.padding(Padding.big),
                )
            }

            SimpleButton(
                modifier = Modifier
                    .fillMaxWidth()
                    .padding(Padding.big),
                style = ButtonStyle.TERTIARY,
                text = continueButtonText,
                enabled = !hasRestrictedNavigation,
            ) {
                coroutineScope.launch {
                    if (isLastPage) {
                        onFinish()
                    } else {
                        navigationContext.goToNextPage()
                    }
                }
            }

            BottomSafeZone()
        }
    }
}

@Composable
private fun PageIndicators(
    pageCount: Int,
    currentPage: Int,
    modifier: Modifier = Modifier,
) {
    Row(
        horizontalArrangement = Arrangement.Center,
        modifier = modifier,
    ) {
        repeat(pageCount) { index ->
            val isSelected = index == currentPage
            Box(
                modifier = Modifier
                    .padding(horizontal = Padding.tiny)
                    .size(if (isSelected) Sizes.Dots.Regular else Sizes.Dots.Regular)
                    .background(
                        color = if (isSelected) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.outline,
                        shape = CircleShape,
                    ),
            )
        }
    }
}
