
using DeviceCommand.Devices;
using Logger;
using MaterialDesignThemes.Wpf;
using Microsoft.Win32;
using Model.Models;
using Notifications.Wpf.Core;
using System.Collections.Concurrent;
using System.Diagnostics;
using System.IO;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Threading; 
using UIShare;
using UIShare.GlobalVariable;
using UIShare.PubEvent;
using UIShare.UIViewModel;
using SqlSugar;

namespace ADP.ViewModels
{
    public class ShellViewModel : BindableBase
    {
        #region 私有字段
        private string _Title = "";
        private bool _IsLeftDrawerOpen;

        private readonly ConcurrentDictionary<string, Task> _executionTasks = new();
        private readonly ConcurrentDictionary<string, Task> _errorExecutionTasks = new();

        private readonly IEventAggregator _eventAggregator;
        private readonly IRegionManager _regionManager;
        private readonly IDialogService _dialogService;
        private readonly IContainerProvider _containerProvider;
        private readonly INotificationManager _notificationManager;
        private readonly IModuleManager _moduleManager;
        private readonly GlobalInfo _globalInfo;

        // 💡 新增：UI 刷新定时器，用于高频让前端重新拉取当前工位的 SW 累计时间
        private readonly DispatcherTimer _uiRefreshTimer;
        #endregion

        #region 属性
        public string Title
        {
            get => _Title;
            set => SetProperty(ref _Title, value);
        }
        public bool IsLeftDrawerOpen
        {
            get => _IsLeftDrawerOpen;
            set => SetProperty(ref _IsLeftDrawerOpen, value);
        }

        public TimeSpan RunningTime
        {
            get
            {
                if (CurrentContext == null) return TimeSpan.Zero;
                return CurrentContext.SW.IsRunning ? CurrentContext.SW.Elapsed : CurrentContext.RunningTime;
            }
            set
            {
                if (CurrentContext != null && CurrentContext.RunningTime != value)
                {
                    CurrentContext.RunningTime = value;
                    RaisePropertyChanged();
                }
            }
        }

        public bool IsTerminate
        {
            get => CurrentContext?.IsTerminate ?? false;
            set
            {
                if (CurrentContext != null && CurrentContext.IsTerminate != value)
                {
                    CurrentContext.IsTerminate = value;
                    RaisePropertyChanged();
                }
            }
        }

        private ScopedContext? CurrentContext =>
            _globalInfo.ContextDic.TryGetValue(_globalInfo.CurrentScope, out var ctx) ? ctx : null;
        private StepRunning? CurrentRunner =>
            _globalInfo.StepRunningDic.TryGetValue(_globalInfo.CurrentScope, out var runner) ? runner : null;
        private SystemConfig? CurrentConfig =>
          _globalInfo.ConfigDic.TryGetValue(_globalInfo.CurrentScope, out var config) ? config : null;
        public string RunState
        {
            get => CurrentContext?.RunState ?? "运行";
            set
            {
                if (CurrentContext != null && CurrentContext.RunState != value)
                {
                    CurrentContext.RunState = value;
                    RaisePropertyChanged();
                }
            }
        }

        public bool SingleStep
        {
            get => CurrentContext?.SingleStep ?? false;
            set
            {
                if (CurrentContext != null && CurrentContext.SingleStep != value)
                {
                    CurrentContext.SingleStep = value;
                    RaisePropertyChanged();
                }
            }
        }

        public PackIconKind RunIcon
        {
            get => CurrentContext?.RunIcon ?? PackIconKind.Play;
            set
            {
                if (CurrentContext != null && CurrentContext.RunIcon != value)
                {
                    CurrentContext.RunIcon = value;
                    RaisePropertyChanged();
                }
            }
        }
        #endregion

