//! 事件系统
//!
//! 提供 MasterEvents 和 SlaveEvents 结构体，封装 DLL 回调事件。
//! 通过 `EtherCATMaster::events()` 获取主站事件集合。
//!
//! 所有回调注册线程安全，使用 `Arc<Mutex<Vec<Box<dyn Fn(...)>>>>` 存储。

use crate::utils::ffi;
use std::collections::HashSet;
use std::sync::{Arc, Mutex, Once};

// ===================== 回调列表类型别名 =====================

/// PDO 周期回调 (master_index)
type PdoCyclicList = Arc<Mutex<Vec<Box<dyn Fn(u16) + Send + 'static>>>>;
/// 从站状态变化回调 (master_index, slave_index, old_state, new_state)
type SlaveStateChangeList = Arc<Mutex<Vec<Box<dyn Fn(u16, u16, i32, i32) + Send + 'static>>>>;
/// 紧急事件回调 (master_index, slave_index, error_code, error_reg, b1, w1, w2)
type EmergencyList = Arc<Mutex<Vec<Box<dyn Fn(u16, u16, u16, u16, u8, u16, u16) + Send + 'static>>>>;
/// 从站发现回调 (master_index, slave_index, is_found)
type SlaveDiscoveryList = Arc<Mutex<Vec<Box<dyn Fn(u16, u16, bool) + Send + 'static>>>>;
/// PDO 丢帧回调 (master_index, group, consecutive, total)
type PdoFrameLossList = Arc<Mutex<Vec<Box<dyn Fn(u16, u8, u32, u32) + Send + 'static>>>>;
/// DC 同步丢失回调 (master_index, slave_index, diff_ns)
type DcSyncLostList = Arc<Mutex<Vec<Box<dyn Fn(u16, u16, i32) + Send + 'static>>>>;
/// 冗余模式变化回调 (master_index, old_mode, new_mode)
type RedundancyChangedList = Arc<Mutex<Vec<Box<dyn Fn(u16, i32, i32) + Send + 'static>>>>;
/// 输入数据变化回调 (master_index, slave_bits_ptr, changed_count)
type InputChangedList = Arc<Mutex<Vec<Box<dyn Fn(u16, *const u8, u16) + Send + 'static>>>>;
/// PreOp 重配置回调 (master_index, slave_index)
type PreOpReconfigList = Arc<Mutex<Vec<Box<dyn Fn(u16, u16) + Send + 'static>>>>;
/// 从站身份不符回调 (SlaveIdentityMismatch, 含 expected/actual 三元组)
type SlaveIdentityMismatchList = Arc<Mutex<Vec<Box<dyn Fn(SlaveIdentityMismatch) + Send + 'static>>>>;
/// 从站端口链路变化回调 (master_index, slave_index, port, is_up)
type SlavePortLinkChangedList = Arc<Mutex<Vec<Box<dyn Fn(u16, u16, u8, bool) + Send + 'static>>>>;

// ===================== 事件数据结构 =====================

/// 从站身份不符事件参数 (v2 热插拔自修复)
///
/// 触发时机: 断电重插从站后 ident FSM 读取到的 Vendor/Product 与配置不匹配,
/// 或 Revision 低于配置 (向后兼容: actual >= configured 视为匹配).
///
/// 去重: 进入 IDENT_REJECTED 状态时仅触发一次, 需调用
/// [`crate::master::core::EtherCATMaster::acknowledge_slave_replacement`]
/// 后才会重新探测并可能再次触发.
#[derive(Debug, Clone, Copy)]
pub struct SlaveIdentityMismatch {
    /// 主站索引
    pub master_index: u16,
    /// 从站索引 (1-based)
    pub slave_index: u16,
    /// 配置期望的厂商 ID
    pub expected_vendor: u32,
    /// 配置期望的产品代码
    pub expected_product: u32,
    /// 配置期望的最低修订号
    pub expected_revision: u32,
    /// 当前实测厂商 ID
    pub actual_vendor: u32,
    /// 当前实测产品代码
    pub actual_product: u32,
    /// 当前实测修订号
    pub actual_revision: u32,
}

