//! 文字注入（10E/10F）：剪贴板写入 → 模拟粘贴（mac ⌘V / win Ctrl+V）→ 恢复剪贴板。
//! 兼容性最好的方案；macOS 需辅助功能权限（首次启动引导授予）。

use enigo::{Direction, Enigo, Key, Keyboard, Settings as EnigoSettings};
use std::{thread, time::Duration};

// ─── macOS 辅助功能权限（10E）────────────────────────────────────────────────

#[cfg(target_os = "macos")]
#[link(name = "ApplicationServices", kind = "framework")]
extern "C" {
    /// 进程是否已被授予辅助功能权限（不弹系统提示）。
    fn AXIsProcessTrusted() -> u8;
}

/// 是否已具备注入所需的辅助功能权限；非 macOS 恒为 true。
pub fn accessibility_ok() -> bool {
    #[cfg(target_os = "macos")]
    {
        unsafe { AXIsProcessTrusted() != 0 }
    }
    #[cfg(not(target_os = "macos"))]
    {
        true
    }
}

#[tauri::command]
pub fn check_accessibility() -> bool {
    accessibility_ok()
}

/// 打开系统设置的辅助功能面板（macOS）；其他平台 no-op。
#[tauri::command]
pub fn open_accessibility_settings() {
    #[cfg(target_os = "macos")]
    {
        let _ = std::process::Command::new("open")
            .arg("x-apple.systempreferences:com.apple.preference.security?Privacy_Accessibility")
            .spawn();
    }
}

pub fn inject_text(text: &str) -> Result<(), String> {
    if text.is_empty() {
        return Ok(());
    }
    let mut clipboard = arboard::Clipboard::new().map_err(|e| e.to_string())?;
    let saved = clipboard.get_text().ok();

    clipboard.set_text(text).map_err(|e| e.to_string())?;
    thread::sleep(Duration::from_millis(30)); // 等剪贴板生效

    let mut enigo = Enigo::new(&EnigoSettings::default()).map_err(|e| e.to_string())?;
    #[cfg(target_os = "macos")]
    let modifier = Key::Meta;
    #[cfg(not(target_os = "macos"))]
    let modifier = Key::Control;

    // 粘贴键 V：
    // macOS 用物理键码 9（kVK_ANSI_V），直接走 CGEvent，避开 enigo 对
    // Key::Unicode 的键盘布局查询——那条路径调 TSMGetInputSourceProperty，
    // 该 API 必须在主线程执行，在 tokio 后台线程上调用会触发断言崩溃
    // （macOS 15/26 收紧了主线程校验）。物理键码与布局无关，粘贴恒为此键位。
    #[cfg(target_os = "macos")]
    let paste_key = Key::Other(9);
    #[cfg(not(target_os = "macos"))]
    let paste_key = Key::Unicode('v');

    enigo.key(modifier, Direction::Press).map_err(|e| e.to_string())?;
    enigo.key(paste_key, Direction::Click).map_err(|e| e.to_string())?;
    enigo
        .key(modifier, Direction::Release)
        .map_err(|e| e.to_string())?;

    // 粘贴完成后恢复用户剪贴板
    thread::sleep(Duration::from_millis(120));
    if let Some(old) = saved {
        let _ = clipboard.set_text(old);
    }
    Ok(())
}