        #region 命令
        public ICommand LeftDrawerOpenCommand { get; set; }
        public ICommand MinimizeCommand { get; set; }
        public ICommand MaximizeCommand { get; set; }
        public ICommand CloseCommand { get; set; }
        public ICommand NavigateCommand { get; set; }
        public ICommand LoadCommand { get; set; }
        public ICommand RefreshCommand { get; set; }
        public ICommand DestroyCommand { get; set; }
        public ICommand RunningCommand { get; set; }
        public ICommand RunSingleCommand { get; set; }
        public ICommand RestorationCommand { get; set; }
        public ICommand RunAbnormalStepsCommand { get; set; }
        public ICommand SaveAsCommand { get; set; }
        public ICommand SaveCommand { get; set; }
        public ICommand OpenCommand { get; set; }
        public ICommand NewCommand { get; set; }
        public ICommand SetDefaultCommand { get; set; }
        public ICommand ShowDialogManagerViewCommand { get; set; }
        public ICommand SelectCANSignalMonitorCommand { get; set; }
        public ICommand SelectCANMessageCommand { get; set; }
        public ICommand MonitorValueSettingCommand { get; set; }
        public ICommand GetFileStringCommand { get; set; }
        public ICommand SilenceBuzzerCommand { get; set; }
        #endregion

        public ShellViewModel(IContainerProvider containerProvider)
        {
            _containerProvider = containerProvider;
            _dialogService= containerProvider.Resolve<IDialogService>();
            _globalInfo = containerProvider.Resolve<GlobalInfo>();
            _eventAggregator = containerProvider.Resolve<IEventAggregator>();
            _regionManager = containerProvider.Resolve<IRegionManager>();
            _notificationManager = containerProvider.Resolve<INotificationManager>();
            _moduleManager = containerProvider.Resolve<IModuleManager>();
            LeftDrawerOpenCommand = new DelegateCommand(LeftDrawerOpen);
            ShowDialogManagerViewCommand = new DelegateCommand(ShowDialogManagerView);
            MinimizeCommand = new DelegateCommand<Window>(MinimizeWindow);
            MaximizeCommand = new DelegateCommand<Window>(MaximizeWindow);
            CloseCommand = new DelegateCommand<Window>(CloseWindow);
            NavigateCommand = new DelegateCommand<string>(Navigate);
            LoadCommand = new DelegateCommand(Load);
            RefreshCommand = new DelegateCommand(OnRefresh);
            DestroyCommand = new DelegateCommand(OnDestroy);
            RunningCommand = new DelegateCommand(OnRunning);
            RunSingleCommand = new DelegateCommand(RunSingle);
            RestorationCommand = new AsyncDelegateCommand(OnRestoration);
            RunAbnormalStepsCommand = new AsyncDelegateCommand(OnRunAbnormalSteps);
            NewCommand = new DelegateCommand(New);
            OpenCommand = new AsyncDelegateCommand<string>(Open);
            SaveAsCommand = new DelegateCommand(SaveAs);
            SaveCommand = new DelegateCommand(Save);
            SetDefaultCommand = new DelegateCommand(SetDefault);
            SelectCANSignalMonitorCommand = new DelegateCommand(SelectCANSignalMonitor);
            SelectCANMessageCommand = new DelegateCommand(SelectCANMessage);
            MonitorValueSettingCommand = new DelegateCommand(MonitorValueSetting);
            GetFileStringCommand = new DelegateCommand(GetFileString);
            SilenceBuzzerCommand = new AsyncDelegateCommand(SilenceBuzzer);

            _globalInfo.ContextDic.Add("default", new ScopedContext());

            _eventAggregator.GetEvent<LoginSuccessEvent>().Subscribe(() =>
            {
                Application.Current.MainWindow.Show();
                _regionManager.RequestNavigate("ShellViewManager", "MainView");
            });
       
            _eventAggregator.GetEvent<RunSingalCompletedEvent>().Subscribe(UpdateRunIcon);

            _globalInfo.ScopeChanged += (s, e) =>
            {
                RefreshAllContextProperties();
            };

            // 💡 初始化轻量级 UI 定时器：每 100 毫秒刷新一次当前可见工位的界面时间
            _uiRefreshTimer = new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(100) };
            _uiRefreshTimer.Tick += (s, e) => RaisePropertyChanged(nameof(RunningTime));
            _uiRefreshTimer.Start();
        }


        private void RefreshAllContextProperties()
        {
            RaisePropertyChanged(nameof(RunState));
            RaisePropertyChanged(nameof(SingleStep));
            RaisePropertyChanged(nameof(RunIcon));
            RaisePropertyChanged(nameof(RunningTime));
            RaisePropertyChanged(nameof(IsTerminate));
        }