// ===================== 全局回调列表 (静态) =====================

fn pdo_cyclic_sync() -> &'static PdoCyclicList {
    use std::sync::OnceLock;
    static INSTANCE: OnceLock<PdoCyclicList> = OnceLock::new();
    INSTANCE.get_or_init(|| Arc::new(Mutex::new(Vec::new())))
}

fn pdo_cyclic_async() -> &'static PdoCyclicList {
    use std::sync::OnceLock;
    static INSTANCE: OnceLock<PdoCyclicList> = OnceLock::new();
    INSTANCE.get_or_init(|| Arc::new(Mutex::new(Vec::new())))
}

fn slave_state_change_list() -> &'static SlaveStateChangeList {
    use std::sync::OnceLock;
    static INSTANCE: OnceLock<SlaveStateChangeList> = OnceLock::new();
    INSTANCE.get_or_init(|| Arc::new(Mutex::new(Vec::new())))
}

fn emergency_list() -> &'static EmergencyList {
    use std::sync::OnceLock;
    static INSTANCE: OnceLock<EmergencyList> = OnceLock::new();
    INSTANCE.get_or_init(|| Arc::new(Mutex::new(Vec::new())))
}

fn slave_discovery_list() -> &'static SlaveDiscoveryList {
    use std::sync::OnceLock;
    static INSTANCE: OnceLock<SlaveDiscoveryList> = OnceLock::new();
    INSTANCE.get_or_init(|| Arc::new(Mutex::new(Vec::new())))
}

fn pdo_frame_loss_list() -> &'static PdoFrameLossList {
    use std::sync::OnceLock;
    static INSTANCE: OnceLock<PdoFrameLossList> = OnceLock::new();
    INSTANCE.get_or_init(|| Arc::new(Mutex::new(Vec::new())))
}

fn dc_sync_lost_list() -> &'static DcSyncLostList {
    use std::sync::OnceLock;
    static INSTANCE: OnceLock<DcSyncLostList> = OnceLock::new();
    INSTANCE.get_or_init(|| Arc::new(Mutex::new(Vec::new())))
}

fn redundancy_changed_list() -> &'static RedundancyChangedList {
    use std::sync::OnceLock;
    static INSTANCE: OnceLock<RedundancyChangedList> = OnceLock::new();
    INSTANCE.get_or_init(|| Arc::new(Mutex::new(Vec::new())))
}

fn input_changed_list() -> &'static InputChangedList {
    use std::sync::OnceLock;
    static INSTANCE: OnceLock<InputChangedList> = OnceLock::new();
    INSTANCE.get_or_init(|| Arc::new(Mutex::new(Vec::new())))
}

fn preop_reconfig_list() -> &'static PreOpReconfigList {
    use std::sync::OnceLock;
    static INSTANCE: OnceLock<PreOpReconfigList> = OnceLock::new();
    INSTANCE.get_or_init(|| Arc::new(Mutex::new(Vec::new())))
}

fn slave_identity_mismatch_list() -> &'static SlaveIdentityMismatchList {
    use std::sync::OnceLock;
    static INSTANCE: OnceLock<SlaveIdentityMismatchList> = OnceLock::new();
    INSTANCE.get_or_init(|| Arc::new(Mutex::new(Vec::new())))
}

fn slave_port_link_changed_list() -> &'static SlavePortLinkChangedList {
    use std::sync::OnceLock;
    static INSTANCE: OnceLock<SlavePortLinkChangedList> = OnceLock::new();
    INSTANCE.get_or_init(|| Arc::new(Mutex::new(Vec::new())))
}

/// 从站状态变化异步回调列表
fn slave_state_change_async_list() -> &'static SlaveStateChangeList {
    use std::sync::OnceLock;
    static INSTANCE: OnceLock<SlaveStateChangeList> = OnceLock::new();
    INSTANCE.get_or_init(|| Arc::new(Mutex::new(Vec::new())))
}

