using System;
using System.Drawing;
using System.IO;
using System.IO.Pipes;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using Microsoft.Win32.SafeHandles;
using XP.Hardware.RaySource.Comet;
using XP.Hardware.RaySource.Comet.Host.Pipe;
using XP.Hardware.RaySource.Comet.Host.Properties;
using XP.Hardware.RaySource.Comet.Messages;
using XP.Hardware.RaySource.Comet.Messages.Responses;

namespace XP.Hardware.RaySource.Comet.Host
{
    /// <summary>
    /// XplorePlane Comet Host 主窗体
    /// 集成托盘图标、管道通信、PVI 客户端生命周期和功能测试按钮
    /// </summary>
    public partial class XplorePlaneCometHost : Form
    {
        #region 管道通信常量和字段

        /// <summary>
        /// 命令管道名称（客户端写 → Host 读）
        /// </summary>
        private const string CmdPipeName = "XP.Hardware.RaySource.Comet.Cmd";

        /// <summary>
        /// 响应管道名称（Host 写 → 客户端读）
        /// </summary>
        private const string RspPipeName = "XP.Hardware.RaySource.Comet.Rsp";

        /// <summary>
        /// 写入锁，防止命令响应和推送消息交错
        /// </summary>
        private static readonly object WriteLock = new object();

        /// <summary>
        /// 管道是否已连接，用于控制日志是否推送到管道
        /// </summary>
        private volatile bool _isPipeConnected;

        /// <summary>
        /// 管道轮询定时器
        /// </summary>
        private System.Windows.Forms.Timer _pipeTimer;

        /// <summary>
        /// 命令管道服务端
        /// </summary>
        private NamedPipeServerStream _cmdPipe;

        /// <summary>
        /// 响应管道服务端
        /// </summary>
        private NamedPipeServerStream _rspPipe;

        /// <summary>
        /// 管道读取器
        /// </summary>
        private StreamReader _pipeReader;

        /// <summary>
        /// 管道写入器
        /// </summary>
        private StreamWriter _pipeWriter;

        /// <summary>
        /// 是否正在等待客户端连接
        /// </summary>
        private bool _isWaitingConnection;

        /// <summary>
        /// 异步连接结果（命令管道）
        /// </summary>
        private IAsyncResult _cmdConnectResult;

        /// <summary>
        /// 异步连接结果（响应管道）
        /// </summary>
        private IAsyncResult _rspConnectResult;

        /// <summary>
        /// Win32 PeekNamedPipe API，用于非阻塞检测管道中是否有可读数据
        /// StreamReader.Peek() 在异步模式 NamedPipe 上不可靠：
        /// 当内部缓冲区为空时，Peek 调用底层同步 Read，异步管道会返回 0 字节，
        /// 导致 StreamReader 误判为 EOF，后续所有读取永远返回 -1/null
        /// </summary>
        [DllImport("kernel32.dll", SetLastError = true)]
        private static extern bool PeekNamedPipe(
            SafePipeHandle hNamedPipe,
            IntPtr lpBuffer,
            uint nBufferSize,
            IntPtr lpBytesRead,
            out uint lpTotalBytesAvail,
            IntPtr lpBytesLeftThisMessage);

        /// <summary>
        /// 检查命令管道中是否有可读数据（非阻塞）
        /// </summary>
        private bool HasPipeData()
        {
            if (_cmdPipe == null || !_cmdPipe.IsConnected)
                return false;

            bool result = PeekNamedPipe(
                _cmdPipe.SafePipeHandle,
                IntPtr.Zero, 0, IntPtr.Zero,
                out uint bytesAvailable,
                IntPtr.Zero);

            return result && bytesAvailable > 0;
        }

        #endregion

        #region Comet Timer常量
        /// <summary>
        /// 连接状态定时器
        /// </summary>
        private System.Windows.Forms.Timer _pviConnectTimer;

        /// <summary>
        /// 看门狗定时器
        /// </summary>
        private System.Windows.Forms.Timer _watchDogTimer;