        #region 命令处理与事件

        private async Task SilenceBuzzer()
        {
            _eventAggregator.GetEvent<SilenceBuzzerEvent>().Publish(_globalInfo.CurrentScope);
          
        }
        private void GetFileString()
        {
            var openFileDialog = new OpenFileDialog
            {
                Title = "选择文件",
                Filter = "所有文件 (*.*)|*.*",
            };
            if (openFileDialog.ShowDialog() == true)
            {
                string filePath = openFileDialog.FileName;
                Application.Current.Dispatcher.Invoke(() =>
                {
                    Clipboard.SetDataObject(filePath);
                });
            }
        }
        private void MonitorValueSetting()
        {
            if ( _globalInfo.CurrentScope == "default")
            {
                LoggerHelper.Warn("当前作用域未配置 CAN 设备，无法打开报文选择窗口。");
                return;
            }
            _dialogService.ShowDialog("ValueLimitView", new DialogParameters
            {
                { "Scope", _globalInfo.ScopeDic[_globalInfo.CurrentScope] }
            }, _ => { });
        }

        private void SelectCANSignalMonitor()
        {
            var canfd = CurrentConfig?.CANFD;
            if (canfd == null || _globalInfo.CurrentScope == "default")
            {
                return;
            }

            _dialogService.ShowDialog("CollectCANSignalSettingView", new DialogParameters
            {
                { "SystemConfig", CurrentConfig }
            }, _ => { });
        }

        private void SelectCANMessage()
        {
            var canfd = CurrentConfig?.CANFD;
            if (canfd == null||_globalInfo.CurrentScope=="default")
            {
                LoggerHelper.Warn("当前作用域未配置 CAN 设备，无法打开报文选择窗口。");
                return;
            }

            _dialogService.ShowDialog("SelectCanMessageView", new DialogParameters
            {
                { "CANFD", canfd }
            }, _ => { });
        }

        private void ShowDialogManagerView()
        {
            _eventAggregator.GetEvent<CancelMinimizeEvent>().Publish();
        }
        private async void OnRunning()
        {
            string runningScope = _globalInfo.CurrentScope;
            ScopedContext? targetContext = CurrentContext;
            StepRunning? targetRunner = CurrentRunner;

            if (runningScope == "default" || string.IsNullOrEmpty(runningScope) || targetContext == null || targetRunner == null)
            {
                return;
            }

            if (targetContext.RunState == "运行")
            {
                targetContext.SingleStep = false;
                LoggerHelper.InfoWithNotify(runningScope, $"{_globalInfo.UserName} 执行工位 [{runningScope}] 运行命令");

                targetContext.RunState = "暂停";
                targetContext.RunIcon = PackIconKind.Pause;

                if (_globalInfo.CurrentScope == runningScope) RefreshAllContextProperties();

                if (targetContext.IsStop == null)
                {
                    targetContext.IsStop = false;

                    // 💡 启动或恢复：启动属于该快照工位独立的 SW 计时器
                    targetContext.SW.Start();

                    if (!_executionTasks.TryGetValue(runningScope, out var existingTask) || existingTask == null)
                    {
                        existingTask = targetRunner.ExecuteSteps(targetContext.Program, cancellationToken: targetRunner.stepCTS.Token);
                        _executionTasks[runningScope] = existingTask;
                    }

                    try
                    {
                        await existingTask;
                    }
                    catch (Exception ex)
                    {
                        LoggerHelper.ErrorWithNotify(runningScope, $"工位 [{runningScope}] 异常中止: {ex.Message}");
                    }

                    // 💡 测试正常完毕或取消：停止当前工位的 SW，并将最终时间固化到 RunningTime 字段中
                    targetContext.SW.Stop();
                    targetContext.RunningTime = targetContext.SW.Elapsed;

                    targetContext.RunState = "运行";
                    targetContext.RunIcon = PackIconKind.Play;
                    targetContext.IsStop = null;

                    if (targetRunner.stepCTS.IsCancellationRequested)
                    {
                        targetRunner.stepCTS = new CancellationTokenSource();
                        _executionTasks.TryRemove(runningScope, out _);
                    }
                    else if (_executionTasks.TryGetValue(runningScope, out var currentTask) && currentTask != null && currentTask.IsCompleted)
                    {
                        targetContext.IsTerminate = true;
                        _executionTasks.TryRemove(runningScope, out _);
                    }

                    if (_globalInfo.CurrentScope == runningScope) RefreshAllContextProperties();
                }
                else if (targetContext.IsStop == true)
                {
                    targetContext.IsStop = false;
                    // 💡 从暂停中恢复，继续累加当前工位计时
                    targetContext.SW.Start();
                }
            }
            else // 用户点击了暂停
            {
                LoggerHelper.InfoWithNotify(runningScope, $"{_globalInfo.UserName} 点击工位 [{runningScope}] 暂停命令");
                targetContext.SingleStep = true;
                targetContext.IsStop = true;
                targetContext.RunState = "运行";
                targetContext.RunIcon = PackIconKind.Play;
                if (_globalInfo.CurrentScope == runningScope) RefreshAllContextProperties();
            }
        }

