import UIKit

/// T-iPad-3 · 终端面板的指针（次要点击/右键）· 长按上下文菜单。
///
/// 纯菜单模型（可单测）+ `UIContextMenuInteraction` 桥。每个动作都**复用既有
/// 通道**，绝不新增网络路径：
/// - `.copySelection` → SwiftTerm 自带的 `copy(_:)`（读选区 → 剪贴板，绝不改
///   字节流，纯 UI —— hover 高亮同理）；
/// - `.newInCwd`      → T-iOS-29 的 `onNewInCwd`（当前会话 cwd fresh spawn）；
/// - `.kill`          → `onKill`（wiring 侧走 `APIClient.killSession` —— 带
///   Origin 的 G 端点，RO/G 铁律不变）。
///
/// 指针菜单仅在 iPad idiom 启用（`isPointerMenuEnabled`）—— iPhone 长按仍归
/// SwiftTerm 选区手势，字节级零回归。

/// One context-menu action, each mapped to an existing channel (no new path).
enum TerminalContextAction: String, CaseIterable, Sendable, Equatable {
    case copySelection
    case newInCwd
    case kill
}

/// Display spec for one menu row (Chinese copy + SF Symbol + destructive flag).
struct TerminalContextItem: Equatable, Sendable {
    let action: TerminalContextAction
    let title: String
    let systemImage: String
    let isDestructive: Bool
}

enum TerminalContextMenu {
    /// 用户可见文案（named constants，plan §4）。
    enum Copy {
        static let copySelection = "复制选区"
        static let newInCwd = "在当前目录开新会话"
        static let kill = "结束会话"
    }

    private enum Symbol {
        static let copySelection = "doc.on.doc"
        static let newInCwd = "plus.rectangle.on.folder"
        static let kill = "xmark.circle"
    }

    /// 指针上下文菜单仅在 iPad 启用。设备 idiom 与 size class 正交（不属
    /// `LayoutPolicy` 的 stack/split 判据），故独立成谓词；iPhone 上不安装
    /// interaction，长按保持 SwiftTerm 原生选区手势（零回归）。
    static func isPointerMenuEnabled(idiom: UIUserInterfaceIdiom) -> Bool {
        idiom == .pad
    }

    /// 依可用性过滤出菜单项（固定顺序：复制选区 → 开新会话 → 结束会话）。纯函数。
    static func items(
        canCopySelection: Bool,
        canNewInCwd: Bool,
        canKill: Bool
    ) -> [TerminalContextItem] {
        var result: [TerminalContextItem] = []
        if canCopySelection {
            result.append(TerminalContextItem(
                action: .copySelection, title: Copy.copySelection,
                systemImage: Symbol.copySelection, isDestructive: false
            ))
        }
        if canNewInCwd {
            result.append(TerminalContextItem(
                action: .newInCwd, title: Copy.newInCwd,
                systemImage: Symbol.newInCwd, isDestructive: false
            ))
        }
        if canKill {
            result.append(TerminalContextItem(
                action: .kill, title: Copy.kill,
                systemImage: Symbol.kill, isDestructive: true
            ))
        }
        return result
    }
}

/// 上下文菜单的可测装配核：把可用性 + 既有通道闭包收拢成 `items` 与 `perform`。
/// wiring 供给 `onNewInCwd`（T-iOS-29）/ `onKill`（APIClient.killSession）；
/// `onCopySelection`/`hasSelection` 由终端视图注入。动作 ↔ 通道一一映射，无旁路。
@MainActor
struct TerminalContextMenuModel {
    let onNewInCwd: (@MainActor () -> Void)?
    let onKill: (@MainActor () -> Void)?
    let onCopySelection: @MainActor () -> Void
    let hasSelection: @MainActor () -> Bool

    /// 当前可用的菜单项：复制选区随实时选区、开新会话/结束会话随 wiring 是否
    /// 供给了对应闭包（无闭包 = 隐藏，绝不呈现死项）。
    var items: [TerminalContextItem] {
        TerminalContextMenu.items(
            canCopySelection: hasSelection(),
            canNewInCwd: onNewInCwd != nil,
            canKill: onKill != nil
        )
    }

    /// 把一个动作路由到它对应的既有通道（映射的唯一实现点）。
    func perform(_ action: TerminalContextAction) {
        switch action {
        case .copySelection:
            onCopySelection()
        case .newInCwd:
            onNewInCwd?()
        case .kill:
            onKill?()
        }
    }
}

/// `UIContextMenuInteraction` 委托：菜单展开时用 `makeModel()` 取当前快照
/// （实时选区/闭包），构建 `UIMenu`，每个 `UIAction` 触发 `model.perform`。
/// 仅在 iPad 由终端视图安装（见 `TerminalContextMenu.isPointerMenuEnabled`）。
@MainActor
final class TerminalContextMenuInteractionDelegate: NSObject, UIContextMenuInteractionDelegate {
    private let makeModel: @MainActor () -> TerminalContextMenuModel

    init(makeModel: @escaping @MainActor () -> TerminalContextMenuModel) {
        self.makeModel = makeModel
    }

    func contextMenuInteraction(
        _ interaction: UIContextMenuInteraction,
        configurationForMenuAtLocation location: CGPoint
    ) -> UIContextMenuConfiguration? {
        let model = makeModel()
        let items = model.items
        guard !items.isEmpty else { return nil } // 无可用项 → 不弹菜单
        return UIContextMenuConfiguration(identifier: nil, previewProvider: nil) { _ in
            UIMenu(title: "", children: items.map { item in
                UIAction(
                    title: item.title,
                    image: UIImage(systemName: item.systemImage),
                    attributes: item.isDestructive ? .destructive : []
                ) { _ in
                    model.perform(item.action)
                }
            })
        }
    }
}
