package com.aegir.demo.ui

import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
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.Spacer
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.safeDrawing
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.windowInsetsPadding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Check
import androidx.compose.material.icons.filled.Close
import androidx.compose.material.icons.filled.KeyboardArrowLeft
import androidx.compose.material.icons.filled.KeyboardArrowRight
import androidx.compose.material.icons.filled.List
import androidx.compose.material.icons.filled.Refresh
import androidx.compose.material3.Button
import androidx.compose.material3.Divider
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.ModalBottomSheet
import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.rotate
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.aegir.vmms.vmd.model.BaseMapBuildingFloor

/**
 * Top-level Compose overlay layer drawn on top of the Google Maps + VectorMapView.
 * Mirrors the iOS demo visuals: top nav bar (back chevron, title, reload), bearing
 * compass (top right under nav bar), tap info banner (top), floor switcher (bottom),
 * wayfinding bar (above floor switcher).
 */
@Composable
fun MapOverlays(
    state: MapOverlayState,
    onSelectFloor: (BaseMapBuildingFloor) -> Unit,
    onToggleWayfinding: () -> Unit,
    onWayfindingGo: () -> Unit,
    onWayfindingClear: () -> Unit,
    onShowSteps: () -> Unit,
    onDismissSteps: () -> Unit,
    onBack: () -> Unit,
    onReload: () -> Unit,
    onSelectBasemap: (BasemapMode) -> Unit,
    onShowFloorList: () -> Unit,
    onDismissFloorList: () -> Unit,
) {
    Box(
        modifier = Modifier
            .fillMaxSize()
            .windowInsetsPadding(WindowInsets.safeDrawing)
    ) {
        Column(modifier = Modifier.fillMaxWidth()) {
            MapTopBar(
                basemapMode = state.basemapMode,
                onBack = onBack,
                onReload = onReload,
                onSelectBasemap = onSelectBasemap,
                onShowFloorList = onShowFloorList,
            )
        }

        BearingCompass(
            bearing = state.bearing,
            modifier = Modifier
                .align(Alignment.TopEnd)
                .padding(top = 52.dp, end = 12.dp),
        )

        state.selectedUnitInfo?.let { info ->
            UnitInfoBanner(
                info = info,
                modifier = Modifier
                    .align(Alignment.TopCenter)
                    .padding(top = 60.dp, start = 16.dp, end = 16.dp),
            )
        }

        Column(
            modifier = Modifier
                .align(Alignment.BottomCenter)
                .padding(start = 16.dp, end = 16.dp, bottom = 12.dp),
            verticalArrangement = Arrangement.spacedBy(8.dp),
        ) {
            if (state.wayfindingActive) {
                WayfindingBar(
                    state = state,
                    onGo = onWayfindingGo,
                    onClear = onWayfindingClear,
                    onShowSteps = onShowSteps,
                )
            }
            FloorSwitcher(
                floors = state.floors,
                current = state.currentFloor,
                onSelect = onSelectFloor,
            )
        }

        if (state.directionsSheetShown) {
            DirectionsSheet(state = state, onDismiss = onDismissSteps)
        }

        if (state.floorListSheetShown) {
            FloorListSheet(
                groups = state.floorGroups,
                current = state.currentFloor,
                onSelect = { floor ->
                    onSelectFloor(floor)
                    onDismissFloorList()
                },
                onDismiss = onDismissFloorList,
            )
        }
    }
}