        private async void RunSingle()
        {
            string runningScope = _globalInfo.CurrentScope;
            ScopedContext? targetContext = CurrentContext;
            StepRunning? targetRunner = CurrentRunner;

            if (runningScope == "default" || string.IsNullOrEmpty(runningScope) || targetContext == null || targetRunner == null)
            {
                return;
            }

            if (targetContext.RunState == "运行")
            {
                targetContext.SingleStep = true;
                LoggerHelper.InfoWithNotify(runningScope, $"{_globalInfo.UserName} 执行工位 [{runningScope}] 单步执行命令");

                targetContext.RunState = "暂停";
                targetContext.RunIcon = PackIconKind.Pause;

                if (_globalInfo.CurrentScope == runningScope) RefreshAllContextProperties();

                if (targetContext.IsStop == null)
                {
                    targetContext.IsStop = false;

                    // 💡 单步启动：让专属工位的 SW 跑起来
                    targetContext.SW.Start();

                    if (!_executionTasks.TryGetValue(runningScope, out var existingTask) || existingTask == null)
                    {
                        existingTask = targetRunner.ExecuteSteps(targetContext.Program, cancellationToken: targetRunner.stepCTS.Token);
                        _executionTasks[runningScope] = existingTask;
                    }

                    try
                    {
                        await existingTask;
                    }
                    catch (Exception ex)
                    {
                        LoggerHelper.ErrorWithNotify(runningScope, $"工位 [{runningScope}] 单步执行异常: {ex.Message}");
                    }

                    // 💡 单步单步完成后会被 StepRunning 挂起，在此暂时停止 SW
                    targetContext.SW.Stop();
                    targetContext.RunningTime = targetContext.SW.Elapsed;

                    targetContext.RunState = "运行";
                    targetContext.RunIcon = PackIconKind.Play;
                    targetContext.IsStop = null;

                    if (targetRunner.stepCTS.IsCancellationRequested)
                    {
                        targetRunner.stepCTS = new CancellationTokenSource();
                        _executionTasks.TryRemove(runningScope, out _);
                    }
                    else if (_executionTasks.TryGetValue(runningScope, out var currentTask) && currentTask != null && currentTask.IsCompleted)
                    {
                        targetContext.IsTerminate = true;
                        _executionTasks.TryRemove(runningScope, out _);
                    }

                    if (_globalInfo.CurrentScope == runningScope) RefreshAllContextProperties();
                }
                else if (targetContext.IsStop == true)
                {
                    targetContext.IsStop = false;
                    // 💡 继续单步，继续计时
                    targetContext.SW.Start();
                }
            }
        }