        /// <summary>
        /// 心跳闪烁状态（true=绿色，false=灰色）
        /// </summary>
        private bool _heartbeatToggle;

        #endregion

        public XplorePlaneCometHost()
        {
            InitializeComponent();
            InitializeTrayIcon();
            SetupLogger();
            SubscribeLocalEvents();
            StartPipeLoop();
            StartCometPviTimer();
        }

        #region 托盘图标

        /// <summary>
        /// 初始化系统托盘图标和右键菜单
        /// </summary>
        private void InitializeTrayIcon()
        {
            var contextMenu = new ContextMenuStrip();
            contextMenu.Items.Add("XplorePlane Comet Host", null, null).Enabled = false;
            contextMenu.Items.Add(new ToolStripSeparator());
            contextMenu.Items.Add("测试窗口|Test(&S)", null, (s, e) =>
            {
                this.ShowInTaskbar = true;
                this.Show();
                this.WindowState = FormWindowState.Normal;
                this.Activate();
            });
            contextMenu.Items.Add("退出|Exit(&X)", null, OnExitClick);

            _notifyIcon = new NotifyIcon
            {
                Icon = Resource.Comet_Host_Icon,
                Text = "XP.Hardware.RaySource.Comet.Host",
                Visible = true,
                ContextMenuStrip = contextMenu
            };
            _notifyIcon.DoubleClick += (s, e) =>
            {
                this.ShowInTaskbar = true;
                this.Show();
                this.WindowState = FormWindowState.Normal;
                this.Activate();
            };
        }

        #endregion

        #region 统一日志

        /// <summary>
        /// 设置统一日志回调
        /// 界面日志始终输出，管道推送仅在管道连接后生效
        /// </summary>
        private void SetupLogger()
        {
            CometPviClient.SetLogger((level, message, logArgs) =>
            {
                // 始终输出到界面
                string formatted = logArgs != null && logArgs.Length > 0
                    ? FormatLogMessage(message, logArgs)
                    : message;
                AppendLog($"[{level}] {formatted}");

                // 管道已连接时，同步推送到主进程
                if (_isPipeConnected)
                {
                    var logResponse = new LogResponse
                    {
                        Success = true,
                        PushType = "Log",
                        Level = level.ToString(),
                        Message = message,
                        Args = logArgs != null ? Array.ConvertAll(logArgs, a => a?.ToString() ?? "") : null
                    };
                    PushNotifier.SendPush(logResponse);
                }
            });
        }

        #endregion

        #region  管道通信

        /// <summary>
        /// 启动管道通信：创建管道并开始异步等待连接，启动轮询定时器
        /// </summary>
        private void StartPipeLoop()
        {
            // 创建管道
            _cmdPipe = new NamedPipeServerStream(CmdPipeName, PipeDirection.In, 1, PipeTransmissionMode.Byte, PipeOptions.Asynchronous);
            _rspPipe = new NamedPipeServerStream(RspPipeName, PipeDirection.Out, 1, PipeTransmissionMode.Byte, PipeOptions.Asynchronous);

            // 异步等待客户端连接
            _cmdConnectResult = _cmdPipe.BeginWaitForConnection(null, null);
            _rspConnectResult = _rspPipe.BeginWaitForConnection(null, null);
            _isWaitingConnection = true;

            AppendLog("[管道] 等待客户端连接...");

            // 启动定时器轮询（50ms 间隔）
            _pipeTimer = new System.Windows.Forms.Timer();
            _pipeTimer.Interval = 50;
            _pipeTimer.Tick += PipeTimer_Tick;
            _pipeTimer.Start();
        }

        /// <summary>
        /// 是否正在处理管道命令，防止 DoEvents 期间 Timer 重入
        /// </summary>
        private bool _isProcessingCommand;

