using LoopViewerApp;
using Newtonsoft.Json;
using SimpleLite.RCS;
using SimpleLite.RCS.CarTypes;
using SimpleCore;
using SimpleCore.Compiler;
using SimpleCore.Library;
using SimpleCore.PropType;
using StandardScene.CarTypes;
using StandardScene.Chained.Loop;
using StandardScene.Model;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

namespace StandardScene.Chained
{
    /// <summary>
    /// 抽象环线任务基类
    /// <para>核心功能：</para>
    /// <list type="bullet">
    ///   <item><description>支持多种启动类型：AutoLoop（自动循环）、Api、Plc、ButtonBox（外部触发）</description></item>
    ///   <item><description>支持多种任务类别：Loop（普通循环）、BranchPoint（分流点）、JoinPoint（汇合点）</description></item>
    ///   <item><description>支持流量控制：限制目标站点的最大车辆数</description></item>
    ///   <item><description>支持优先级调度：高优先级任务优先处理</description></item>
    ///   <item><description>支持配置热更新：tasklist.json 文件变更自动刷新</description></item>
    ///   <item><description>外部触发接口：子类可重写 OnApiTrigger/OnPlcTrigger/OnButtonTrigger 实现业务逻辑</description></item>
    /// </list>
    /// </summary>
    /// <remarks>
    /// <para>子类实现示例：</para>
    /// <code>
    /// public class MyLoopMission : AbstractLoopMission
    /// {
    ///     protected override ExternalTriggerResult OnApiTrigger(int currentSiteId, LoopTask task, Car car)
    ///     {
    ///         // 返回 UseTarget(目标站点) - 使用子类指定的目标
    ///         // 返回 UseConfigTarget() - 使用配置文件目标
    ///         // 返回 Fail() - 不分配任务
    ///         return ExternalTriggerResult.UseConfigTarget();
    ///     }
    /// }
    /// </code>
    /// </remarks>
    public abstract class AbstractLoopMission : Mission, IDisposable
    {
        #region 常量定义

        /// <summary>策略同步线程轮询间隔（毫秒）</summary>
        private const int STRATEGY_SYNC_INTERVAL_MS = 1000;

        /// <summary>业务逻辑线程轮询间隔（毫秒）</summary>
        private const int LOGIC_LOOP_INTERVAL_MS = 300;

        /// <summary>文件变更防抖延迟（毫秒）</summary>
        private const int FILE_CHANGE_DEBOUNCE_MS = 50;

        /// <summary>异常恢复等待时间（毫秒）</summary>
        private const int ERROR_RECOVERY_DELAY_MS = 3000;

        /// <summary>脚本异常检测触发延迟（毫秒）</summary>
        private const int SCRIPT_ERROR_TRIGGER_DELAY_MS = 3000;

        #endregion

        #region 外部触发结果类

        /// <summary>
        /// 外部触发处理结果类
        /// <para>用于子类重写外部触发接口时返回处理结果，决定目标站点的分配方式</para>
        /// </summary>
        /// <example>
        /// 使用示例：
        /// <code>
        /// // 方式1：使用子类指定的目标站点
        /// return ExternalTriggerResult.UseTarget(200);
        /// 
        /// // 方式2：使用配置文件中的目标站点（相当于返回 true）
        /// return ExternalTriggerResult.UseConfigTarget();
        /// 
        /// // 方式3：业务失败，不分配任务
        /// return ExternalTriggerResult.Fail();
        /// </code>
        /// </example>
        public class ExternalTriggerResult
        {
            /// <summary>
            /// 是否处理成功
            /// <para>true = 成功，将根据 CustomTargetSiteId 分配目标站点</para>
            /// <para>false = 失败或跳过，不分配任务</para>
            /// </summary>
            public bool Success { get; set; }

            /// <summary>
            /// 子类指定的目标站点ID
            /// <para>有值时使用此目标站点</para>
            /// <para>null 时使用配置文件中的 TargetStationId</para>
            /// </summary>
            public int? CustomTargetSiteId { get; set; }

            /// <summary>
            /// 创建成功结果，使用子类指定的目标站点
            /// </summary>
            /// <param name="targetSiteId">目标站点ID</param>
            /// <returns>包含指定目标的成功结果</returns>
            public static ExternalTriggerResult UseTarget(int targetSiteId)
            {
                return new ExternalTriggerResult
                {
                    Success = true,
                    CustomTargetSiteId = targetSiteId
                };
            }

            /// <summary>
            /// 创建成功结果，使用配置文件中的目标站点
            /// <para>等同于业务处理成功返回 true 的效果</para>
            /// </summary>
            /// <returns>使用配置目标的成功结果</returns>
            public static ExternalTriggerResult UseConfigTarget()
            {
                return new ExternalTriggerResult
                {
                    Success = true,
                    CustomTargetSiteId = null
                };
            }

            /// <summary>
            /// 创建失败结果，不分配任务
            /// <para>等同于业务处理失败返回 false 的效果</para>
            /// </summary>
            /// <returns>失败结果</returns>
            public static ExternalTriggerResult Fail()
            {
                return new ExternalTriggerResult { Success = false };
            }
        }

        #endregion

        #region 状态与字段

        /// <summary>
        /// 环线任务状态类
        /// </summary>
        public class AbstractLoopMissionStatus : MissionStatus
        {
            /// <summary>当前任务数量</summary>
            public int TaskCount { get; set; }

            /// <summary>最后一次错误信息</summary>
            public string LastError { get; set; } = "/";
        }

        /// <summary>任务状态对象</summary>
      /*  [JsonIgnore]
        public override MissionStatus status { get; set; } = new LoopMissionStatus();*/

        /// <summary>策略同步线程</summary>
        [JsonIgnore]
        private Thread _strategyThread;

        /// <summary>策略同步线程运行标志</summary>
        [JsonIgnore]
        private volatile bool _strategyRunning;

        /// <summary>业务逻辑线程</summary>
        [JsonIgnore]
        private Thread _logicThread;

        /// <summary>业务逻辑线程运行标志</summary>
        [JsonIgnore]
        private volatile bool _logicRunning;

        /// <summary>任务集合同步锁</summary>
        [JsonIgnore]
        private readonly object _tasksLock = new object();

        /// <summary>任务列表（线程安全访问需使用 _tasksLock）</summary>
        [JsonIgnore]
        protected readonly List<LoopTask> Tasks = new List<LoopTask>();

        /// <summary>触发器适配器列表</summary>
        [JsonIgnore]
        private readonly List<ITriggerAdapter> _adapters = new List<ITriggerAdapter>();

        /// <summary>任务策略实例</summary>
        private ITaskStrategy _taskStrategy;

        /// <summary>
        /// 任务策略属性
        /// <para>支持热更新，设置时自动订阅/取消订阅变更事件</para>
        /// </summary>
        public ITaskStrategy TaskStrategy
        {
            get => _taskStrategy;
            set
            {
                // 取消旧策略的事件订阅
                if (_taskStrategy is JsonFileTaskStrategy oldStrategy)
                {
                    oldStrategy.Changed -= OnTaskStrategyChanged;
                    oldStrategy.DisposeWatcher();
                }

                // 设置新策略（null 时使用默认策略）
                _taskStrategy = value ?? new JsonFileTaskStrategy();

                // 订阅新策略的变更事件
                if (_taskStrategy is JsonFileTaskStrategy newStrategy)
                {
                    newStrategy.Changed += OnTaskStrategyChanged;
                    newStrategy.EnsureWatcher();
                }
            }
        }

        /// <summary>任务列表变更事件</summary>
        public event EventHandler<TaskListChangedEventArgs> TaskListChanged;

        #endregion

        #region 构造函数

        /// <summary>
        /// 初始化抽象环线任务基类
        /// <para>自动使用默认的 JSON 文件策略并加载初始任务配置</para>
        /// </summary>
        protected AbstractLoopMission()
        {
            TaskStrategy = new JsonFileTaskStrategy();
            ApplyTaskStrategy();
        }

        #endregion

        #region 任务管理方法

        /// <summary>
        /// 获取当前任务列表的只读副本（线程安全）
        /// </summary>
        /// <returns>任务列表快照</returns>
        public IReadOnlyList<LoopTask> GetTasks()
        {
            lock (_tasksLock)
            {
                return Tasks.ToArray();
            }
        }

        /// <summary>
        /// 添加任务到列表末尾
        /// </summary>
        /// <param name="task">要添加的任务</param>
        /// <returns>新任务的索引</returns>
        /// <exception cref="ArgumentNullException">task 为 null 时抛出</exception>
        public int EnqueueTask(LoopTask task)
        {
            if (task == null)
                throw new ArgumentNullException(nameof(task));

            lock (_tasksLock)
            {
                Tasks.Add(task);
                int index = Tasks.Count - 1;

                // 触发任务添加事件
                TaskListChanged?.Invoke(this, new TaskListChangedEventArgs(TaskChangeType.Added, index, task));

                // 更新状态中的任务计数
                ((AbstractLoopMissionStatus)status).TaskCount = Tasks.Count;

                return index;
            }
        }