/// 从站发现异步回调列表
fn slave_discovery_async_list() -> &'static SlaveDiscoveryList {
    use std::sync::OnceLock;
    static INSTANCE: OnceLock<SlaveDiscoveryList> = OnceLock::new();
    INSTANCE.get_or_init(|| Arc::new(Mutex::new(Vec::new())))
}

/// 离线从站追踪集合
fn offline_slaves() -> &'static Mutex<HashSet<u16>> {
    use std::sync::OnceLock;
    static INSTANCE: OnceLock<Mutex<HashSet<u16>>> = OnceLock::new();
    INSTANCE.get_or_init(|| Mutex::new(HashSet::new()))
}

// ===================== DLL 回调注册 (仅一次) =====================

static CALLBACKS_INIT: Once = Once::new();

/// 初始化 DLL 回调注册
///
/// 在首次创建 `MasterEvents` 时自动调用，确保只注册一次。
/// 也可手动调用以提前注册。
pub fn initialize_callbacks() {
    CALLBACKS_INIT.call_once(|| {
        unsafe {
            ffi::RegisterProcessDataCyclicCallbackSync(on_pdo_cyclic_sync);
            ffi::RegisterProcessDataCyclicCallbackAsync(on_pdo_cyclic_async);
            ffi::RegisterSlaveStateChangeCallbackSync(on_slave_state_change);
            ffi::RegisterSlaveStateChangeCallbackAsync(on_slave_state_change_async);
            ffi::RegisterEmergencyEventCallback(on_emergency);
            ffi::RegisterSlaveDiscoveryCallbackSync(on_slave_discovery);
            ffi::RegisterSlaveDiscoveryCallbackAsync(on_slave_discovery_async);
            ffi::RegisterPDOFrameLossCallback(on_pdo_frame_loss);
            ffi::SetDCSyncLostCallback(on_dc_sync_lost);
            ffi::RegisterRedundancyModeChangedCallback(on_redundancy_changed);
            ffi::RegisterInputDataChangedCallback(on_input_changed);
            ffi::RegisterSlavePreOpReconfigCallback(on_preop_reconfig);
            ffi::RegisterSlaveIdentityMismatchCallback(on_slave_identity_mismatch);
            ffi::RegisterSlavePortLinkChangedCallback(on_slave_port_link_changed);
        }
    });
}

// ===================== 静态 extern "C" 回调函数 =====================

/// PDO 同步回调
extern "C" fn on_pdo_cyclic_sync(master_index: u16) {
    if let Ok(list) = pdo_cyclic_sync().lock() {
        for cb in list.iter() {
            cb(master_index);
        }
    }
}

/// PDO 异步回调
extern "C" fn on_pdo_cyclic_async(master_index: u16) {
    if let Ok(list) = pdo_cyclic_async().lock() {
        for cb in list.iter() {
            cb(master_index);
        }
    }
}

/// 从站状态变化回调
extern "C" fn on_slave_state_change(master_index: u16, slave_index: u16, old_state: i32, new_state: i32) {
    if let Ok(list) = slave_state_change_list().lock() {
        for cb in list.iter() {
            cb(master_index, slave_index, old_state, new_state);
        }
    }
}

/// 从站状态变化异步回调
extern "C" fn on_slave_state_change_async(master_index: u16, slave_index: u16, old_state: i32, new_state: i32) {
    if let Ok(list) = slave_state_change_async_list().lock() {
        for cb in list.iter() {
            cb(master_index, slave_index, old_state, new_state);
        }
    }
}

/// 紧急事件回调
extern "C" fn on_emergency(
    master_index: u16, slave_index: u16,
    error_code: u16, error_reg: u16, b1: u8, w1: u16, w2: u16,
) {
    if let Ok(list) = emergency_list().lock() {
        for cb in list.iter() {
            cb(master_index, slave_index, error_code, error_reg, b1, w1, w2);
        }
    }
}