        /// <summary>
        /// 定时器回调：检查管道连接状态和读取命令
        /// </summary>
        private void PipeTimer_Tick(object sender, EventArgs e)
        {
            // 防止 HandleInitialize 中 DoEvents 导致的 Timer 重入
            if (_isProcessingCommand)
                return;

            try
            {
                // 阶段1：等待客户端连接
                if (_isWaitingConnection)
                {
                    if (_cmdConnectResult.IsCompleted && _rspConnectResult.IsCompleted)
                    {
                        _cmdPipe.EndWaitForConnection(_cmdConnectResult);
                        _rspPipe.EndWaitForConnection(_rspConnectResult);

                        _pipeReader = new StreamReader(_cmdPipe);
                        _pipeWriter = new StreamWriter(_rspPipe) { AutoFlush = true };

                        // 初始化推送管理器
                        PushNotifier.Initialize(_pipeWriter, WriteLock);

                        // 订阅 PVI 推送事件
                        SubscribePviPushEvents();

                        _isPipeConnected = true;
                        _isWaitingConnection = false;

                        AppendLog("[管道] 客户端已连接");
                    }
                    return;
                }

                // 阶段2：轮询读取命令
                if (!_cmdPipe.IsConnected)
                {
                    AppendLog("[管道] 客户端已断开");
                    CleanupPipe();
                    return;
                }

                // 检查管道中是否有可读数据（非阻塞）
                // 使用 Win32 PeekNamedPipe 替代 StreamReader.Peek()
                // StreamReader.Peek() 在异步模式 NamedPipe 上会误判 EOF，导致后续命令永远无法读取
                if (!HasPipeData())
                    return;

                _isProcessingCommand = true;
                try
                {
                    string line = _pipeReader.ReadLine();
                    if (line == null)
                    {
                        AppendLog("[管道] 客户端已关闭连接");
                        CleanupPipe();
                        return;
                    }

                    AppendLog($"[管道] 收到命令：{line}", Color.Cyan);

                    var command = MessageSerializer.DeserializeCommand(line);
                    if (command == null)
                    {
                        var errorResponse = new OperationResponse
                        {
                            Success = false,
                            ErrorMessage = "命令反序列化失败"
                        };
                        WriteResponse(_pipeWriter, errorResponse);
                        return;
                    }

                    var response = CommandDispatcher.Dispatch(command);
                    WriteResponse(_pipeWriter, response);

                    if (CommandDispatcher.ShouldExit)
                    {
                        AppendLog("[管道] 收到断开命令，管道循环退出");
                        CleanupPipe();
                    }
                }
                finally
                {
                    _isProcessingCommand = false;
                }
            }
            catch (Exception ex)
            {
                AppendLog($"[管道] 通信异常：{ex.Message}", Color.Red);
                CleanupPipe();
            }
        }

        /// <summary>
        /// 清理管道资源
        /// </summary>
        private void CleanupPipe()
        {
            _pipeTimer?.Stop();
            _isPipeConnected = false;

            try { _pipeReader?.Dispose(); } catch { }
            try { _pipeWriter?.Dispose(); } catch { }
            try { _cmdPipe?.Dispose(); } catch { }
            try { _rspPipe?.Dispose(); } catch { }

            _pipeReader = null;
            _pipeWriter = null;
            _cmdPipe = null;
            _rspPipe = null;
        }

        /// <summary>
        /// 线程安全地写入响应到管道
        /// </summary>
        private static void WriteResponse(StreamWriter writer, RaySourceResponse response)
        {
            var json = MessageSerializer.Serialize(response);
            lock (WriteLock)
            {
                writer.WriteLine(json);
            }
        }

        #endregion

        #region PVI 管道推送事件