        private async Task OnRestoration()
        {
            string runningScope = _globalInfo.CurrentScope;
            ScopedContext? targetContext = CurrentContext;
            StepRunning? targetRunner = CurrentRunner;

            if (runningScope == "default" || string.IsNullOrEmpty(runningScope) || targetContext == null || targetRunner == null)
            {
                return;
            }

            LoggerHelper.InfoWithNotify(runningScope, $"{_globalInfo.UserName} 执行工位 [{runningScope}] 复位命令");

            _executionTasks.TryGetValue(runningScope, out var currentTask);
            _errorExecutionTasks.TryGetValue(runningScope, out var errorTask);

            if (currentTask != null || errorTask != null)
            {
                targetRunner.stepCTS.Cancel();
                targetRunner.errorStepCTS.Cancel();

                await Task.Delay(200);

                // 💡 彻底复位：停止当前工位的计时器，并且完全归零（Reset）
                targetContext.SW.Reset();
                targetContext.RunningTime = TimeSpan.Zero;

                targetContext.IsStop = null;
                targetRunner.ResetAllStepStatus(targetContext.Program.StepCollection);
                targetRunner.ResetAllStepStatus(targetContext.Program.ErrorStepCollection);
                targetContext.IsTerminate = false;
            }
            else
            {
                targetRunner.stepCTS = new CancellationTokenSource();
                targetRunner.errorStepCTS = new CancellationTokenSource();

                // 💡 无任务状态下的直接归零
                targetContext.SW.Reset();
                targetContext.RunningTime = TimeSpan.Zero;

                targetContext.IsStop = null;
                targetRunner.ResetAllStepStatus(targetContext.Program.StepCollection);
                targetRunner.ResetAllStepStatus(targetContext.Program.ErrorStepCollection);
                targetContext.IsTerminate = false;
            }

            if (_globalInfo.CurrentScope == runningScope) RefreshAllContextProperties();
        }

        private async Task OnRunAbnormalSteps()
        {
            string runningScope = _globalInfo.CurrentScope;
            ScopedContext? targetContext = CurrentContext;
            StepRunning? targetRunner = CurrentRunner;

            if (runningScope == "default" || string.IsNullOrEmpty(runningScope) || targetContext == null || targetRunner == null)
            {
                return;
            }

            LoggerHelper.InfoWithNotify(runningScope, $"{_globalInfo.UserName} 执行工位 [{runningScope}] 异常流程命令");

            // 💡 异常测试启动计时
            targetContext.SW.Start();

            if (!_errorExecutionTasks.TryGetValue(runningScope, out var existingErrorTask) || existingErrorTask == null)
            {
                existingErrorTask = targetRunner.ExecuteErrorSteps(targetContext.Program, cancellationToken: targetRunner.errorStepCTS.Token);
                _errorExecutionTasks[runningScope] = existingErrorTask;
            }

            try
            {
                await existingErrorTask;
            }
            catch (Exception ex)
            {
                LoggerHelper.ErrorWithNotify(runningScope, $"工位 [{runningScope}] 异常流程执行出错: {ex.Message}");
            }

            // 💡 异常测试结束停止计时
            targetContext.SW.Stop();
            targetContext.RunningTime = targetContext.SW.Elapsed;

            if (targetRunner.errorStepCTS.IsCancellationRequested)
            {
                targetRunner.errorStepCTS = new CancellationTokenSource();
                _errorExecutionTasks.TryRemove(runningScope, out _);
            }
            else if (_errorExecutionTasks.TryGetValue(runningScope, out var currentErrorTask) && currentErrorTask != null && currentErrorTask.IsCompleted)
            {
                targetContext.IsTerminate = true;
                _errorExecutionTasks.TryRemove(runningScope, out _);
            }

            if (_globalInfo.CurrentScope == runningScope) RefreshAllContextProperties();
        }

        private void SetDefault()
        {
            if (CurrentConfig == null) return;
            // 💡 1. 抓取触发瞬间的 Scope 与 Context 快照
            string runningScope = _globalInfo.CurrentScope;
            ScopedContext? targetContext = CurrentContext;

            if (runningScope == "default" || string.IsNullOrEmpty(runningScope) || targetContext == null) return;

            if (targetContext.CurrentFilePath != null)
            {
                CurrentConfig.DefaultProgramFilePath = targetContext.CurrentFilePath;
                ConfigService.Save(CurrentConfig);
                LoggerHelper.SuccessWithNotify(runningScope, $"工位 [{runningScope}] 已成功将当前程序设为默认启动程序");
            }
        }