        /// <summary>
        /// 更新指定索引的任务
        /// </summary>
        /// <param name="index">任务索引</param>
        /// <param name="task">新的任务数据</param>
        /// <returns>是否更新成功</returns>
        public bool UpdateTask(int index, LoopTask task)
        {
            lock (_tasksLock)
            {
                if (index < 0 || index >= Tasks.Count)
                    return false;

                Tasks[index] = task;

                // 触发任务更新事件
                TaskListChanged?.Invoke(this, new TaskListChangedEventArgs(TaskChangeType.Updated, index, task));

                return true;
            }
        }

        /// <summary>
        /// 移除指定索引的任务
        /// </summary>
        /// <param name="index">任务索引</param>
        /// <returns>是否移除成功</returns>
        public bool RemoveTask(int index)
        {
            lock (_tasksLock)
            {
                if (index < 0 || index >= Tasks.Count)
                    return false;

                LoopTask task = Tasks[index];
                Tasks.RemoveAt(index);

                // 触发任务移除事件
                TaskListChanged?.Invoke(this, new TaskListChangedEventArgs(TaskChangeType.Removed, index, task));

                // 更新状态中的任务计数
                ((AbstractLoopMissionStatus)status).TaskCount = Tasks.Count;

                return true;
            }
        }

        #endregion

        #region 车辆查找辅助方法

        /// <summary>
        /// 查找恰好停在指定站点的车辆
        /// <para>条件：车辆的 holdingLocks 只包含该站点（表示车辆已到达并停稳）</para>
        /// </summary>
        /// <param name="siteId">站点ID</param>
        /// <returns>找到的车辆，未找到返回 null</returns>
        protected virtual Car FindCarArrivedAtSite(int siteId)
        {
            try
            {
                return SimpleLib.GetAllCars()
                    .OfType<Car>()
                    .FirstOrDefault(car =>
                        car?.status?.holdingLocks != null &&
                        car.status.holdingLocks.Length == 1 &&
                        car.status.holdingLocks[0] == siteId);
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine($"[AbstractLoopMission] FindCarArrivedAtSite({siteId}) error: {ex.Message}");
                return null;
            }
        }

        /// <summary>
        /// 获取当前在站或正在前往指定站点的所有车辆
        /// <para>用于流量控制统计</para>
        /// </summary>
        /// <param name="siteId">站点ID</param>
        /// <returns>车辆集合</returns>
        protected IEnumerable<Car> GetCarsAtOrHeadingToSite(int siteId)
        {
            try
            {
                return SimpleLib.GetAllCars()
                    .OfType<Car>()
                    .Where(car =>
                    {
                        if (car?.status == null)
                            return false;

                        // 检查是否在站：holdingLocks 包含该站点
                        if (car.status.holdingLocks?.Contains(siteId) == true)
                            return true;

                        // 检查是否前往：pendingLocks 最后一个锁定点为该站点
                        if (car.status.pendingLocks.LastOrDefault()==siteId)
                        {
                            return true;
                        }
                        // 检查是否前往：goalSite 标签指向该站点
                     /*   if (car.tags?.TryGetValue("goalSite", out var destStr) == true &&
                            int.TryParse(destStr, out int destId) &&
                            destId == siteId)
                            return true;*/

                        return false;
                    })
                    .ToList();
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine($"[AbstractLoopMission] GetCarsAtOrHeadingToSite({siteId}) error: {ex.Message}");
                return Array.Empty<Car>();
            }
        }

        /// <summary>
        /// 统计当前在站或正在前往指定站点的车辆数量
        /// </summary>
        /// <param name="siteId">站点ID</param>
        /// <returns>车辆数量</returns>
        protected int CountCarsAtOrHeadingToSite(int siteId)
        {
            return GetCarsAtOrHeadingToSite(siteId).Count();
        }

        /// <summary>
        /// 检查车辆是否空闲（未被占用、未有目标、未执行任务）
        /// </summary>
        /// <param name="car">车辆</param>
        /// <returns>是否空闲</returns>
        protected bool IsCarIdle(Car car)
        {
            if (car?.tags == null)
                return false;

            try
            {
                // 检查是否存在表示忙碌状态的标签
                if (car.tags.ContainsKey("occupied")) return false;
                if (car.tags.ContainsKey("dest")) return false;
                if (car.tags.ContainsKey("deliver")) return false;

                return true;
            }
            catch
            {
                return false;
            }
        }

        #endregion

        #region 流量控制检查

        /// <summary>
        /// 检查目标站点是否满足流量控制条件
        /// <para>统计当前在站或正在前往该站点的车辆数量，与最大允许数比较</para>
        /// </summary>
        /// <param name="targetSiteId">目标站点ID</param>
        /// <param name="maxAllowed">最大允许车辆数（0或负数表示不限制）</param>
        /// <returns>true=可以发车，false=已达上限需等待</returns>
        protected bool CheckTrafficControl(int targetSiteId, int maxAllowed)
        {
            // 不限制流量的情况
            if (maxAllowed <= 0)
                return true;

            int currentCount = CountCarsAtOrHeadingToSite(targetSiteId);
            return currentCount < maxAllowed;
        }

        #endregion

        #region 外部触发接口（子类重写）

        /// <summary>
        /// API 触发处理接口
        /// <para>当任务的 StartType 为 Api 时，车辆到达当前站点后会调用此方法</para>
        /// <para>子类重写此方法实现 API 触发的业务逻辑</para>
        /// </summary>
        /// <param name="currentSiteId">当前站点ID</param>
        /// <param name="task">匹配的任务配置</param>
        /// <param name="car">到达的车辆</param>
        /// <returns>
        /// 处理结果：
        /// <list type="bullet">
        ///   <item><description><see cref="ExternalTriggerResult.UseTarget"/> - 使用子类指定的目标站点</description></item>
        ///   <item><description><see cref="ExternalTriggerResult.UseConfigTarget"/> - 使用配置文件中的目标站点</description></item>
        ///   <item><description><see cref="ExternalTriggerResult.Fail"/> - 业务失败，不分配任务</description></item>
        /// </list>
        /// </returns>
        protected virtual ExternalTriggerResult OnApiTrigger(int currentSiteId, LoopTask task, Car car)
        {
            // 默认返回失败，子类需重写以启用 API 触发功能
            return ExternalTriggerResult.Fail();
        }

        /// <summary>
        /// PLC 信号触发处理接口
        /// <para>当任务的 StartType 为 Plc 时，车辆到达当前站点后会调用此方法</para>
        /// <para>子类重写此方法实现 PLC 触发的业务逻辑</para>
        /// </summary>
        /// <param name="currentSiteId">当前站点ID</param>
        /// <param name="task">匹配的任务配置</param>
        /// <param name="car">到达的车辆</param>
        /// <returns>处理结果</returns>
        protected virtual ExternalTriggerResult OnPlcTrigger(int currentSiteId, LoopTask task, Car car)
        {
            // 默认返回失败，子类需重写以启用 PLC 触发功能
            return ExternalTriggerResult.Fail();
        }

        /// <summary>
        /// 充电条件信号触发处理接口
        /// <para>当任务的 StartType 为 Plc 时，车辆到达当前站点后会调用此方法</para>
        /// <para>子类重写此方法实现 PLC 触发的业务逻辑</para>
        /// </summary>
        /// <param name="currentSiteId">当前站点ID</param>
        /// <param name="task">匹配的任务配置</param>
        /// <param name="car">到达的车辆</param>
        /// <returns>处理结果</returns>
        protected virtual ExternalTriggerResult OnChargeTrigger(int currentSiteId, LoopTask task, Car car)
        {
            // 默认返回失败，子类需重写已启用去充电触发功能
            return ExternalTriggerResult.Fail();
        }

        /// <summary>
        /// 按钮盒触发处理接口
        /// <para>当任务的 StartType 为 ButtonBox 时，车辆到达当前站点后会调用此方法</para>
        /// <para>子类重写此方法实现按钮盒触发的业务逻辑</para>
        /// </summary>
        /// <param name="currentSiteId">当前站点ID</param>
        /// <param name="task">匹配的任务配置</param>
        /// <param name="car">到达的车辆</param>
        /// <returns>处理结果</returns>
        protected virtual ExternalTriggerResult OnButtonTrigger(int currentSiteId, LoopTask task, Car car)
        {
            // 默认返回失败，子类需重写以启用按钮盒触发功能
            return ExternalTriggerResult.Fail();
        }

