//! FSoE 高级功能：CRC16、多连接管理器、MDP 封装
//!
//! 实现 ETG.5001.4 CCITT-False CRC16 校验算法，
//! 以及多 FSoE 连接的统一管理接口，并封装所有 SafeMdp* FFI 函数。

use std::collections::HashMap;
use std::sync::{Arc, Mutex};
use std::time::SystemTime;
use crate::data::error::{DarraError, Result};
use crate::utils::ffi::{self, FsoeConfig, SafeMdpConfig, FsoeStatus, FsoeState, FsoeError};

// ===================== CCITT-False CRC16 =====================

/// CCITT-False CRC16 计算器 (多项式 0x1021, 初始值 0xFFFF, 不反射)
///
/// 符合 ETG.5001.4 第 7.2 节规范，用于验证 FSoE 安全帧完整性。
pub struct FsoeCrc16;

impl FsoeCrc16 {
    /// 预计算查找表（编译期固定，避免运行时重复计算）
    const TABLE: [u16; 256] = Self::build_table();

    const fn build_table() -> [u16; 256] {
        let mut table = [0u16; 256];
        let mut i = 0usize;
        while i < 256 {
            let mut crc = (i as u16) << 8;
            let mut j = 0;
            while j < 8 {
                if (crc & 0x8000) != 0 {
                    crc = (crc << 1) ^ 0x1021;
                } else {
                    crc <<= 1;
                }
                j += 1;
            }
            table[i] = crc;
            i += 1;
        }
        table
    }

    /// 计算字节切片的 CCITT-False CRC16
    pub fn compute(data: &[u8]) -> u16 {
        let mut crc: u16 = 0xFFFF;
        for &byte in data {
            let idx = (((crc >> 8) as u8) ^ byte) as usize;
            crc = (crc << 8) ^ Self::TABLE[idx];
        }
        crc
    }

    /// 增量更新 CRC（用于分段数据流）
    pub fn update(crc: u16, data: &[u8]) -> u16 {
        let mut crc = crc;
        for &byte in data {
            let idx = (((crc >> 8) as u8) ^ byte) as usize;
            crc = (crc << 8) ^ Self::TABLE[idx];
        }
        crc
    }

    /// 验证数据末尾附带的 CRC16（小端序）
    ///
    /// data 最后 2 字节为期望的 CRC16（小端），
    /// 对 data[..len-2] 计算 CRC 并与末尾比较。
    pub fn verify(data: &[u8]) -> bool {
        if data.len() < 2 {
            return false;
        }
        let payload = &data[..data.len() - 2];
        let expected = u16::from_le_bytes([data[data.len() - 2], data[data.len() - 1]]);
        Self::compute(payload) == expected
    }

    /// 在数据末尾追加 CRC16（小端序）并返回新的 Vec
    pub fn append(data: &[u8]) -> Vec<u8> {
        let crc = Self::compute(data);
        let mut out = data.to_vec();
        out.extend_from_slice(&crc.to_le_bytes());
        out
    }
}

// ===================== FSoE 连接信息 =====================

/// 单个 FSoE 连接的运行时信息
#[derive(Debug, Clone)]
pub struct FsoeConnectionInfo {
    /// 从站索引
    pub slave_index: u16,
    /// 连接配置（拷贝）
    pub config: FsoeConfig,
    /// 最近一次状态快照
    pub last_status: Option<FsoeStatus>,
}

// ===================== FSoE 多连接管理器 =====================

/// FSoE 多连接管理器
///
/// 统一管理一个主站上的所有 FSoE 连接，
/// 提供批量状态查询、全局失效安全控制等高层接口。
pub struct SafetyManager {
    /// 主站索引
    master_index: u16,
    /// 连接表：key = 从站索引
    connections: HashMap<u16, FsoeConnectionInfo>,
}

impl SafetyManager {
    /// 创建新的 FSoE 管理器
    pub fn new(master_index: u16) -> Self {
        Self {
            master_index,
            connections: HashMap::new(),
        }
    }

    /// 初始化指定从站的 FSoE 连接并加入管理
    pub fn add_connection(&mut self, slave_index: u16, config: FsoeConfig) -> Result<()> {
        let mut cfg = config;
        let ret = unsafe {
            ffi::FSoEInitConnection(self.master_index, slave_index, &mut cfg)
        };
        // DLL 返回 非零=成功, 0=失败 (与 C# bool 约定一致)
        if ret == 0 {
            return Err(DarraError::Other(format!(
                "FSoE 连接初始化失败 (从站: {})", slave_index
            )));
        }
        self.connections.insert(slave_index, FsoeConnectionInfo {
            slave_index,
            config: cfg,
            last_status: None,
        });
        Ok(())
    }

    /// 关闭并移除指定从站的 FSoE 连接
    pub fn remove_connection(&mut self, slave_index: u16) -> Result<()> {
        let ret = unsafe {
            ffi::FSoECloseConnection(self.master_index, slave_index)
        };
        self.connections.remove(&slave_index);
        // DLL 返回 非零=成功, 0=失败
        if ret == 0 {
            Err(DarraError::Other(format!(
                "FSoE 连接关闭失败 (从站: {})", slave_index
            )))
        } else {
            Ok(())
        }
    }

    /// 刷新并返回所有连接的状态快照
    pub fn refresh_all_status(&mut self) -> HashMap<u16, FsoeStatus> {
        let mut result = HashMap::new();
        let keys: Vec<u16> = self.connections.keys().copied().collect();
        for slave in keys {
            let mut status = FsoeStatus {
                state: FsoeState::Reset,
                last_error: FsoeError::None,
                error_count: 0,
                frames_sent: 0,
                frames_received: 0,
                crc_errors: 0,
                watchdog_errors: 0,
                watchdog_expired: 0,
                in_failsafe: 0,
                toggle_bit: 0,
                initialized: 0,
            };
            let ret = unsafe {
                ffi::FSoEGetStatus(self.master_index, slave, &mut status)
            };
            if ret != 0 {
                if let Some(info) = self.connections.get_mut(&slave) {
                    info.last_status = Some(status);
                }
                result.insert(slave, status);
            }
        }
        result
    }

    /// 获取所有连接的安全输入数据 (slave_index -> data)
    ///
    /// 返回能成功读取的连接数据，读取失败的连接跳过。
    pub fn all_in_data(&self) -> HashMap<u16, Vec<u8>> {
        let mut result = HashMap::new();
        for (&slave, info) in &self.connections {
            let size = info.config.safe_input_size as usize;
            if size == 0 { continue; }
            let mut buf = vec![0u8; size];
            let mut actual_size = size as u32;
            let ret = unsafe {
                ffi::FSoEReadSafeInput(self.master_index, slave, buf.as_mut_ptr(), &mut actual_size)
            };
            if ret != 0 {
                buf.truncate(actual_size as usize);
                result.insert(slave, buf);
            }
        }
        result
    }

    /// 检查是否有任何连接处于失效安全状态
    pub fn any_in_failsafe(&mut self) -> bool {
        let statuses = self.refresh_all_status();
        statuses.values().any(|s| s.in_failsafe != 0)
    }

    /// 将所有连接强制进入失效安全模式
    ///
    /// 向每个连接发送空的失效安全输出（全零），触发从站进入 Failsafe 状态。
    pub fn enter_all_failsafe(&self) -> Vec<(u16, Result<()>)> {
        let mut results = Vec::new();
        for (&slave, info) in &self.connections {
            let size = info.config.safe_output_size as usize;
            let zeros = vec![0u8; size];
            let ret = unsafe {
                ffi::FSoESetFailsafeOutput(self.master_index, slave, zeros.as_ptr(), size as u32)
            };
            let result = if ret != 0 {
                Ok(())
            } else {
                Err(DarraError::Other(format!(
                    "从站 {} 进入失效安全失败 (返回码: {})", slave, ret
                )))
            };
            results.push((slave, result));
        }
        results
    }

    /// 执行一次 FSoE 帧处理周期 (由 PDO 循环回调调用)
    pub fn process_cycle(&self) {
        unsafe { ffi::FSoEProcessCycle(self.master_index) };
    }