        private void New()
        {
            // 💡 1. 抓取快照
            string runningScope = _globalInfo.CurrentScope;
            ScopedContext? targetContext = CurrentContext;

            if (runningScope == "default" || string.IsNullOrEmpty(runningScope) || targetContext == null) return;
            CurrentConfig.CurrentADPFile = "新建ADP文件";
            // 💡 2. 严格对快照隔离的 Context 数据进行清理，不影响其他工位
            targetContext.CurrentFilePath = null;
            targetContext.Program.Parameters.Clear();
            targetContext.Program.StepCollection.Clear();
            targetContext.Program.ErrorStepCollection.Clear();
            foreach (var item in CurrentConfig.ParameterList)
            {
                var param = CurrentConfig.SharedParameterList.FirstOrDefault(x => x.ParameterName == item.Name);
                if (param != null)
                {
                    item.Value = param.Value;
                }
                targetContext.Program.Parameters.Add(item);
            }
            LoggerHelper.InfoWithNotify(runningScope, $"工位 [{runningScope}] 创建了空程序文件");

            // 如果当前正看着该工位，刷新 UI 显示
            if (_globalInfo.CurrentScope == runningScope) RefreshAllContextProperties();
        }

        private async Task Open(string filePath = null)
        {
            // 💡 1. 抓取进方法瞬间的快照，锁死上下文
            string runningScope = _globalInfo.CurrentScope;
            ScopedContext? targetContext = CurrentContext;

            if (runningScope == "default" || string.IsNullOrEmpty(runningScope) || targetContext == null) return;

            try
            {
                // 如果没有传路径，弹出文件选择对话框（WPF 对话框是模态的，会阻塞当前 UI 线程）
                if (string.IsNullOrEmpty(filePath))
                {
                    var openFileDialog = new Microsoft.Win32.OpenFileDialog
                    {
                        Filter = "ADP程序文件|*.ADP|所有文件|*.*",
                        Title = $"工位 [{runningScope}] 打开程序",
                    };

                    if (openFileDialog.ShowDialog() != true)
                        return; // 用户取消选择

                    filePath = openFileDialog.FileName;
                }

                // 确认文件存在
                if (!File.Exists(filePath))
                {
                    LoggerHelper.ErrorWithNotify(runningScope, $"文件不存在: {filePath}");
                    return;
                }

                // 读取 JSON 文件
                string json = File.ReadAllText(filePath);

                // 反序列化为 ProgramVM
                var program = Newtonsoft.Json.JsonConvert.DeserializeObject<ProgramVM>(json);

                if (program == null)
                {
                    LoggerHelper.WarnWithNotify(runningScope, $"文件格式不正确或为空: {filePath}"); 
                    return;
                }
                CurrentConfig.CurrentADPFile = filePath;
                // 💡 2. 严格赋值给快照锁定下的当前工位上下文，实现数据完全隔离
                targetContext.Program.Parameters = program.Parameters;
                targetContext.Program.StepCollection = program.StepCollection;
                targetContext.Program.ErrorStepCollection = program.ErrorStepCollection;
                targetContext.CurrentFilePath = filePath;

                foreach (var item in CurrentConfig.SharedParameterList)
                {
                    var parameter = targetContext?.Program?.Parameters?.FirstOrDefault(x => x.Name == item.ParameterName);

                    if (parameter != null)
                    {
                        parameter.Value = item.Value;
                    }
                }

                LoggerHelper.SuccessWithNotify(runningScope, $"工位 [{runningScope}] 成功打开文件: {filePath}"); 

                // 💡 3. 安全调用异步复位，确保重置的是对应工位的数据
                // 注意：由于在 OnRestoration 内部第一行也做了快照拦截，
                // 如果用户此时正好在看这个工位，它会自动完美执行
                await OnRestoration();
            }
            catch (Exception ex)
            {
                LoggerHelper.ErrorWithNotify(runningScope, $"工位 [{runningScope}] 打开文件失败: {ex.Message}");
            }
            finally
            {
                // 💡 4. 异步回归：不管中途用户切去了哪里，回到该工位时及时刷新显示
                if (_globalInfo.CurrentScope == runningScope) RefreshAllContextProperties();
            }
        }