/// 从站发现回调 (上线/离线)
extern "C" fn on_slave_discovery(master_index: u16, slave_index: u16, is_found: i32) {
    let found = is_found != 0;

    // 更新离线追踪集合 (去重)
    if let Ok(mut set) = offline_slaves().lock() {
        if found {
            set.remove(&slave_index);
        } else {
            set.insert(slave_index);
        }
    }

    if let Ok(list) = slave_discovery_list().lock() {
        for cb in list.iter() {
            cb(master_index, slave_index, found);
        }
    }
}

/// 从站发现异步回调 (上线/离线)
extern "C" fn on_slave_discovery_async(master_index: u16, slave_index: u16, is_found: i32) {
    let found = is_found != 0;
    if let Ok(list) = slave_discovery_async_list().lock() {
        for cb in list.iter() {
            cb(master_index, slave_index, found);
        }
    }
}

/// PDO 丢帧回调
extern "C" fn on_pdo_frame_loss(master_index: u16, group: u8, consecutive: u32, total: u32) {
    if let Ok(list) = pdo_frame_loss_list().lock() {
        for cb in list.iter() {
            cb(master_index, group, consecutive, total);
        }
    }
}

/// DC 同步丢失回调
extern "C" fn on_dc_sync_lost(master_index: u16, slave_index: u16, diff_ns: i32) {
    if let Ok(list) = dc_sync_lost_list().lock() {
        for cb in list.iter() {
            cb(master_index, slave_index, diff_ns);
        }
    }
}

/// 冗余模式变化回调
extern "C" fn on_redundancy_changed(master_index: u16, old_mode: i32, new_mode: i32) {
    if let Ok(list) = redundancy_changed_list().lock() {
        for cb in list.iter() {
            cb(master_index, old_mode, new_mode);
        }
    }
}

/// 输入数据变化回调
extern "C" fn on_input_changed(master_index: u16, changed_slave_bits: *const u8, changed_count: u16) {
    if let Ok(list) = input_changed_list().lock() {
        for cb in list.iter() {
            cb(master_index, changed_slave_bits, changed_count);
        }
    }
}

/// PreOp 重配置回调
extern "C" fn on_preop_reconfig(master_index: u16, slave_index: u16) {
    if let Ok(list) = preop_reconfig_list().lock() {
        for cb in list.iter() {
            cb(master_index, slave_index);
        }
    }
}

/// 从站身份不符回调 (v2 热插拔自修复)
extern "C" fn on_slave_identity_mismatch(
    master_index: u16,
    slave_index: u16,
    expected_vendor: u32,
    expected_product: u32,
    expected_revision: u32,
    actual_vendor: u32,
    actual_product: u32,
    actual_revision: u32,
) {
    let args = SlaveIdentityMismatch {
        master_index,
        slave_index,
        expected_vendor,
        expected_product,
        expected_revision,
        actual_vendor,
        actual_product,
        actual_revision,
    };
    if let Ok(list) = slave_identity_mismatch_list().lock() {
        for cb in list.iter() {
            cb(args);
        }
    }
}

/// 从站端口链路变化回调 (断线检测)
extern "C" fn on_slave_port_link_changed(master_index: u16, slave_index: u16, port: u8, is_up: i32) {
    let up = is_up != 0;
    if let Ok(list) = slave_port_link_changed_list().lock() {
        for cb in list.iter() {
            cb(master_index, slave_index, port, up);
        }
    }
}

// ===================== MasterEvents =====================

/// 主站事件集合
///
/// 通过 `EtherCATMaster::events()` 获取实例。
/// 提供所有 DLL 回调事件的注册接口。
///
/// # 示例
/// ```no_run
/// let master = EtherCATMaster::new().unwrap();
/// let events = master.events();
/// events.on_pdo_cyclic_async(|master_idx| {
///     // PDO 周期回调
/// });
/// events.on_slave_offline(|slave_idx| {
///     println!("从站 {} 离线", slave_idx);
/// });
/// ```
pub struct MasterEvents {
    _master_index: u16,
}