        /// <summary>
        /// 根据启动类型调用对应的子类触发接口
        /// </summary>
        /// <param name="startType">启动类型</param>
        /// <param name="currentSiteId">当前站点ID</param>
        /// <param name="task">匹配的任务配置</param>
        /// <param name="car">到达的车辆</param>
        /// <returns>子类返回的处理结果</returns>
        private ExternalTriggerResult InvokeExternalTrigger(TaskStartType startType, int currentSiteId, LoopTask task, Car car)
        {
            return startType switch
            {
                TaskStartType.Api => OnApiTrigger(currentSiteId, task, car),
                TaskStartType.Plc => OnPlcTrigger(currentSiteId, task, car),
                TaskStartType.ButtonBox => OnButtonTrigger(currentSiteId, task, car),
                TaskStartType.Charge => OnChargeTrigger(currentSiteId, task, car),
                _ => ExternalTriggerResult.Fail()
            };
        }

      

        #endregion

        #region 任务策略管理

        /// <summary>
        /// 从任务策略刷新并应用任务列表
        /// <para>读取配置文件内容并替换当前任务列表</para>
        /// </summary>
        public void ApplyTaskStrategy()
        {
            try
            {
                // 刷新策略数据
                TaskStrategy?.Refresh();
                var sourceTasks = TaskStrategy?.GetTasks();

                if (sourceTasks == null)
                    return;

                lock (_tasksLock)
                {
                    // 清空并重新加载任务
                    Tasks.Clear();
                    foreach (var task in sourceTasks)
                    {
                        Tasks.Add(task);
                    }

                    // 触发任务替换事件
                    TaskListChanged?.Invoke(this, new TaskListChangedEventArgs(TaskChangeType.Replaced, -1, null));

                    // 更新状态中的任务计数
                    ((AbstractLoopMissionStatus)status).TaskCount = Tasks.Count;
                }

                System.Diagnostics.Debug.WriteLine($"[AbstractLoopMission] ApplyTaskStrategy: 加载了 {Tasks.Count} 个任务");
            }
            catch (Exception ex)
            {
                // 记录错误信息
                ((AbstractLoopMissionStatus)status).LastError = ex.Message;
                System.Diagnostics.Debug.WriteLine($"[AbstractLoopMission] ApplyTaskStrategy error: {ex}");
            }
        }

        /// <summary>
        /// 任务策略配置文件变更处理
        /// </summary>
        private void OnTaskStrategyChanged(object sender, EventArgs e)
        {
            try
            {
                ApplyTaskStrategy();
                System.Diagnostics.Debug.WriteLine("[AbstractLoopMission] OnTaskStrategyChanged: 配置文件已更新");
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine($"[AbstractLoopMission] OnTaskStrategyChanged error: {ex}");
            }
        }

        #endregion

        #region 核心业务逻辑

        /// <summary>
        /// 业务逻辑主循环
        /// <para>在 _logicThread 线程中执行，每 500ms 处理一次任务调度</para>
        /// </summary>
        protected virtual void ExecuteLogicLoop()
        {
            while (_logicRunning)
            {
                try
                {
                    ProcessAutoLoopTasks();
                    Thread.Sleep(LOGIC_LOOP_INTERVAL_MS);
                }
                catch (ThreadAbortException)
                {
                    break;
                }
                catch (Exception ex)
                {
                    System.Diagnostics.Debug.WriteLine($"[AbstractLoopMission] ExecuteLogicLoop error: {ex}");
                }
            }
        }

        /// <summary>
        /// 处理所有任务（主调度入口）
        /// <para>按顺序处理：自动循环任务 → 外部触发任务 → 分流点任务 → 汇合点任务 → 循环启动动作</para>
        /// </summary>
        protected virtual void ProcessAutoLoopTasks()
        {
            // 获取任务快照（避免长时间持锁）
            List<LoopTask> snapshot;
            lock (_tasksLock)
            {
                snapshot = Tasks.ToList();
            }

            // 1. 处理自动循环任务（StartType=AutoLoop, Kind=Loop）
            ProcessAutoLoopTypeTasks(snapshot);

            // 2. 处理外部触发任务（StartType=Api/Plc/ButtonBox/charge）
            ProcessExternalTriggerTasks(snapshot);

            // 3. 处理自动分流点任务（StartType=AutoLoop, Kind=BranchPoint）
            ProcessBranchPointTasks(snapshot);

            // 4. 处理自动汇合点任务（StartType=AutoLoop, Kind=JoinPoint）
            ProcessJoinPointTasks(snapshot);

            // 5. 执行循环启动动作（处理站点默认目标、执行导航、异常恢复等）
            LoopStartAction();
        }

        /// <summary>
        /// 处理自动循环类型任务
        /// <para>筛选 StartType=AutoLoop 且 Kind=Loop 的任务，按优先级处理</para>
        /// </summary>
        /// <param name="snapshot">任务快照</param>
        private void ProcessAutoLoopTypeTasks(List<LoopTask> snapshot)
        {
            // 筛选自动循环任务并按优先级排序
            var autoTasks = snapshot
                .Where(t => t.StartType == TaskStartType.AutoLoop && t.Kind == TaskKind.Loop)
                .OrderByDescending(t => t.Priority)
                .ToList();

            foreach (var task in autoTasks)
            {
                try
                {
                    // 查找到达当前站点的车辆
                    var car = FindCarArrivedAtSite(task.CurrentStationId);
                    if (car == null)
                        continue;

                    // 检查车辆是否可用（SelectCar 返回 1 表示可用）
                    if (Commons.SelectCar(car) != 1)
                        continue;

                    // 流量控制检查
                    if (!CheckTrafficControl(task.TargetStationId, task.TrafficControl))
                    {
                     
                        Diagnosis.Post($"[AbstractLoopMission] AutoLoop: 目标站点 {task.TargetStationId} 流量已满，车辆 {car.name} 等待", "Loop-AutoLoop", true);
                        continue;
                    }

                    // 分配目标站点
                    AssignCarToTarget(car, task.TargetStationId);
                    Diagnosis.Post($"[AbstractLoopMission] AutoLoop: 车辆 {car.name} 从站点 {task.CurrentStationId} 自动分配到目标站点 {task.TargetStationId}", "Loop-AutoLoop", true);
                   
                }
                catch (Exception ex)
                {
                    Diagnosis.Post($"[AbstractLoopMission] ProcessAutoLoopTypeTasks error: {ex}", "Loop-AutoLoop", true);
        
                }
            }
        }

        /// <summary>
        /// 处理外部触发类型任务（API/PLC/ButtonBox）
        /// <para>依次处理各类型的外部触发任务</para>
        /// </summary>
        /// <param name="snapshot">任务快照</param>
        private void ProcessExternalTriggerTasks(List<LoopTask> snapshot)
        {
            // 依次处理 API、PLC、ButtonBox 类型任务
            ProcessExternalTasksByType(snapshot, TaskStartType.Api);
            ProcessExternalTasksByType(snapshot, TaskStartType.Plc);
            ProcessExternalTasksByType(snapshot, TaskStartType.ButtonBox);
            ProcessExternalTasksByType(snapshot, TaskStartType.Charge);
        }

        /// <summary>
        /// 按启动类型处理外部触发任务
        /// <para>处理普通循环任务、分流点任务、汇合点任务</para>
        /// </summary>
        /// <param name="snapshot">任务快照</param>
        /// <param name="startType">启动类型</param>
        private void ProcessExternalTasksByType(List<LoopTask> snapshot, TaskStartType startType)
        {
            // 筛选指定启动类型的普通循环任务
            var externalTasks = snapshot
                .Where(t => t.StartType == startType && t.Kind == TaskKind.Loop)
                .OrderByDescending(t => t.Priority)
                .ToList();

            foreach (var task in externalTasks)
            {
                try
                {
                    // 查找到达当前站点的车辆
                    var car = FindCarArrivedAtSite(task.CurrentStationId);
                    if (car == null)
                        continue;

                    // 检查车辆是否可用
                    if (Commons.SelectCar(car) != 1)
                        continue;

                    // 调用子类接口获取处理结果
                    ExternalTriggerResult result = InvokeExternalTrigger(startType, task.CurrentStationId, task, car);

                    // 子类返回失败则跳过
                    if (result?.Success != true)
                        continue;

                    // 确定目标站点：子类指定 > 配置文件
                    int targetSiteId = result.CustomTargetSiteId ?? task.TargetStationId;

                    // 流量控制检查
                    if (!CheckTrafficControl(targetSiteId, task.TrafficControl))
                    {
                        Diagnosis.Post($"[AbstractLoopMission] {startType}: 目标站点 {targetSiteId} 流量已满，车辆 {car.name} 等待", $"Loop-{startType}", true);
                     
                        continue;
                    }

                    // 分配目标站点
                    AssignCarToTarget(car, targetSiteId);
                    Diagnosis.Post($"[AbstractLoopMission] {startType}: 车辆 {car.name} 从站点 {task.CurrentStationId} 分配到目标站点 {targetSiteId}", $"Loop-{startType}", true);
                  
                }
                catch (Exception ex)
                {
                    Diagnosis.Post($"[AbstractLoopMission] ProcessExternalTasksByType({startType}) error: {ex}", $"Loop-{startType}", true);
                  
                }
            }

            // 处理分流点类型的外部触发任务
            ProcessExternalBranchTasks(snapshot, startType);

            // 处理汇合点类型的外部触发任务
            ProcessExternalJoinTasks(snapshot, startType);
        }