        private void SaveAs()
        {
            if (!_globalInfo.IsAdmin) return;

            // 💡 1. 抓取快照
            string runningScope = _globalInfo.CurrentScope;
            ScopedContext? targetContext = CurrentContext;

            if (runningScope == "default" || string.IsNullOrEmpty(runningScope) || targetContext == null) return;

            string defaultPath = @"D:\ADP\子程序";
            if (!Directory.Exists(defaultPath))
                Directory.CreateDirectory(defaultPath);

            var saveFileDialog = new Microsoft.Win32.SaveFileDialog
            {
                Filter = "ADP程序文件|*.adp|所有文件|*.*",
                Title = $"工位 [{runningScope}] 程序另存为",
                FileName = "NewProgram.ADP",
                InitialDirectory = defaultPath
            };

            if (saveFileDialog.ShowDialog() == true)
            {
                // 💡 2. 将新路径安全写入快照工位
                CurrentConfig.CurrentADPFile = saveFileDialog.FileName;
                targetContext.CurrentFilePath = saveFileDialog.FileName;

                // 💡 3. 调用你的底层文件保存逻辑，传入快照工位的 Program 模型
                SaveProgramToFile(targetContext.CurrentFilePath, targetContext.Program);

                LoggerHelper.InfoWithNotify(runningScope, $"{_globalInfo.UserName} 另存为文件成功: {saveFileDialog.FileName}");

                if (_globalInfo.CurrentScope == runningScope) RefreshAllContextProperties();
            }
        }

        private void Save()
        {
            if (!_globalInfo.IsAdmin) return;

            // 💡 1. 抓取快照
            string runningScope = _globalInfo.CurrentScope;
            ScopedContext? targetContext = CurrentContext;

            if (runningScope == "default" || string.IsNullOrEmpty(runningScope) || targetContext == null) return;

            // 💡 2. 判断当前工位是否有历史路径
            if (targetContext.CurrentFilePath == null)
            {
                SaveAs();
                return;
            }

            // 💡 3. 持久化当前快照工位的 Program
            SaveProgramToFile(targetContext.CurrentFilePath, targetContext.Program);
            LoggerHelper.SuccessWithNotify(_globalInfo.CurrentScope,$"工位 [{runningScope}] 程序保存成功！");
        }

        // 💡 辅助方法：建议将你的通用序列化落盘代码调整为接收 ProgramVM 参数，提高复用性
        private void SaveProgramToFile(string filePath, ProgramVM ProgramVM)
        {
            try
            {
                string json = Newtonsoft.Json.JsonConvert.SerializeObject(ProgramVM, Newtonsoft.Json.Formatting.Indented);
                File.WriteAllText(filePath, json);
            }
            catch (Exception ex)
            {
                LoggerHelper.ErrorWithNotify(_globalInfo.CurrentScope,$"写入程序文件失败: {ex.Message}");
            }
        }

        private void UpdateRunIcon(string obj)
        {
            CurrentContext?.SW.Stop();
            CurrentContext.RunningTime = CurrentContext.SW.Elapsed;
            RunIcon = obj switch
            {
                "Play" => PackIconKind.Play,
                "Pause" => PackIconKind.Pause,
                _ => RunIcon
            };
        }