    /// 获取当前管理的连接数量
    pub fn connection_count(&self) -> usize {
        self.connections.len()
    }

    /// 获取 DLL 内部记录的连接总数
    pub fn dll_connection_count(&self) -> u16 {
        unsafe { ffi::FSoEGetConnectionCount(self.master_index) }
    }

    /// 检查指定从站是否支持 FSoE
    pub fn is_slave_capable(&self, slave_index: u16) -> bool {
        unsafe { ffi::FSoEIsSlaveCapable(self.master_index, slave_index) != 0 }
    }

    /// 指定从站的当前 FSoE 状态
    pub fn state(&self, slave_index: u16) -> Option<FsoeState> {
        let raw = unsafe { ffi::FSoEGetState(self.master_index, slave_index) };
        // 将 i32 映射到 FsoeState 枚举
        match raw {
            0x100 => Some(FsoeState::Reset),
            0x101 => Some(FsoeState::Session),
            0x102 => Some(FsoeState::Connection),
            0x103 => Some(FsoeState::Parameter),
            0x104 => Some(FsoeState::Data),
            0x105 => Some(FsoeState::Failsafe),
            _ => None,
        }
    }

    /// 向指定从站写入安全输出数据
    pub fn write_safe_output(&self, slave_index: u16, data: &[u8]) -> Result<()> {
        let ret = unsafe {
            ffi::FSoEWriteSafeOutput(self.master_index, slave_index, data.as_ptr(), data.len() as u32)
        };
        if ret != 0 { Ok(()) } else {
            Err(DarraError::Other(format!("FSoE 安全输出写入失败 (从站: {})", slave_index)))
        }
    }

    /// 下载安全参数到指定从站（在 PARAMETER 状态调用）
    pub fn download_parameters(&self, slave_index: u16, params: &[u8]) -> Result<u32> {
        let mut sra_crc: u32 = 0;
        let ret = unsafe {
            ffi::FSoEDownloadParameters(
                self.master_index, slave_index,
                params.as_ptr(), params.len() as u32, &mut sra_crc,
            )
        };
        if ret != 0 { Ok(sra_crc) } else {
            Err(DarraError::Other(format!("FSoE 参数下载失败 (从站: {})", slave_index)))
        }
    }

    /// 重置指定从站的 FSoE 连接
    pub fn reset_connection(&self, slave_index: u16) -> Result<()> {
        let ret = unsafe { ffi::FSoEReset(self.master_index, slave_index) };
        if ret != 0 { Ok(()) } else {
            Err(DarraError::Other(format!("FSoE 连接重置失败 (从站: {})", slave_index)))
        }
    }

    /// 清除指定从站的 FSoE 错误
    pub fn clear_error(&self, slave_index: u16) {
        unsafe { ffi::FSoEClearError(self.master_index, slave_index) };
    }

    /// 按安全地址查找连接
    ///
    /// 对应 C# FindByAddress
    pub fn find_by_address(&self, safety_address: u16) -> Option<u16> {
        for (&slave, info) in &self.connections {
            if info.config.safety_address == safety_address {
                return Some(slave);
            }
        }
        None
    }

    /// 按连接 ID 查找连接
    ///
    /// 对应 C# FindByConnectionId
    pub fn find_by_connection_id(&self, connection_id: u16) -> Option<u16> {
        for (&slave, info) in &self.connections {
            if info.config.connection_id == connection_id {
                return Some(slave);
            }
        }
        None
    }

    /// 按安全地址查找连接 (Manager 级别)
    ///
    /// 对应 C# FindConnectionByAddress
    pub fn find_connection_by_address(&self, safety_address: u16) -> Option<u16> {
        self.find_by_address(safety_address)
    }

    /// 绑定安全输入
    ///
    /// 对应 C# BindSafeInput
    pub fn bind_safe_input(&mut self, slave_index: u16, safety_address: u16,
                            input_size: u16, watchdog_ms: u32) -> Result<()> {
        let config = FsoeConfig {
            connection_id: slave_index + 1,
            safety_address,
            watchdog_time_ms: watchdog_ms,
            safe_input_size: input_size,
            safe_output_size: 0,
            pdo_input_offset: 0,
            pdo_output_offset: 0,
        };
        self.add_connection(slave_index, config)
    }

    /// 绑定安全输出
    ///
    /// 对应 C# BindSafeOutput
    pub fn bind_safe_output(&mut self, slave_index: u16, safety_address: u16,
                             output_size: u16, watchdog_ms: u32) -> Result<()> {
        let config = FsoeConfig {
            connection_id: slave_index + 1,
            safety_address,
            watchdog_time_ms: watchdog_ms,
            safe_input_size: 0,
            safe_output_size: output_size,
            pdo_input_offset: 0,
            pdo_output_offset: 0,
        };
        self.add_connection(slave_index, config)
    }

    /// 同时绑定安全输入和安全输出
    ///
    /// 对应 C# BindSafeIO
    ///
    /// # 参数
    /// - `slave_index`: 从站索引
    /// - `safe_input_offset`: 输入PDO中安全数据的字节偏移
    /// - `safe_input_size`: 安全输入数据大小 (字节)
    /// - `safe_output_offset`: 输出PDO中安全数据的字节偏移
    /// - `safe_output_size`: 安全输出数据大小 (字节)
    /// - `safety_address`: 安全地址
    /// - `watchdog_ms`: 看门狗超时 (毫秒)
    pub fn bind_safe_io(&mut self, slave_index: u16,
                        safe_input_offset: u32, safe_input_size: u16,
                        safe_output_offset: u32, safe_output_size: u16,
                        safety_address: u16, watchdog_ms: u32) -> Result<()> {
        let config = FsoeConfig {
            connection_id: slave_index + 1,
            safety_address,
            watchdog_time_ms: watchdog_ms,
            safe_input_size,
            safe_output_size,
            pdo_input_offset: safe_input_offset,
            pdo_output_offset: safe_output_offset,
        };
        self.add_connection(slave_index, config)
    }

    /// MDP 驱动轴安全绑定 (自动从 MDP 模块信息发现安全 PDO 偏移)
    ///
    /// 对应 C# BindMdpDriveAxis
    ///
    /// # 参数
    /// - `slave_index`: 从站索引
    /// - `axis_index`: MDP 轴/模块索引
    /// - `safety_address`: 安全地址
    /// - `watchdog_ms`: 看门狗超时 (毫秒)
    pub fn bind_mdp_drive_axis(&mut self, slave_index: u16, axis_index: u16,
                               safety_address: u16, watchdog_ms: u32) -> Result<()> {
        // 通过 MDP 模块索引查询安全 PDO 偏移和大小
        let conn_index = axis_index + 1;
        let mdp = SafeMdp::new(self.master_index, slave_index);
        // 安全数据大小由 DLL 从 MDP 模块信息自动发现
        let config = SafeMdpConfig {
            connection_id: conn_index,
            safety_address,
            watchdog_time_ms: watchdog_ms,
            safe_input_size: 0,
            safe_output_size: 0,
            pdo_input_offset: 0,
            pdo_output_offset: 0,
            module_number: axis_index,
            module_profile: 790, // FSoE Drive Connection
            axis_number: axis_index,
            connection_type: 0,
        };
        mdp.init_connection(conn_index, config)
    }

    /// 写入 FSoE 原始输出帧 (对应 C# WriteOutputFrame)
    ///
    /// 将完整的 FSoE 输出帧数据写入指定从站的安全输出区域。
    pub fn write_output_frame(&self, slave_index: u16, frame_data: &[u8]) -> bool {
        if frame_data.is_empty() {
            return false;
        }
        if !self.connections.contains_key(&slave_index) {
            return false;
        }
        let ret = unsafe {
            ffi::FSoEWriteSafeOutput(
                self.master_index, slave_index,
                frame_data.as_ptr(), frame_data.len() as u32,
            )
        };
        ret != 0
    }