        /// <summary>
        /// 订阅 CometPviClient 事件，通过 PushNotifier 推送给主进程
        /// </summary>
        private void SubscribePviPushEvents()
        {
            CometPviClient.StatusChanged += (sender, status) =>
            {
                PushNotifier.SendPush(new StatusResponse
                {
                    Success = true,
                    PushType = "StatusChanged",
                    SetVoltage = status.SetVoltage,
                    ActualVoltage = status.ActualVoltage,
                    SetCurrent = status.SetCurrent,
                    ActualCurrent = status.ActualCurrent,
                    IsXRayOn = status.IsXRayOn,
                    WarmUpStatus = status.WarmUpStatus,
                    VacuumStatus = status.VacuumStatus,
                    StartUpStatus = status.StartUpStatus,
                    AutoCenterStatus = status.AutoCenterStatus,
                    FilamentAdjustStatus = status.FilamentAdjustStatus,
                    IsInterlockActive = status.IsInterlockActive,
                    WatchdogStatus = status.WatchdogStatus,
                    PowerMode = status.PowerMode,
                    TxiStatus = status.TxiStatus
                });
            };

            CometPviClient.XRayStateChanged += (sender, isXRayOn) =>
            {
                PushNotifier.SendPush(new OperationResponse
                {
                    Success = true,
                    PushType = "XRayStateChanged",
                    Data = isXRayOn
                });
            };

            CometPviClient.ErrorOccurred += (sender, errorMessage) =>
            {
                PushNotifier.SendPush(new OperationResponse
                {
                    Success = false,
                    PushType = "ErrorOccurred",
                    ErrorMessage = errorMessage
                });
            };

            CometPviClient.ConnectionStateChanged += (sender, state) =>
            {
                PushNotifier.SendPush(new OperationResponse
                {
                    Success = true,
                    PushType = "ConnectionStateChanged",
                    Data = state.ToString()
                });
            };
        }

        #endregion

        #region Comet Timer事件

        private void StartCometPviTimer()
        {
            // 启动连接状态定时器轮询（100ms 间隔）
            _pviConnectTimer = new System.Windows.Forms.Timer();
            _pviConnectTimer.Interval = 100;
            _pviConnectTimer.Tick += PviConnectTimer_Tick;
            _pviConnectTimer.Start();

            // 启动看门狗定时器轮询（1000ms 间隔）
            _watchDogTimer = new System.Windows.Forms.Timer();
            _watchDogTimer.Interval = 1000;
            _watchDogTimer.Tick += WatchDogTimer_Tick;
            _watchDogTimer.Start();
        }

        private void PviConnectTimer_Tick(object sender, EventArgs e)
        {
            try
            {
                bool bRaySourceConnected = CometPviClient.ReadRaySourceConnectStatus();
                // 根据当前连接状态更新标签
                var state = CometPviClient.CurrentConnectionState;
                switch (state)
                {
                    case PviConnectionState.RaySourceConnected:
                        _lblPviState.Text = "射线源就绪";
                        _lblPviState.ForeColor = Color.Green;
                        break;
                    case PviConnectionState.VariablesConnected:
                        _lblPviState.Text = "变量已连接";
                        _lblPviState.ForeColor = Color.DarkGoldenrod;
                        break;
                    case PviConnectionState.ServiceConnected:
                        _lblPviState.Text = "Service已连接";
                        _lblPviState.ForeColor = Color.Orange;
                        break;
                    default:
                        _lblPviState.Text = "未连接";
                        _lblPviState.ForeColor = Color.Red;
                        break;
                }
            }
            catch (Exception ex)
            {
                AppendLog($"[错误] 连接状态定时器出错失败：{ex.Message}", Color.Red);
            }
        }

        private void WatchDogTimer_Tick(object sender, EventArgs e)
        {
            try
            {
                CometPviClient.SetWatchDog();
                // 心跳闪烁：绿色/灰色交替
                _heartbeatToggle = !_heartbeatToggle;
                _lblHeartbeat.ForeColor = _heartbeatToggle ? Color.LimeGreen : Color.Gray;
            }
            catch (Exception ex)
            {
                _lblHeartbeat.ForeColor = Color.Red;
                AppendLog($"[错误] 看门狗定时器出错失败：{ex.Message}", Color.Red);
            }
        }

        #endregion

        #region 本地界面事件订阅

