package com.example.m20_gamepad.ui

import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.BorderStroke
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.navigationBars
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.windowInsetsPadding
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Info
import androidx.compose.material.icons.filled.Settings
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Outline
import androidx.compose.ui.graphics.Path
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.Density
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.LayoutDirection
import androidx.compose.ui.unit.sp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.lifecycle.viewmodel.initializer
import androidx.lifecycle.viewmodel.viewModelFactory
import com.erz.joysticklibrary.Joystick
import com.erz.joysticklibrary.JoystickType
import com.example.m20_gamepad.M20App
import com.example.m20_gamepad.R
import com.example.m20_gamepad.data.SettingsRepository
import com.example.m20_gamepad.network.ProtocolClient
import com.example.m20_gamepad.network.models.ControlCommands
import com.example.m20_gamepad.network.models.LedStatus
import com.example.m20_gamepad.ui.components.StatusPanel
import com.example.m20_gamepad.video.RtspVideoPlayer

// 半透明覆盖层颜色
private val OverlayBg = Color(0x88000000)
private val OverlayText = Color.White

/** 平行四边形形状，用于功能按钮。skewLeft=true → 左下-右上斜边（左侧按钮）；
 *  skewLeft=false → 左上-右下斜边（右侧按钮）。 */
private class ParallelogramShape(
    private val skewDp: Dp = 10.dp,
    private val skewLeft: Boolean = true
) : Shape {
    override fun createOutline(
        size: Size,
        layoutDirection: LayoutDirection,
        density: Density
    ): Outline {
        val skewPx = with(density) { skewDp.toPx() }
        val path = Path().apply {
            if (skewLeft) {
                // 左下 → 右上 斜边（平行四边形向右倾斜）
                moveTo(skewPx, 0f)
                lineTo(size.width, 0f)
                lineTo(size.width - skewPx, size.height)
                lineTo(0f, size.height)
            } else {
                // 左上 → 右下 斜边（平行四边形向左倾斜）
                moveTo(0f, 0f)
                lineTo(size.width - skewPx, 0f)
                lineTo(size.width, size.height)
                lineTo(skewPx, size.height)
            }
            close()
        }
        return Outline.Generic(path)
    }
}

/**
 * 主界面：RTSP 视频背景 + 双摇杆覆盖层 + 状态栏 + 控制按钮。
 *
 * @param repository 应用级设置仓库（注入 MainViewModel）
 * @param onSettingsClick 打开设置界面
 */