@Composable
private fun MapTopBar(
    basemapMode: BasemapMode,
    onBack: () -> Unit,
    onReload: () -> Unit,
    onSelectBasemap: (BasemapMode) -> Unit,
    onShowFloorList: () -> Unit,
) {
    Surface(
        modifier = Modifier.fillMaxWidth(),
        color = Color.White.copy(alpha = 0.95f),
        shadowElevation = 0.5.dp,
    ) {
        Box(
            modifier = Modifier
                .fillMaxWidth()
                .height(44.dp)
                .padding(horizontal = 8.dp),
        ) {
            BackButton(
                onClick = onBack,
                modifier = Modifier.align(Alignment.CenterStart),
            )
            BasemapToggle(
                mode = basemapMode,
                onSelect = onSelectBasemap,
                modifier = Modifier
                    .align(Alignment.Center)
                    .width(180.dp),
            )
            Row(
                modifier = Modifier.align(Alignment.CenterEnd),
                verticalAlignment = Alignment.CenterVertically,
                horizontalArrangement = Arrangement.spacedBy(8.dp),
            ) {
                TopBarFloorListButton(onClick = onShowFloorList)
                TopBarReloadButton(onClick = onReload)
            }
        }
    }
}

@Composable
private fun TopBarFloorListButton(onClick: () -> Unit, modifier: Modifier = Modifier) {
    CircleIconButton(
        icon = Icons.Default.List,
        contentDescription = "Floor list",
        onClick = onClick,
        modifier = modifier,
    )
}

@Composable
private fun TopBarReloadButton(onClick: () -> Unit, modifier: Modifier = Modifier) {
    CircleIconButton(
        icon = Icons.Default.Refresh,
        contentDescription = "Reload",
        onClick = onClick,
        modifier = modifier,
    )
}

@Composable
private fun BackButton(onClick: () -> Unit, modifier: Modifier = Modifier) {
    CircleIconButton(
        icon = Icons.Default.KeyboardArrowLeft,
        contentDescription = "Back",
        onClick = onClick,
        modifier = modifier,
    )
}

/**
 * iOS-style circular bubble icon button. Mirrors the iOS demo's
 * `makeCircleIconButton`: 36dp diameter, white at 85% alpha, blue glyph,
 * subtle drop shadow.
 */
@Composable
private fun CircleIconButton(
    icon: androidx.compose.ui.graphics.vector.ImageVector,
    contentDescription: String,
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
) {
    Surface(
        modifier = modifier.size(36.dp),
        shape = CircleShape,
        color = Color.White.copy(alpha = 0.85f),
        shadowElevation = 2.dp,
        onClick = onClick,
    ) {
        Box(contentAlignment = Alignment.Center) {
            Icon(
                imageVector = icon,
                contentDescription = contentDescription,
                tint = Color(0xFF007AFF),
                modifier = Modifier.size(22.dp),
            )
        }
    }
}

@Composable
private fun BasemapToggle(
    mode: BasemapMode,
    onSelect: (BasemapMode) -> Unit,
    modifier: Modifier = Modifier,
) {
    val options = remember {
        listOf(
            BasemapMode.MAPLIBRE to "MapLibre",
            BasemapMode.GOOGLE_MAPS to "Google",
        )
    }
    Surface(
        modifier = modifier.height(30.dp),
        shape = RoundedCornerShape(8.dp),
        color = Color(0xFFEFEFEF),
        border = BorderStroke(0.5.dp, Color(0xFFD1D1D6)),
    ) {
        Row(modifier = Modifier.fillMaxWidth()) {
            options.forEach { (m, label) ->
                val selected = m == mode
                Surface(
                    modifier = Modifier
                        .weight(1f)
                        .fillMaxWidth()
                        .padding(2.dp),
                    color = if (selected) Color.White else Color.Transparent,
                    onClick = { if (!selected) onSelect(m) },
                    shape = RoundedCornerShape(6.dp),
                    shadowElevation = if (selected) 1.dp else 0.dp,
                ) {
                    Box(
                        modifier = Modifier.fillMaxSize(),
                        contentAlignment = Alignment.Center,
                    ) {
                        Text(
                            text = label,
                            fontSize = 13.sp,
                            fontWeight = if (selected) FontWeight.SemiBold else FontWeight.Normal,
                            color = Color.Black,
                        )
                    }
                }
            }
        }
    }
}