impl MasterEvents {
    /// 创建主站事件集合 (内部使用)
    pub(crate) fn new(master_index: u16) -> Self {
        // 确保 DLL 回调已注册
        initialize_callbacks();
        Self { _master_index: master_index }
    }

    /// 注册 PDO 周期同步回调 (在实时线程中直接执行, 必须快速返回)
    pub fn on_pdo_cyclic_sync<F>(&self, callback: F)
    where
        F: Fn(u16) + Send + 'static,
    {
        if let Ok(mut list) = pdo_cyclic_sync().lock() {
            list.push(Box::new(callback));
        }
    }

    /// 注册 PDO 周期异步回调 (不阻塞实时线程, 推荐)
    pub fn on_pdo_cyclic_async<F>(&self, callback: F)
    where
        F: Fn(u16) + Send + 'static,
    {
        if let Ok(mut list) = pdo_cyclic_async().lock() {
            list.push(Box::new(callback));
        }
    }

    /// 注册从站状态变化回调
    ///
    /// 回调参数: (master_index, slave_index, old_state, new_state)
    pub fn on_slave_state_changed<F>(&self, callback: F)
    where
        F: Fn(u16, u16, i32, i32) + Send + 'static,
    {
        if let Ok(mut list) = slave_state_change_list().lock() {
            list.push(Box::new(callback));
        }
    }

    /// 注册从站状态变化异步回调 (不阻塞实时线程, 推荐)
    ///
    /// 回调参数: (master_index, slave_index, old_state, new_state)
    pub fn on_slave_state_changed_async<F>(&self, callback: F)
    where
        F: Fn(u16, u16, i32, i32) + Send + 'static,
    {
        if let Ok(mut list) = slave_state_change_async_list().lock() {
            list.push(Box::new(callback));
        }
    }

    /// 注册紧急事件回调 (EMCY)
    ///
    /// 回调参数: (master_index, slave_index, error_code, error_reg, b1, w1, w2)
    pub fn on_emergency<F>(&self, callback: F)
    where
        F: Fn(u16, u16, u16, u16, u8, u16, u16) + Send + 'static,
    {
        if let Ok(mut list) = emergency_list().lock() {
            list.push(Box::new(callback));
        }
    }

    /// 注册从站离线回调
    ///
    /// 回调参数: (slave_index)
    /// 内部自动去重, 同一从站仅触发一次直到上线
    pub fn on_slave_offline<F>(&self, callback: F)
    where
        F: Fn(u16) + Send + 'static,
    {
        if let Ok(mut list) = slave_discovery_list().lock() {
            let cb = Box::new(move |_master: u16, slave: u16, found: bool| {
                if !found {
                    callback(slave);
                }
            });
            list.push(cb);
        }
    }

    /// 注册从站上线回调
    ///
    /// 回调参数: (slave_index)
    /// 内部自动去重, 仅当从站之前离线时触发
    pub fn on_slave_online<F>(&self, callback: F)
    where
        F: Fn(u16) + Send + 'static,
    {
        if let Ok(mut list) = slave_discovery_list().lock() {
            let cb = Box::new(move |_master: u16, slave: u16, found: bool| {
                if found {
                    callback(slave);
                }
            });
            list.push(cb);
        }
    }

    /// 注册从站发现回调 (上线和离线)
    ///
    /// 回调参数: (master_index, slave_index, is_found)
    pub fn on_slave_discovery<F>(&self, callback: F)
    where
        F: Fn(u16, u16, bool) + Send + 'static,
    {
        if let Ok(mut list) = slave_discovery_list().lock() {
            list.push(Box::new(callback));
        }
    }

    /// 注册从站发现异步回调 (上线和离线, 不阻塞实时线程, 推荐)
    ///
    /// 回调参数: (master_index, slave_index, is_found)
    pub fn on_slave_discovery_async<F>(&self, callback: F)
    where
        F: Fn(u16, u16, bool) + Send + 'static,
    {
        if let Ok(mut list) = slave_discovery_async_list().lock() {
            list.push(Box::new(callback));
        }
    }