        /// <summary>
        /// 处理外部触发的分流点任务
        /// <para>按当前站点分组，优先级排序，调用子类接口后分配目标</para>
        /// </summary>
        /// <param name="snapshot">任务快照</param>
        /// <param name="startType">启动类型</param>
        private void ProcessExternalBranchTasks(List<LoopTask> snapshot, TaskStartType startType)
        {
            // 按当前站点分组
            var branchGroups = snapshot
                .Where(t => t.Kind == TaskKind.BranchPoint && t.StartType == startType)
                .GroupBy(t => t.CurrentStationId)
                .ToList();

            foreach (var group in branchGroups)
            {
                int currentSiteId = group.Key;

                // 查找到达当前站点的车辆
                var car = FindCarArrivedAtSite(currentSiteId);
                if (car == null || Commons.SelectCar(car) != 1)
                    continue;

                // 按优先级排序
                var sortedTasks = group.OrderByDescending(t => t.Priority).ToList();

                foreach (var task in sortedTasks)
                {
                    // 调用子类接口
                    ExternalTriggerResult result = InvokeExternalTrigger(startType, currentSiteId, task, car);

                    if (result?.Success != true)
                        continue;

                    // 确定目标：子类指定 > 按优先级选择流量允许的目标
                    int targetSiteId = result.CustomTargetSiteId ?? SelectBranchTarget(task, snapshot);

                    if (CheckTrafficControl(targetSiteId, task.TrafficControl))
                    {
                        AssignCarToTarget(car, targetSiteId);
                        Diagnosis.Post($"[AbstractLoopMission] {startType} BranchPoint: 车辆 {car.name} 从分流点 {currentSiteId} 分配到目标 {targetSiteId}", $"BranchPoint-{startType}", true);
                      
                        break; // 分流点只分配一个目标
                    }
                }
            }
        }

      


        /// <summary>
        /// 处理外部触发的汇合点任务
        /// <para>按目标站点分组（汇合点），每组中的策略按优先级排列，排列后每个策略根据流量判断，最后采用接口返回结果</para>
        /// </summary>
        /// <param name="snapshot">任务快照</param>
        /// <param name="startType">启动类型</param>
        private void ProcessExternalJoinTasks(List<LoopTask> snapshot, TaskStartType startType)
        {
            // 按目标站点分组（汇合点）
            var joinGroups = snapshot
                .Where(t => t.Kind == TaskKind.JoinPoint && t.StartType == startType)
                .GroupBy(t => t.TargetStationId)
                .ToList();

            foreach (var group in joinGroups)
            {
                int targetSiteId = group.Key;

                // 按优先级降序排列组内任务
                var sortedTasks = group.OrderByDescending(t => t.Priority).ToList();

                // 遍历排序后的任务，根据流量和接口返回结果处理
                foreach (var task in sortedTasks)
                {
                    try
                    {

                        // 查找到达当前站点的车辆
                        var car = FindCarArrivedAtSite(task.CurrentStationId);
                        if (car == null)
                            continue;

                        // 检查车辆是否可用
                        if (Commons.SelectCar(car) != 1)
                            continue;


                        // 流量控制检查（优先判断，避免无效的接口调用）
                        if (!CheckTrafficControl(targetSiteId, task.TrafficControl))
                        {
                            Diagnosis.Post($"[AbstractLoopMission] {startType} JoinPoint: 目标站点 {targetSiteId} 流量已满，跳过任务 {task.Id}", $"JoinPoint-{startType}", true);
                            continue;
                        }
                  

                        // 调用子类接口获取处理结果
                        ExternalTriggerResult result = InvokeExternalTrigger(startType, task.CurrentStationId, task, car);

                        // 子类返回失败则跳过当前任务
                        if (result?.Success != true)
                            continue;

                        // 确定最终目标：子类指定 > 配置文件
                        int finalTarget = result.CustomTargetSiteId ?? targetSiteId;

                        // 如果子类指定了不同的目标，需要再次检查流量
                        if (finalTarget != targetSiteId && !CheckTrafficControl(finalTarget, task.TrafficControl))
                        {
                            Diagnosis.Post($"[AbstractLoopMission] {startType} JoinPoint: 子类指定目标站点 {finalTarget} 流量已满，车辆 {car.name} 等待", $"JoinPoint-{startType}", true);
                            continue;
                        }

                        // 分配目标站点
                        AssignCarToTarget(car, finalTarget);
                        Diagnosis.Post($"[AbstractLoopMission] {startType} JoinPoint: 车辆 {car.name} 从站点 {task.CurrentStationId} 汇入目标 {finalTarget}（优先级 {task.Priority}）", $"JoinPoint-{startType}", true);
                    }
                    catch (Exception ex)
                    {
                        Diagnosis.Post($"[AbstractLoopMission] ProcessExternalJoinTasks({startType}) task {task.Id} error: {ex.Message}", $"JoinPoint-{startType}", true);
                    }
                }
            }
        }
        /// <summary>
        /// 循环启动动作
        /// <para>处理站点配置的默认目标、执行路径规划导航、检测并处理脚本异常</para>
        /// <para>注意：此方法不拆分，保持原有逻辑完整性</para>
        /// </summary>
        private void LoopStartAction()
        {
            try
            {
                foreach (var car in SimpleLib.GetAllCars())
                {
                    // 如果车辆可用且没有目标，尝试从站点配置读取默认目标
                    if (Commons.SelectCar(car) == 1 && !car.tags.Contains("goalSite"))
                    {
                        var carSite = SimpleLib.GetSite(car.GetLastSite());
                        if (carSite != null && carSite.fields.TryGetValue("goSite", out var dst))
                        {
                            Commons.AddOrUpdateTag(car.tags, "goalSite", dst);
                        }
                        if (carSite != null && !car.tags.Contains("goalSite"))
                        {
                            var taskLine = FindBestTaskForCar((Car)car);
                            if (taskLine!=null  && !taskLine.IsAtStartPoint && !taskLine.IsAtEndPoint)
                            {
                                Commons.AddOrUpdateTag(car.tags, "goalSite", taskLine.TargetSiteId.ToString());
                            }
                        }
                    }

                    // 如果车辆可用且有目标，执行导航
                    if (Commons.SelectCar(car) == 1 && car.tags.Contains("goalSite"))
                    {
                        var goalSite = SimpleLib.GetAllSites()
                            .FirstOrDefault(s => car.tags.IsEqual("goalSite", s.id.ToString()));
                        var holdingSite=car.status.holdingLocks.FirstOrDefault();
                        if (goalSite != null && holdingSite!=goalSite.id )
                        {
                             _=GoSite(car, goalSite);
                         
                        }
                        else if (goalSite != null && holdingSite == goalSite.id)
                        {
                            // 已到达目标，清理 goalSite 标签
                            car.tags.Remove("goalSite");
                            car.tags.Remove("loopAssigned");
                        }
                    
                    }

                    // 以下处理声明了脚本异常自恢复能力的车辆（IScriptErrorRecoverable，当前为 Kiva）
                    if (!(car is IScriptErrorRecoverable recoverable) || !(car is Car mcar))
                        continue;

                    // 检测脚本异常状态：车辆被占用但脚本状态为 Error 或 Bad
                    LadderLogic.TriggerOnce(
                        mcar.tags.Contains("occupied") &&
                        (mcar.status.programs.printStatus().Contains("Error") || mcar.status.programs.printStatus().Contains("Bad")),
                        SCRIPT_ERROR_TRIGGER_DELAY_MS,
                        () =>
                        {
                            // 获取车辆最后持有的站点锁
                            var lastHoldingLocks = car.status.holdingLocks.First();
                            var site = SimpleLib.GetSite(lastHoldingLocks);

                            // 标记站点不可用
                            site.MakeAllCarsUnavailable();

                            // 禁止车辆调度
                            mcar.NoSchedule(true);
                            Diagnosis.Post($"errStatus ", "NoSchedule", true);

                            // 重置车辆站点ID
                            mcar.siteID = -1;

                            // 更新车辆使用状态
                            mcar.status.usage.AddUsage("base", new CarUsage.CarUsageInfo()
                            {
                                scheduling = false,
                                refreshing = false
                            });

                            // 设置车辆状态为返厂检修
                            mcar.lstatus = "返厂检修";

                            // 清理车辆标签
                            Commons.DeleteTag(mcar.tags, "occupied");
                           // Commons.DeleteTag(mcar.tags, "goalSite");

                            // 执行车辆重置
                            ((Car)car).Intercept((_) =>
                            {
                                recoverable.RecoverReset(lastHoldingLocks);
                            });
                        },
                        mcar.id
                    );
                }
            }
            catch (Exception e)
            {
                Diagnosis.Post($"loop mission error {ExceptionFormatter.FormatEx(e)}");
            }
        }

   
        /// <summary>
        /// 导航车辆到目标站点
        /// <para>创建路径规划并执行移动任务</para>
        /// </summary>
        /// <param name="car">车辆</param>
        /// <param name="targetSite">目标站点</param>
        /// <param name="action">动作参数，默认为 "/"</param>
        /// <param name="reverse">是否倒车，默认为 false</param>
        public async Task GoSite(AbstractCar car, Site targetSite, string action = "/", bool reverse = false)
        {
            try
            {
                // 创建路径规划
                var plan = new SegmentPlan() { usingCar = car };
                plan.fields["reverse"] = reverse.ToString();
                plan.fields["action"] = action;
                plan.fields["allow_destination_on_route"] = "true";

                // 查找从当前位置到目标站点的路径
                plan.FindRoute(SimpleLib.GetSite(car.GetLastSite()), targetSite);

                // 编译并执行移动脚本（默认 Forecast）
                var program = plan.Compile("move");

                // 标记车辆为占用状态
                car.tags.Add("occupied", $"go{targetSite.id}");

                Console.WriteLine($">>Script:{program.script}");

                // 等待任务完成
                var tsk = program.Queue();
                await tsk;

                // 任务完成后清理标签
                car.tags.Remove("occupied");
                car.tags.Remove("goalSite");
                car.tags.Remove("loopAssigned");
            }
            catch (Exception ex)
            {
                try
                {
                    car.tags.Remove("occupied");
                    if (car is Car trafficCar && car.GetLastSite() > 0)
                    {
                        var currentSite = SimpleLib.GetSite(car.GetLastSite());
                        if (currentSite != null)
                        {
                            trafficCar.TrafficReset(currentSite, true, strict: false);
                        }
                    }
                }
                catch
                {
                }

                // 记录异常并等待后重试
                Diagnosis.Post(
                    $"{car.name}循环任务报错{ExceptionFormatter.FormatEx(ex)}--去往循环点id:{targetSite.id},name:{targetSite.name}",
                    $"重新执行循环任务",
                    true
                );
                Thread.Sleep(ERROR_RECOVERY_DELAY_MS);
            }
        }