@Composable
private fun BearingCompass(bearing: Double, modifier: Modifier = Modifier) {
    val degrees = ((bearing % 360) + 360) % 360
    Surface(
        modifier = modifier
            .width(44.dp)
            .height(52.dp),
        shape = RoundedCornerShape(8.dp),
        color = Color.White.copy(alpha = 0.85f),
        shadowElevation = 2.dp,
    ) {
        Column(
            horizontalAlignment = Alignment.CenterHorizontally,
            verticalArrangement = Arrangement.Center,
            modifier = Modifier.padding(vertical = 6.dp)
        ) {
            Text(
                text = "N",
                color = Color.Black,
                fontWeight = FontWeight.Bold,
                fontSize = 14.sp,
                modifier = Modifier.rotate((-degrees).toFloat()),
            )
            Spacer(modifier = Modifier.height(2.dp))
            Text(
                text = "${degrees.toInt()}°",
                color = Color(0xFF8E8E93),
                fontFamily = FontFamily.Monospace,
                fontSize = 11.sp,
            )
        }
    }
}

@Composable
private fun UnitInfoBanner(info: UnitInfo, modifier: Modifier = Modifier) {
    Surface(
        modifier = modifier.fillMaxWidth(),
        shape = RoundedCornerShape(8.dp),
        color = Color.Black.copy(alpha = 0.75f),
    ) {
        Column(
            modifier = Modifier.padding(horizontal = 12.dp, vertical = 10.dp),
        ) {
            BannerLine("uid: ${info.uid}")
            if (info.name.isNotBlank()) BannerLine("name: ${info.name}")
            if (info.category.isNotBlank()) BannerLine("cat: ${info.category}")
            BannerLine("floor: ${info.floorId}")
            info.areaSqFt?.let { BannerLine("area: $it sq ft") }
        }
    }
}

@Composable
private fun BannerLine(text: String) {
    Text(
        text = text,
        color = Color.White,
        fontSize = 12.sp,
        fontFamily = FontFamily.Monospace,
        fontWeight = FontWeight.Medium,
    )
}

@Composable
private fun WayfindingBar(
    state: MapOverlayState,
    onGo: () -> Unit,
    onClear: () -> Unit,
    onShowSteps: () -> Unit,
) {
    Surface(
        modifier = Modifier.fillMaxWidth(),
        shape = RoundedCornerShape(12.dp),
        color = MaterialTheme.colorScheme.surface.copy(alpha = 0.95f),
        shadowElevation = 6.dp,
    ) {
        Row(
            modifier = Modifier.padding(12.dp),
            horizontalArrangement = Arrangement.spacedBy(12.dp),
        ) {
            Column(
                modifier = Modifier.weight(1f),
                verticalArrangement = Arrangement.spacedBy(8.dp),
            ) {
                WayfindingRow(
                    label = "Start",
                    value = state.startWaypoint?.name?.takeIf { it.isNotBlank() }
                        ?: state.startWaypoint?.id
                        ?: "Tap a unit on the map",
                )
                WayfindingRow(
                    label = "End",
                    value = state.endWaypoint?.name?.takeIf { it.isNotBlank() }
                        ?: state.endWaypoint?.id
                        ?: "Tap another unit",
                )
            }
            Column(
                horizontalAlignment = Alignment.CenterHorizontally,
                verticalArrangement = Arrangement.spacedBy(8.dp),
            ) {
                Button(
                    onClick = onGo,
                    enabled = state.startWaypoint != null && state.endWaypoint != null,
                    modifier = Modifier
                        .width(100.dp)
                        .height(44.dp),
                ) {
                    Text("GO", fontWeight = FontWeight.Bold)
                }
                Row(horizontalArrangement = Arrangement.spacedBy(12.dp)) {
                    OutlinedButton(onClick = onClear) {
                        Text("Clear", fontSize = 13.sp)
                    }
                    OutlinedButton(
                        onClick = onShowSteps,
                        enabled = state.routeAvailable,
                    ) {
                        Text("Steps", fontSize = 13.sp)
                    }
                }
            }
        }
    }
}