@Composable
fun MainScreen(
    repository: SettingsRepository,
    onSettingsClick: () -> Unit
) {
    val app = LocalContext.current.applicationContext as M20App
    val viewModel: MainViewModel = viewModel(
        factory = viewModelFactory {
            initializer { MainViewModel(repository, app) }
        }
    )
    val connectionState by viewModel.connectionState.collectAsStateWithLifecycle()
    val status by viewModel.latestStatus.collectAsStateWithLifecycle()
    val settings by viewModel.settings.collectAsStateWithLifecycle()
    val motionState by viewModel.motionState.collectAsStateWithLifecycle()
    val errorList by viewModel.errorList.collectAsStateWithLifecycle()
    val motionStatus by viewModel.motionStatus.collectAsStateWithLifecycle()
    val deviceTemperature by viewModel.deviceTemperature.collectAsStateWithLifecycle()
    val batteryStatus by viewModel.batteryStatus.collectAsStateWithLifecycle()
    val ledStatus by viewModel.ledStatus.collectAsStateWithLifecycle()
    val lastUpdate by viewModel.lastUpdate.collectAsStateWithLifecycle()
    val actionFeedback by viewModel.actionFeedback.collectAsStateWithLifecycle()
    val pingLatencyMs by viewModel.pingLatencyMs.collectAsStateWithLifecycle()
    val wifiSignalLevel by viewModel.wifiSignalLevel.collectAsStateWithLifecycle()

    var statusPanelVisible by remember { mutableStateOf(false) }
    val snackbarHostState = remember { SnackbarHostState() }

    // 指令校验反馈 -> Snackbar
    LaunchedEffect(actionFeedback) {
        val msg = actionFeedback
        if (!msg.isNullOrBlank()) {
            snackbarHostState.showSnackbar(msg)
            viewModel.clearActionFeedback()
        }
    }

    Box(modifier = Modifier.fillMaxSize()) {
        // ---- 底图层（无视频流时显示） ----
        Image(
            painter = painterResource(id = R.drawable.bg1),
            contentDescription = null,
            contentScale = ContentScale.FillBounds,
            modifier = Modifier.fillMaxSize()
        )

        // ---- 视频背景层 ----
        RtspVideoPlayer(
            url = settings.rtspUrl,
            codec = settings.videoCodec,
            resizeMode = settings.videoResizeMode,
            modifier = Modifier.fillMaxSize()
        )

        // ---- 顶部状态栏 ----
        StatusBar(
            connectionState = connectionState,
            status = status,
            pingLatencyMs = pingLatencyMs,
            wifiSignalLevel = wifiSignalLevel,
            onStatusClick = { statusPanelVisible = true },
            onSettingsClick = onSettingsClick,
            onConnectToggle = {
                if (connectionState == ProtocolClient.State.CONNECTED) {
                    viewModel.disconnect()
                } else {
                    viewModel.connect()
                }
            },
            modifier = Modifier.align(Alignment.TopCenter)
        )

        // ---- 左上角控制区：模式选择 + 步态切换 + 起立/趴下 ----
        Column(
            modifier = Modifier
                .align(Alignment.TopStart)
                .padding(top = 56.dp, start = 12.dp),
            verticalArrangement = Arrangement.spacedBy(6.dp)
        ) {
            ModeSelector(
                currentMode = status?.basicStatus?.controlUsageMode ?: 0,
                connected = connectionState == ProtocolClient.State.CONNECTED,
                onSelectMode = { mode -> viewModel.sendSwitchMode(mode) }
            )
            // 步态切换——始终显示，仅普通模式 + RL 控制时可点击
            GaitSelector(
                currentGait = status?.basicStatus?.gait ?: 0,
                enabled = connectionState == ProtocolClient.State.CONNECTED &&
                        motionState == ControlCommands.MOTION_RL_CONTROL &&
                        status?.basicStatus?.controlUsageMode == ControlCommands.MODE_NORMAL,
                onSelectGait = { gait -> viewModel.sendSwitchGait(gait) }
            )
            StandToggleButton(
                motionState = motionState,
                connected = connectionState == ProtocolClient.State.CONNECTED,
                onToggle = {
                    if (motionState == ControlCommands.MOTION_IDLE ||
                        motionState == ControlCommands.MOTION_LIE_DOWN
                    ) {
                        viewModel.sendMotionControl(ControlCommands.MOTION_STAND)
                    } else {
                        viewModel.sendMotionControl(ControlCommands.MOTION_LIE_DOWN)
                    }
                }
            )
        }

        // ---- 右上角控制区：照明 + 休眠 + 充电 ----
        Column(
            modifier = Modifier
                .align(Alignment.TopEnd)
                .padding(top = 56.dp, end = 12.dp),
            horizontalAlignment = Alignment.End,
            verticalArrangement = Arrangement.spacedBy(6.dp)
        ) {
            // 照明：前灯+后灯，无缝隙
            val frontOn = ledStatus?.front == 1
            val backOn = ledStatus?.back == 1
            Row(horizontalArrangement = Arrangement.spacedBy(0.dp)) {
                LightToggleButton(
                    text = "前灯",
                    isOn = frontOn,
                    enabled = connectionState == ProtocolClient.State.CONNECTED
                ) {
                    viewModel.sendLightControl(if (frontOn) 0 else 1, ledStatus?.back ?: 0)
                }
                LightToggleButton(
                    text = "后灯",
                    isOn = backOn,
                    enabled = connectionState == ProtocolClient.State.CONNECTED
                ) {
                    viewModel.sendLightControl(ledStatus?.front ?: 0, if (backOn) 0 else 1)
                }
            }
            // 休眠/唤醒
            val isSleeping = status?.basicStatus?.sleep == 1
            SleepToggleButton(
                isSleeping = isSleeping,
                connected = connectionState == ProtocolClient.State.CONNECTED,
                onToggle = { viewModel.sendSleepSettings(!isSleeping) }
            )
            // 充电/结束充电
            val isCharging = status?.basicStatus?.charge == 1
            ChargeToggleButton(
                isCharging = isCharging,
                connected = connectionState == ProtocolClient.State.CONNECTED,
                onToggle = { viewModel.sendChargeControl(if (isCharging) 0 else 1) }
            )
        }

        // ---- 底部控制区 ----
        BottomControls(
            viewModel = viewModel,
            connectionState = connectionState,
            motionState = motionState,
            modifier = Modifier
                .align(Alignment.BottomCenter)
                .windowInsetsPadding(WindowInsets.navigationBars)
        )

        // ---- 状态上报面板 ----
        StatusPanel(
            visible = statusPanelVisible,
            errorList = errorList,
            motionStatus = motionStatus,
            deviceTemperature = deviceTemperature,
            batteryStatus = batteryStatus,
            lastUpdate = lastUpdate,
            onDismiss = { statusPanelVisible = false },
            modifier = Modifier.fillMaxSize()
        )

        // ---- Snackbar ----
        SnackbarHost(
            hostState = snackbarHostState,
            modifier = Modifier.align(Alignment.BottomCenter)
        )
    }
}

