import Cocoa
import CoreGraphics

/// 全局热键监听器：监听 Fn 键（长按录音）和 Control 键（双击切换模式）
final class KeyMonitor {

    // Fn 键标志
    private static let fnMask: UInt64 = 0x00800000
    // Control 键标志
    private static let controlMask: UInt64 = 0x00040000

    // 双击检测
    private static let doubleClickWindow: TimeInterval = 0.40   // 两次点击的最大间隔
    private static let longPressThreshold: TimeInterval = 0.20  // 长按判定阈值

    private var eventTap: CFMachPort?
    private var runLoopSource: CFRunLoopSource?

    // Fn 键状态
    private var isFnPressed = false
    private var fnDownTime: TimeInterval = 0
    private var longPressTimer: Timer?

    // Control 键双击检测
    private var isControlPressed = false
    private var lastControlUpTime: TimeInterval = 0

    // Fn 回调
    var onFnDown: (() -> Void)?
    var onFnUp: (() -> Void)?

    // Control 回调
    var onControlDoubleClick: (() -> Void)?    // 双击 Control 切换模式

    func start() -> Bool {
        guard eventTap == nil else { return true }

        guard CGPreflightListenEventAccess() else {
            CGRequestListenEventAccess()
            print("[KeyMonitor] ❌ Accessibility permission not granted")
            return false
        }

        let eventMask = (1 << CGEventType.flagsChanged.rawValue)

        let callback: CGEventTapCallBack = { (proxy, type, event, refcon) -> Unmanaged<CGEvent>? in
            let monitor = Unmanaged<KeyMonitor>.fromOpaque(refcon!).takeUnretainedValue()
            return monitor.handleEvent(proxy: proxy, type: type, event: event)
        }

        var tap = CGEvent.tapCreate(
            tap: .cghidEventTap,
            place: .headInsertEventTap,
            options: .defaultTap,
            eventsOfInterest: CGEventMask(eventMask),
            callback: callback,
            userInfo: Unmanaged.passUnretained(self).toOpaque()
        )

        if tap == nil {
            print("[KeyMonitor] ⚠️ HID tap failed, falling back to session tap")
            tap = CGEvent.tapCreate(
                tap: .cgSessionEventTap,
                place: .headInsertEventTap,
                options: .defaultTap,
                eventsOfInterest: CGEventMask(eventMask),
                callback: callback,
                userInfo: Unmanaged.passUnretained(self).toOpaque()
            )
        }

        guard let tap = tap else {
            print("[KeyMonitor] ❌ Failed to create event tap")
            return false
        }

        eventTap = tap
        runLoopSource = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, tap, 0)
        CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, .commonModes)
        CGEvent.tapEnable(tap: tap, enable: true)

        print("[KeyMonitor] ✅ Started")
        return true
    }

    func stop() {
        guard let tap = eventTap else { return }
        CGEvent.tapEnable(tap: tap, enable: false)
        if let source = runLoopSource {
            CFRunLoopRemoveSource(CFRunLoopGetCurrent(), source, .commonModes)
        }
        eventTap = nil
        runLoopSource = nil
        print("[KeyMonitor] Stopped")
    }

    private func handleEvent(proxy: CGEventTapProxy, type: CGEventType, event: CGEvent) -> Unmanaged<CGEvent>? {
        guard type == .flagsChanged else {
            return Unmanaged.passUnretained(event)
        }

        let flags = event.flags.rawValue
        let fnActive = (flags & Self.fnMask) != 0
        let controlActive = (flags & Self.controlMask) != 0

        // MARK: - Fn 键：长按录音
        if fnActive && !isFnPressed {
            isFnPressed = true
            fnDownTime = ProcessInfo.processInfo.systemUptime

            // 延迟 200ms 判定是否为长按
            print("[KeyMonitor] ⚡️ Fn DOWN (waiting for long-press)")
            longPressTimer?.invalidate()
            longPressTimer = Timer.scheduledTimer(withTimeInterval: Self.longPressThreshold, repeats: false) { [weak self] _ in
                guard let self = self, self.isFnPressed else { return }
                print("[KeyMonitor] ⚡️ Fn LONG-PRESS → start recording")
                self.longPressTimer = nil
                DispatchQueue.main.async {
                    self.onFnDown?()
                }
            }
            return nil
        }
        if !fnActive && isFnPressed {
            isFnPressed = false
            let fnUpTime = ProcessInfo.processInfo.systemUptime

            // 取消长按 timer（说明是短按，不触发录音）
            longPressTimer?.invalidate()
            longPressTimer = nil

            print("[KeyMonitor] ⚡️ Fn UP (was pressed for \(String(format: "%.0f", (fnUpTime - fnDownTime) * 1000))ms)")

            // 如果长按 timer 已被触发（已开始录音），正常触发 onFnUp
            if fnUpTime - fnDownTime >= Self.longPressThreshold {
                DispatchQueue.main.async { [weak self] in
                    self?.onFnUp?()
                }
            }
            return nil
        }

        // MARK: - Control 键：双击切换模式
        if controlActive && !isControlPressed {
            isControlPressed = true
            let controlDownTime = ProcessInfo.processInfo.systemUptime

            // 检测双击：上次松开距现在 < 400ms
            let elapsed = controlDownTime - lastControlUpTime
            if elapsed > 0 && elapsed < Self.doubleClickWindow {
                print("[KeyMonitor] ⚡️ Control DOUBLE-CLICK → switch mode")
                DispatchQueue.main.async { [weak self] in
                    self?.onControlDoubleClick?()
                }
            }
            return nil
        }
        if !controlActive && isControlPressed {
            isControlPressed = false
            lastControlUpTime = ProcessInfo.processInfo.systemUptime
            return nil
        }

        return Unmanaged.passUnretained(event)
    }
}
