package wang.yaojia.webterm.components

import androidx.compose.foundation.layout.Box
import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.pointer.isSecondaryPressed
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.unit.DpOffset
import wang.yaojia.webterm.nav.LayoutMode
import wang.yaojia.webterm.nav.PointerMenuPolicy

/**
 * # PointerContextMenu (A26) — the large-screen right-click / trackpad-secondary menu.
 *
 * The Android analogue of iOS's pointer context menu (open-in-cwd / kill / copy). A reusable wrapper
 * that installs a `Modifier.pointerInput` detecting a **secondary** pointer button (mouse right-click,
 * trackpad two-finger / secondary click) and anchors a Material `DropdownMenu` at the click position.
 *
 * ### Gating (plan §5 A26, §"iPad-equivalent", R13, §8)
 * The whole affordance is gated by the pure [PointerMenuPolicy.enabled] predicate — enabled **only** in
 * [LayoutMode.LIST_DETAIL] on a genuine tablet (`smallestScreenWidthDp >= 600`). When disabled the
 * wrapper is a transparent pass-through (no pointer interception, no menu) so phones behave exactly as
 * before. This is `Modifier.pointerInput` + an anchored `DropdownMenu` — deliberately NOT Compose
 * Desktop's `ContextMenuArea`, which is not stable on Android (platform review).
 *
 * The pointer detection / menu placement / gesture behaviour is device-QA (plan §7); the gate is the
 * JVM-tested [PointerMenuPolicy] core.
 *
 * @param mode the current [LayoutMode] from [wang.yaojia.webterm.nav.LayoutPolicy].
 * @param actions the menu entries (e.g. 在当前目录开新会话 / 终止 / 复制), each a label + callback.
 * @param smallestScreenWidthDp the device's smallest-width; defaults to the current configuration.
 * @param content the wrapped content the secondary-click targets.
 */
@Composable
public fun PointerContextMenu(
    mode: LayoutMode,
    actions: List<ContextMenuAction>,
    modifier: Modifier = Modifier,
    smallestScreenWidthDp: Int = LocalConfiguration.current.smallestScreenWidthDp,
    content: @Composable () -> Unit,
) {
    // Gate: on a phone / compact layout the menu never exists and the pointer is never intercepted.
    if (!PointerMenuPolicy.enabled(mode, smallestScreenWidthDp)) {
        Box(modifier = modifier) { content() }
        return
    }

    var expanded by remember { mutableStateOf(false) }
    var anchor by remember { mutableStateOf(DpOffset.Zero) }
    val density = LocalDensity.current

    Box(
        modifier = modifier.pointerInput(actions) {
            awaitPointerEventScope {
                while (true) {
                    val event = awaitPointerEvent()
                    if (event.buttons.isSecondaryPressed) {
                        val position = event.changes.first().position
                        anchor = with(density) { DpOffset(position.x.toDp(), position.y.toDp()) }
                        expanded = true
                        // Consume so the underlying content doesn't also react to the secondary press.
                        event.changes.forEach { it.consume() }
                    }
                }
            }
        },
    ) {
        content()
        DropdownMenu(
            expanded = expanded,
            onDismissRequest = { expanded = false },
            offset = anchor,
        ) {
            for (action in actions) {
                DropdownMenuItem(
                    text = { Text(action.label) },
                    onClick = {
                        expanded = false
                        action.onClick()
                    },
                )
            }
        }
    }
}

/** One entry in the [PointerContextMenu]: an inert label + the callback fired when it is chosen. */
public data class ContextMenuAction(val label: String, val onClick: () -> Unit)