// ==================== 顶部状态栏 ====================

@Composable
private fun StatusBar(
    connectionState: ProtocolClient.State,
    status: com.example.m20_gamepad.network.models.StatusReport?,
    pingLatencyMs: Long?,
    wifiSignalLevel: Int,
    onStatusClick: () -> Unit,
    onSettingsClick: () -> Unit,
    onConnectToggle: () -> Unit,
    modifier: Modifier = Modifier
) {
    Box(
        modifier = modifier
            .fillMaxWidth()
            .background(OverlayBg)
    ) {
        Row(
            modifier = Modifier
                .fillMaxWidth()
                .padding(horizontal = 12.dp, vertical = 4.dp),
            verticalAlignment = Alignment.CenterVertically,
            horizontalArrangement = Arrangement.SpaceBetween
        ) {
        // 连接状态 + WiFi 信号 + Ping 延迟
        Row(verticalAlignment = Alignment.CenterVertically) {
            ConnectionIndicator(connectionState, onConnectToggle)
            Spacer(Modifier.width(12.dp))
            WifiSignalIcon(level = wifiSignalLevel)
            Spacer(Modifier.width(12.dp))
            PingIndicator(pingLatencyMs)
        }

        // 电量 / 运动状态
        Row(
            verticalAlignment = Alignment.CenterVertically,
            horizontalArrangement = Arrangement.spacedBy(16.dp)
        ) {
            status?.batteryStatus?.let {
                val avgLevel = (it.batteryLevelLeft + it.batteryLevelRight) / 2
                StatusChip("电量 ${avgLevel.toInt()}%")
            }
            status?.basicStatus?.let {
                StatusChip(motionStateText(it.motionState))
            }
        }

        // 状态详情 + 设置按钮
        Row(verticalAlignment = Alignment.CenterVertically) {
            IconButton(onClick = onStatusClick) {
                Icon(
                    Icons.Default.Info,
                    contentDescription = "状态",
                    tint = OverlayText
                )
            }
            IconButton(onClick = onSettingsClick) {
                Icon(
                    Icons.Default.Settings,
                    contentDescription = "设置",
                    tint = OverlayText
                )
            }
        }
    }
    }
}