    /// 注册 PDO 丢帧回调
    ///
    /// 回调参数: (master_index, group, consecutive_lost, total_lost)
    pub fn on_pdo_frame_loss<F>(&self, callback: F)
    where
        F: Fn(u16, u8, u32, u32) + Send + 'static,
    {
        if let Ok(mut list) = pdo_frame_loss_list().lock() {
            list.push(Box::new(callback));
        }
    }

    /// 注册 DC 同步丢失回调
    ///
    /// 回调参数: (master_index, slave_index, diff_ns)
    pub fn on_dc_sync_lost<F>(&self, callback: F)
    where
        F: Fn(u16, u16, i32) + Send + 'static,
    {
        if let Ok(mut list) = dc_sync_lost_list().lock() {
            list.push(Box::new(callback));
        }
    }

    /// 注册冗余模式变化回调
    ///
    /// 回调参数: (master_index, old_mode, new_mode)
    /// 模式: 0=未激活, 1=双向冗余, 2=降级(仅primary)
    pub fn on_redundancy_mode_changed<F>(&self, callback: F)
    where
        F: Fn(u16, i32, i32) + Send + 'static,
    {
        if let Ok(mut list) = redundancy_changed_list().lock() {
            list.push(Box::new(callback));
        }
    }

    /// 注册输入数据变化回调 (原始位图)
    ///
    /// 回调参数: (master_index, changed_slave_bits, changed_count)
    /// 位图中第 N 位为 1 表示从站 N 的输入数据发生了变化
    pub fn on_input_data_changed_raw<F>(&self, callback: F)
    where
        F: Fn(u16, *const u8, u16) + Send + 'static,
    {
        if let Ok(mut list) = input_changed_list().lock() {
            list.push(Box::new(callback));
        }
    }

    /// 注册输入数据变化回调 (解析后的从站列表)
    ///
    /// 回调参数: (master_index, changed_slave_indices)
    /// 自动解析 DLL 位图, 返回变化的从站索引列表
    pub fn on_input_data_changed<F>(&self, callback: F)
    where
        F: Fn(u16, Vec<u16>) + Send + 'static,
    {
        if let Ok(mut list) = input_changed_list().lock() {
            let cb = Box::new(move |master: u16, bits_ptr: *const u8, count: u16| {
                if bits_ptr.is_null() || count == 0 {
                    return;
                }
                let mut slaves = Vec::with_capacity(count as usize);
                let mut found: u16 = 0;
                // 修复: 位图最大字节数 = (count + 7) / 8，防止无限循环越界读取
                let max_bytes = ((count as usize) + 7) / 8;
                let mut byte_idx: usize = 0;
                while found < count && byte_idx < max_bytes {
                    let b = unsafe { *bits_ptr.add(byte_idx) };
                    if b != 0 {
                        for bit_idx in 0..8u16 {
                            if found >= count {
                                break;
                            }
                            if (b & (1 << bit_idx)) != 0 {
                                slaves.push(byte_idx as u16 * 8 + bit_idx);
                                found += 1;
                            }
                        }
                    }
                    byte_idx += 1;
                }
                callback(master, slaves);
            });
            list.push(cb);
        }
    }

    /// 注册 PreOp 重配置回调 (热插拔恢复后重新应用启动参数)
    ///
    /// 回调参数: (master_index, slave_index)
    pub fn on_preop_reconfig<F>(&self, callback: F)
    where
        F: Fn(u16, u16) + Send + 'static,
    {
        if let Ok(mut list) = preop_reconfig_list().lock() {
            list.push(Box::new(callback));
        }
    }