    /// 读取指定从站的原始输入帧
    ///
    /// 对应 C# ReadInputFrame
    pub fn read_input_frame(&self, slave_index: u16, buffer_size: usize) -> Option<Vec<u8>> {
        let info = self.connections.get(&slave_index)?;
        let read_size = if buffer_size > 0 {
            buffer_size
        } else {
            info.config.safe_input_size as usize
        };
        if read_size == 0 {
            return None;
        }
        let mut buf = vec![0u8; read_size];
        let mut actual_size = buf.len() as u32;
        let ret = unsafe {
            ffi::FSoEReadSafeInput(
                self.master_index, slave_index,
                buf.as_mut_ptr(), &mut actual_size,
            )
        };
        if ret != 0 && actual_size > 0 {
            buf.truncate(actual_size as usize);
            Some(buf)
        } else {
            None
        }
    }

    /// 返回所有连接的状态摘要字符串
    ///
    /// 对应 C# GetStatusSummary
    pub fn status_summary(&self) -> String {
        if self.connections.is_empty() {
            return "未初始化".to_string();
        }
        let mut lines = vec![format!("FSoE Manager: 连接数={}", self.connections.len())];
        for (&slave, info) in &self.connections {
            let state = self.state(slave)
                .map(|s| format!("{:?}", s))
                .unwrap_or_else(|| "未知".to_string());
            lines.push(format!("  连接[从站={}]: 状态={}, 地址=0x{:04X}",
                slave, state, info.config.safety_address));
        }
        lines.join("\n")
    }
}

impl Drop for SafetyManager {
    /// 销毁时关闭所有连接
    fn drop(&mut self) {
        let keys: Vec<u16> = self.connections.keys().copied().collect();
        for slave in keys {
            unsafe { ffi::FSoECloseConnection(self.master_index, slave) };
        }
    }
}

// ===================== FSoE MDP 封装 =====================

/// FSoE MDP (Multi-Device Profile) 连接管理
///
/// MDP 设备支持在单个从站上承载多个独立的 FSoE 连接（模块），
/// 典型场景如安全 I/O 模块、安全驱动器。
pub struct SafeMdp {
    /// 主站索引
    master_index: u16,
    /// 从站索引
    slave_index: u16,
}

impl SafeMdp {
    /// 创建 MDP 封装实例
    pub fn new(master_index: u16, slave_index: u16) -> Self {
        Self { master_index, slave_index }
    }

    /// 探测从站支持的 FSoE MDP 连接数量
    pub fn detect_connections(&self) -> u16 {
        unsafe { ffi::SafeMdpDetectConnections(self.master_index, self.slave_index) }
    }

    /// 获取从站已配置的 MDP 连接数
    pub fn slave_connection_count(&self) -> u16 {
        unsafe { ffi::SafeMdpGetSlaveConnectionCount(self.master_index, self.slave_index) }
    }

    /// 读取从站设备级 FSoE 安全地址 (0xF980:01)
    pub fn device_address(&self) -> Result<u16> {
        let mut safety_addr: u16 = 0;
        let ret = unsafe {
            ffi::SafeMdpGetDeviceAddress(self.master_index, self.slave_index, &mut safety_addr)
        };
        if ret != 0 { Ok(safety_addr) } else {
            Err(DarraError::Other(format!(
                "读取 MDP 设备地址失败 (从站: {})", self.slave_index
            )))
        }
    }

    /// 初始化指定模块的 FSoE MDP 连接
    pub fn init_connection(&self, connection_index: u16, config: SafeMdpConfig) -> Result<()> {
        let mut cfg = config;
        let ret = unsafe {
            ffi::SafeMdpInitConnection(
                self.master_index, self.slave_index, connection_index, &mut cfg,
            )
        };
        if ret != 0 { Ok(()) } else {
            Err(DarraError::Other(format!(
                "FSoE MDP 连接 {} 初始化失败 (从站: {})", connection_index, self.slave_index
            )))
        }
    }

    /// 关闭指定模块的 FSoE MDP 连接
    pub fn close_connection(&self, connection_index: u16) -> Result<()> {
        let ret = unsafe {
            ffi::SafeMdpCloseConnection(self.master_index, self.slave_index, connection_index)
        };
        if ret != 0 { Ok(()) } else {
            Err(DarraError::Other(format!(
                "FSoE MDP 连接 {} 关闭失败 (从站: {})", connection_index, self.slave_index
            )))
        }
    }

    /// 指定连接的状态
    pub fn status(&self, connection_index: u16) -> Result<FsoeStatus> {
        let mut status = FsoeStatus {
            state: FsoeState::Reset,
            last_error: FsoeError::None,
            error_count: 0,
            frames_sent: 0,
            frames_received: 0,
            crc_errors: 0,
            watchdog_errors: 0,
            watchdog_expired: 0,
            in_failsafe: 0,
            toggle_bit: 0,
            initialized: 0,
        };
        let ret = unsafe {
            ffi::SafeMdpGetStatus(
                self.master_index, self.slave_index, connection_index, &mut status,
            )
        };
        if ret != 0 { Ok(status) } else {
            Err(DarraError::Other(format!(
                "获取 FSoE MDP 连接 {} 状态失败 (从站: {})", connection_index, self.slave_index
            )))
        }
    }

    /// 请求指定连接的状态转换
    pub fn request_state(&self, connection_index: u16, target_state: FsoeState) -> Result<()> {
        let ret = unsafe {
            ffi::SafeMdpRequestState(
                self.master_index, self.slave_index, connection_index, target_state as i32,
            )
        };
        if ret != 0 { Ok(()) } else {
            Err(DarraError::Other(format!(
                "FSoE MDP 连接 {} 状态请求失败", connection_index
            )))
        }
    }

    /// 指定连接的当前状态
    pub fn state(&self, connection_index: u16) -> Option<FsoeState> {
        let raw = unsafe {
            ffi::SafeMdpGetState(self.master_index, self.slave_index, connection_index)
        };
        match raw {
            0x100 => Some(FsoeState::Reset),
            0x101 => Some(FsoeState::Session),
            0x102 => Some(FsoeState::Connection),
            0x103 => Some(FsoeState::Parameter),
            0x104 => Some(FsoeState::Data),
            0x105 => Some(FsoeState::Failsafe),
            _ => None,
        }
    }

    /// 重置指定连接
    pub fn reset(&self, connection_index: u16) -> Result<()> {
        let ret = unsafe {
            ffi::SafeMdpReset(self.master_index, self.slave_index, connection_index)
        };
        if ret != 0 { Ok(()) } else {
            Err(DarraError::Other(format!(
                "FSoE MDP 连接 {} 重置失败", connection_index
            )))
        }
    }

    /// 写入指定连接的安全输出数据
    pub fn write_safe_output(&self, connection_index: u16, data: &[u8]) -> Result<()> {
        let ret = unsafe {
            ffi::SafeMdpWriteSafeOutput(
                self.master_index, self.slave_index, connection_index,
                data.as_ptr(), data.len() as u32,
            )
        };
        if ret != 0 { Ok(()) } else {
            Err(DarraError::Other(format!(
                "FSoE MDP 连接 {} 安全输出写入失败", connection_index
            )))
        }
    }

    /// 读取指定连接的安全输入数据
    pub fn read_safe_input(&self, connection_index: u16, max_size: usize) -> Result<Vec<u8>> {
        let mut buf = vec![0u8; max_size];
        let mut actual_size = max_size as u32;
        let ret = unsafe {
            ffi::SafeMdpReadSafeInput(
                self.master_index, self.slave_index, connection_index,
                buf.as_mut_ptr(), &mut actual_size,
            )
        };
        if ret != 0 {
            buf.truncate(actual_size as usize);
            Ok(buf)
        } else {
            Err(DarraError::Other(format!(
                "FSoE MDP 连接 {} 安全输入读取失败", connection_index
            )))
        }
    }

    /// 下载指定连接的安全参数，返回 SRA CRC
    pub fn download_parameters(&self, connection_index: u16, params: &[u8]) -> Result<u32> {
        let mut sra_crc: u32 = 0;
        let ret = unsafe {
            ffi::SafeMdpDownloadParameters(
                self.master_index, self.slave_index, connection_index,
                params.as_ptr(), params.len() as u32, &mut sra_crc,
            )
        };
        if ret != 0 { Ok(sra_crc) } else {
            Err(DarraError::Other(format!(
                "FSoE MDP 连接 {} 参数下载失败", connection_index
            )))
        }
    }