@Composable
private fun ConnectionIndicator(state: ProtocolClient.State, onClick: () -> Unit) {
    val (color, text) = when (state) {
        ProtocolClient.State.CONNECTED -> Color(0xFF4CAF50) to "已连接"
        ProtocolClient.State.CONNECTING -> Color(0xFFFFC107) to "连接中"
        ProtocolClient.State.TIMEOUT -> Color(0xFFFF9800) to "断线"
        ProtocolClient.State.ERROR -> Color(0xFFF44336) to "错误"
        ProtocolClient.State.DISCONNECTED -> Color(0xFF9E9E9E) to "未连接"
    }
    Surface(
        onClick = onClick,
        shape = RoundedCornerShape(14.dp),
        border = BorderStroke(1.dp, Color(0x55FFFFFF)),
        color = Color(0x22000000)
    ) {
        Row(
            modifier = Modifier.padding(horizontal = 10.dp, vertical = 2.dp),
            verticalAlignment = Alignment.CenterVertically
        ) {
            Box(
                modifier = Modifier
                    .size(10.dp)
                    .background(color, CircleShape)
            )
            Spacer(Modifier.width(6.dp))
            Text(text, color = OverlayText, fontSize = 14.sp)
        }
    }
}

/** WiFi 信号强度图标（0-5 格信号柱），白色填充、灰色未填充。 */
@Composable
private fun WifiSignalIcon(level: Int) {
    val activeColor = OverlayText
    val inactiveColor = Color(0x66FFFFFF)
    val clamped = level.coerceIn(0, 5)

    Row(
        verticalAlignment = Alignment.Bottom,
        horizontalArrangement = Arrangement.spacedBy(2.dp)
    ) {
        // 5 根信号柱，从低到高
        val barHeights = intArrayOf(6, 10, 14, 18, 22)
        for (i in 0 until 5) {
            val isActive = i < clamped
            Box(
                modifier = Modifier
                    .width(4.dp)
                    .height(barHeights[i].dp)
                    .background(if (isActive) activeColor else inactiveColor, RoundedCornerShape(1.dp))
            )
        }
    }
}

@Composable
private fun PingIndicator(latencyMs: Long?) {
    if (latencyMs == null) {
        Text("- -", color = Color(0xFF9E9E9E), fontSize = 13.sp)
    } else {
        val color = when {
            latencyMs < 50 -> Color(0xFF4CAF50)  // 绿色 — 良好
            latencyMs < 150 -> Color(0xFFFFC107) // 黄色 — 一般
            latencyMs < 300 -> Color(0xFFFF9800) // 橙色 — 较差
            else -> Color(0xFFF44336)            // 红色 — 很差
        }
        Text("${latencyMs}ms", color = color, fontSize = 13.sp)
    }
}

@Composable
private fun StatusChip(text: String) {
    Surface(
        color = Color(0x44000000),
        shape = RoundedCornerShape(12.dp)
    ) {
        Text(
            text = text,
            color = OverlayText,
            fontSize = 13.sp,
            modifier = Modifier.padding(horizontal = 10.dp, vertical = 4.dp)
        )
    }
}

// ==================== 底部控制区 ====================

@Composable
private fun BottomControls(
    viewModel: MainViewModel,
    connectionState: ProtocolClient.State,
    motionState: Int,
    modifier: Modifier = Modifier
) {
    Row(
        modifier = modifier
            .fillMaxWidth()
            .padding(bottom = 16.dp, start = 12.dp, end = 12.dp),
        verticalAlignment = Alignment.Bottom,
        horizontalArrangement = Arrangement.SpaceBetween
    ) {
        // 左摇杆（X/Y 移动）
        Joystick(
            modifier = Modifier.size(180.dp),
            type = JoystickType.EIGHT_AXIS,
            padColor = Color(0x55808080),
            buttonColor = Color(0xCCFFFFFF),
            onMove = { angle, power, _ ->
                viewModel.updateLeftStick(angle, power)
            }
        )

        // 右摇杆（Yaw 旋转）
        Joystick(
            modifier = Modifier.size(180.dp),
            type = JoystickType.EIGHT_AXIS,
            padColor = Color(0x55808080),
            buttonColor = Color(0xCCFFFFFF),
            onMove = { angle, power, _ ->
                viewModel.updateRightStick(angle, power)
            }
        )
    }
}

