package com.github.nullptroma.wallenc.ui.elements

import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.widthIn
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
import androidx.compose.ui.platform.LocalHapticFeedback
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.semantics.Role
import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.role
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.unit.dp
import com.github.nullptroma.wallenc.ui.navigation.NavBarItemData

/** Вертикальный зазор между вложенной и корневой плавающими панелями навигации. */
val WallencNestedNavBarGap = 2.dp

@Composable
fun FloatingWallencNavigationBar(
    items: Map<String, NavBarItemData>,
    routes: Map<String, *>,
    currentRoute: String?,
    onNavigate: (NavBarItemData) -> Unit,
    modifier: Modifier = Modifier,
    compact: Boolean = false,
) {
    val haptic = LocalHapticFeedback.current
    val barHeight = if (compact) 48.dp else 56.dp
    val barShape = if (compact) RoundedCornerShape(22.dp) else RoundedCornerShape(28.dp)
    val barHorizontalPadding = if (compact) 4.dp else 6.dp

    val barSurface: @Composable () -> Unit = {
        Surface(
            modifier = Modifier
                .then(
                    if (compact) {
                        Modifier
                            .widthIn(max = 300.dp)
                            .fillMaxWidth(0.68f)
                    } else {
                        Modifier.fillMaxWidth()
                    },
                ),
            shape = barShape,
            color = MaterialTheme.colorScheme.surfaceContainerHigh,
            shadowElevation = 6.dp,
            tonalElevation = 2.dp,
        ) {
            Row(
                modifier = Modifier
                    .fillMaxWidth()
                    .height(barHeight)
                    .padding(horizontal = barHorizontalPadding, vertical = 4.dp),
                verticalAlignment = Alignment.CenterVertically,
            ) {
                items.forEach { (routeClassName, navBarItemData) ->
                    val iconVector = navBarItemData.icon ?: return@forEach
                    val selected = currentRoute?.startsWith(routeClassName) == true
                    val enabled = routes[navBarItemData.screenRouteClass] != null
                    FloatingNavItem(
                        modifier = Modifier
                            .weight(1f)
                            .fillMaxWidth(),
                        icon = iconVector,
                        label = stringResource(navBarItemData.nameStringResourceId),
                        contentDescription = stringResource(navBarItemData.iconContentDescriptionResourceId),
                        selected = selected,
                        enabled = enabled,
                        compact = compact,
                        onClick = {
                            if (!selected && enabled) {
                                haptic.performHapticFeedback(HapticFeedbackType.TextHandleMove)
                                onNavigate(navBarItemData)
                            }
                        },
                    )
                }
            }
        }
    }

    if (compact) {
        Box(
            modifier = modifier.fillMaxWidth(),
            contentAlignment = Alignment.Center,
        ) {
            barSurface()
        }
    } else {
        Box(modifier = modifier.fillMaxWidth()) {
            barSurface()
        }
    }
}

@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun FloatingNavItem(
    icon: ImageVector,
    label: String,
    contentDescription: String,
    selected: Boolean,
    enabled: Boolean,
    compact: Boolean,
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
) {
    val iconSize = if (compact) 22.dp else 24.dp
    val itemPaddingH = if (compact) 6.dp else 8.dp
    val itemPaddingV = if (compact) 6.dp else 8.dp
    val labelStyle = if (compact) {
        MaterialTheme.typography.labelSmall
    } else {
        MaterialTheme.typography.labelMedium
    }
    val labelVelocity = if (compact) 24.dp else 28.dp
    val itemShape = if (compact) RoundedCornerShape(16.dp) else RoundedCornerShape(20.dp)
    val containerColor = if (selected) {
        MaterialTheme.colorScheme.secondaryContainer
    } else {
        MaterialTheme.colorScheme.surfaceContainerHigh
    }
    val contentColor = if (selected) {
        MaterialTheme.colorScheme.onSecondaryContainer
    } else {
        MaterialTheme.colorScheme.onSurfaceVariant
    }
    Surface(
        onClick = onClick,
        enabled = enabled,
        modifier = modifier
            .padding(horizontal = if (compact) 1.dp else 2.dp)
            .semantics {
                role = Role.Tab
                this.contentDescription = contentDescription
            },
        shape = itemShape,
        color = containerColor,
        contentColor = contentColor,
    ) {
        Row(
            modifier = Modifier
                .fillMaxWidth()
                .padding(horizontal = itemPaddingH, vertical = itemPaddingV),
            horizontalArrangement = if (selected) Arrangement.Start else Arrangement.Center,
            verticalAlignment = Alignment.CenterVertically,
        ) {
            Icon(
                imageVector = icon,
                contentDescription = null,
                modifier = Modifier.size(iconSize),
            )
            if (selected) {
                NavigationBarMarqueeText(
                    text = label,
                    modifier = Modifier
                        .weight(1f)
                        .padding(start = if (compact) 4.dp else 6.dp),
                    style = labelStyle,
                    velocity = labelVelocity,
                )
            }
        }
    }
}