    /// 设置指定连接的失效安全输出值
    pub fn set_failsafe_output(&self, connection_index: u16, data: &[u8]) -> Result<()> {
        let ret = unsafe {
            ffi::SafeMdpSetFailsafeOutput(
                self.master_index, self.slave_index, connection_index,
                data.as_ptr(), data.len() as u32,
            )
        };
        if ret != 0 { Ok(()) } else {
            Err(DarraError::Other(format!(
                "FSoE MDP 连接 {} 失效安全输出设置失败", connection_index
            )))
        }
    }

    /// 检查指定连接的看门狗状态
    pub fn check_watchdog(&self, connection_index: u16) -> bool {
        unsafe {
            ffi::SafeMdpCheckWatchdog(self.master_index, self.slave_index, connection_index) != 0
        }
    }

    /// 获取指定连接的最后错误代码
    pub fn last_error(&self, connection_index: u16) -> i32 {
        unsafe {
            ffi::SafeMdpGetLastError(self.master_index, self.slave_index, connection_index)
        }
    }

    /// 清除指定连接的错误
    pub fn clear_error(&self, connection_index: u16) {
        unsafe {
            ffi::SafeMdpClearError(self.master_index, self.slave_index, connection_index)
        };
    }

    /// 读取指定模块的通信参数 (0x9nn1)
    pub fn module_comm_param(&self, module_number: u16) -> Result<Vec<u8>> {
        let mut buf = vec![0u8; 256];
        let mut size: u32 = 256;
        let ret = unsafe {
            ffi::SafeMdpGetModuleCommParam(
                self.master_index, self.slave_index, module_number,
                buf.as_mut_ptr(), &mut size,
            )
        };
        if ret != 0 {
            buf.truncate(size as usize);
            Ok(buf)
        } else {
            Err(DarraError::Other(format!(
                "读取 MDP 模块 {} 通信参数失败", module_number
            )))
        }
    }

    /// 读取指定模块的诊断数据 (0xAnn0)
    ///
    /// 返回 (连接状态, 连接诊断)
    pub fn module_diagnosis(&self, module_number: u16) -> Result<(u16, u16)> {
        let mut conn_state: u16 = 0;
        let mut conn_diag: u16 = 0;
        let ret = unsafe {
            ffi::SafeMdpGetModuleDiagnosis(
                self.master_index, self.slave_index, module_number,
                &mut conn_state, &mut conn_diag,
            )
        };
        if ret != 0 { Ok((conn_state, conn_diag)) } else {
            Err(DarraError::Other(format!(
                "读取 MDP 模块 {} 诊断数据失败", module_number
            )))
        }
    }
}

impl std::fmt::Debug for SafeMdp {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_struct("SafeMdp")
            .field("master_index", &self.master_index)
            .field("slave_index", &self.slave_index)
            .finish()
    }
}

// ===================== FSoE 高级枚举和结构体 =====================

/// FSoE 命令类型 (ETG.5100)
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[repr(u8)]
pub enum FsoeCommand {
    /// 重置命令
    Reset = 0x00,
    /// 会话请求/响应
    Session = 0x01,
    /// 连接请求/响应
    Connection = 0x02,
    /// 参数下载
    Parameter = 0x03,
    /// 失效安全模式
    Failsafe = 0x04,
    /// 正常数据交换
    Data = 0x05,
}

/// FSoE 失效安全触发原因
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum FsoeFailsafeReason {
    /// 看门狗超时
    WatchdogTimeout,
    /// CRC错误
    CrcError,
    /// 通信错误
    CommunicationError,
    /// 应用请求
    ApplicationRequest,
    /// 从站请求
    SlaveRequest,
    /// 主站请求
    MasterRequest,
    /// 恢复到数据模式
    RecoveryToData,
}

/// FSoE 连接模式
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum FsoeConnectionMode {
    /// 单连接模式 - 所有模块共用一个 FSoE 连接和安全地址
    Single,
    /// 多连接模式 - 每个模块有独立的 FSoE 连接和安全地址
    Multiple,
}

/// FSoE 连接类型 (ETG.5120 SI6)
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[repr(u16)]
pub enum FsoeConnectionType {
    /// FSoE 主站连接
    Master = 0,
    /// FSoE 从站连接
    Slave = 1,
}

/// FSoE MDP 模块配置文件编号 (ETG.5001.4)
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[repr(u16)]
pub enum SafeModuleProfile {
    /// FSoE Digital Input
    DigitalInput = 190,
    /// FSoE Digital In-/Output
    DigitalInOut = 195,
    /// FSoE Digital Output
    DigitalOutput = 290,
    /// FSoE MDP Drive Connection
    DriveConnection = 790,
    /// FSoE Master
    Master = 6900,
}

/// FSoE 连接配置
#[derive(Clone, Debug)]
pub struct FsoeConnectionConfig {
    /// 唯一连接标识符
    pub connection_id: u16,
    /// FSoE从站安全地址
    pub safety_address: u16,
    /// 看门狗超时(毫秒)
    pub watchdog_time_ms: u32,
    /// 安全输入数据大小(字节)
    pub safe_input_size: u16,
    /// 安全输出数据大小(字节)
    pub safe_output_size: u16,
    /// IOmap中输入偏移
    pub pdo_input_offset: u32,
    /// IOmap中输出偏移
    pub pdo_output_offset: u32,
}

impl Default for FsoeConnectionConfig {
    fn default() -> Self {
        Self {
            connection_id: 0,
            safety_address: 0,
            watchdog_time_ms: 100,
            safe_input_size: 0,
            safe_output_size: 0,
            pdo_input_offset: 0,
            pdo_output_offset: 0,
        }
    }
}

/// FSoE 连接状态
#[derive(Clone, Debug)]
pub struct FsoeConnectionStatus {
    /// 当前FSoE状态
    pub state: FsoeState,
    /// 最后的错误代码
    pub last_error: FsoeError,
    /// 总错误计数
    pub error_count: u32,
    /// 发送帧数
    pub frames_sent: u32,
    /// 接收有效帧数
    pub frames_received: u32,
    /// CRC错误计数
    pub crc_errors: u32,
    /// 看门狗超时计数
    pub watchdog_errors: u32,
    /// 看门狗是否过期
    pub watchdog_expired: bool,
    /// 是否处于失效安全模式
    pub in_failsafe: bool,
    /// 当前切换位值
    pub toggle_bit: u8,
    /// 连接是否已初始化
    pub is_initialized: bool,
}

/// FSoE 通信参数 (ETG.5120 section 5.2.3)
#[derive(Clone, Debug)]
pub struct FsoeCommParameters {
    /// 连接ID (SI3)
    pub connection_id: u16,
    /// FSoE从站安全地址 (SI2)
    pub safety_address: u16,
    /// 看门狗超时(毫秒) (SI4)
    pub watchdog_time_ms: u32,
    /// 通信参数长度 (SI7)
    pub comm_param_length: u16,
    /// 应用参数长度 (SI8)
    pub app_param_length: u16,
    /// 版本 (SI1)
    pub version: String,
    /// 连接类型 (SI6): 0=Master, 1=Slave
    pub connection_type: u16,
}

impl Default for FsoeCommParameters {
    fn default() -> Self {
        Self {
            connection_id: 0,
            safety_address: 0,
            watchdog_time_ms: 0,
            comm_param_length: 0,
            app_param_length: 0,
            version: "01".to_string(),
            connection_type: 0,
        }
    }
}

// ===================== FSoE 诊断位定义 (ETG.5001.4 Table 9) =====================