@Composable
private fun WayfindingRow(label: String, value: String) {
    Surface(
        modifier = Modifier.fillMaxWidth(),
        shape = RoundedCornerShape(8.dp),
        color = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.5f),
    ) {
        Column(
            modifier = Modifier.padding(horizontal = 12.dp, vertical = 6.dp),
        ) {
            Text(text = label, fontSize = 12.sp, color = MaterialTheme.colorScheme.onSurfaceVariant)
            Text(text = value, fontSize = 14.sp, color = MaterialTheme.colorScheme.onSurface)
        }
    }
}

@Composable
private fun FloorSwitcher(
    floors: List<BaseMapBuildingFloor>,
    current: BaseMapBuildingFloor?,
    onSelect: (BaseMapBuildingFloor) -> Unit,
) {
    if (floors.isEmpty()) return

    val currentIndex by remember(floors, current) {
        derivedStateOf {
            floors.indexOfFirst { it.id == current?.id }.coerceAtLeast(0)
        }
    }

    Surface(
        modifier = Modifier
            .fillMaxWidth()
            .height(50.dp),
        shape = RoundedCornerShape(10.dp),
        color = Color.White.copy(alpha = 0.9f),
        shadowElevation = 4.dp,
    ) {
        Row(
            modifier = Modifier.padding(horizontal = 8.dp),
            verticalAlignment = Alignment.CenterVertically,
            horizontalArrangement = Arrangement.SpaceBetween,
        ) {
            IconButton(
                enabled = floors.size > 1,
                onClick = {
                    val next = (currentIndex - 1 + floors.size) % floors.size
                    onSelect(floors[next])
                },
            ) {
                Icon(
                    imageVector = Icons.Default.KeyboardArrowLeft,
                    contentDescription = "Previous floor",
                    tint = Color(0xFF007AFF),
                )
            }
            val current2 = floors.getOrNull(currentIndex)
            Text(
                text = current2?.name?.takeIf { it.isNotBlank() } ?: current2?.id ?: "",
                fontSize = 15.sp,
                fontWeight = FontWeight.Medium,
                color = Color.Black,
                modifier = Modifier.weight(1f),
                textAlign = androidx.compose.ui.text.style.TextAlign.Center,
            )
            IconButton(
                enabled = floors.size > 1,
                onClick = {
                    val next = (currentIndex + 1) % floors.size
                    onSelect(floors[next])
                },
            ) {
                Icon(
                    imageVector = Icons.Default.KeyboardArrowRight,
                    contentDescription = "Next floor",
                    tint = Color(0xFF007AFF),
                )
            }
        }
    }
}

@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun DirectionsSheet(state: MapOverlayState, onDismiss: () -> Unit) {
    val sheetState = androidx.compose.material3.rememberModalBottomSheetState(skipPartiallyExpanded = false)

    ModalBottomSheet(
        onDismissRequest = onDismiss,
        sheetState = sheetState,
    ) {
        Text(
            text = "Directions",
            style = MaterialTheme.typography.titleMedium,
            modifier = Modifier.padding(start = 24.dp, top = 8.dp, bottom = 8.dp),
        )
        if (state.directions.isEmpty()) {
            Text(
                text = "No directions available.",
                modifier = Modifier.padding(horizontal = 24.dp, vertical = 16.dp),
            )
        } else {
            LazyColumn(modifier = Modifier.fillMaxWidth()) {
                items(state.directions) { step ->
                    Column(
                        modifier = Modifier
                            .fillMaxWidth()
                            .padding(horizontal = 24.dp, vertical = 12.dp),
                    ) {
                        Text(
                            text = step.instructions ?: "",
                            style = MaterialTheme.typography.bodyMedium,
                        )
                        val floorId = step.segment?.floorId ?: "?"
                        Text(
                            text = "${step.distance ?: ""}  -  floor: $floorId",
                            style = MaterialTheme.typography.bodySmall,
                            color = MaterialTheme.colorScheme.onSurfaceVariant,
                        )
                    }
                    Divider()
                }
            }
        }
    }

    LaunchedEffect(Unit) { sheetState.show() }
}