@Composable
private fun LightToggleButton(
    text: String,
    isOn: Boolean,
    enabled: Boolean = true,
    onClick: () -> Unit
) {
    Button(
        onClick = onClick,
        enabled = enabled,
        shape = ParallelogramShape(skewLeft = false),
        colors = ButtonDefaults.buttonColors(
            containerColor = if (isOn) Color(0xCCFFC107) else Color(0x66333333),
            disabledContainerColor = Color(0x33222222)
        ),
        contentPadding = ButtonDefaults.TextButtonContentPadding,
        modifier = Modifier.height(32.dp)
    ) {
        Text(
            "$text ${if (isOn) "开" else "关"}",
            color = if (enabled) OverlayText else Color(0x88FFFFFF),
            fontSize = 12.sp,
            fontWeight = FontWeight.Medium
        )
    }
}

@Composable
private fun StandToggleButton(
    motionState: Int,
    connected: Boolean,
    onToggle: () -> Unit,
    modifier: Modifier = Modifier
) {
    val isStanding = motionState == ControlCommands.MOTION_STAND ||
            motionState == ControlCommands.MOTION_RL_CONTROL
    Button(
        onClick = onToggle,
        enabled = connected,
        shape = ParallelogramShape(skewLeft = true),
        colors = ButtonDefaults.buttonColors(
            containerColor = if (isStanding) Color(0xCCFFC107) else Color(0x66333333),
            disabledContainerColor = Color(0x33222222)
        ),
        contentPadding = ButtonDefaults.TextButtonContentPadding,
        modifier = modifier.height(32.dp)
    ) {
        Text(
            text = if (isStanding) "趴下" else "起立",
            color = if (connected) OverlayText else Color(0x88FFFFFF),
            fontSize = 12.sp,
            fontWeight = FontWeight.Medium
        )
    }
}

// ==================== 模式选择器（3个互斥无缝隙） ====================

@Composable
private fun ModeSelector(
    currentMode: Int,
    connected: Boolean,
    onSelectMode: (Int) -> Unit,
    modifier: Modifier = Modifier
) {
    Row(
        modifier = modifier,
        horizontalArrangement = Arrangement.spacedBy(4.dp)
    ) {
        ModeButton("常规", ControlCommands.MODE_NORMAL, currentMode, connected, onSelectMode)
        ModeButton("导航", ControlCommands.MODE_NAVIGATION, currentMode, connected, onSelectMode)
        ModeButton("辅助", ControlCommands.MODE_ASSIST, currentMode, connected, onSelectMode)
    }
}

@Composable
private fun ModeButton(
    text: String,
    mode: Int,
    currentMode: Int,
    connected: Boolean,
    onClick: (Int) -> Unit
) {
    val isActive = currentMode == mode
    Button(
        onClick = { onClick(mode) },
        enabled = connected,
        shape = ParallelogramShape(skewLeft = true),
        colors = ButtonDefaults.buttonColors(
            containerColor = if (isActive) Color(0xCCFFC107) else Color(0x66333333),
            disabledContainerColor = Color(0x33222222)
        ),
        contentPadding = ButtonDefaults.TextButtonContentPadding,
        modifier = Modifier.height(32.dp)
    ) {
        Text(
            text,
            color = if (connected) OverlayText else Color(0x88FFFFFF),
            fontSize = 12.sp,
            fontWeight = if (isActive) FontWeight.Bold else FontWeight.Normal
        )
    }
}