        /// <summary>
        /// 订阅 CometPviClient 事件，将状态输出到界面
        /// </summary>
        private void SubscribeLocalEvents()
        {
            // 订阅连接状态变更
            CometPviClient.ConnectionStateChanged += (sender, state) =>
            {
                AppendLog($"[连接状态] {state}");
                SafeInvoke(() =>
                {
                    switch (state)
                    {
                        case PviConnectionState.RaySourceConnected:
                            _lblConnectionState.Text = "状态: 射线源已连接";
                            _lblConnectionState.ForeColor = Color.Green;
                            _btnConnectVariables.Enabled = false;
                            _btnDisconnect.Enabled = true;
                            _btnInitialize.Enabled = false;
                            break;
                        case PviConnectionState.ServiceConnected:
                            _lblConnectionState.Text = "状态: PVI Service 已连接";
                            _lblConnectionState.ForeColor = Color.Orange;
                            _btnConnectVariables.Enabled = true;
                            _btnDisconnect.Enabled = true;
                            _btnInitialize.Enabled = false;
                            break;
                        case PviConnectionState.VariablesConnected:
                            _lblConnectionState.Text = "状态: 变量已连接";
                            _lblConnectionState.ForeColor = Color.DarkGoldenrod;
                            SetOperationButtonsEnabled(true);
                            _btnConnectVariables.Enabled = false;
                            break;
                        case PviConnectionState.Disconnected:
                            _lblConnectionState.Text = "状态: 已断开";
                            _lblConnectionState.ForeColor = Color.Red;
                            SetOperationButtonsEnabled(false);
                            _btnConnectVariables.Enabled = false;
                            _btnDisconnect.Enabled = false;
                            _btnInitialize.Enabled = true;
                            break;
                    }
                });
            };

            // 订阅状态更新
            CometPviClient.StatusChanged += (sender, status) =>
            {
                AppendLog($"[状态更新] 电压={status.ActualVoltage}kV, 电流={status.ActualCurrent}μA, XRay={status.IsXRayOn}");
            };

            // 订阅射线状态变更
            CometPviClient.XRayStateChanged += (sender, isOn) =>
            {
                AppendLog($"[射线状态] XRay {(isOn ? "已开启" : "已关闭")}");
            };

            // 订阅错误事件
            CometPviClient.ErrorOccurred += (sender, errorMsg) =>
            {
                AppendLog($"[错误] {errorMsg}", Color.Red);
            };
        }

        /// <summary>
        /// 格式化日志消息，替换占位符
        /// </summary>
        private string FormatLogMessage(string message, object[] args)
        {
            try
            {
                string result = message;
                for (int i = 0; i < args.Length; i++)
                {
                    result = result.Replace("{" + i + "}", args[i]?.ToString() ?? "null");
                }
                return result;
            }
            catch
            {
                return message;
            }
        }

        #endregion

        #region 按钮事件处理

        private void OnInitialize(object sender, EventArgs e)
        {
            try
            {
                _btnInitialize.Enabled = false;
                AppendLog("[操作] 开始初始化 PVI 连接...");
                CometPviClient.Initialize(
                    _txtIpAddress.Text,
                    (int)_nudPort.Value,
                    _txtCpuName.Text,
                    (int)_nudSourcePort.Value,
                    (int)_nudStationNumber.Value);
            }
            catch (Exception ex)
            {
                AppendLog($"[错误] 初始化失败：{ex.Message}", Color.Red);
                _btnInitialize.Enabled = true;
            }
        }

        private void OnConnectVariables(object sender, EventArgs e)
        {
            try
            {
                AppendLog("[操作] 开始连接 PVI 变量...");
                CometPviClient.ConnectVariables();
            }
            catch (Exception ex)
            {
                AppendLog($"[错误] 连接变量失败：{ex.Message}", Color.Red);
            }
        }