        /// <summary>
        /// 处理自动分流点任务
        /// <para>筛选 StartType=AutoLoop 且 Kind=BranchPoint 的任务</para>
        /// <para>按当前站点分组，优先级排序，选择流量允许的目标</para>
        /// </summary>
        /// <param name="allTasks">任务列表</param>
        protected virtual void ProcessBranchPointTasks(List<LoopTask> allTasks)
        {
            // 按当前站点分组
            var branchGroups = allTasks
                .Where(t => t.Kind == TaskKind.BranchPoint && t.StartType == TaskStartType.AutoLoop)
                .GroupBy(t => t.CurrentStationId)
                .ToList();

            foreach (var group in branchGroups)
            {
                int currentSiteId = group.Key;

                // 查找到达当前站点的车辆
                var car = FindCarArrivedAtSite(currentSiteId);
                if (car == null || Commons.SelectCar(car) != 1)
                    continue;

                // 按优先级排序，选择流量允许的目标
                var sortedTasks = group.OrderByDescending(t => t.Priority).ToList();

                foreach (var task in sortedTasks)
                {
                    if (CheckTrafficControl(task.TargetStationId, task.TrafficControl))
                    {
                        AssignCarToTarget(car, task.TargetStationId);
                        Diagnosis.Post($"[AbstractLoopMission] BranchPoint: 车辆 {car.name}-{car.id} 从分流点 {currentSiteId} 分配到目标 {task.TargetStationId}（优先级 {task.Priority}）", $"BranchPoint-AutoLoop", true);
                       
                        break; // 分流点只分配一个目标
                    }
                }
            }
        }

        /// <summary>
        /// 处理自动汇合点任务
        /// <para>筛选 StartType=AutoLoop 且 Kind=JoinPoint 的任务</para>
        /// <para>按目标站点分组，优先级排序，选择有车在站的最高优先级任务</para>
        /// </summary>
        /// <param name="allTasks">任务列表</param>
        protected virtual void ProcessJoinPointTasks(List<LoopTask> allTasks)
        {
            // 按目标站点分组（汇合点）
            var joinGroups = allTasks
                .Where(t => t.Kind == TaskKind.JoinPoint && t.StartType == TaskStartType.AutoLoop)
                .GroupBy(t => t.TargetStationId)
                .ToList();

            foreach (var group in joinGroups)
            {
                int targetSiteId = group.Key;

                // 检查汇合点流量控制
                var firstTask = group.First();
                if (!CheckTrafficControl(targetSiteId, firstTask.TrafficControl))
                    continue;

                // 按优先级排序，选择有车在站的最高优先级任务
                var sortedTasks = group.OrderByDescending(t => t.Priority).ToList();

                foreach (var task in sortedTasks)
                {
                    var car = FindCarArrivedAtSite(task.CurrentStationId);

                    if (car != null && Commons.SelectCar(car) == 1)
                    {
                        AssignCarToTarget(car, targetSiteId);
                        Diagnosis.Post($"[AbstractLoopMission] JoinPoint: 车辆 {car.name} 从站点 {task.CurrentStationId} 汇入目标 {targetSiteId}（优先级 {task.Priority}）", $"JoinPoint-AutoLoop", true);
                      
                        //break; // 汇合点一次只放行一辆车
                    }
                }
            }
        }

        /// <summary>
        /// 分流点目标选择
        /// <para>按优先级选择流量允许的目标站点</para>
        /// </summary>
        /// <param name="branchTask">当前分流任务</param>
        /// <param name="allTasks">所有任务列表</param>
        /// <returns>选中的目标站点ID</returns>
        protected virtual int SelectBranchTarget(LoopTask branchTask, List<LoopTask> allTasks)
        {
            // 查找同一当前站点的所有分流目标
            var branches = allTasks
                .Where(t => t.Kind == TaskKind.BranchPoint && t.CurrentStationId == branchTask.CurrentStationId)
                .OrderByDescending(t => t.Priority)
                .ToList();

            // 按优先级选择流量允许的目标
            foreach (var branch in branches)
            {
                if (CheckTrafficControl(branch.TargetStationId, branch.TrafficControl))
                {
                    return branch.TargetStationId;
                }
            }

            // 默认返回原任务目标
            return branchTask.TargetStationId;
        }

        /// <summary>
        /// 汇合点通行判断
        /// <para>检查当前任务是否有最高优先级通行权（是否有更高优先级的车在等待）</para>
        /// </summary>
        /// <param name="joinTask">当前汇合任务</param>
        /// <param name="allTasks">所有任务列表</param>
        /// <returns>true=可以通行，false=需要等待更高优先级的车</returns>
        protected virtual bool CanJoinPass(LoopTask joinTask, List<LoopTask> allTasks)
        {
            // 查找同一目标站点的所有汇合来源
            var joinSources = allTasks
                .Where(t => t.Kind == TaskKind.JoinPoint && t.TargetStationId == joinTask.TargetStationId)
                .OrderByDescending(t => t.Priority)
                .ToList();

            // 检查是否有更高优先级的任务且其站点有空闲车等待
            foreach (var source in joinSources)
            {
                if (source.Priority > joinTask.Priority)
                {
                    var higherPriorityCar = FindCarArrivedAtSite(source.CurrentStationId);
                    if (higherPriorityCar != null && IsCarIdle(higherPriorityCar))
                    {
                        return false; // 有更高优先级的车等待，当前车需要让行
                    }
                }
            }

            return true;
        }

        /// <summary>
        /// 为车辆分配目标站点
        /// <para>设置车辆的 goalSite 标签和 loopAssigned 时间戳</para>
        /// </summary>
        /// <param name="car">车辆</param>
        /// <param name="targetSiteId">目标站点ID</param>
        protected virtual void AssignCarToTarget(Car car, int targetSiteId)
        {
            if (car == null)
                return;

            try
            {
                string targetIdStr = targetSiteId.ToString();

                // 设置或更新目标站点标签
                if (car.tags.ContainsKey("goalSite"))
                    car.tags["goalSite"] = targetIdStr;
                else
                    car.tags.Add("goalSite", targetIdStr);

                // 记录分配时间（用于调试和监控）
                if (!car.tags.ContainsKey("loopAssigned"))
                    car.tags.Add("loopAssigned", DateTime.Now.ToString("HH:mm:ss"));
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine($"[AbstractLoopMission] AssignCarToTarget error: {ex}");
            }
        }

        #endregion

        #region 线程生命周期