/// FSoE 诊断位定义 (ETG.5001.4 Table 9)
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[repr(u16)]
pub enum FsoeDiagnosisBits {
    /// 无错误
    NoError = 0x0000,
    /// 错误的命令
    WrongCommand = 0x0001,
    /// 未知命令
    UnknownCommand = 0x0002,
    /// 连接ID不匹配
    WrongConnectionId = 0x0003,
    /// CRC校验失败
    WrongCrc = 0x0004,
    /// 看门狗过期
    WatchdogExpired = 0x0005,
    /// 错误的FSoE地址
    WrongFsoeAddress = 0x0006,
    /// 无效数据
    WrongData = 0x0007,
    /// 通信参数长度错误
    WrongCommParamLength = 0x0008,
    /// 通信参数错误
    WrongCommParam = 0x0009,
    /// 应用参数长度错误
    WrongApplParamLength = 0x000A,
    /// 应用参数错误
    WrongApplParam = 0x000B,
    /// 意外的会话命令
    UnexpectedSessionCmd = 0x000C,
    /// 收到失效安全数据
    FailsafeDataReceived = 0x000D,
    /// 错误掩码
    ErrorMask = 0x000F,
    /// 错误发生在从站
    ErrorInSlave = 0x0010,
    /// 从站处于失效安全
    SlaveInFailsafe = 0x0020,
    /// 连接处于启动
    ConnectionInStartup = 0x0040,
    /// 主站处于失效安全
    MasterInFailsafe = 0x0080,
}

// ===================== FSoE 常量定义 =====================

/// FSoE 常量定义
pub struct FsoeConstants;

impl FsoeConstants {
    /// 每个主站的最大FSoE连接数
    pub const MAX_CONNECTIONS: u32 = 64;
    /// 每个连接的最大SafeData大小(字节)
    pub const MAX_SAFE_DATA_SIZE: u32 = 64;
    /// 最大CRC段数 (数据大于2字节时)
    pub const MAX_CRC_SEGMENTS: u32 = 32;
    /// FSoE帧头大小 (Command + ConnID)
    pub const FRAME_HEADER_SIZE: u32 = 3;
    /// FSoE帧CRC大小
    pub const FRAME_CRC_SIZE: u32 = 2;
    /// FSoE CRC16多项式 (ETG.5100)
    pub const CRC16_POLY: u16 = 0x1021;
    /// FSoE CRC16初始值
    pub const CRC16_INITIAL: u16 = 0xFFFF;
    /// FSoE SRA CRC32多项式 (ETG.5120 section 6.3)
    pub const SRA_CRC32_POLY: u32 = 0x814141AB;
    /// 默认看门狗超时(毫秒)
    pub const DEFAULT_WATCHDOG_TIME_MS: u32 = 100;
    /// 命令类型掩码
    pub const COMMAND_TYPE_MASK: u8 = 0x0F;
    /// 切换位掩码
    pub const TOGGLE_BIT_MASK: u8 = 0x80;
    /// 主站重置请求掩码
    pub const MASTER_RESET_MASK: u8 = 0x40;
    /// 从站重置请求掩码
    pub const SLAVE_RESET_MASK: u8 = 0x20;
}

// ===================== FSoE 帮助函数 =====================

/// FSoE 帮助函数
pub struct FsoeHelper;

impl FsoeHelper {
    /// 提取命令类型
    pub fn get_command_type(command: u8) -> Option<FsoeCommand> {
        match command & FsoeConstants::COMMAND_TYPE_MASK {
            0x00 => Some(FsoeCommand::Reset),
            0x01 => Some(FsoeCommand::Session),
            0x02 => Some(FsoeCommand::Connection),
            0x03 => Some(FsoeCommand::Parameter),
            0x04 => Some(FsoeCommand::Failsafe),
            0x05 => Some(FsoeCommand::Data),
            _ => None,
        }
    }

    /// 提取切换位
    pub fn get_toggle_bit(command: u8) -> bool {
        (command & FsoeConstants::TOGGLE_BIT_MASK) != 0
    }

    /// 检查是否为主站重置请求
    pub fn is_master_reset_request(command: u8) -> bool {
        (command & FsoeConstants::MASTER_RESET_MASK) != 0
    }

    /// 检查是否为从站重置请求
    pub fn is_slave_reset_request(command: u8) -> bool {
        (command & FsoeConstants::SLAVE_RESET_MASK) != 0
    }

    /// 构建命令字节
    pub fn build_command(
        cmd_type: FsoeCommand,
        toggle_bit: bool,
        master_reset: bool,
        slave_reset: bool,
    ) -> u8 {
        let mut cmd = cmd_type as u8;
        if toggle_bit {
            cmd |= FsoeConstants::TOGGLE_BIT_MASK;
        }
        if master_reset {
            cmd |= FsoeConstants::MASTER_RESET_MASK;
        }
        if slave_reset {
            cmd |= FsoeConstants::SLAVE_RESET_MASK;
        }
        cmd
    }

    /// 检查状态转换是否有效
    pub fn is_valid_state_transition(current: FsoeState, target: FsoeState) -> bool {
        match current {
            FsoeState::Reset => matches!(target, FsoeState::Session),
            FsoeState::Session => matches!(target, FsoeState::Connection | FsoeState::Reset),
            FsoeState::Connection => matches!(target, FsoeState::Parameter | FsoeState::Reset),
            FsoeState::Parameter => matches!(target, FsoeState::Data | FsoeState::Reset),
            FsoeState::Data => matches!(target, FsoeState::Failsafe | FsoeState::Reset),
            FsoeState::Failsafe => matches!(target, FsoeState::Data | FsoeState::Reset),
        }
    }

    /// 获取错误描述
    pub fn get_error_description(error: FsoeError) -> &'static str {
        match error {
            FsoeError::None => "无错误",
            FsoeError::WrongCommand => "错误的命令",
            FsoeError::UnknownCommand => "未知命令",
            FsoeError::WrongConnId => "连接ID不匹配",
            FsoeError::Crc => "CRC校验失败",
            FsoeError::Watchdog => "看门狗超时",
            FsoeError::WrongAddress => "错误的FSoE地址",
            FsoeError::WrongData => "无效数据",
            FsoeError::CommParamLength => "通信参数长度错误",
            FsoeError::CommParam => "通信参数错误",
            FsoeError::AppParamLength => "应用参数长度错误",
            FsoeError::AppParam => "应用参数错误",
            FsoeError::UnexpectedSession => "意外的会话命令",
            FsoeError::FailsafeData => "收到失效安全数据",
            FsoeError::NotInitialized => "FSoE未初始化",
            FsoeError::MaxConnections => "达到最大连接数",
            FsoeError::InvalidState => "无效状态转换",
        }
    }
}

// ===================== FSoE 事件回调 =====================

/// FSoE 状态变化事件参数
#[derive(Clone, Debug)]
pub struct FsoeStateChangedEventArgs {
    /// 从站索引
    pub slave_index: u16,
    /// 连接索引 (多连接模式)
    pub connection_index: u16,
    /// 旧状态
    pub old_state: FsoeState,
    /// 新状态
    pub new_state: FsoeState,
}

/// FSoE 错误事件参数
#[derive(Clone, Debug)]
pub struct FsoeErrorEventArgs {
    /// 从站索引
    pub slave_index: u16,
    /// 连接索引
    pub connection_index: u16,
    /// 错误代码
    pub error: FsoeError,
    /// 当前状态
    pub current_state: FsoeState,
}

impl FsoeErrorEventArgs {
    /// 获取错误描述
    pub fn description(&self) -> &'static str {
        FsoeHelper::get_error_description(self.error)
    }
}

/// FSoE 失效安全事件参数
#[derive(Clone, Debug)]
pub struct FsoeFailsafeEventArgs {
    /// 从站索引
    pub slave_index: u16,
    /// 连接索引
    pub connection_index: u16,
    /// 触发原因
    pub reason: FsoeFailsafeReason,
    /// 是否进入失效安全
    pub entering_failsafe: bool,
}

/// FSoE 安全数据更新事件参数
#[derive(Clone, Debug)]
pub struct FsoeDataUpdatedEventArgs {
    /// 从站索引
    pub slave_index: u16,
    /// 连接索引
    pub connection_index: u16,
    /// 是否为输入数据
    pub is_input: bool,
    /// 数据内容
    pub data: Vec<u8>,
}