        private void OnDisconnect(object sender, EventArgs e)
        {
            try
            {
                AppendLog("[操作] 断开连接...");
                CometPviClient.Disconnect();
            }
            catch (Exception ex)
            {
                AppendLog($"[错误] 断开连接失败：{ex.Message}", Color.Red);
            }
        }

        private void OnTurnOn(object sender, EventArgs e)
        {
            try
            {
                AppendLog("[操作] 开启高压...");
                CometPviClient.TurnOn();
                AppendLog("[操作] TurnOn 命令已发送");
            }
            catch (Exception ex)
            {
                AppendLog($"[错误] TurnOn 失败：{ex.Message}", Color.Red);
            }
        }

        private void OnTurnOff(object sender, EventArgs e)
        {
            try
            {
                AppendLog("[操作] 关闭高压...");
                CometPviClient.TurnOff();
                AppendLog("[操作] TurnOff 命令已发送");
            }
            catch (Exception ex)
            {
                AppendLog($"[错误] TurnOff 失败：{ex.Message}", Color.Red);
            }
        }

        private void OnSetVoltage(object sender, EventArgs e)
        {
            try
            {
                float voltage = (float)_nudVoltage.Value;
                AppendLog($"[操作] 设置电压：{voltage} kV");
                CometPviClient.SetVoltage(voltage);
                AppendLog($"[操作] SetVoltage 命令已发送，电压={voltage}kV");
            }
            catch (Exception ex)
            {
                AppendLog($"[错误] SetVoltage 失败：{ex.Message}", Color.Red);
            }
        }

        private void OnSetCurrent(object sender, EventArgs e)
        {
            try
            {
                float current = (float)_nudCurrent.Value;
                AppendLog($"[操作] 设置电流：{current} μA");
                CometPviClient.SetCurrent(current);
                AppendLog($"[操作] SetCurrent 命令已发送，电流={current}μA");
            }
            catch (Exception ex)
            {
                AppendLog($"[错误] SetCurrent 失败：{ex.Message}", Color.Red);
            }
        }

        private void OnReadVoltage(object sender, EventArgs e)
        {
            try
            {
                float voltage = CometPviClient.ReadVoltage();
                AppendLog($"[读取] 实际电压：{voltage} kV");
            }
            catch (Exception ex)
            {
                AppendLog($"[错误] ReadVoltage 失败：{ex.Message}", Color.Red);
            }
        }

        private void OnReadCurrent(object sender, EventArgs e)
        {
            try
            {
                float current = CometPviClient.ReadCurrent();
                AppendLog($"[读取] 实际电流：{current} μA");
            }
            catch (Exception ex)
            {
                AppendLog($"[错误] ReadCurrent 失败：{ex.Message}", Color.Red);
            }
        }

        private void OnReadSystemStatus(object sender, EventArgs e)
        {
            try
            {
                var status = CometPviClient.ReadSystemStatus();
                AppendLog("========== 系统状态 ==========");
                AppendLog($"  设定电压: {status.SetVoltage} kV | 实际电压: {status.ActualVoltage} kV");
                AppendLog($"  设定电流: {status.SetCurrent} μA | 实际电流: {status.ActualCurrent} μA");
                AppendLog($"  射线状态: {(status.IsXRayOn ? "开启" : "关闭")}");
                AppendLog($"  暖机: {status.WarmUpStatus} | 真空: {status.VacuumStatus}");
                AppendLog($"  训机: {status.StartUpStatus} | 自动定心: {status.AutoCenterStatus}");
                AppendLog($"  灯丝调整: {status.FilamentAdjustStatus}");
                AppendLog($"  连锁: {(status.IsInterlockActive ? "激活" : "未激活")} | 看门狗: {status.WatchdogStatus}");
                AppendLog($"  功率模式: {status.PowerMode} | TXI: {status.TxiStatus}");
                AppendLog("==============================");
            }
            catch (Exception ex)
            {
                AppendLog($"[错误] ReadSystemStatus 失败：{ex.Message}", Color.Red);
            }
        }

