package app.dudu.ime.ui

import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.interaction.collectIsPressedAsState
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.RowScope
import androidx.compose.foundation.layout.defaultMinSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.navigationBarsPadding
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.runtime.Composable
import androidx.compose.runtime.State
import androidx.compose.runtime.collectAsState
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.clip
import androidx.compose.ui.draw.drawBehind
import androidx.compose.ui.draw.scale
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.withStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.foundation.text.BasicText
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import app.dudu.data.AccountState
import app.dudu.design.DText
import app.dudu.design.DuduLogoMark
import app.dudu.design.IconArrowUp
import app.dudu.design.IconBackspace
import app.dudu.design.IconCheck
import app.dudu.design.IconEnter
import app.dudu.design.IconGlobe
import app.dudu.design.IconSliders
import app.dudu.design.LocalDuduPalette
import app.dudu.ime.KeyboardController
import app.dudu.ime.KeyboardUiState

/**
 * 键盘面板（设计规范 6.1，自上而下）：
 * 工具条 → 功能键行 / partial 文本条（录音中替换）→ 大麦克风条 → 取消提示。
 * 面板底色 surface-2 + 顶部 1px border-1，跟随系统 light/dark。
 */
@Composable
fun KeyboardScreen(
    controller: KeyboardController,
    onSwitchIme: () -> Unit,
    onText: (String) -> Unit,
    onBackspace: () -> Unit,
    onEnter: () -> Unit,
    onOpenApp: () -> Unit,
) {
    val p = LocalDuduPalette.current
    // 单点收集整个状态，但下面各区只通过 derivedStateOf 读各自所需字段：
    // partial（~5-10/s）只重组 PartialBar，不波及 Toolbar / MicBar / CancelHint。
    val ui = controller.state.collectAsState()

    Column(
        Modifier
            .fillMaxWidth()
            .background(p.surface2)
            .drawBehind {
                drawLine(p.border1, Offset(0f, 0.5f), Offset(size.width, 0.5f), 1f)
            }
            .padding(start = 8.dp, end = 8.dp, top = 6.dp, bottom = 10.dp)
            .navigationBarsPadding(),
    ) {
        Toolbar(ui, onOpenApp)

        // 中部区域选择：录音 / 已有文本 → 文本条；否则 notice / 功能键行。
        // showTextBar 仅在"有无文本/是否录音"翻转时变化，partial 持续刷新不触发本处重组。
        val showTextBar by remember(ui) {
            derivedStateOf {
                ui.value.recording || ui.value.finalText.isNotEmpty() || ui.value.partialText.isNotEmpty()
            }
        }
        val notice by remember(ui) { derivedStateOf { ui.value.notice } }
        when {
            showTextBar -> PartialBar(ui)
            notice != null -> NoticeBar(notice!!)
            else -> FunctionRow(onSwitchIme, onText, onBackspace, onEnter)
        }

        Box(Modifier.padding(horizontal = 2.dp)) {
            val micBarState by remember(ui) { derivedStateOf { micState(ui.value) } }
            val willCancel by remember(ui) { derivedStateOf { ui.value.willCancel } }
            MicBar(
                state = micBarState,
                willCancel = willCancel,
                onPressDown = controller::onPressDown,
                onDrag = controller::onDrag,
                onRelease = controller::onRelease,
                onCancel = controller::onCancel,
            )
        }

        val recording by remember(ui) { derivedStateOf { ui.value.recording } }
        if (recording) CancelHint(ui)
    }
}

private fun micState(ui: KeyboardUiState): MicBarState = when {
    ui.account.state == AccountState.GUEST -> MicBarState.Disabled
    ui.account.state == AccountState.QUOTA -> MicBarState.Quota
    ui.recording -> MicBarState.Recording
    else -> MicBarState.Idle
}

// ─── 工具条：左 logo + 名称，右 账户态文案（设计规范 6.2） ─────────────────────

@Composable
private fun Toolbar(ui: State<KeyboardUiState>, onOpenApp: () -> Unit) {
    val p = LocalDuduPalette.current
    // 仅读 recording / seconds / account：partial 刷新不进入本作用域。
    val recording by remember(ui) { derivedStateOf { ui.value.recording } }
    val seconds by remember(ui) { derivedStateOf { ui.value.seconds } }
    val account by remember(ui) { derivedStateOf { ui.value.account } }
    Row(
        Modifier
            .fillMaxWidth()
            .padding(start = 6.dp, end = 6.dp, top = 2.dp, bottom = 8.dp),
        horizontalArrangement = Arrangement.SpaceBetween,
        verticalAlignment = Alignment.CenterVertically,
    ) {
        Row(
            horizontalArrangement = Arrangement.spacedBy(6.dp),
            verticalAlignment = Alignment.CenterVertically,
        ) {
            DuduLogoMark(13.dp, p.text2)
            DText("dudu 语音输入", 12.sp, p.text2)
        }

        Row(
            horizontalArrangement = Arrangement.spacedBy(8.dp),
            verticalAlignment = Alignment.CenterVertically,
        ) {
            when {
                recording -> DText(fmtTimer(seconds), 12.sp, p.positive, mono = true)
                account.state == AccountState.GUEST -> DText("未登录", 12.sp, p.text3)
                account.state == AccountState.QUOTA -> DText("今日试用已用完", 12.sp, p.warning)
                account.state == AccountState.TRIAL ->
                    DText("试用 · 今日剩 ${fmtDuration(account.trialRemainingSeconds.toLong())}", 12.sp, p.text3)
                else -> Row(
                    horizontalArrangement = Arrangement.spacedBy(4.dp),
                    verticalAlignment = Alignment.CenterVertically,
                ) {
                    DText("余额 ${fmtDuration(account.balanceSeconds)}", 12.sp, p.text3)
                    IconCheck(11.dp, p.text3)
                }
            }
            // 设置入口 → 主 App
            val src = remember { MutableInteractionSource() }
            IconSliders(
                14.dp, p.text3,
                Modifier.clickable(interactionSource = src, indication = null, onClick = onOpenApp),
            )
        }
    }
}