/// FSoE 数据交换事件参数 (对齐 C# `FSoEDataExchangeEventArgs`).
///
/// 每个 PDO 周期, 输入刷新后输出提交前触发, 携带当前 FSoE 状态快照.
#[derive(Clone, Debug)]
pub struct FsoeDataExchangeEventArgs {
    /// 从站索引
    pub slave_index: u16,
    /// 本周期当前 FSoE 状态
    pub current_state: FsoeState,
    /// 本周期安全输入快照 (拷贝, 可自由读取)
    pub safe_inputs: Vec<u8>,
    /// 本周期安全输出快照 (拷贝, 反映提交前的当前值)
    pub safe_outputs: Vec<u8>,
    /// 是否处于失效安全模式
    pub in_failsafe: bool,
    /// 累计 PDO 周期计数 (从实例创建起递增)
    pub cycle_count: u32,
    /// 事件触发时间戳
    pub timestamp: SystemTime,
}

/// FSoE 数据交换回调类型别名
///
/// 使用 `Arc<dyn Fn(...) + Send + Sync>` 支持多个回调共享, 对齐 Rust 习惯.
pub type FsoeDataExchangeCallback =
    Arc<dyn Fn(&FsoeDataExchangeEventArgs) + Send + Sync>;

/// FSoE 数据交换事件分发器 (对齐 C# `event DataExchanged`).
///
/// Rust 惯例: `Arc<Mutex<Vec<Callback>>>` 保证多线程安全; 调用阶段在锁内快照回调列表,
/// 释放锁后再逐个调用, 避免回调阻塞其他注册 / 注销.
pub struct FsoeDataExchangeDispatcher {
    callbacks: Arc<Mutex<Vec<FsoeDataExchangeCallback>>>,
    cycle_count: Arc<Mutex<u32>>,
}

impl FsoeDataExchangeDispatcher {
    /// 创建空分发器
    pub fn new() -> Self {
        Self {
            callbacks: Arc::new(Mutex::new(Vec::new())),
            cycle_count: Arc::new(Mutex::new(0)),
        }
    }

    /// 注册 DataExchanged 回调
    pub fn add_data_exchanged_callback(&self, cb: FsoeDataExchangeCallback) {
        if let Ok(mut list) = self.callbacks.lock() {
            list.push(cb);
        }
    }

    /// 注销 DataExchanged 回调 (按 `Arc::ptr_eq` 匹配)
    pub fn remove_data_exchanged_callback(&self, cb: &FsoeDataExchangeCallback) {
        if let Ok(mut list) = self.callbacks.lock() {
            list.retain(|c| !Arc::ptr_eq(c, cb));
        }
    }

    /// 触发 DataExchanged 事件 (PDO 周期内部调用)
    pub fn fire_data_exchanged(
        &self,
        slave_index: u16,
        current_state: FsoeState,
        safe_inputs: &[u8],
        safe_outputs: &[u8],
        in_failsafe: bool,
    ) {
        let cycle = {
            let mut c = match self.cycle_count.lock() {
                Ok(g) => g,
                Err(_) => return,
            };
            *c = c.wrapping_add(1);
            *c
        };

        let snapshot: Vec<FsoeDataExchangeCallback> = match self.callbacks.lock() {
            Ok(list) => list.clone(),
            Err(_) => return,
        };

        if snapshot.is_empty() {
            return;
        }

        let args = FsoeDataExchangeEventArgs {
            slave_index,
            current_state,
            safe_inputs: safe_inputs.to_vec(),
            safe_outputs: safe_outputs.to_vec(),
            in_failsafe,
            cycle_count: cycle,
            timestamp: SystemTime::now(),
        };

        for cb in &snapshot {
            // 使用 catch_unwind 吞掉回调 panic, 避免影响 PDO 周期
            let _ = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| cb(&args)));
        }
    }
}

impl Default for FsoeDataExchangeDispatcher {
    fn default() -> Self {
        Self::new()
    }
}

/// FSoE 事件回调集合
///
/// 使用 `Box<dyn Fn(...)>` 存储回调，通过 `set_on_*` 方法注册。
pub struct FsoeEventCallbacks {
    /// 状态变化回调
    pub on_state_changed: Option<Box<dyn Fn(&FsoeStateChangedEventArgs) + Send + Sync>>,
    /// 错误回调
    pub on_error: Option<Box<dyn Fn(&FsoeErrorEventArgs) + Send + Sync>>,
    /// 失效安全回调
    pub on_failsafe: Option<Box<dyn Fn(&FsoeFailsafeEventArgs) + Send + Sync>>,
    /// 安全数据更新回调
    pub on_safe_data_updated: Option<Box<dyn Fn(&FsoeDataUpdatedEventArgs) + Send + Sync>>,
}

impl FsoeEventCallbacks {
    /// 创建空的回调集合
    pub fn new() -> Self {
        Self {
            on_state_changed: None,
            on_error: None,
            on_failsafe: None,
            on_safe_data_updated: None,
        }
    }

    /// 注册状态变化回调
    pub fn set_on_state_changed<F>(&mut self, f: F)
    where
        F: Fn(&FsoeStateChangedEventArgs) + Send + Sync + 'static,
    {
        self.on_state_changed = Some(Box::new(f));
    }

    /// 注册错误回调
    pub fn set_on_error<F>(&mut self, f: F)
    where
        F: Fn(&FsoeErrorEventArgs) + Send + Sync + 'static,
    {
        self.on_error = Some(Box::new(f));
    }

    /// 注册失效安全回调
    pub fn set_on_failsafe<F>(&mut self, f: F)
    where
        F: Fn(&FsoeFailsafeEventArgs) + Send + Sync + 'static,
    {
        self.on_failsafe = Some(Box::new(f));
    }

    /// 注册安全数据更新回调
    pub fn set_on_safe_data_updated<F>(&mut self, f: F)
    where
        F: Fn(&FsoeDataUpdatedEventArgs) + Send + Sync + 'static,
    {
        self.on_safe_data_updated = Some(Box::new(f));
    }

    /// 触发状态变化事件
    pub fn fire_state_changed(&self, args: &FsoeStateChangedEventArgs) {
        if let Some(ref cb) = self.on_state_changed {
            cb(args);
        }
    }

    /// 触发错误事件
    pub fn fire_error(&self, args: &FsoeErrorEventArgs) {
        if let Some(ref cb) = self.on_error {
            cb(args);
        }
    }

    /// 触发失效安全事件
    pub fn fire_failsafe(&self, args: &FsoeFailsafeEventArgs) {
        if let Some(ref cb) = self.on_failsafe {
            cb(args);
        }
    }

    /// 触发安全数据更新事件
    pub fn fire_safe_data_updated(&self, args: &FsoeDataUpdatedEventArgs) {
        if let Some(ref cb) = self.on_safe_data_updated {
            cb(args);
        }
    }
}

impl Default for FsoeEventCallbacks {
    fn default() -> Self {
        Self::new()
    }
}

// ===================== FSoE 模块结构体 =====================

/// FSoE 模块通信参数 (0x9nn1)
#[derive(Clone, Debug)]
pub struct SafeModuleCommParam {
    /// 版本 (2字节)
    pub version: [u8; 2],
    /// 安全地址
    pub safety_address: u16,
    /// 连接ID
    pub connection_id: u16,
    /// 看门狗超时
    pub watchdog_time: u32,
    /// 唯一设备ID (6字节)
    pub unique_device_id: [u8; 6],
    /// 连接类型
    pub connection_type: u16,
    /// 通信参数长度
    pub comm_param_length: u16,
    /// 应用参数长度
    pub appl_param_length: u16,
    /// SRA CRC
    pub sra_crc: u32,
}

impl Default for SafeModuleCommParam {
    fn default() -> Self {
        Self {
            version: [0; 2],
            safety_address: 0,
            connection_id: 0,
            watchdog_time: 0,
            unique_device_id: [0; 6],
            connection_type: 0,
            comm_param_length: 0,
            appl_param_length: 0,
            sra_crc: 0,
        }
    }
}

/// FSoE 模块诊断 (0xAnn0)
#[derive(Clone, Debug, Default)]
pub struct SafeModuleDiag {
    /// 连接状态
    pub connection_state: u16,
    /// 连接诊断
    pub connection_diagnosis: u16,
}