        private void OnRefresh()
        {
            _eventAggregator.GetEvent<ExpandViewEvent>().Publish("");
            _globalInfo.CurrentScope = "default";
        }
        private void OnDestroy()
        {
            if (_globalInfo.CurrentScope == "default" || string.IsNullOrEmpty(_globalInfo.CurrentScope)) return;

            string targetRegionName = _globalInfo.CurrentScope;

            // 💡 物理销毁工位时，顺便清理任务字典，防止内存泄漏
            _executionTasks.TryRemove(targetRegionName, out _);
            _errorExecutionTasks.TryRemove(targetRegionName, out _);

            if (_regionManager.Regions.ContainsRegionWithName(targetRegionName))
            {
                var region = _regionManager.Regions[targetRegionName];
                var viewsToDestroy = region.Views.ToList();

                foreach (var view in viewsToDestroy)
                {
                    if (view is FrameworkElement element)
                    {
                        var viewModel = element.DataContext;
                        region.Remove(view);
                        if (viewModel is IDisposable disposableVM) disposableVM.Dispose();
                    }
                }
            }

           var parameters = new NavigationParameters { { "Name", targetRegionName } };
            _regionManager.RequestNavigate(targetRegionName, "ProtocolStartView", parameters);
            _eventAggregator.GetEvent<ExpandViewEvent>().Publish("");
        }
        private void Load()
        {
            _notificationManager.ShowAsync(new NotificationContent { Title = "登录成功", Message = "", Type = NotificationType.Success });
            //默认导航到主界面
            Type moduleAType = typeof(MainModule.MainModule);
            _moduleManager.LoadModule(moduleAType.Name);
        }
        private void Navigate(string content)
        {
            switch (content)
            {
                case "主界面":
                    if (_globalInfo.CurrentScope == "default" || string.IsNullOrEmpty(_globalInfo.CurrentScope))
                    {
                        _regionManager.RequestNavigate("ShellViewManager", "MainView");
                        break;
                    }
                    var TestingRegion = _globalInfo.CurrentScope;
                    if (!_regionManager.Regions.ContainsRegionWithName(TestingRegion)) break;
                    _regionManager.RequestNavigate(TestingRegion, "AutomatedTestingView");
                    break; 
                case "监控界面":
                    // 仅当某个工位被选中（九宫格已展开/选择）时才跳转，默认 default 跳过。
                    if (_globalInfo.CurrentScope == "default" || string.IsNullOrEmpty(_globalInfo.CurrentScope)) break;

                    // 记录界面不是填到全局的 ShellViewManager，而是填到该工位专属的 region。
                    var monitorRegion = _globalInfo.CurrentScope;
                    if (!_regionManager.Regions.ContainsRegionWithName(monitorRegion)) break;

                    var monitorParameters = new NavigationParameters { { "Name", monitorRegion } };
                    _regionManager.RequestNavigate(monitorRegion, "MonitorView", monitorParameters);
                    IsLeftDrawerOpen = false;
                    break;
                case "记录界面":
                    if (_globalInfo.CurrentScope == "default" || string.IsNullOrEmpty(_globalInfo.CurrentScope)) break;

                    // 记录界面不是填到全局的 ShellViewManager，而是填到该工位专属的 region。
                    var recordRegion = _globalInfo.CurrentScope;
                    if (!_regionManager.Regions.ContainsRegionWithName(recordRegion)) break;

                    var recordParameters = new NavigationParameters { { "Name", recordRegion } };
                    _regionManager.RequestNavigate(recordRegion, "RecordView", recordParameters);
                    IsLeftDrawerOpen = false;
                    break;
                case "设置界面":
                    if (_globalInfo.CurrentScope == "default" || string.IsNullOrEmpty(_globalInfo.CurrentScope)) break;

                    // 记录界面不是填到全局的 ShellViewManager，而是填到该工位专属的 region。
                    var settingRegion = _globalInfo.CurrentScope;
                    if (!_regionManager.Regions.ContainsRegionWithName(settingRegion)) break;

                    var settingParameters = new NavigationParameters { { "Name", settingRegion } };
                    _regionManager.RequestNavigate(settingRegion, "SettingView", settingParameters);
                    IsLeftDrawerOpen = false;
                    break;
                case "台架移动界面":
                    if (_globalInfo.CurrentScope != "default") return;
                    _regionManager.RequestNavigate("ShellViewManager", "BenchMovementView");
                    break;
                case "曲线回读界面":
                    if (_globalInfo.CurrentScope != "default") return;
                    _regionManager.RequestNavigate("ShellViewManager", "CurveRecallView");
                    break;  
                case "测试报告导出界面":
                    if (_globalInfo.CurrentScope != "default") return;
                    _regionManager.RequestNavigate("ShellViewManager", "ExportView");
                    break;
            }
        }

        private void LeftDrawerOpen()
        {
            IsLeftDrawerOpen = true;
        }

        private void MinimizeWindow(Window window)
        {
            if (window != null)
                window.WindowState = WindowState.Minimized;
        }

        private void MaximizeWindow(Window window)
        {
            if (window != null)
            {
                window.WindowState = window.WindowState == WindowState.Maximized ? WindowState.Normal : WindowState.Maximized;
            }
        }

        private void CloseWindow(Window window)
        {
            window?.Close();
        }
        #endregion
    }
}