        private void OnReadErrors(object sender, EventArgs e)
        {
            try
            {
                var errors = CometPviClient.ReadErrors();
                AppendLog("========== 错误信息 ==========");
                AppendLog($"  系统错误: {errors.SystemError}");
                AppendLog($"  HSG错误: {errors.HSGError}");
                AppendLog($"  管错误: {errors.TubeError}");
                AppendLog($"  管真空错误: {errors.TubeVacError}");
                AppendLog("==============================");
            }
            catch (Exception ex)
            {
                AppendLog($"[错误] ReadErrors 失败：{ex.Message}", Color.Red);
            }
        }

        private void OnWarmUp(object sender, EventArgs e)
        {
            try
            {
                AppendLog("[维护] 执行暖机设置...", Color.Yellow);
                CometPviClient.WarmUp();
                AppendLog("[维护] 暖机设置指令已发送", Color.Lime);
            }
            catch (Exception ex)
            {
                AppendLog($"[错误] 暖机设置失败：{ex.Message}", Color.Red);
            }
        }

        private void OnTraining(object sender, EventArgs e)
        {
            try
            {
                AppendLog("[维护] 执行训机设置...", Color.Yellow);
                CometPviClient.Training();
                AppendLog("[维护] 训机设置指令已发送", Color.Lime);
            }
            catch (Exception ex)
            {
                AppendLog($"[错误] 训机设置失败：{ex.Message}", Color.Red);
            }
        }

        private void OnFilamentCalibration(object sender, EventArgs e)
        {
            try
            {
                AppendLog("[维护] 执行灯丝校准...", Color.Yellow);
                CometPviClient.FilamentCalibration();
                AppendLog("[维护] 灯丝校准指令已发送", Color.Lime);
            }
            catch (Exception ex)
            {
                AppendLog($"[错误] 灯丝校准失败：{ex.Message}", Color.Red);
            }
        }

        private void OnAutoCenter(object sender, EventArgs e)
        {
            try
            {
                AppendLog("[维护] 执行全部电压自动定心...", Color.Yellow);
                CometPviClient.AutoCenter();
                AppendLog("[维护] 自动定心指令已发送", Color.Lime);
            }
            catch (Exception ex)
            {
                AppendLog($"[错误] 自动定心失败：{ex.Message}", Color.Red);
            }
        }

        private void OnTxiOn(object sender, EventArgs e)
        {
            try
            {
                AppendLog("[维护] 执行 TXI ON...", Color.Yellow);
                CometPviClient.TxiOn();
                AppendLog("[维护] TXI ON 指令已发送", Color.Lime);
            }
            catch (Exception ex)
            {
                AppendLog($"[错误] TXI ON 失败：{ex.Message}", Color.Red);
            }
        }

        private void OnTxiOff(object sender, EventArgs e)
        {
            try
            {
                AppendLog("[维护] 执行 TXI OFF...", Color.Yellow);
                CometPviClient.TxiOff();
                AppendLog("[维护] TXI OFF 指令已发送", Color.Lime);
            }
            catch (Exception ex)
            {
                AppendLog($"[错误] TXI OFF 失败：{ex.Message}", Color.Red);
            }
        }

        #endregion

        #region 辅助方法

        /// <summary>
        /// 设置操作类按钮的启用状态
        /// </summary>
        private void SetOperationButtonsEnabled(bool enabled)
        {
            _btnTurnOn.Enabled = enabled;
            _btnTurnOff.Enabled = enabled;
            _btnSetVoltage.Enabled = enabled;
            _btnSetCurrent.Enabled = enabled;
            _btnReadVoltage.Enabled = enabled;
            _btnReadCurrent.Enabled = enabled;
            _btnReadSystemStatus.Enabled = enabled;
            _btnReadErrors.Enabled = enabled;
            _btnWarmUp.Enabled = enabled;
            _btnTraining.Enabled = enabled;
            _btnFilamentCalibration.Enabled = enabled;
            _btnAutoCenter.Enabled = enabled;
            _btnTxiOn.Enabled = enabled;
            _btnTxiOff.Enabled = enabled;
        }