        /// <summary>
        /// 启动策略同步线程
        /// <para>每秒同步一次配置文件，自动更新任务列表</para>
        /// </summary>
        public virtual void StartLoop()
        {
            if (_strategyRunning)
                return;

            _strategyRunning = true;
            _strategyThread = new Thread(() =>
            {
                while (_strategyRunning)
                {
                    try
                    {
                        ApplyTaskStrategy();
                        Thread.Sleep(STRATEGY_SYNC_INTERVAL_MS);
                    }
                    catch (ThreadAbortException)
                    {
                        break;
                    }
                    catch (Exception ex)
                    {
                        System.Diagnostics.Debug.WriteLine($"[AbstractLoopMission] Strategy loop error: {ex}");
                    }
                }
            })
            {
                Name = "AbstractLoopMission_Strategy",
                IsBackground = true
            };
            _strategyThread.Start();

            status.status = "策略同步已启动";
            System.Diagnostics.Debug.WriteLine("[AbstractLoopMission] StartLoop: 策略同步线程已启动");
        }

        /// <summary>
        /// 启动业务逻辑线程
        /// <para>每 500ms 处理一次任务调度</para>
        /// </summary>
        public virtual void StartLogicLoop()
        {
            if (_logicRunning)
                return;

            _logicRunning = true;
            _logicThread = new Thread(ExecuteLogicLoop)
            {
                Name = "AbstractLoopMission_Logic",
                IsBackground = true
            };
            _logicThread.Start();

            status.status = "业务逻辑已启动";
            System.Diagnostics.Debug.WriteLine("[AbstractLoopMission] StartLogicLoop: 业务逻辑线程已启动");
        }

        /// <summary>
        /// 停止策略同步线程
        /// </summary>
        public virtual void StopLoop()
        {
            try
            {
                _strategyRunning = false;
                _strategyThread?.Join(2000);
                _strategyThread = null;
                System.Diagnostics.Debug.WriteLine("[AbstractLoopMission] StopLoop: 策略同步线程已停止");
            }
            catch { }
        }

        /// <summary>
        /// 停止业务逻辑线程
        /// </summary>
        public virtual void StopLogicLoop()
        {
            try
            {
                _logicRunning = false;
                _logicThread?.Join(2000);
                _logicThread = null;
                System.Diagnostics.Debug.WriteLine("[AbstractLoopMission] StopLogicLoop: 业务逻辑线程已停止");
            }
            catch { }
        }

        /// <summary>
        /// 启动所有线程（策略同步 + 业务逻辑）
        /// </summary>
        public virtual void StartAll()
        {
           // ApplyTaskStrategy();
            MarkTaskStartSitesAsTerminal();
            StartLoop();
            StartLogicLoop();
            status.status = "已启动";
        }

        /// <summary>
        /// 将任务策略中的起始站点标记为 terminal=true
        /// </summary>
        private void MarkTaskStartSitesAsTerminal()
        {
            List<int> startSiteIds;
            lock (_tasksLock)
            {
                startSiteIds = Tasks
                    .Select(t => t.CurrentStationId)
                    .Where(id => id > 0)
                    .Distinct()
                    .ToList();
            }

            foreach (var siteId in startSiteIds)
            {
                var site = SimpleLib.GetSite(siteId);
                if (site == null)
                    continue;

                Commons.AddOrUpdateSiteField(site, "terminal", "true");
            }
        }

        /// <summary>
        /// 停止所有线程
        /// </summary>
        public virtual void StopAll()
        {
            StopLoop();
            StopLogicLoop();
            status.status = "已停止";
        }

        /// <summary>
        /// 释放资源
        /// <para>清理触发器适配器、停止所有线程、取消策略订阅</para>
        /// </summary>
        public void Dispose()
        {
            // 清理触发器适配器
            foreach (var adapter in _adapters.ToArray())
            {
                try
                {
                    adapter?.Dispose();
                }
                catch { }
            }
            _adapters.Clear();

            // 停止所有线程
            StopAll();

            // 取消策略订阅
            if (_taskStrategy is JsonFileTaskStrategy jsonStrategy)
            {
                jsonStrategy.Changed -= OnTaskStrategyChanged;
                jsonStrategy.DisposeWatcher();
            }

            System.Diagnostics.Debug.WriteLine("[AbstractLoopMission] Dispose: 资源已释放");
        }

        #endregion

        #region 辅助类型

        /// <summary>
        /// 任务列表变更事件参数
        /// </summary>
        public class TaskListChangedEventArgs : EventArgs
        {
            /// <summary>变更类型</summary>
            public TaskChangeType ChangeType { get; }

            /// <summary>变更的任务索引（Replaced 时为 -1）</summary>
            public int Index { get; }

            /// <summary>变更的任务（Replaced 时为 null）</summary>
            public LoopTask Task { get; }

            /// <summary>
            /// 创建任务列表变更事件参数
            /// </summary>
            /// <param name="changeType">变更类型</param>
            /// <param name="index">任务索引</param>
            /// <param name="task">任务对象</param>
            public TaskListChangedEventArgs(TaskChangeType changeType, int index, LoopTask task)
            {
                ChangeType = changeType;
                Index = index;
                Task = task;
            }
        }

        /// <summary>
        /// 任务变更类型枚举
        /// </summary>
        public enum TaskChangeType
        {
            /// <summary>添加任务</summary>
            Added,
            /// <summary>更新任务</summary>
            Updated,
            /// <summary>移除任务</summary>
            Removed,
            /// <summary>替换全部任务</summary>
            Replaced
        }

        /// <summary>
        /// 循环点配置类
        /// <para>用于定义循环点的规则和属性</para>
        /// </summary>
        public class LoopPoint
        {
            /// <summary>唯一标识</summary>
            public string Id { get; set; } = Guid.NewGuid().ToString("N");

            /// <summary>名称</summary>
            public string Name { get; set; } = string.Empty;

            /// <summary>自定义标签集合</summary>
            public Dictionary<string, object> Tags { get; } = new Dictionary<string, object>();

            /// <summary>进入规则</summary>
            public IEnterRule EnterRule { get; set; }

            /// <summary>退出规则</summary>
            public IExitRule ExitRule { get; set; }

            /// <summary>汇合规则</summary>
            public IJoinRule JoinRule { get; set; }

            /// <summary>分流规则</summary>
            public IBranchRule BranchRule { get; set; }
        }

        /// <summary>
        /// JSON 文件任务策略类
        /// <para>从 tasklist.json 读取任务配置，支持文件变更自动刷新</para>
        /// </summary>
        public class JsonFileTaskStrategy : ITaskStrategy, IDisposable
        {
            /// <summary>JSON 文件路径</summary>
            public string JsonPath { get; set; }

            /// <summary>任务缓存列表</summary>
            private List<LoopTask> _cache = new List<LoopTask>();

            /// <summary>文件系统监听器</summary>
            private FileSystemWatcher _watcher;

            /// <summary>配置变更事件</summary>
            public event EventHandler Changed;

            /// <summary>
            /// 创建 JSON 文件任务策略
            /// </summary>
            /// <param name="jsonPath">JSON 文件路径（null 时使用默认路径 tasklist.json）</param>
            public JsonFileTaskStrategy(string jsonPath = null)
            {
                JsonPath = string.IsNullOrWhiteSpace(jsonPath)
                    ? Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "tasklist.json")
                    : jsonPath;

                EnsureWatcher();
                Refresh();
            }

            /// <summary>
            /// 获取任务列表
            /// </summary>
            /// <returns>任务列表副本</returns>
            public IEnumerable<LoopTask> GetTasks()
            {
                return _cache.ToArray();
            }

            /// <summary>
            /// 刷新任务列表（从文件重新读取）
            /// </summary>
            public void Refresh()
            {
                try
                {
                    if (!File.Exists(JsonPath))
                    {
                        _cache = new List<LoopTask>();
                        return;
                    }

                    string json = File.ReadAllText(JsonPath);
                    _cache = JsonConvert.DeserializeObject<List<LoopTask>>(json) ?? new List<LoopTask>();
                }
                catch
                {
                    _cache = new List<LoopTask>();
                }
            }

            /// <summary>
            /// 确保文件监听器已启动
            /// </summary>
            public void EnsureWatcher()
            {
                try
                {
                    if (_watcher != null)
                        return;

                    string directory = Path.GetDirectoryName(JsonPath);
                    string fileName = Path.GetFileName(JsonPath);

                    if (string.IsNullOrEmpty(directory))
                        return;

                    _watcher = new FileSystemWatcher(directory, fileName)
                    {
                        NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.Size | NotifyFilters.FileName
                    };

                    _watcher.Changed += (s, e) => OnFileChanged();
                    _watcher.Renamed += (s, e) => OnFileChanged();
                    _watcher.EnableRaisingEvents = true;
                }
                catch { }
            }

            private void OnFileChanged()
            {
                try
                {
                    Thread.Sleep(50);
                    Refresh();
                    Changed?.Invoke(this, EventArgs.Empty);
                }
                catch { }
            }

            public void DisposeWatcher()
            {
                try
                {
                    if (_watcher != null)
                    {
                        _watcher.EnableRaisingEvents = false;
                        _watcher.Dispose();
                        _watcher = null;
                    }
                }
                catch { }
            }