/// FSoE 模块信息 (0x9nn0)
#[derive(Clone, Debug, Default)]
pub struct SafeModuleInfo {
    /// 连接ID
    pub connection_id: u16,
    /// 设备类型
    pub device_type: u16,
    /// 供应商ID
    pub vendor_id: u32,
    /// 产品代码
    pub product_code: u32,
    /// 修订号
    pub revision_number: u32,
    /// 序列号
    pub serial_number: u32,
}

// ===================== FSoE MDP 对象索引定义 (ETG.5001.4) =====================

/// FSoE MDP 对象索引区域定义 (ETG.5001.4)
pub struct SafeMdpIndex;

impl SafeMdpIndex {
    /// 轴索引偏移
    pub const AXIS_INDEX_OFFSET: u16 = 0x0800;
    /// 配置区域基地址
    pub const CONFIG_AREA_BASE: u16 = 0x8000;
    /// 设备FSoE地址
    pub const DEVICE_FSOE_ADDRESS: u16 = 0xF980;
    /// 诊断区域基地址
    pub const DIAG_AREA_BASE: u16 = 0xA000;
    /// 驱动配置区域基地址
    pub const DRIVE_CONFIG_AREA_BASE: u16 = 0xE800;
    /// 驱动诊断区域基地址
    pub const DRIVE_DIAG_AREA_BASE: u16 = 0xEA00;
    /// 驱动信息区域基地址
    pub const DRIVE_INFO_AREA_BASE: u16 = 0xE900;
    /// 驱动输入区域基地址
    pub const DRIVE_INPUT_AREA_BASE: u16 = 0xE600;
    /// 驱动输出区域基地址
    pub const DRIVE_OUTPUT_AREA_BASE: u16 = 0xE700;
    /// 信息区域基地址
    pub const INFO_AREA_BASE: u16 = 0x9000;
    /// 输入区域基地址
    pub const INPUT_AREA_BASE: u16 = 0x6000;
    /// 模块索引偏移
    pub const MODULE_INDEX_OFFSET: u16 = 0x0010;
    /// 输出区域基地址
    pub const OUTPUT_AREA_BASE: u16 = 0x7000;
    /// 参数集映射基地址
    pub const PARAM_SET_MAPPING_BASE: u16 = 0x1E00;
    /// 接收PDO映射基地址
    pub const RX_PDO_MAPPING_BASE: u16 = 0x1600;
    /// 发送PDO映射基地址
    pub const TX_PDO_MAPPING_BASE: u16 = 0x1A00;

    /// 获取轴索引
    pub fn get_axis_index(base_index: u16, axis_number: u16) -> u16 {
        base_index + axis_number * Self::AXIS_INDEX_OFFSET
    }

    /// 获取模块索引
    pub fn get_module_index(base_index: u16, module_number: u16) -> u16 {
        base_index + module_number * Self::MODULE_INDEX_OFFSET
    }
}

// ===================== FSoE 模块配置 =====================

/// FSoE MDP 模块配置
#[derive(Clone, Debug)]
pub struct SafeModuleConfig {
    /// 模块编号
    pub module_number: u16,
    /// 轴编号
    pub axis_number: u16,
    /// 模块配置文件
    pub profile: SafeModuleProfile,
    /// 安全地址
    pub safety_address: u16,
    /// 连接ID
    pub connection_id: u16,
    /// 连接类型
    pub connection_type: FsoeConnectionType,
    /// 安全输入数据大小(字节)
    pub safe_input_size: u16,
    /// 安全输出数据大小(字节)
    pub safe_output_size: u16,
    /// PDO输入偏移
    pub pdo_input_offset: u32,
    /// PDO输出偏移
    pub pdo_output_offset: u32,
    /// 看门狗超时(毫秒)
    pub watchdog_time_ms: u32,
}

impl Default for SafeModuleConfig {
    fn default() -> Self {
        Self {
            module_number: 0,
            axis_number: 0,
            profile: SafeModuleProfile::DigitalInOut,
            safety_address: 0,
            connection_id: 0,
            connection_type: FsoeConnectionType::Slave,
            safe_input_size: 0,
            safe_output_size: 0,
            pdo_input_offset: 0,
            pdo_output_offset: 0,
            watchdog_time_ms: 100,
        }
    }
}

impl SafeModuleConfig {
    /// 转换为连接配置
    pub fn to_connection_config(&self) -> FsoeConnectionConfig {
        FsoeConnectionConfig {
            connection_id: self.connection_id,
            safety_address: self.safety_address,
            watchdog_time_ms: self.watchdog_time_ms,
            safe_input_size: self.safe_input_size,
            safe_output_size: self.safe_output_size,
            pdo_input_offset: self.pdo_input_offset,
            pdo_output_offset: self.pdo_output_offset,
        }
    }
}

/// FSoE MDP 设备配置
#[derive(Clone, Debug)]
pub struct SafeMdpDeviceConfig {
    /// 连接模式
    pub connection_mode: FsoeConnectionMode,
    /// 设备级安全地址
    pub device_safety_address: u16,
    /// 是否为驱动设备
    pub is_drive: bool,
    /// 轴数量
    pub axis_count: u16,
    /// 模块列表
    pub modules: Vec<SafeModuleConfig>,
}

impl Default for SafeMdpDeviceConfig {
    fn default() -> Self {
        Self {
            connection_mode: FsoeConnectionMode::Single,
            device_safety_address: 0,
            is_drive: false,
            axis_count: 1,
            modules: Vec::new(),
        }
    }
}

impl SafeMdpDeviceConfig {
    /// 添加模块配置
    pub fn add_module(&mut self, profile: SafeModuleProfile, safety_address: u16) -> &mut SafeModuleConfig {
        let idx = self.modules.len() as u16;
        self.modules.push(SafeModuleConfig {
            module_number: idx,
            profile,
            safety_address,
            connection_id: 0x0001 + idx,
            ..Default::default()
        });
        self.modules.last_mut().unwrap()
    }

    /// 添加驱动轴配置
    pub fn add_drive_axis(&mut self, axis_number: u16, safety_address: u16) -> &mut SafeModuleConfig {
        let idx = self.modules.len() as u16;
        self.modules.push(SafeModuleConfig {
            module_number: idx,
            axis_number,
            profile: SafeModuleProfile::DriveConnection,
            safety_address,
            connection_id: 0x0001 + idx,
            ..Default::default()
        });
        self.modules.last_mut().unwrap()
    }

    /// 获取连接数量
    pub fn get_connection_count(&self) -> usize {
        match self.connection_mode {
            FsoeConnectionMode::Single => 1,
            FsoeConnectionMode::Multiple => self.modules.len(),
        }
    }
}

// ===================== FSoE PDO 帧布局 =====================

/// FSoE PDO 帧布局配置
#[derive(Clone, Debug)]
pub struct FsoePdoLayout {
    /// 命令偏移
    pub command_offset: usize,
    /// 标志偏移
    pub flags_offset: usize,
    /// 连接ID偏移
    pub connection_id_offset: usize,
    /// 序列号偏移
    pub sequence_offset: usize,
    /// 数据偏移
    pub data_offset: usize,
    /// 数据区长度
    pub data_length: usize,
    /// CRC长度
    pub crc_length: usize,
}

impl Default for FsoePdoLayout {
    fn default() -> Self {
        Self {
            command_offset: 0,
            flags_offset: 1,
            connection_id_offset: 2,
            sequence_offset: 4,
            data_offset: 6,
            data_length: 0,
            crc_length: 2,
        }
    }
}

impl FsoePdoLayout {
    /// 帧总长度
    pub fn total_length(&self) -> usize {
        self.data_offset + self.data_length + self.crc_length
    }

    /// 验证布局参数
    pub fn validate(&self) -> Result<()> {
        if self.data_offset < self.sequence_offset {
            return Err(DarraError::Other(
                "DataOffset 必须大于等于 SequenceOffset".to_string(),
            ));
        }
        if self.crc_length == 0 {
            return Err(DarraError::Other(
                "CRC 长度必须大于 0".to_string(),
            ));
        }
        Ok(())
    }
}

/// FSoE PDO 帧结构
#[derive(Clone, Debug)]
pub struct FsoePdoFrame {
    /// 命令
    pub command: FsoeCommand,
    /// 标志字节
    pub flags: u8,
    /// 连接ID
    pub connection_id: u16,
    /// 序列号
    pub sequence: u16,
    /// 数据
    pub data: Vec<u8>,
    /// CRC校验值
    pub crc: u16,
}