    /// 注册从站身份不符回调 (v2 热插拔自修复)
    ///
    /// 回调参数: [`SlaveIdentityMismatch`] 结构体, 包含 expected/actual 各三元组。
    ///
    /// 触发时机: 断电重插从站后 ident FSM 读取到的 Vendor/Product 与配置不匹配,
    /// 或 Revision 低于配置。进入 IDENT_REJECTED 状态期间仅触发一次, 用户调用
    /// [`crate::master::core::EtherCATMaster::acknowledge_slave_replacement`]
    /// 后才会重新探测并可能再次触发。
    pub fn on_slave_identity_mismatch<F>(&self, callback: F)
    where
        F: Fn(SlaveIdentityMismatch) + Send + 'static,
    {
        if let Ok(mut list) = slave_identity_mismatch_list().lock() {
            list.push(Box::new(callback));
        }
    }

    /// 注册从站端口链路变化回调 (断线检测)
    ///
    /// 回调参数: (master_index, slave_index, port, is_up)
    /// - `port`: 0-3 对应 P0/P1/P2/P3
    /// - `is_up`: true = link 恢复, false = link 断开
    ///
    /// 每 1 秒诊断周期检测 DL Status (0x0110) 的 port link bit,
    /// 从 1→0 触发"断开", 从 0→1 触发"恢复", 每次翻转触发一次 (不重复)。
    pub fn on_slave_port_link_changed<F>(&self, callback: F)
    where
        F: Fn(u16, u16, u8, bool) + Send + 'static,
    {
        if let Ok(mut list) = slave_port_link_changed_list().lock() {
            list.push(Box::new(callback));
        }
    }

    /// 清除所有事件订阅，防止内存泄漏
    ///
    /// 移除所有已注册的回调函数。适用于主站重新初始化或程序退出前的清理。
    pub fn clear_all(&self) {
        if let Ok(mut list) = pdo_cyclic_sync().lock() { list.clear(); }
        if let Ok(mut list) = pdo_cyclic_async().lock() { list.clear(); }
        if let Ok(mut list) = slave_state_change_list().lock() { list.clear(); }
        if let Ok(mut list) = slave_state_change_async_list().lock() { list.clear(); }
        if let Ok(mut list) = emergency_list().lock() { list.clear(); }
        if let Ok(mut list) = slave_discovery_list().lock() { list.clear(); }
        if let Ok(mut list) = slave_discovery_async_list().lock() { list.clear(); }
        if let Ok(mut list) = pdo_frame_loss_list().lock() { list.clear(); }
        if let Ok(mut list) = dc_sync_lost_list().lock() { list.clear(); }
        if let Ok(mut list) = redundancy_changed_list().lock() { list.clear(); }
        if let Ok(mut list) = input_changed_list().lock() { list.clear(); }
        if let Ok(mut list) = preop_reconfig_list().lock() { list.clear(); }
        if let Ok(mut list) = slave_identity_mismatch_list().lock() { list.clear(); }
        if let Ok(mut list) = slave_port_link_changed_list().lock() { list.clear(); }
        if let Ok(mut set) = offline_slaves().lock() { set.clear(); }
    }

    /// 查询从站是否处于离线状态
    pub fn is_slave_offline(&self, slave_index: u16) -> bool {
        if let Ok(set) = offline_slaves().lock() {
            set.contains(&slave_index)
        } else {
            false
        }
    }

    /// 获取所有离线从站索引
    pub fn offline_slaves(&self) -> Vec<u16> {
        if let Ok(set) = offline_slaves().lock() {
            set.iter().copied().collect()
        } else {
            Vec::new()
        }
    }

    /// 获取离线从站数量
    pub fn offline_slave_count(&self) -> usize {
        if let Ok(set) = offline_slaves().lock() {
            set.len()
        } else {
            0
        }
    }
}

// ===================== SlaveEvents =====================

/// 从站事件集合
///
/// 通过 `Slave::events()` 获取实例。
/// 事件自动过滤到当前从站, 回调参数不含 master_index/slave_index。
pub struct SlaveEvents {
    _master_index: u16,
    slave_index: u16,
}

impl SlaveEvents {
    /// 创建从站事件集合 (内部使用)
    pub(crate) fn new(master_index: u16, slave_index: u16) -> Self {
        initialize_callbacks();
        Self { _master_index: master_index, slave_index }
    }