            public void Dispose()
            {
                DisposeWatcher();
            }
        }

        #endregion

        #region 路径查找辅助方法

        /// <summary>
        /// 查找从起点到终点之间的所有站点（基于轨道连接的广度优先搜索）
        /// </summary>
        /// <param name="startSiteId">起点站点ID</param>
        /// <param name="endSiteId">终点站点ID</param>
        /// <returns>从起点到终点的站点ID列表（包含起点和终点），未找到路径返回空列表</returns>
        /// <example>
        /// <code>
        /// // 查找站点100到站点200之间的所有站点
        /// var sites = GetSitesBetween(100, 200);
        /// // 返回: [100, 150, 180, 200]
        /// </code>
        /// </example>
        protected List<int> GetSitesBetween(int startSiteId, int endSiteId)
        {
            if (startSiteId == endSiteId)
                return new List<int> { startSiteId };

            try
            {
                // 构建站点邻接表
                var adjacency = BuildSiteAdjacency();

                // 广度优先搜索
                var visited = new HashSet<int>();
                var queue = new Queue<List<int>>();
                queue.Enqueue(new List<int> { startSiteId });
                visited.Add(startSiteId);

                while (queue.Count > 0)
                {
                    var currentPath = queue.Dequeue();
                    int currentSite = currentPath[currentPath.Count - 1];

                    // 找到终点，返回路径
                    if (currentSite == endSiteId)
                        return currentPath;

                    // 获取相邻站点
                    if (!adjacency.TryGetValue(currentSite, out var neighbors))
                        continue;

                    foreach (var neighbor in neighbors)
                    {
                        if (visited.Contains(neighbor))
                            continue;

                        visited.Add(neighbor);
                        var newPath = new List<int>(currentPath) { neighbor };
                        queue.Enqueue(newPath);
                    }
                }

                // 未找到路径
                return new List<int>();
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine($"[AbstractLoopMission] GetSitesBetween({startSiteId}, {endSiteId}) error: {ex.Message}");
                return new List<int>();
            }
        }

        /// <summary>
        /// 查找从起点到终点之间的所有站点对象
        /// </summary>
        /// <param name="startSiteId">起点站点ID</param>
        /// <param name="endSiteId">终点站点ID</param>
        /// <returns>从起点到终点的站点对象列表</returns>
        protected List<Site> GetSiteObjectsBetween(int startSiteId, int endSiteId)
        {
            var siteIds = GetSitesBetween(startSiteId, endSiteId);
            var result = new List<Site>();

            foreach (var siteId in siteIds)
            {
                var site = SimpleLib.GetSite(siteId);
                if (site != null)
                    result.Add(site);
            }

            return result;
        }

        /// <summary>
        /// 构建站点邻接表（基于轨道连接，考虑轨道方向）
        /// </summary>
        /// <returns>邻接表：站点ID -> 可达的相邻站点ID列表</returns>
        private Dictionary<int, HashSet<int>> BuildSiteAdjacency()
        {
            var adjacency = new Dictionary<int, HashSet<int>>();

            foreach (var track in SimpleLib.GetAllTracks())
            {
                int siteA = track.siteA;
                int siteB = track.siteB;

                // 根据轨道方向添加邻接关系
                // direction: 0=双向, 1=A->B, 2=B->A
                switch (track.direction)
                {
                    case 0: // 双向
                        AddAdjacency(adjacency, siteA, siteB);
                        AddAdjacency(adjacency, siteB, siteA);
                        break;
                    case 1: // A -> B
                        AddAdjacency(adjacency, siteA, siteB);
                        break;
                    case 2: // B -> A
                        AddAdjacency(adjacency, siteB, siteA);
                        break;
                    default:
                        AddAdjacency(adjacency, siteA, siteB);
                        AddAdjacency(adjacency, siteB, siteA);
                        break;
                }
            }

            return adjacency;
        }

        /// <summary>
        /// 向邻接表添加边
        /// </summary>
        private void AddAdjacency(Dictionary<int, HashSet<int>> adjacency, int from, int to)
        {
            if (!adjacency.ContainsKey(from))
                adjacency[from] = new HashSet<int>();

            adjacency[from].Add(to);
        }

        /// <summary>
        /// 检查路径上是否有其他车辆（不包含起点和终点）
        /// </summary>
        /// <param name="startSiteId">起点站点ID</param>
        /// <param name="endSiteId">终点站点ID</param>
        /// <param name="excludeCar">排除的车辆（通常是当前车辆）</param>
        /// <returns>true=路径上有车辆，false=路径畅通</returns>
        protected bool HasCarOnPath(int startSiteId, int endSiteId, Car excludeCar = null)
        {
            var pathSites = GetSitesBetween(startSiteId, endSiteId);

            // 排除起点和终点
            var middleSites = pathSites
                .Skip(1)
                .Take(pathSites.Count - 2)
                .ToList();

            if (middleSites.Count == 0)
                return false;

            foreach (var car in SimpleLib.GetAllCars().OfType<Car>())
            {
                if (excludeCar != null && car == excludeCar)
                    continue;

                if (car?.status?.holdingLocks == null)
                    continue;

                // 检查车辆是否在路径中间站点
                foreach (var siteId in middleSites)
                {
                    if (car.status.holdingLocks.Contains(siteId))
                        return true;
                }
            }

            return false;
        }

        /// <summary>
        /// 获取路径上的所有车辆
        /// </summary>
        /// <param name="startSiteId">起点站点ID</param>
        /// <param name="endSiteId">终点站点ID</param>
        /// <param name="includeEndpoints">是否包含起点和终点的车辆</param>
        /// <returns>路径上的车辆列表</returns>
        protected List<Car> GetCarsOnPath(int startSiteId, int endSiteId, bool includeEndpoints = false)
        {
            var pathSites = GetSitesBetween(startSiteId, endSiteId);

            if (!includeEndpoints && pathSites.Count > 2)
            {
                pathSites = pathSites
                    .Skip(1)
                    .Take(pathSites.Count - 2)
                    .ToList();
            }

            var carsOnPath = new List<Car>();

            foreach (var car in SimpleLib.GetAllCars().OfType<Car>())
            {
                if (car?.status?.holdingLocks == null)
                    continue;

                foreach (var siteId in pathSites)
                {
                    if (car.status.holdingLocks.Contains(siteId))
                    {
                        carsOnPath.Add(car);
                        break;
                    }
                }
            }

            return carsOnPath;
        }

        /// <summary>
        /// 计算两站点之间的路径长度（经过的站点数）
        /// </summary>
        /// <param name="startSiteId">起点站点ID</param>
        /// <param name="endSiteId">终点站点ID</param>
        /// <returns>路径长度（站点数），未找到路径返回 -1</returns>
        protected int GetPathLength(int startSiteId, int endSiteId)
        {
            var path = GetSitesBetween(startSiteId, endSiteId);
            return path.Count > 0 ? path.Count : -1;
        }

        #endregion

        #region 任务策略匹配

        /// <summary>
        /// 路径缓存（避免重复计算）
        /// </summary>
        [JsonIgnore]
        private readonly Dictionary<(int, int), List<int>> _pathCache = new Dictionary<(int, int), List<int>>();

        /// <summary>
        /// 路径缓存锁
        /// </summary>
        [JsonIgnore]
        private readonly object _pathCacheLock = new object();

        /// <summary>
        /// 根据车辆当前站点匹配最优任务策略
        /// <para>匹配逻辑：</para>
        /// <list type="number">
        ///   <item>遍历所有任务策略，获取每个策略从当前点到目标点的完整路径</item>
        ///   <item>检查车辆当前站点是否在该路径上</item>
        ///   <item>返回包含当前站点且优先级最高的策略</item>
        /// </list>
        /// </summary>
        /// <param name="car">车辆</param>
        /// <returns>最优匹配结果，无匹配返回 null</returns>
        protected TaskPathMatchResult FindBestTaskForCar(Car car)
        {
            if (car?.status?.holdingLocks == null || car.status.holdingLocks.Length == 0)
                return null;

            int currentSiteId = car.status.holdingLocks[0];
            return FindBestTaskForSite(currentSiteId);
        }