impl Default for FsoePdoFrame {
    fn default() -> Self {
        Self {
            command: FsoeCommand::Reset,
            flags: 0,
            connection_id: 0,
            sequence: 0,
            data: Vec::new(),
            crc: 0,
        }
    }
}

impl FsoePdoFrame {
    /// 序列化为字节数组
    ///
    /// `crc_func` 可选的 CRC 计算函数，传 None 则使用已有的 crc 字段值。
    pub fn to_bytes(&mut self, layout: &FsoePdoLayout, crc_func: Option<fn(&[u8]) -> u16>) -> Result<Vec<u8>> {
        layout.validate()?;
        if self.data.len() != layout.data_length {
            return Err(DarraError::Other(format!(
                "Data 长度必须为 {} 字节，但收到 {}",
                layout.data_length,
                self.data.len()
            )));
        }

        let total = layout.total_length();
        let mut buf = vec![0u8; total];
        buf[layout.command_offset] = self.command as u8;
        buf[layout.flags_offset] = self.flags;
        buf[layout.connection_id_offset] = (self.connection_id & 0xFF) as u8;
        buf[layout.connection_id_offset + 1] = ((self.connection_id >> 8) & 0xFF) as u8;
        buf[layout.sequence_offset] = (self.sequence & 0xFF) as u8;
        buf[layout.sequence_offset + 1] = ((self.sequence >> 8) & 0xFF) as u8;
        buf[layout.data_offset..layout.data_offset + layout.data_length]
            .copy_from_slice(&self.data);

        if let Some(f) = crc_func {
            self.crc = f(&buf[..total - layout.crc_length]);
        }

        let crc_offset = layout.data_offset + layout.data_length;
        buf[crc_offset] = (self.crc & 0xFF) as u8;
        buf[crc_offset + 1] = ((self.crc >> 8) & 0xFF) as u8;
        Ok(buf)
    }

    /// 从字节数组反序列化
    ///
    /// `crc_func` 可选的 CRC 验证函数，传 None 则跳过验证。
    pub fn from_bytes(data: &[u8], layout: &FsoePdoLayout, crc_func: Option<fn(&[u8]) -> u16>) -> Result<Self> {
        layout.validate()?;
        let total = layout.total_length();
        if data.len() < total {
            return Err(DarraError::Other(format!(
                "数据长度不足，期望 {} 字节，实际 {}",
                total,
                data.len()
            )));
        }

        let command = match data[layout.command_offset] & 0x0F {
            0x00 => FsoeCommand::Reset,
            0x01 => FsoeCommand::Session,
            0x02 => FsoeCommand::Connection,
            0x03 => FsoeCommand::Parameter,
            0x04 => FsoeCommand::Failsafe,
            0x05 => FsoeCommand::Data,
            v => return Err(DarraError::Other(format!("无效的 FSoE 命令: 0x{:02X}", v))),
        };
        let flags = data[layout.flags_offset];
        let connection_id = u16::from_le_bytes([
            data[layout.connection_id_offset],
            data[layout.connection_id_offset + 1],
        ]);
        let sequence = u16::from_le_bytes([
            data[layout.sequence_offset],
            data[layout.sequence_offset + 1],
        ]);
        let frame_data = data[layout.data_offset..layout.data_offset + layout.data_length].to_vec();
        let crc_offset = layout.data_offset + layout.data_length;
        let crc = u16::from_le_bytes([data[crc_offset], data[crc_offset + 1]]);

        if let Some(f) = crc_func {
            let computed = f(&data[..total - layout.crc_length]);
            if computed != crc {
                return Err(DarraError::Other(format!(
                    "FSoE CRC 校验失败：期望 0x{:04X}，计算值 0x{:04X}",
                    crc, computed
                )));
            }
        }

        Ok(Self {
            command,
            flags,
            connection_id,
            sequence,
            data: frame_data,
            crc,
        })
    }
}

// ===================== 可配置 CRC-16 实现 =====================

/// 可配置的 CRC-16 实现（默认：CRC-16/CCITT-FALSE）
pub struct FsoeCrc16Configurable {
    polynomial: u16,
    initial: u16,
    xor_out: u16,
}

impl FsoeCrc16Configurable {
    /// 创建自定义 CRC-16 计算器
    pub fn new(polynomial: u16, initial: u16, xor_out: u16) -> Self {
        Self { polynomial, initial, xor_out }
    }

    /// 计算 CRC-16
    pub fn compute(&self, data: &[u8]) -> u16 {
        let mut crc = self.initial;
        for &b in data {
            crc ^= (b as u16) << 8;
            for _ in 0..8 {
                if (crc & 0x8000) != 0 {
                    crc = (crc << 1) ^ self.polynomial;
                } else {
                    crc <<= 1;
                }
            }
        }
        (crc ^ self.xor_out) & 0xFFFF
    }
}

impl Default for FsoeCrc16Configurable {
    fn default() -> Self {
        Self::new(0x1021, 0xFFFF, 0x0000)
    }
}

/// 预置的 CCITT-False CRC16 实例（惰性初始化）
pub fn fsoe_crc16_ccitt_false() -> FsoeCrc16Configurable {
    FsoeCrc16Configurable::new(0x1021, 0xFFFF, 0x0000)
}

/// 便捷函数：计算 FSoE CRC16 校验值 (CCITT-False 算法)
pub fn fsoe_crc16(data: &[u8]) -> u16 {
    FsoeCrc16::compute(data)
}

/// 便捷函数：使用查找表加速计算 FSoE CRC16
pub fn fsoe_crc16_fast(data: &[u8]) -> u16 {
    FsoeCrc16::compute(data)
}

// ===================== ConnID 校验 (对齐 C# FSoEValidateConnId) =====================

/// 校验指定 ConnID 是否可用 (未被占用). 对齐 C# `FSoEValidateConnId` (ETG.5120 §5.2.3).
///
/// 实现: 直接调用 DLL `FSoEValidateConnId` 导出.
///
/// # 参数
/// - `conn_id`: 待校验的连接 ID (0 总是非法)
///
/// # 返回
/// `true` = 可用 (未被活动连接占用且非 0), `false` = 已占用或为 0
pub fn validate_conn_id(conn_id: u16) -> bool {
    unsafe { ffi::FSoEValidateConnId(conn_id) != 0 }
}

/// 校验 ConnID 是否可用 (模块级便捷别名, 对齐任务清单 `is_connection_id_available`).
///
/// 等价于 [`validate_conn_id`], 命名对齐 C# `IsConnectionIdAvailable`.
pub fn is_connection_id_available(conn_id: u16) -> bool {
    validate_conn_id(conn_id)
}

// ===================== IMailboxProtocol trait impl (对齐 C# FSoEInstance) =====================
//
// FSoE 在 C# 中以单从站实例形态 (FSoEInstance) 暴露邮箱接口; Rust 以
// `SafeMdp` (单主站+单从站) 最接近该语义. `SafetyManager` 管理多个连接,
// 不绑单一 slave, 因此不实现本 trait.

impl crate::abstractions::MailboxProtocol for SafeMdp {
    fn protocol_type(&self) -> u8 { 0x08 }
    fn protocol_name(&self) -> &'static str { "FSoE" }

    /// FSoE 能力探测: 从站是否支持 MDP (FSoE over CoE).
    /// `SafeMdpDetectConnections` 返回 >0 表示支持.
    fn is_supported(&self) -> bool {
        self.detect_connections() > 0
    }

    fn statistics(&self) -> crate::abstractions::MailboxStatistics {
        let mut stats = ffi::EcMbxStatsC::default();
        let rc = unsafe {
            ffi::mbx_get_stats_by_master(
                self.master_index, self.slave_index, 0x08, &mut stats,
            )
        };
        if rc == 1 {
            stats.into()
        } else {
            crate::abstractions::MailboxStatistics::empty()
        }
    }

    fn reset_statistics(&self) {
        unsafe {
            ffi::mbx_reset_stats_by_master(self.master_index, self.slave_index, 0x08);
        }
    }
}