    /// 注册从站状态变化回调
    ///
    /// 回调参数: (old_state, new_state)
    pub fn on_state_changed<F>(&self, callback: F)
    where
        F: Fn(i32, i32) + Send + 'static,
    {
        let target_slave = self.slave_index;
        if let Ok(mut list) = slave_state_change_list().lock() {
            list.push(Box::new(move |_master, slave, old_state, new_state| {
                if slave == target_slave {
                    callback(old_state, new_state);
                }
            }));
        }
    }

    /// 注册紧急事件回调 (EMCY)
    ///
    /// 回调参数: (error_code, error_reg, b1, w1, w2)
    pub fn on_emergency<F>(&self, callback: F)
    where
        F: Fn(u16, u16, u8, u16, u16) + Send + 'static,
    {
        let target_slave = self.slave_index;
        if let Ok(mut list) = emergency_list().lock() {
            list.push(Box::new(move |_master, slave, ec, er, b1, w1, w2| {
                if slave == target_slave {
                    callback(ec, er, b1, w1, w2);
                }
            }));
        }
    }

    /// 注册从站离线回调
    pub fn on_offline<F>(&self, callback: F)
    where
        F: Fn() + Send + 'static,
    {
        let target_slave = self.slave_index;
        if let Ok(mut list) = slave_discovery_list().lock() {
            list.push(Box::new(move |_master, slave, found| {
                if slave == target_slave && !found {
                    callback();
                }
            }));
        }
    }

    /// 注册从站上线回调
    pub fn on_online<F>(&self, callback: F)
    where
        F: Fn() + Send + 'static,
    {
        let target_slave = self.slave_index;
        if let Ok(mut list) = slave_discovery_list().lock() {
            list.push(Box::new(move |_master, slave, found| {
                if slave == target_slave && found {
                    callback();
                }
            }));
        }
    }

    /// 注册 DC 同步丢失回调
    ///
    /// 回调参数: (diff_ns)
    pub fn on_dc_sync_lost<F>(&self, callback: F)
    where
        F: Fn(i32) + Send + 'static,
    {
        let target_slave = self.slave_index;
        if let Ok(mut list) = dc_sync_lost_list().lock() {
            list.push(Box::new(move |_master, slave, diff_ns| {
                if slave == target_slave {
                    callback(diff_ns);
                }
            }));
        }
    }

    /// 清除所有事件订阅，防止内存泄漏
    ///
    /// 注意: 由于全局回调列表是共享的，此方法会清除所有回调 (包括其他从站的)。
    /// 如果需要精确清理，建议使用 `MasterEvents::clear_all()` 统一清理。
    pub fn clear_all(&self) {
        if let Ok(mut list) = slave_state_change_list().lock() { list.clear(); }
        if let Ok(mut list) = emergency_list().lock() { list.clear(); }
        if let Ok(mut list) = slave_discovery_list().lock() { list.clear(); }
        if let Ok(mut list) = dc_sync_lost_list().lock() { list.clear(); }
        if let Ok(mut list) = input_changed_list().lock() { list.clear(); }
    }

    /// 注册输入数据变化回调
    ///
    /// 当此从站的输入 PDO 数据变化时触发 (DLL 层 memcmp 检测)
    pub fn on_input_changed<F>(&self, callback: F)
    where
        F: Fn() + Send + 'static,
    {
        let target_slave = self.slave_index;
        if let Ok(mut list) = input_changed_list().lock() {
            list.push(Box::new(move |_master, bits_ptr, count| {
                if bits_ptr.is_null() || count == 0 {
                    return;
                }
                // 修复: 检查位图边界，防止越界读取
                let byte_idx = (target_slave / 8) as usize;
                let max_bytes = ((count as usize) + 7) / 8;
                if byte_idx >= max_bytes {
                    return;
                }
                let bit_idx = target_slave % 8;
                let b = unsafe { *bits_ptr.add(byte_idx) };
                if (b & (1 << bit_idx)) != 0 {
                    callback();
                }
            }));
        }
    }
}