        /// <summary>
        /// 根据站点ID匹配最优任务策略
        /// <para>遍历所有任务，找出包含该站点的路径，返回优先级最高的任务</para>
        /// </summary>
        /// <param name="siteId">当前站点ID</param>
        /// <returns>最优匹配结果，无匹配返回 null</returns>
        protected TaskPathMatchResult FindBestTaskForSite(int siteId)
        {
            List<LoopTask> snapshot;
            lock (_tasksLock)
            {
                snapshot = Tasks.Where(T=>T.IsViaPoint).ToList();
            }

            var matchResults = new List<TaskPathMatchResult>();

            foreach (var task in snapshot)
            {
                // 获取任务的完整路径（从当前点到目标点）
                var fullPath = GetSitesBetweenCached(task.CurrentStationId, task.TargetStationId);

                if (fullPath.Count == 0)
                    continue;

                // 检查站点是否在路径上
                int indexInPath = fullPath.IndexOf(siteId);
                if (indexInPath < 0)
                    continue;
              
                
                // 创建匹配结果
                var result = new TaskPathMatchResult
                {
                    Task = task,
                    CurrentSiteId = siteId,
                    FullPath = fullPath,
                    IndexInPath = indexInPath,
                    RemainingPath = fullPath.Skip(indexInPath).ToList(),
                    DistanceToTarget = fullPath.Count - indexInPath - 1,
                    IsAtStartPoint = (indexInPath == 0),
                    IsAtEndPoint = (indexInPath == fullPath.Count - 1),
                    IsOnMiddlePath = (indexInPath > 0 && indexInPath < fullPath.Count - 1)
                };

                matchResults.Add(result);
            }

            if (matchResults.Count == 0)
                return null;

            // 按匹配优先级排序：
            // 1. 起点匹配优先
            // 2. 任务优先级高的优先
            // 3. 距离目标近的优先
            var bestMatch = matchResults.Where(r=>!r.IsAtEndPoint && !r.IsAtStartPoint )
                .OrderByDescending(r => r.IsAtStartPoint ? 1 : 0)  // 起点匹配优先
                .ThenByDescending(r => r.Task.Priority)            // 任务优先级高的优先
                .ThenBy(r => r.DistanceToTarget)                   // 距离目标近的优先
                .FirstOrDefault();
            Diagnosis.Post($"[AbstractLoopMission]  小车获取到的任务策略 {bestMatch.ToString()} ）", $"路径中间点初始化", true);
            return bestMatch;
        }

        /// <summary>
        /// 根据站点ID查找所有匹配的任务策略
        /// <para>返回所有包含该站点的任务，按优先级排序</para>
        /// </summary>
        /// <param name="siteId">站点ID</param>
        /// <returns>匹配结果列表（按优先级降序）</returns>
        protected List<TaskPathMatchResult> FindAllTasksForSite(int siteId)
        {
            List<LoopTask> snapshot;
            lock (_tasksLock)
            {
                snapshot = Tasks.ToList();
            }

            var matchResults = new List<TaskPathMatchResult>();

            foreach (var task in snapshot)
            {
                // 获取任务的完整路径
                var fullPath = GetSitesBetweenCached(task.CurrentStationId, task.TargetStationId);

                if (fullPath.Count == 0)
                    continue;

                // 检查站点是否在路径上
                int indexInPath = fullPath.IndexOf(siteId);
                if (indexInPath < 0)
                    continue;

                var result = new TaskPathMatchResult
                {
                    Task = task,
                    CurrentSiteId = siteId,
                    FullPath = fullPath,
                    IndexInPath = indexInPath,
                    RemainingPath = fullPath.Skip(indexInPath).ToList(),
                    DistanceToTarget = fullPath.Count - indexInPath - 1,
                    IsAtStartPoint = (indexInPath == 0),
                    IsAtEndPoint = (indexInPath == fullPath.Count - 1),
                    IsOnMiddlePath = (indexInPath > 0 && indexInPath < fullPath.Count - 1)
                };

                matchResults.Add(result);
            }

            // 按优先级排序
            return matchResults
                .OrderByDescending(r => r.IsAtStartPoint ? 1 : 0)
                .ThenByDescending(r => r.Task.Priority)
                .ThenBy(r => r.DistanceToTarget)
                .ToList();
        }

        /// <summary>
        /// 获取车辆应该前往的下一个目标站点
        /// <para>根据最优匹配策略返回目标站点ID</para>
        /// </summary>
        /// <param name="car">车辆</param>
        /// <returns>目标站点ID，无匹配返回 -1</returns>
        protected int GetRecommendedTargetForCar(Car car)
        {
            var match = FindBestTaskForCar(car);
            return match?.Task?.TargetStationId ?? -1;
        }

        /// <summary>
        /// 获取车辆的下一个中间站点
        /// <para>返回当前位置的下一个路径节点</para>
        /// </summary>
        /// <param name="car">车辆</param>
        /// <returns>下一站点ID，无匹配返回 -1</returns>
        protected int GetNextSiteForCar(Car car)
        {
            var match = FindBestTaskForCar(car);
            if (match?.RemainingPath == null || match.RemainingPath.Count < 2)
                return -1;

            return match.RemainingPath[1];
        }

        /// <summary>
        /// 获取缓存的路径（避免重复计算）
        /// </summary>
        private List<int> GetSitesBetweenCached(int startSiteId, int endSiteId)
        {
            var key = (startSiteId, endSiteId);

            lock (_pathCacheLock)
            {
                if (_pathCache.TryGetValue(key, out var cached))
                    return new List<int>(cached);

                var path = GetSitesBetween(startSiteId, endSiteId);
                _pathCache[key] = path;
                return new List<int>(path);
            }
        }

        /// <summary>
        /// 清除路径缓存
        /// <para>当任务策略变更或地图变更时调用</para>
        /// </summary>
        protected void ClearPathCache()
        {
            lock (_pathCacheLock)
            {
                _pathCache.Clear();
            }
        }

        /// <summary>
        /// 根据任务ID查找任务
        /// </summary>
        /// <param name="taskId">任务ID</param>
        /// <returns>任务对象，未找到返回 null</returns>
        protected LoopTask FindTaskById(int taskId)
        {
            lock (_tasksLock)
            {
                return Tasks.FirstOrDefault(t => t.Id == taskId);
            }
        }

        /// <summary>
        /// 判断车辆是否在指定任务的路径上
        /// </summary>
        /// <param name="car">车辆</param>
        /// <param name="task">任务</param>
        /// <returns>是否在路径上</returns>
        protected bool IsCarOnTaskPath(Car car, LoopTask task)
        {
            if (car?.status?.holdingLocks == null || car.status.holdingLocks.Length == 0)
                return false;

            int currentSiteId = car.status.holdingLocks[0];
            var path = GetSitesBetweenCached(task.CurrentStationId, task.TargetStationId);

            return path.Contains(currentSiteId);
        }

        #endregion

        #region 任务匹配结果类型

        /// <summary>
        /// 任务路径匹配结果
        /// </summary>
        public class TaskPathMatchResult
        {
            /// <summary>匹配的任务</summary>
            public LoopTask Task { get; set; }

            /// <summary>车辆当前站点ID</summary>
            public int CurrentSiteId { get; set; }

            /// <summary>完整路径（从任务起点到终点）</summary>
            public List<int> FullPath { get; set; } = new List<int>();

            /// <summary>当前站点在路径中的索引</summary>
            public int IndexInPath { get; set; }

            /// <summary>剩余路径（从当前站点到终点）</summary>
            public List<int> RemainingPath { get; set; } = new List<int>();

            /// <summary>到目标的距离（剩余站点数）</summary>
            public int DistanceToTarget { get; set; }

            /// <summary>是否在任务起点</summary>
            public bool IsAtStartPoint { get; set; }

            /// <summary>是否在任务终点</summary>
            public bool IsAtEndPoint { get; set; }

            /// <summary>是否在路径中间</summary>
            public bool IsOnMiddlePath { get; set; }

            /// <summary>任务ID</summary>
            public int TaskId => Task?.Id ?? 0;

            /// <summary>任务优先级</summary>
            public int TaskPriority => Task?.Priority ?? 0;

            /// <summary>目标站点ID</summary>
            public int TargetSiteId => Task?.TargetStationId ?? -1;

            /// <summary>下一个站点ID（当前站点的下一跳）</summary>
            public int NextSiteId => RemainingPath.Count > 1 ? RemainingPath[1] : -1;

            /// <summary>路径进度百分比</summary>
            public double ProgressPercent => FullPath.Count > 1
                ? (double)IndexInPath / (FullPath.Count - 1) * 100
                : 0;

            /// <summary>
            /// 获取匹配信息描述
            /// </summary>
            public override string ToString()
            {
                string position = IsAtStartPoint ? "起点" : (IsAtEndPoint ? "终点" : "中间");
                return $"任务[ID={TaskId}, {Task?.CurrentStationId}->{Task?.TargetStationId}] " +
                       $"优先级={TaskPriority}, 当前={CurrentSiteId}({position}), " +
                       $"进度={ProgressPercent:F1}%, 剩余={DistanceToTarget}站, " +
                       $"下一站={NextSiteId}";
            }
        }

        #endregion

        private LoopViewer lv;


        [MethodMember(Name = "任务管理", Description = "任务管理")]
        public void Print()
        {
            lv = new LoopViewer();
            lv.Show();
        }

        [MethodMember(Name = "启动环线", Description = "启动环线")]
        public void Start()
        {
            StartAll();
        }

        [MethodMember(Name = "停止环线", Description = "停止环线")]
        public void Stop()
        {
            StopAll();
        }

    }
}