private fun fmtTimer(s: Int): String = "%02d:%02d".format(s / 60, s % 60)

private fun fmtDuration(seconds: Long): String =
    if (seconds >= 60) "${seconds / 60} 分钟" else "$seconds 秒"

// ─── partial 文本条：深色玻璃（硬规则），final 亮 / partial 灰拼接 ─────────────

@Composable
private fun PartialBar(ui: State<KeyboardUiState>) {
    val p = LocalDuduPalette.current
    // 只有本作用域读 final / partial：partial 刷新仅重组 PartialBar。
    val finalText by remember(ui) { derivedStateOf { ui.value.finalText } }
    val partialText by remember(ui) { derivedStateOf { ui.value.partialText } }
    val text: AnnotatedString = buildAnnotatedString {
        if (finalText.isEmpty() && partialText.isEmpty()) {
            withStyle(SpanStyle(color = p.overlayText2)) { append("聆听中…") }
        } else {
            withStyle(SpanStyle(color = p.overlayText)) { append(finalText) }
            withStyle(SpanStyle(color = p.overlayText2)) { append(partialText) }
        }
    }
    Box(
        Modifier
            .fillMaxWidth()
            .padding(start = 2.dp, end = 2.dp, bottom = 8.dp)
            .defaultMinSize(minHeight = 40.dp)
            .clip(RoundedCornerShape(10.dp))
            .background(p.overlayBg)
            .padding(horizontal = 12.dp, vertical = 9.dp),
        contentAlignment = Alignment.CenterStart,
    ) {
        BasicText(text = text, style = TextStyle(fontSize = 15.sp, lineHeight = 22.5.sp))
    }
}

/** 错误/引导文案：占 partial 条位置，同样深色玻璃，warning 色文字。 */
@Composable
private fun NoticeBar(notice: String) {
    val p = LocalDuduPalette.current
    Box(
        Modifier
            .fillMaxWidth()
            .padding(start = 2.dp, end = 2.dp, bottom = 8.dp)
            .defaultMinSize(minHeight = 40.dp)
            .clip(RoundedCornerShape(10.dp))
            .background(p.overlayBg)
            .padding(horizontal = 12.dp, vertical = 9.dp),
        contentAlignment = Alignment.CenterStart,
    ) {
        DText(notice, 15.sp, p.warning, lineHeight = 22.5.sp)
    }
}

// ─── 功能键行：切输入法 / ， / 。 / 退格 / 发送（不做 26 键，语音为主） ─────────

@Composable
private fun FunctionRow(
    onSwitchIme: () -> Unit,
    onText: (String) -> Unit,
    onBackspace: () -> Unit,
    onEnter: () -> Unit,
) {
    val p = LocalDuduPalette.current
    Row(
        Modifier
            .fillMaxWidth()
            .padding(start = 2.dp, end = 2.dp, bottom = 8.dp),
        horizontalArrangement = Arrangement.spacedBy(6.dp),
    ) {
        FnKey(flex = 1.3f, onClick = onSwitchIme) { IconGlobe(17.dp, p.text1) }
        FnKey(flex = 1f, onClick = { onText("，") }) { DText("，", 15.sp, p.text1) }
        FnKey(flex = 1f, onClick = { onText("。") }) { DText("。", 15.sp, p.text1) }
        FnKey(flex = 1.3f, onClick = onBackspace) { IconBackspace(17.dp, p.text1) }
        FnKey(flex = 1.3f, onClick = onEnter) { IconEnter(16.dp, p.text1) }
    }
}

@Composable
private fun RowScope.FnKey(
    flex: Float,
    onClick: () -> Unit,
    content: @Composable () -> Unit,
) {
    val p = LocalDuduPalette.current
    val src = remember { MutableInteractionSource() }
    val pressed by src.collectIsPressedAsState()
    Box(
        Modifier
            .weight(flex)
            .height(40.dp)
            .scale(if (pressed) 0.97f else 1f) // 键帽按压缩 0.97（设计规范）
            .clip(RoundedCornerShape(6.dp))
            .background(if (pressed) p.surface3 else p.surfaceCard)
            .clickable(interactionSource = src, indication = null, onClick = onClick),
        contentAlignment = Alignment.Center,
    ) {
        content()
    }
}

// ─── 取消提示（仅录音中）："↑ 上滑取消"，越过阈值转 danger"松开取消" ───────────

@Composable
private fun CancelHint(ui: State<KeyboardUiState>) {
    val p = LocalDuduPalette.current
    val willCancel by remember(ui) { derivedStateOf { ui.value.willCancel } }
    val color = if (willCancel) p.danger else p.text3
    Row(
        Modifier
            .fillMaxWidth()
            .padding(top = 6.dp),
        horizontalArrangement = Arrangement.spacedBy(4.dp, Alignment.CenterHorizontally),
        verticalAlignment = Alignment.CenterVertically,
    ) {
        IconArrowUp(11.dp, color)
        DText(if (willCancel) "松开取消" else "上滑取消", 12.sp, color)
    }
}