        /// <summary>
        /// 线程安全地追加日志到 RichTextBox
        /// </summary>
        private void AppendLog(string message, Color? color = null)
        {
            SafeInvoke(() =>
            {
                var timestamp = DateTime.Now.ToString("HH:mm:ss.fff");
                var logLine = $"[{timestamp}] {message}\n";

                _rtbLog.SelectionStart = _rtbLog.TextLength;
                _rtbLog.SelectionLength = 0;
                _rtbLog.SelectionColor = color ?? Color.LightGreen;
                _rtbLog.AppendText(logLine);
                _rtbLog.ScrollToCaret();
            });
        }

        /// <summary>
        /// 线程安全地在 UI 线程执行操作
        /// </summary>
        private void SafeInvoke(Action action)
        {
            if (this.IsDisposed) return;
            if (this.InvokeRequired)
            {
                try { this.Invoke(action); }
                catch (ObjectDisposedException) { }
            }
            else
            {
                action();
            }
        }

        #endregion

        #region 窗体关闭和退出

        /// <summary>
        /// 窗体加载后立即隐藏，默认只显示托盘图标
        /// </summary>
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            this.Visible = false;
            this.ShowInTaskbar = false;
            this.WindowState = FormWindowState.Minimized;
        }

        /// <summary>
        /// 关闭窗体时最小化到托盘，不退出应用
        /// </summary>
        private void OnFormClosing(object sender, FormClosingEventArgs e)
        {
            if (e.CloseReason == CloseReason.UserClosing)
            {
                e.Cancel = true;
                this.Hide();
                this.ShowInTaskbar = false;
                _notifyIcon.ShowBalloonTip(1000, "XplorePlane Comet Host",
                    "程序已最小化到系统托盘", ToolTipIcon.Info);
            }
        }

        /// <summary>
        /// 托盘菜单退出（已禁用，仅提示）
        /// </summary>
        private void OnExitClick(object sender, EventArgs e)
        {
            MessageBox.Show("XplorePlane Comet Host does not allow manual exit; it will close along with the shutdown of XplorePlane.\r\nXplorePlane Comet Host不允许手动退出，它会跟随XplorePlane的关闭一并退出。", "XplorePlane Comet Host Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
        }

        /// <summary>
        /// 强制退出按钮点击 — 需要输入密码 Hexagon 才可退出
        /// Force exit button click — requires password "Hexagon" to exit
        /// </summary>
        private void OnForceExitClick(object sender, EventArgs e)
        {
            // 使用自定义输入对话框获取密码 | Use custom input dialog to get password
            using (var dlg = new ForceExitPasswordDialog())
            {
                if (dlg.ShowDialog(this) == DialogResult.OK && dlg.EnteredPassword == "Hexagon")
                {
                    AppendLog("[系统] 强制退出已授权，正在退出... | Force exit authorized, exiting...", Color.Orange);
                    ColseForm(sender, e);
                }
                else if (dlg.DialogResult == DialogResult.OK)
                {
                    // 密码错误 | Wrong password
                    MessageBox.Show("密码错误，无法退出。\r\nIncorrect password, cannot exit.",
                        "XplorePlane Comet Host", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    AppendLog("[警告] 强制退出尝试失败：密码错误 | Force exit attempt failed: wrong password", Color.Red);
                }
            }
        }

        /// <summary>
        /// 托盘菜单退出
        /// </summary>
        private void ColseForm(object sender, EventArgs e)
        {
            CleanupPipe();
            try { CometPviClient.Dispose(); } catch { }

            if (_notifyIcon != null)
            {
                _notifyIcon.Visible = false;
                _notifyIcon.Dispose();
                _notifyIcon = null;
            }

            // 移除 FormClosing 拦截，允许窗体真正关闭
            this.FormClosing -= OnFormClosing;
            Application.Exit();
        }

        #endregion
    }
}