@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun FloorListSheet(
    groups: List<FloorGroup>,
    current: BaseMapBuildingFloor?,
    onSelect: (BaseMapBuildingFloor) -> Unit,
    onDismiss: () -> Unit,
) {
    val sheetState = androidx.compose.material3.rememberModalBottomSheetState(skipPartiallyExpanded = false)

    ModalBottomSheet(
        onDismissRequest = onDismiss,
        sheetState = sheetState,
    ) {
        // Mirror iOS: X close button (left) with centered "Floors" title.
        // The trailing 48.dp spacer balances the leading IconButton so the
        // title stays centered.
        Row(
            modifier = Modifier
                .fillMaxWidth()
                .padding(horizontal = 8.dp, vertical = 4.dp),
            verticalAlignment = Alignment.CenterVertically,
        ) {
            IconButton(onClick = onDismiss) {
                Icon(
                    imageVector = Icons.Default.Close,
                    contentDescription = "Close",
                    tint = Color(0xFF007AFF),
                )
            }
            Text(
                text = "Floors",
                style = MaterialTheme.typography.titleMedium,
                fontWeight = FontWeight.SemiBold,
                textAlign = androidx.compose.ui.text.style.TextAlign.Center,
                modifier = Modifier.weight(1f),
            )
            Spacer(Modifier.size(48.dp))
        }
        if (groups.isEmpty()) {
            Text(
                text = "No floors available.",
                modifier = Modifier.padding(horizontal = 24.dp, vertical = 16.dp),
            )
        } else {
            LazyColumn(modifier = Modifier.fillMaxWidth()) {
                groups.forEach { group ->
                    item(key = "header_${group.buildingId}") {
                        Text(
                            text = group.buildingName.ifBlank { group.buildingId },
                            style = MaterialTheme.typography.labelLarge,
                            color = MaterialTheme.colorScheme.onSurfaceVariant,
                            fontWeight = FontWeight.Medium,
                            modifier = Modifier
                                .fillMaxWidth()
                                .padding(start = 24.dp, end = 24.dp, top = 12.dp, bottom = 4.dp),
                        )
                        Divider()
                    }
                    items(group.floors, key = { "row_${group.buildingId}_${it.id}" }) { floor ->
                        val isCurrent = floor.id == current?.id
                        Row(
                            modifier = Modifier
                                .fillMaxWidth()
                                .background(
                                    if (isCurrent) MaterialTheme.colorScheme.primary.copy(alpha = 0.08f)
                                    else Color.Transparent
                                )
                                .clickable { onSelect(floor) }
                                .padding(horizontal = 24.dp, vertical = 12.dp),
                            verticalAlignment = Alignment.CenterVertically,
                        ) {
                            Text(
                                text = "[${floor.ordinal}]",
                                style = MaterialTheme.typography.bodyMedium,
                                color = MaterialTheme.colorScheme.onSurfaceVariant,
                                fontFamily = FontFamily.Monospace,
                                modifier = Modifier.width(48.dp),
                            )
                            Text(
                                text = floor.name.ifBlank { floor.id },
                                style = MaterialTheme.typography.bodyMedium,
                                color = MaterialTheme.colorScheme.onSurface,
                                modifier = Modifier.weight(1f),
                            )
                            if (isCurrent) {
                                Icon(
                                    imageVector = Icons.Default.Check,
                                    contentDescription = "Current floor",
                                    tint = MaterialTheme.colorScheme.primary,
                                )
                            }
                        }
                        Divider()
                    }
                }
            }
        }
    }

    LaunchedEffect(Unit) { sheetState.show() }
}