// ==================== 步态切换（4个互斥无缝隙，仅普通模式可用） ====================

@Composable
private fun GaitSelector(
    currentGait: Int,
    enabled: Boolean,
    onSelectGait: (Int) -> Unit,
    modifier: Modifier = Modifier
) {
    Row(
        modifier = modifier,
        horizontalArrangement = Arrangement.spacedBy(4.dp)
    ) {
        GaitButton("基础", ControlCommands.GAIT_BASIC, currentGait, enabled, onSelectGait)
        GaitButton("楼梯", ControlCommands.GAIT_STAIRS, currentGait, enabled, onSelectGait)
        GaitButton("平地敏捷", ControlCommands.GAIT_FLAT_AGILE, currentGait, enabled, onSelectGait)
        GaitButton("楼梯敏捷", ControlCommands.GAIT_STAIRS_AGILE, currentGait, enabled, onSelectGait)
    }
}

@Composable
private fun GaitButton(
    text: String,
    gait: Int,
    currentGait: Int,
    enabled: Boolean,
    onClick: (Int) -> Unit
) {
    val isActive = currentGait == gait
    Button(
        onClick = { onClick(gait) },
        enabled = enabled,
        shape = ParallelogramShape(skewLeft = true),
        colors = ButtonDefaults.buttonColors(
            containerColor = if (isActive) Color(0xCCFFC107) else Color(0x66333333),
            disabledContainerColor = Color(0x33222222)
        ),
        contentPadding = ButtonDefaults.TextButtonContentPadding,
        modifier = Modifier.height(32.dp)
    ) {
        Text(
            text,
            color = if (enabled) OverlayText else Color(0x88FFFFFF),
            fontSize = 12.sp,
            fontWeight = if (isActive) FontWeight.Bold else FontWeight.Normal
        )
    }
}

// ==================== 休眠/唤醒切换 ====================

@Composable
private fun SleepToggleButton(
    isSleeping: Boolean,
    connected: Boolean,
    onToggle: () -> Unit,
    modifier: Modifier = Modifier
) {
    Button(
        onClick = onToggle,
        enabled = connected,
        shape = ParallelogramShape(skewLeft = false),
        colors = ButtonDefaults.buttonColors(
            containerColor = if (isSleeping) Color(0xCCFFC107) else Color(0x66333333),
            disabledContainerColor = Color(0x33222222)
        ),
        contentPadding = ButtonDefaults.TextButtonContentPadding,
        modifier = modifier.height(32.dp)
    ) {
        Text(
            text = if (isSleeping) "唤醒" else "休眠",
            color = if (connected) OverlayText else Color(0x88FFFFFF),
            fontSize = 12.sp,
            fontWeight = FontWeight.Medium
        )
    }
}

// ==================== 充电/结束充电切换 ====================

@Composable
private fun ChargeToggleButton(
    isCharging: Boolean,
    connected: Boolean,
    onToggle: () -> Unit,
    modifier: Modifier = Modifier
) {
    Button(
        onClick = onToggle,
        enabled = connected,
        shape = ParallelogramShape(skewLeft = false),
        colors = ButtonDefaults.buttonColors(
            containerColor = if (isCharging) Color(0xCCFFC107) else Color(0x66333333),
            disabledContainerColor = Color(0x33222222)
        ),
        contentPadding = ButtonDefaults.TextButtonContentPadding,
        modifier = modifier.height(32.dp)
    ) {
        Text(
            text = if (isCharging) "充电中" else "充电",
            color = if (connected) OverlayText else Color(0x88FFFFFF),
            fontSize = 12.sp,
            fontWeight = FontWeight.Medium
        )
    }
}

// ==================== 辅助函数 ====================

private fun motionStateText(state: Int): String = when (state) {
    0 -> "空闲"
    1 -> "站立"
    2 -> "软急停"
    3 -> "开机阻尼"
    4 -> "趴下"
    17 -> "RL控制"
    else -> "未知($state)"
}