using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Autodesk.Navisworks.Api;
using NavisworksTransport.Core.Animation;
using NavisworksTransport.Core.Collision;
using NavisworksTransport.Core.Config;
using NavisworksTransport.Core.Models;
using NavisworksTransport.Core.Services;

namespace NavisworksTransport.Core
{
    /// <summary>
    /// 批处理队列管理器 - 简化版，只维护FIFO队列
    /// </summary>
    public class BatchQueueManager
    {
        private static BatchQueueManager _instance;
        private static readonly object _lock = new object();

        private PathDatabase _database;
        private BatchCollisionProcessor _processor;
        private readonly Queue<int> _queue;
        private readonly object _queueLock = new object();
        private BatchQueueItem _currentItem;
        private bool _shouldStop; // 停止执行标志
        private int _activeTaskCount; // 并行执行中的任务数（IsExecuting 判断）

        public event EventHandler<BatchQueueItemEventArgs> ItemAdded;
        public event EventHandler<BatchQueueItemEventArgs> ItemStarted;
        public event EventHandler<BatchQueueItemEventArgs> ItemCompleted;

        public bool IsExecuting
        {
            get => _currentItem != null || _activeTaskCount > 0;
        }
        public int QueueCount => _queue.Count;

        public static BatchQueueManager Instance
        {
            get
            {
                if (_instance == null)
                {
                    lock (_lock)
                    {
                        if (_instance == null)
                        {
                            _instance = new BatchQueueManager();
                        }
                    }
                }
                return _instance;
            }
        }

        private BatchQueueManager()
        {
            // 延迟初始化，等待 PathDatabase 就绪
            _database = null;
            _processor = null;
            _queue = new Queue<int>();
        }

        /// <summary>
        /// 设置PathPlanningManager（用于获取数据库）
        /// </summary>
        public void SetPathPlanningManager(PathPlanningManager pathPlanningManager)
        {
            _database = pathPlanningManager?.GetPathDatabase();
            LogManager.Info("BatchQueueManager已设置PathPlanningManager");
            
            // 重置残留的Running状态任务（程序异常关闭后重启）
            _ = ResetStaleRunningItemsAsync();
        }
        
        /// <summary>
        /// 重置残留的Running状态任务为Pending
        /// 用于程序异常关闭后重启时恢复状态
        /// </summary>
        private async Task ResetStaleRunningItemsAsync()
        {
            try
            {
                if (_database == null) return;
                
                var allItems = await _database.GetBatchQueueItemsAsync(statusFilter: BatchQueueStatus.All, limit: 1000);
                var staleItems = allItems.Where(item => item.Status == BatchQueueStatus.Running).ToList();
                
                if (staleItems.Count > 0)
                {
                    LogManager.Info($"[批处理队列] 发现 {staleItems.Count} 个残留的Running状态任务，重置为Pending");
                    
                    foreach (var item in staleItems)
                    {
                        item.Status = BatchQueueStatus.Pending;
                        item.StartTime = null;
                        item.EndTime = null;
                        item.ErrorMessage = null;
                        await _database.UpdateBatchQueueItemAsync(item);
                        LogManager.Info($"[批处理队列] 已重置任务: {item.PathRouteName} (ID: {item.Id})");
                    }
                }
            }
            catch (Exception ex)
            {
                LogManager.Error($"[批处理队列] 重置残留Running任务失败: {ex.Message}");
            }
        }

        /// <summary>
        /// 确保 Processor 已初始化
        /// </summary>
        private void EnsureProcessorInitialized()
        {
            if (_processor == null)
            {
                var pathManager = PathPlanningManager.Instance;
                _database = pathManager?.GetPathDatabase();
                if (_database == null)
                {
                    throw new InvalidOperationException("PathDatabase未初始化，请确保文档已加载");
                }

                _processor = new BatchCollisionProcessor();
            }
        }

        /// <summary>
        /// 添加队列项
        /// </summary>
        public async Task<int> AddQueueItemAsync(BatchQueueItem item)
        {
            if (_database == null)
            {
                throw new InvalidOperationException("PathDatabase未初始化");
            }

            var itemId = await _database.CreateBatchQueueItemAsync(item);
            item.Id = itemId;

            lock (_queueLock)
            {
                _queue.Enqueue(itemId);
            }

            ItemAdded?.Invoke(this, new BatchQueueItemEventArgs { Item = item });

            LogManager.Info($"[批处理队列] 已添加队列项: {item.PathRouteName}, ID: {itemId}");
            return itemId;
        }

        /// <summary>
        /// 解析并行副实例数：完全由 config.toml 的 [batch] 配置驱动（use_multi_process + max_parallel_instances）。
        /// 配置缺失/无效时明确报错（禁止 fallback 默认值）；环境变量 TRANSPORTPLUGIN_MAX_PARALLEL 可临时覆盖（运维/测试）。
        /// </summary>
        private static int ResolveMaxParallelInstances()
        {
            var batchConfig = ConfigManager.Instance.Current?.Batch;
            if (batchConfig == null)
            {
                throw new InvalidOperationException("缺少批处理配置（config.toml 的 [batch] 段未加载）");
            }

            if (!batchConfig.UseMultiProcess)
            {
                LogManager.Info("[批处理队列] 多进程已关闭（config），串行执行");
                return 1;
            }

            if (batchConfig.MaxParallelInstances < 1 || batchConfig.MaxParallelInstances > 20)
            {
                throw new InvalidOperationException(
                    $"无效的并发实例数: {batchConfig.MaxParallelInstances}（config.toml [batch] max_parallel_instances，范围 1-20）");
            }

            int maxParallel = batchConfig.MaxParallelInstances;

            // 环境变量临时覆盖（运维/测试场景，显式设置才生效）
            string raw = Environment.GetEnvironmentVariable("TRANSPORTPLUGIN_MAX_PARALLEL");
            if (!string.IsNullOrWhiteSpace(raw) && int.TryParse(raw, out int parsed) && parsed >= 1 && parsed <= 20)
            {
                maxParallel = parsed;
            }

            LogManager.Info($"[批处理队列] 并行副实例数: {maxParallel}");
            return maxParallel;
        }

        /// <summary>
        /// 处理队列（公共方法，供外部调用）
        /// </summary>
        public async Task ProcessQueueAsync()
        {
            Autodesk.Navisworks.Api.Progress progress = null;
            
            // 统计信息
            DateTime startTime = DateTime.Now;
            int totalCount = 0;
            int successCount = 0;
            int failedCount = 0;
            int skippedCount = 0;

            try
            {
                // 清除所有路径可视化（避免截图包含之前的路径）
                try
                {
                    PathPointRenderPlugin.Instance.ClearAllPaths();
                    LogManager.Info("[批处理队列] 已清除所有路径可视化");
                }
                catch (Exception ex)
                {
                    LogManager.Warning($"[批处理队列] 清除路径可视化失败: {ex.Message}");
                }

                // 确保处理器已初始化（会初始化 _database）
                EnsureProcessorInitialized();

                // 🔥 关键：从数据库加载所有待处理项到内存队列（支持重新启动后继续执行）
                await LoadPendingItemsToQueueAsync();

                // 开始进度条
                progress = Autodesk.Navisworks.Api.Application.BeginProgress(
                    "执行批处理队列",
                    "正在处理队列中的任务..."
                );

                // 计算总任务数（队列中已存在的 + 处理过程中可能新增的）
                int initialQueueCount;
                lock (_queueLock)
                {
                    initialQueueCount = _queue.Count;
                }

                int completedCount = 0;

                // 并行执行：F1 项（副实例检测，天然隔离）并行，限并发度；非 F1 项（主 NW 检测）串行保护
                int maxParallel = ResolveMaxParallelInstances();
                using (var parallelGate = new SemaphoreSlim(maxParallel))
                using (var mainDetectionGate = new SemaphoreSlim(1, 1))
                {
                    var tasks = new List<Task>();
                    var statsLock = new object();

                    while (true)
                    {
                        // 检查用户是否取消
                        if (progress != null && progress.IsCanceled)
                        {
                            LogManager.Info("[批处理队列] 用户取消操作");
                            int remaining;
                            lock (_queueLock) { remaining = _queue.Count; }
                            skippedCount = remaining;
                            break;
                        }

                        // 检查是否请求停止执行
                        if (_shouldStop)
                        {
                            LogManager.Info("[批处理队列] 收到停止执行请求，将不再取新任务");
                            int remaining;
                            lock (_queueLock) { remaining = _queue.Count; }
                            skippedCount = remaining;
                            break;
                        }

                        int itemId;
                        lock (_queueLock)
                        {
                            if (_queue.Count == 0)
                            {
                                break;
                            }
                            itemId = _queue.Dequeue();
                        }

                        totalCount++;

                        var item = await _database.GetBatchQueueItemAsync(itemId);
                        if (item == null)
                        {
                            lock (statsLock) { failedCount++; completedCount++; }
                            continue;
                        }

                        // 限并发：超过 maxParallel 个活动任务时等待
                        await parallelGate.WaitAsync();
                        Interlocked.Increment(ref _activeTaskCount);

                        tasks.Add(Task.Run(async () =>
                        {
                            // F1 剖面盒检测（副实例）天然隔离；非 F1（主 NW 检测）用 mainDetectionGate 串行
                            bool usesMainDetection = !(item.DetectAllObjects && SectionBoxBatchDetector.Enabled);
                            if (usesMainDetection)
                            {
                                await mainDetectionGate.WaitAsync().ConfigureAwait(false);
                            }

                            try
                            {
                                _currentItem = item;
                                ItemStarted?.Invoke(this, new BatchQueueItemEventArgs { Item = item });

                                await ExecuteQueueItemAsync(item).ConfigureAwait(false);

                                ItemCompleted?.Invoke(this, new BatchQueueItemEventArgs { Item = item });
                                lock (statsLock) { successCount++; }
                            }
                            catch (Exception ex)
                            {
                                LogManager.Error($"队列项执行失败 (Id: {itemId}): {ex.Message}");
                                lock (statsLock) { failedCount++; }

                                // 更新状态为失败
                                try
                                {
                                    if (_database != null)
                                    {
                                        item.Status = BatchQueueStatus.Failed;
                                        item.ErrorMessage = ex.Message;
                                        item.EndTime = DateTime.Now;
                                        await _database.UpdateBatchQueueItemAsync(item).ConfigureAwait(false);
                                    }
                                }
                                catch
                                {
                                }
                            }
                            finally
                            {
                                if (usesMainDetection)
                                {
                                    mainDetectionGate.Release();
                                }

                                _currentItem = null;
                                Interlocked.Decrement(ref _activeTaskCount);
                                parallelGate.Release();

                                int completed;
                                lock (statsLock)
                                {
                                    completedCount++;
                                    completed = completedCount;
                                }

                                // 更新进度（后台线程更新 NW 进度条）
                                try
                                {
                                    if (progress != null)
                                    {
                                        int currentQueueCount;
                                        lock (_queueLock) { currentQueueCount = _queue.Count; }

                                        int totalItems = initialQueueCount;
                                        if (completed > totalItems)
                                        {
                                            totalItems = completed + currentQueueCount;
                                        }

                                        progress.Update((double)completed / totalItems);
                                    }
                                }
                                catch
                                {
                                }
                            }
                        }));
                    }

                    await Task.WhenAll(tasks).ConfigureAwait(false);
                }

                // 完成进度条
                if (progress != null)
                {
                    progress.Update(1.0);
                }
            }
            finally
            {
                // 确保关闭进度条
                if (progress != null)
                {
                    Autodesk.Navisworks.Api.Application.EndProgress();
                }
                
                // 重置停止标志
                _shouldStop = false;
                
                // 显示执行汇总信息
                DateTime endTime = DateTime.Now;
                TimeSpan duration = endTime - startTime;
                ShowBatchSummary(startTime, endTime, duration, totalCount, successCount, failedCount, skippedCount);
            }
        }

        /// <summary>
        /// 显示批处理执行汇总信息
        /// </summary>
        private void ShowBatchSummary(DateTime startTime, DateTime endTime, TimeSpan duration, 
            int totalCount, int successCount, int failedCount, int skippedCount)
        {
            try
            {
                // 计算成功率
                double successRate = totalCount > 0 ? (double)successCount / totalCount * 100 : 0;
                
                // 格式化执行时长
                string durationText;
                if (duration.TotalHours >= 1)
                {
                    durationText = $"{duration.TotalHours:F1}小时";
                }
                else if (duration.TotalMinutes >= 1)
                {
                    durationText = $"{duration.TotalMinutes:F1}分钟";
                }
                else
                {
                    durationText = $"{duration.TotalSeconds:F1}秒";
                }
                
                // 构建汇总信息
                var summary = new StringBuilder();
                summary.AppendLine("===== 批处理执行汇总 =====");
                summary.AppendLine();
                summary.AppendLine($"开始时间：{startTime:yyyy-MM-dd HH:mm:ss}");
                summary.AppendLine($"结束时间：{endTime:yyyy-MM-dd HH:mm:ss}");
                summary.AppendLine($"执行时长：{durationText}");
                summary.AppendLine();
                summary.AppendLine($"执行数量：{totalCount} 项");
                summary.AppendLine($"成功数量：{successCount} 项");
                summary.AppendLine($"失败数量：{failedCount} 项");
                if (skippedCount > 0)
                {
                    summary.AppendLine($"跳过数量：{skippedCount} 项");
                }
                summary.AppendLine($"成功率：{successRate:F1}%");
                
                if (failedCount > 0)
                {
                    summary.AppendLine();
                    summary.AppendLine("⚠️ 有任务执行失败，请查看日志了解详情。");
                }
                else if (successCount > 0)
                {
                    summary.AppendLine();
                    summary.AppendLine("✅ 所有任务执行成功！");
                }
                
                LogManager.Info($"[批处理队列] 执行汇总 - 总计:{totalCount}, 成功:{successCount}, 失败:{failedCount}, 跳过:{skippedCount}, 耗时:{durationText}");
                
                // 在UI线程显示消息框
                System.Windows.Application.Current?.Dispatcher.Invoke(() =>
                {
                    System.Windows.MessageBox.Show(summary.ToString(), "批处理执行完成", 
                        System.Windows.MessageBoxButton.OK, 
                        failedCount > 0 ? System.Windows.MessageBoxImage.Warning : System.Windows.MessageBoxImage.Information);
                });
            }
            catch (Exception ex)
            {
                LogManager.Error($"[批处理队列] 显示汇总信息失败: {ex.Message}");
            }
        }

        /// <summary>
        /// 执行单个队列项
        /// </summary>
        /// <summary>
        /// 构造 ModelItem 的层级链（AncestorsAndSelf 的 DisplayName，'/' 分隔）。
        /// 导出剖面盒保留节点树结构：去掉根文件名后主/副实例层级链一致，用于跨实例物体匹配。
        /// </summary>
        private static string BuildAncestorChain(ModelItem item)
        {
            try
            {
                var segments = new List<string>();
                var current = item;
                int guard = 0;

                while (current != null && guard < 15)
                {
                    var name = current.DisplayName;
                    if (!string.IsNullOrWhiteSpace(name))
                    {
                        segments.Add(name.Trim());
                    }
                    current = current.Parent;
                    guard++;
                }

                segments.Reverse();
                return string.Join(" / ", segments);
            }
            catch
            {
                return null;
            }
        }

        private async Task ExecuteQueueItemAsync(BatchQueueItem item)
        {
            item.Status = BatchQueueStatus.Running;
            item.StartTime = DateTime.Now;
            await _database.UpdateBatchQueueItemAsync(item);

            try
            {
                var pathRoute = await _database.GetPathRouteAsync(item.RouteId);
                if (pathRoute == null)
                {
                    throw new InvalidOperationException($"路径不存在 (Id: {item.RouteId})");
                }

                // F1：剖面盒自动检测模式——非指定碰撞对象（DetectAllObjects=true，全模型检测小时级）
                // 导出路径包围盒局部模型 → 副 Navisworks 实例检测（分钟级）→ 回传报告
                // 注意：F1 分支在 DetectionRecordId 检查之前（副实例检测自行生成记录，主 item 不需要）
                if (item.DetectAllObjects && SectionBoxBatchDetector.Enabled)
                {
                    // 真实物体名从 ModelItemReferences（Role=MovingObject）读取（BatchQueueItems 表无此列）
                    string movingObjectName = item.MovingObjectName;
                    string expectedAncestorChain = null;
                    int movingModelIndex = 0;
                    string movingObjectPathId = null;
                    if (!item.IsVirtualObject)
                    {
                        var movingRefs = await _database.GetModelItemReferencesAsync(
                            item.Id, "BatchQueueItem", "MovingObject").ConfigureAwait(false);
                        if (movingRefs.Count > 0)
                        {
                            movingObjectName = movingRefs[0].ObjectName ?? movingRefs[0].DisplayName;
                            movingModelIndex = movingRefs[0].ModelIndex;
                            movingObjectPathId = movingRefs[0].PathId;

                            // 主 NW 按 PathId 解析移动物体 → 层级链（导出剖面盒保留树结构，副实例按链匹配）
                            try
                            {
                                var pathIdObj = new Autodesk.Navisworks.Api.DocumentParts.ModelItemPathId
                                {
                                    ModelIndex = movingRefs[0].ModelIndex,
                                    PathId = movingRefs[0].PathId
                                };
                                var movingItem = Application.ActiveDocument.Models.ResolvePathId(pathIdObj);
                                if (movingItem != null)
                                {
                                    expectedAncestorChain = BuildAncestorChain(movingItem);
                                    LogManager.Info($"[批处理] 移动物体层级链: {expectedAncestorChain}");
                                }
                            }
                            catch (Exception chainEx)
                            {
                                LogManager.Warning($"[批处理] 解析移动物体层级链失败: {chainEx.Message}");
                            }
                        }

                        if (string.IsNullOrWhiteSpace(movingObjectName))
                        {
                            throw new InvalidOperationException($"批处理项缺少移动物体引用: {item.PathRouteName}");
                        }
                    }

                    LogManager.Info($"[批处理] 剖面盒自动检测模式: 路径={pathRoute.Name}, DetectAllObjects=true, 虚拟物体={item.IsVirtualObject}, 移动物体={movingObjectName}");
                    var detector = new SectionBoxBatchDetector();
                    var detection = await detector.RunAsync(
                        pathRoute,
                        $"item-{item.Id}",
                        item.IsVirtualObject,
                        movingObjectName,
                        expectedAncestorChain,
                        movingModelIndex,
                        movingObjectPathId,
                        item.VirtualObjectLength,
                        item.VirtualObjectWidth,
                        item.VirtualObjectHeight,
                        item.FrameRate,
                        item.DurationSeconds,
                        Path.Combine(Path.GetTempPath(), "NavisworksTransportBatch", $"item-{item.Id}")).ConfigureAwait(false);

                    if (!detection.Success)
                    {
                        throw new InvalidOperationException($"剖面盒自动检测失败: {detection.ErrorMessage}");
                    }

                    item.CollisionCount = detection.TotalCollisions;
                    item.Status = BatchQueueStatus.Completed;
                    item.EndTime = DateTime.Now;
                    await _database.UpdateBatchQueueItemAsync(item).ConfigureAwait(false);

                    LogManager.Info(
                        $"[批处理] 剖面盒自动检测完成: {pathRoute.Name}, 碰撞={detection.TotalCollisions}, " +
                        $"唯一对象={detection.UniqueCollidedObjectsCount}, 对象=[{string.Join(", ", detection.CollidedObjects)}]");

                    // F2：碰撞对象映射（副实例 → 主模型 PathId，按层级链匹配）
                    int mappedCount = 0;
                    foreach (var mapping in detection.CollidedObjectMappings)
                    {
                        if (!string.IsNullOrWhiteSpace(mapping.MainPathId))
                        {
                            mappedCount++;
                            LogManager.Info($"[F2映射] {mapping.Name}: 副实例={mapping.SecondaryPathId} -> 主模型={mapping.MainPathId}");
                        }
                    }
                    LogManager.Info($"[F2映射] 完成: {mappedCount}/{detection.CollidedObjectMappings.Count} 个碰撞对象映射到主模型");

                    // F3：清理副实例临时工作目录（导出模型/临时库/路径文件）；副实例刚关闭，文件锁可能未释放，带重试
                    string workDirectory = Path.Combine(Path.GetTempPath(), "NavisworksTransportBatch", $"item-{item.Id}");
                    for (int cleanupAttempt = 0; cleanupAttempt < 3; cleanupAttempt++)
                    {
                        try
                        {
                            if (Directory.Exists(workDirectory))
                            {
                                Directory.Delete(workDirectory, true);
                                LogManager.Info($"[批处理] 已清理副实例工作目录: {workDirectory}");
                            }
                            break;
                        }
                        catch (Exception cleanupEx)
                        {
                            LogManager.Warning($"[批处理] 清理工作目录失败（第 {cleanupAttempt + 1} 次）: {cleanupEx.Message}");
                            System.Threading.Thread.Sleep(1500);
                        }
                    }
                    return;
                }

                if (!item.DetectionRecordId.HasValue)
                {
                    throw new InvalidOperationException("批处理队列项缺少 DetectionRecordId，无法保存完整碰撞结果和位姿数据。请重新生成动画后再加入批处理。");
                }

                // 获取运动物体
                ModelItem animatedObject = null;
                bool isVirtualObject = item.IsVirtualObject;

                if (isVirtualObject)
                {
                    // 使用现有的虚拟物体，不创建和清理
                    // ShowVirtualObject 会显示虚拟物体并更新尺寸（如果已存在）
                    VirtualObjectManager.Instance.ShowVirtualObject(
                        item.VirtualObjectLength,
                        item.VirtualObjectWidth,
                        item.VirtualObjectHeight
                    );

                    animatedObject = VirtualObjectManager.Instance.CurrentVirtualObject;

                    if (animatedObject == null)
                    {
                        throw new InvalidOperationException("虚拟物体显示失败");
                    }

                    LogManager.Info($"[批处理] 使用虚拟物体: {animatedObject.DisplayName}");
                }
                else
                {
                    // 从 ModelItemReferences 表查询运动物体
                    var movingObjectReferences = await _database.GetModelItemReferencesAsync(
                        item.Id,
                        "BatchQueueItem",
                        "MovingObject"
                    );

                    if (movingObjectReferences.Count > 0)
                    {
                        var movingObjectRef = movingObjectReferences[0];
                        try
                        {
                            var pathIdObj = new Autodesk.Navisworks.Api.DocumentParts.ModelItemPathId
                            {
                                ModelIndex = movingObjectRef.Item1,
                                PathId = movingObjectRef.Item2
                            };
                            animatedObject = Application.ActiveDocument.Models.ResolvePathId(pathIdObj);

                            if (animatedObject == null)
                            {
                                throw new InvalidOperationException("未找到指定的运动物体");
                            }

                            LogManager.Info($"[批处理] 使用真实物体: {animatedObject.DisplayName}");
                        }
                        catch (Exception ex)
                        {
                            LogManager.Error($"[批处理] 从 PathId 恢复运动物体失败: ModelIndex={movingObjectRef.Item1}, PathId={movingObjectRef.Item2}, 错误: {ex.Message}");
                            throw new InvalidOperationException("恢复运动物体失败", ex);
                        }
                    }
                    else
                    {
                        throw new InvalidOperationException("未找到运动物体的 ModelItem 引用");
                    }
                }

                // 从 ModelItemReferences 表查询手工指定的检测物体（在主线程外完成查询）
                                List<ModelItem> manualDetectionTargets = null;
                                bool isManualMode = !item.DetectAllObjects;
                                
                                if (isManualMode)
                                {
                                    var targetReferences = await _database.GetModelItemReferencesAsync(
                                        item.Id,
                                        "BatchQueueItem",
                                        "CollisionTarget"
                                    );
                
                                    if (targetReferences.Count > 0)
                                    {
                                        manualDetectionTargets = new List<ModelItem>();
                                        var doc = Autodesk.Navisworks.Api.Application.ActiveDocument;
                
                                        foreach (var targetRef in targetReferences)
                                        {
                                            try
                                            {
                                                var pathIdObj = new Autodesk.Navisworks.Api.DocumentParts.ModelItemPathId
                                                {
                                                    ModelIndex = targetRef.Item1,
                                                    PathId = targetRef.Item2
                                                };
                                                var modelItem = doc.Models.ResolvePathId(pathIdObj);
                                                if (modelItem != null)
                                                {
                                                    manualDetectionTargets.Add(modelItem);
                                                }
                                                else
                                                {
                                                    LogManager.Warning($"[批处理] 无法通过 PathId 找到 ModelItem: ModelIndex={targetRef.Item1}, PathId={targetRef.Item2}");
                                                }
                                            }
                                            catch (Exception ex)
                                            {
                                                LogManager.Warning($"[批处理] 恢复手工指定对象失败: {targetRef.Item3}, 错误: {ex.Message}");
                                            }
                                        }
                                        LogManager.Info($"[批处理] 加载手工指定检测物体，成功: {manualDetectionTargets.Count}/{targetReferences.Count}");
                                    }
                                }
                                
                                // 统一准备碰撞检测（根据模式自动决定是否构建全局缓存）
                                ClashDetectiveIntegration.PrepareCollisionDetection(animatedObject, isManualMode, manualDetectionTargets);
                
                                // 🔥 从数据库加载该队列项的检测记录（包括排除列表和手工目标）
                                var detectionRecord = await LoadDetectionRecordForQueueItemAsync(item);
                                var excludedObjects = detectionRecord?.ExcludedObjects ?? new List<ModelItem>();
                                var manualTargetsFromRecord = detectionRecord?.ManualTargets ?? new List<ModelItem>();
                                LogManager.Info($"[批处理] 队列项 {item.Id} (DetectionRecordId={item.DetectionRecordId}) 加载了 {excludedObjects.Count} 个排除对象, {manualTargetsFromRecord.Count} 个手工目标");
                                
                                // 如果检测记录中有手工目标，使用检测记录中的（优先级高于队列项中的）
                                if (manualTargetsFromRecord.Count > 0)
                                {
                                    manualDetectionTargets = manualTargetsFromRecord;
                                    isManualMode = true;
                                }
                
                                // 在主线程执行Navisworks API调用
                                var result = await UIStateManager.Instance.ExecuteUIUpdateAsync(() =>
                                {
                                    // 预计算动画帧和碰撞
                                    var config = new CollisionDetectionConfig
                                    {
                                        FrameRate = item.FrameRate,
                                        DurationSeconds = item.DurationSeconds,
                                        DetectionTolerance = item.DetectionTolerance,
                                        VirtualObjectLength = item.VirtualObjectLength,
                                        VirtualObjectWidth = item.VirtualObjectWidth,
                                        VirtualObjectHeight = item.VirtualObjectHeight,
                                        CollisionDetectionEnabled = true,
                                        ReportGenerationEnabled = true
                                    };
                    
                    var frames = _processor.PrecomputeFrames(
                        pathRoute,
                        animatedObject,
                        isVirtualObject,
                        config.VirtualObjectLength,
                        config.VirtualObjectWidth,
                        config.VirtualObjectHeight,
                        config.FrameRate,
                        config.DurationSeconds,
                        config.DetectionTolerance,
                        manualDetectionTargets,
                        item.ObjectRotationCorrection,
                        excludedObjects
                    );

                    // 检查预计算是否成功
                    if (frames == null || frames.Count == 0)
                    {
                        throw new InvalidOperationException("预计算动画帧失败：未生成任何帧");
                    }

                    // 提取碰撞结果
                    var collisions = frames.SelectMany(f => f.Collisions).ToList();

                    // 创建并运行ClashDetective测试（直接在主线程执行，避免异步切换导致的Navisworks Native对象生命周期问题）
                    // 传入 pathPoints 参数，让 ClashDetective 测试完成后自动恢复到路径起点
                    var pathPoints = pathRoute.Points.Select(p => p.Position).ToList();

                    var testName = _processor.CreateAndRunClashDetectiveTest(
                        collisions,
                        item.DetectionTolerance,
                        pathRoute.Name,
                        pathRoute.Id,
                        animatedObject,
                        isVirtualObject,
                        item.FrameRate,
                        item.DurationSeconds,
                        item.VirtualObjectLength,
                        item.VirtualObjectWidth,
                        item.VirtualObjectHeight,
                        pathPoints,
                        item.DetectionRecordId
                    );

                    // 🔥 使用 ClashDetective 确认的碰撞数，而不是预计算的碰撞数
                    item.CollisionCount = ClashDetectiveIntegration.Instance.ClashDetectiveCollisionCount;

                    // 保存测试名称
                    item.ClashDetectiveTestName = testName;

                    // 🔥 生成碰撞报告（包括截图）
                    // 批处理检测结束时会自动高亮，所以 hasHighlighted=true
                    if (!string.IsNullOrEmpty(testName))
                    {
                        try
                        {
                            // 渲染路径可视化（确保路径在截图中可见）
                            PathPointRenderPlugin.Instance.RenderPath(pathRoute);
                            LogManager.Info($"[批处理队列] 已渲染路径可视化: {pathRoute.Name}");

                            var reportCommand = Commands.GenerateCollisionReportCommand.CreateComprehensive(
                                routeId: item.RouteId,  // 使用任务自己的路径ID
                                hasHighlighted: false,
                                showDialog: false      // 批处理模式不弹窗
                            );
                            reportCommand.SetTestName(testName);

                            // 同步执行报告生成（在UI线程中）
                            var reportTask = reportCommand.ExecuteAsync();
                            reportTask.Wait(); // 等待报告生成完成

                            // 清除路径可视化（避免影响下一个任务）
                            PathPointRenderPlugin.Instance.RemovePath(pathRoute.Id);
                            LogManager.Info($"[批处理队列] 已清除路径可视化: {pathRoute.Name}");
                        }
                        catch (Exception reportEx)
                        {
                            LogManager.Error($"[批处理队列] 生成碰撞报告失败: {reportEx.Message}");
                            // 报告生成失败不影响批处理流程
                        }
                    }

                    return testName;
                });

                // 标记为完成
                item.Status = BatchQueueStatus.Completed;
                item.EndTime = DateTime.Now;
                await _database.UpdateBatchQueueItemAsync(item);

                LogManager.Info($"[批处理队列] 队列项执行完成: {item.PathRouteName}, 碰撞数: {item.CollisionCount}");
            }
            catch (Exception ex)
            {
                // 标记为失败
                item.Status = BatchQueueStatus.Failed;
                item.ErrorMessage = ex.Message;
                item.EndTime = DateTime.Now;
                await _database.UpdateBatchQueueItemAsync(item);
                
                LogManager.Error($"[批处理队列] 队列项执行失败: {item.PathRouteName}, 错误: {ex.Message}");
                throw; // 重新抛出异常，让上层处理
            }
        }

        /// <summary>
        /// 请求停止执行
        /// 执行完当前条目后停止
        /// </summary>
        public void StopExecution()
        {
            _shouldStop = true;
            LogManager.Info("[批处理队列] 已设置停止标志，将在完成当前项后停止执行");
        }

        /// <summary>
        /// 取消当前任务（保留接口兼容性，已废弃）
        /// </summary>
        public void CancelCurrentItem()
        {
            LogManager.Warning("[批处理队列] CancelCurrentItem() 已废弃，请使用 StopExecution() 代替");
        }

        /// <summary>
        /// 从数据库加载所有待处理项到内存队列
        /// 用于重新启动插件后继续执行队列
        /// </summary>
        private async Task LoadPendingItemsToQueueAsync()
        {
            try
            {
                if (_database == null)
                {
                    LogManager.Warning("[批处理队列] 数据库未初始化，无法加载待处理项");
                    return;
                }

                // 获取所有待处理项
                var pendingItems = await _database.GetBatchQueueItemsAsync(
                    statusFilter: BatchQueueStatus.Pending, 
                    limit: 1000);

                if (pendingItems == null || pendingItems.Count == 0)
                {
                    LogManager.Info("[批处理队列] 数据库中没有待处理项");
                    return;
                }

                // 将待处理项加入内存队列（避免重复添加）
                int addedCount = 0;
                lock (_queueLock)
                {
                    // 获取当前队列中已有的项ID
                    var existingIds = new HashSet<int>(_queue.ToArray());

                    foreach (var item in pendingItems)
                    {
                        if (!existingIds.Contains(item.Id))
                        {
                            _queue.Enqueue(item.Id);
                            addedCount++;
                        }
                    }
                }

                LogManager.Info($"[批处理队列] 已从数据库加载 {addedCount} 个待处理项到内存队列");
            }
            catch (Exception ex)
            {
                LogManager.Error($"[批处理队列] 加载待处理项失败: {ex.Message}");
            }
        }

        /// <summary>
        /// 获取队列列表
        /// </summary>
        public async Task<List<BatchQueueItem>> GetQueueItemsAsync(
            BatchQueueStatus statusFilter = BatchQueueStatus.All,
            int limit = 50,
            int offset = 0)
        {
            return await _database.GetBatchQueueItemsAsync(statusFilter, limit, offset);
        }

        /// <summary>
        /// 获取单个队列项
        /// </summary>
        public async Task<BatchQueueItem> GetQueueItemAsync(int itemId)
        {
            return await _database.GetBatchQueueItemAsync(itemId);
        }

        /// <summary>
        /// 删除队列项
        /// </summary>
        public async Task DeleteQueueItemAsync(int itemId)
        {
            await _database.DeleteBatchQueueItemAsync(itemId);
        }

        /// <summary>
        /// 检查并加载排除列表（已废弃，使用 LoadExcludedObjectsForQueueItemAsync 代替）
        /// </summary>
        /// <returns>排除列表</returns>
        private List<ModelItem> CheckAndLoadExcludedObjects()
        {
            try
            {
                // 首先检查 PathAnimationManager 中是否已有排除列表
                var animationManager = PathAnimationManager.GetInstance();
                var existingExcludedObjects = animationManager.GetExcludedObjects();
                
                if (existingExcludedObjects != null && existingExcludedObjects.Count > 0)
                {
                    LogManager.Info($"[批处理队列] 使用 PathAnimationManager 中的排除列表，共 {existingExcludedObjects.Count} 个物体");
                    return existingExcludedObjects.ToList();
                }

                // 从数据库加载排除列表（全局排除列表）
                if (_database != null)
                {
                    var excludedRecords = _database.GetExcludedObjects(routeId: null, includeGlobal: true);
                    if (excludedRecords != null && excludedRecords.Count > 0)
                    {
                        // 将记录转换为 ModelItem
                        var excludedObjects = new List<ModelItem>();
                        var doc = Autodesk.Navisworks.Api.Application.ActiveDocument;
                        
                        foreach (var record in excludedRecords)
                        {
                            try
                            {
                                var pathIdObj = new Autodesk.Navisworks.Api.DocumentParts.ModelItemPathId
                                {
                                    ModelIndex = record.ModelIndex,
                                    PathId = record.PathId
                                };
                                var modelItem = doc.Models.ResolvePathId(pathIdObj);
                                if (modelItem != null)
                                {
                                    excludedObjects.Add(modelItem);
                                }
                            }
                            catch (Exception ex)
                            {
                                LogManager.Warning($"[批处理队列] 加载排除对象失败: {record.ObjectName}, 错误: {ex.Message}");
                            }
                        }

                        if (excludedObjects.Count > 0)
                        {
                            LogManager.Info($"[批处理队列] 从数据库加载排除列表，共 {excludedObjects.Count} 个物体");
                            return excludedObjects;
                        }
                    }
                }

                // 排除列表为空，提示用户
                LogManager.Warning("[批处理队列] 排除列表为空，需要用户确认");
                
                bool shouldContinue = false;
                System.Windows.Application.Current?.Dispatcher.Invoke(() =>
                {
                    var result = System.Windows.MessageBox.Show(
                        "排除列表为空。对于复杂路径，建议先运行\"生成动画\"进行预计算碰撞分析，设置排除列表后再进行批处理。\n\n" +
                        "• 是：继续批处理（不使用排除列表）\n" +
                        "• 否：取消批处理，先去设置排除列表\n\n" +
                        "提示：排除列表可以显著减少复杂路径的碰撞检测时间。",
                        "批处理确认",
                        System.Windows.MessageBoxButton.YesNo,
                        System.Windows.MessageBoxImage.Warning
                    );
                    shouldContinue = (result == System.Windows.MessageBoxResult.Yes);
                });

                if (shouldContinue)
                {
                    LogManager.Info("[批处理队列] 用户选择继续批处理（不使用排除列表）");
                    return new List<ModelItem>(); // 返回空列表，允许继续
                }
                else
                {
                    LogManager.Info("[批处理队列] 用户选择取消批处理，去设置排除列表");
                    return null;
                }
            }
            catch (Exception ex)
            {
                LogManager.Error($"[批处理队列] 检查排除列表失败: {ex.Message}");
                // 发生错误时，允许继续（不阻止批处理）
                return new List<ModelItem>();
            }
        }

        /// <summary>
        /// 获取批处理用的排除列表（已废弃，使用 LoadExcludedObjectsForQueueItemAsync 代替）
        /// </summary>
        private List<ModelItem> GetExcludedObjectsForBatchProcessing()
        {
            try
            {
                // 首先检查 PathAnimationManager 中是否已有排除列表
                var animationManager = PathAnimationManager.GetInstance();
                var existingExcludedObjects = animationManager.GetExcludedObjects();
                
                if (existingExcludedObjects != null && existingExcludedObjects.Count > 0)
                {
                    return existingExcludedObjects.ToList();
                }

                // 从数据库加载排除列表（全局排除列表）
                if (_database != null)
                {
                    var excludedRecords = _database.GetExcludedObjects(routeId: null, includeGlobal: true);
                    if (excludedRecords != null && excludedRecords.Count > 0)
                    {
                        var excludedObjects = new List<ModelItem>();
                        var doc = Autodesk.Navisworks.Api.Application.ActiveDocument;
                        
                        foreach (var record in excludedRecords)
                        {
                            try
                            {
                                var pathIdObj = new Autodesk.Navisworks.Api.DocumentParts.ModelItemPathId
                                {
                                    ModelIndex = record.ModelIndex,
                                    PathId = record.PathId
                                };
                                var modelItem = doc.Models.ResolvePathId(pathIdObj);
                                if (modelItem != null)
                                {
                                    excludedObjects.Add(modelItem);
                                }
                            }
                            catch (Exception ex)
                            {
                                LogManager.Warning($"[批处理队列] 加载排除对象失败: {record.ObjectName}, 错误: {ex.Message}");
                            }
                        }

                        return excludedObjects;
                    }
                }

                return new List<ModelItem>();
            }
            catch (Exception ex)
            {
                LogManager.Error($"[批处理队列] 获取排除列表失败: {ex.Message}");
                return new List<ModelItem>();
            }
        }

        /// <summary>
        /// 从数据库加载指定队列项的排除列表
        /// 从 ExcludedObjects 表读取，根据队列项对应的路径ID (RouteId) 获取
        /// </summary>
        private async Task<List<ModelItem>> LoadExcludedObjectsForQueueItemAsync(BatchQueueItem item)
        {
            try
            {
                if (_database == null)
                {
                    LogManager.Warning($"[批处理队列] 数据库未初始化，无法加载队列项 {item.Id} 的排除列表");
                    return new List<ModelItem>();
                }

                // 从 ExcludedObjects 表加载该路径的排除对象
                // 排除列表在生成动画时已保存，按 RouteId 关联
                var excludedRecords = await Task.Run(() => 
                    _database.GetExcludedObjects(item.RouteId, includeGlobal: true));

                if (excludedRecords == null || excludedRecords.Count == 0)
                {
                    LogManager.Info($"[批处理队列] 队列项 {item.Id} (RouteId={item.RouteId}) 没有排除对象");
                    return new List<ModelItem>();
                }

                var excludedObjects = new List<ModelItem>();
                var doc = Autodesk.Navisworks.Api.Application.ActiveDocument;

                foreach (var record in excludedRecords)
                {
                    try
                    {
                        var pathIdObj = new Autodesk.Navisworks.Api.DocumentParts.ModelItemPathId
                        {
                            ModelIndex = record.ModelIndex,
                            PathId = record.PathId
                        };
                        var modelItem = doc.Models.ResolvePathId(pathIdObj);
                        if (modelItem != null)
                        {
                            excludedObjects.Add(modelItem);
                        }
                        else
                        {
                            LogManager.Warning($"[批处理队列] 无法通过 PathId 找到排除对象: ModelIndex={record.ModelIndex}, PathId={record.PathId}");
                        }
                    }
                    catch (Exception ex)
                    {
                        LogManager.Warning($"[批处理队列] 加载排除对象失败: {record.ObjectName}, 错误: {ex.Message}");
                    }
                }

                LogManager.Info($"[批处理队列] 队列项 {item.Id} 加载了 {excludedObjects.Count}/{excludedRecords.Count} 个排除对象");
                return excludedObjects;
            }
            catch (Exception ex)
            {
                LogManager.Error($"[批处理队列] 加载队列项 {item.Id} 的排除列表失败: {ex.Message}");
                return new List<ModelItem>();
            }
        }

        /// <summary>
        /// 加载队列项关联的检测记录（包含排除列表和手工目标）
        /// </summary>
        private async Task<DetectionRecordData> LoadDetectionRecordForQueueItemAsync(BatchQueueItem item)
        {
            try
            {
                if (_database == null || !item.DetectionRecordId.HasValue)
                {
                    LogManager.Warning($"[批处理队列] 队列项 {item.Id} 没有关联的检测记录");
                    return null;
                }

                // 获取检测记录
                var record = await Task.Run(() => _database.GetCollisionDetectionRecord(item.DetectionRecordId.Value));
                if (record == null)
                {
                    LogManager.Warning($"[批处理队列] 未找到检测记录 (Id={item.DetectionRecordId})");
                    return null;
                }

                var result = new DetectionRecordData
                {
                    RecordId = record.Id,
                    RouteId = record.RouteId,
                    FrameRate = record.FrameRate,
                    DurationSeconds = record.DurationSeconds,
                    DetectionTolerance = record.DetectionTolerance,
                    IsVirtualObject = record.IsVirtualObject,
                    DetectAllObjects = record.DetectAllObjects,
                    ObjectRotationCorrection = record.ObjectRotationCorrection,
                    ExcludedObjects = new List<ModelItem>(),
                    ManualTargets = new List<ModelItem>()
                };

                var doc = Autodesk.Navisworks.Api.Application.ActiveDocument;

                // 加载排除列表
                var excludedRecords = await Task.Run(() => _database.GetCollisionDetectionExcludedObjects(record.Id));
                foreach (var excludedRecord in excludedRecords)
                {
                    try
                    {
                        var pathIdObj = new Autodesk.Navisworks.Api.DocumentParts.ModelItemPathId
                        {
                            ModelIndex = excludedRecord.ModelIndex,
                            PathId = excludedRecord.PathId
                        };
                        var modelItem = doc.Models.ResolvePathId(pathIdObj);
                        if (modelItem != null)
                        {
                            result.ExcludedObjects.Add(modelItem);
                        }
                    }
                    catch (Exception ex)
                    {
                        LogManager.Warning($"[批处理队列] 加载排除对象失败: {excludedRecord.ObjectName}, {ex.Message}");
                    }
                }

                // 加载手工目标
                var manualTargetRecords = await Task.Run(() => _database.GetCollisionDetectionManualTargets(record.Id));
                foreach (var targetRecord in manualTargetRecords)
                {
                    try
                    {
                        var pathIdObj = new Autodesk.Navisworks.Api.DocumentParts.ModelItemPathId
                        {
                            ModelIndex = targetRecord.ModelIndex,
                            PathId = targetRecord.PathId
                        };
                        var modelItem = doc.Models.ResolvePathId(pathIdObj);
                        if (modelItem != null)
                        {
                            result.ManualTargets.Add(modelItem);
                        }
                    }
                    catch (Exception ex)
                    {
                        LogManager.Warning($"[批处理队列] 加载手工目标失败: {targetRecord.ObjectName}, {ex.Message}");
                    }
                }

                LogManager.Info($"[批处理队列] 加载检测记录 (Id={record.Id}): 排除对象={result.ExcludedObjects.Count}, 手工目标={result.ManualTargets.Count}");
                return result;
            }
            catch (Exception ex)
            {
                LogManager.Error($"[批处理队列] 加载检测记录失败: {ex.Message}");
                return null;
            }
        }
    }

    /// <summary>
    /// 检测记录数据（用于批处理）
    /// </summary>
    public class DetectionRecordData
    {
        public int RecordId { get; set; }
        public string RouteId { get; set; }
        public int FrameRate { get; set; }
        public double DurationSeconds { get; set; }
        /// <summary>碰撞检测容差（模型单位）</summary>
        public double DetectionTolerance { get; set; }
        public bool IsVirtualObject { get; set; }
        public bool DetectAllObjects { get; set; }
        public double ObjectRotationCorrection { get; set; }
        public List<ModelItem> ExcludedObjects { get; set; }
        public List<ModelItem> ManualTargets { get; set; }
    }

    /// <summary>
    /// 批处理队列项事件参数
    /// </summary>
    public class BatchQueueItemEventArgs : EventArgs
    {
        public BatchQueueItem Item { get; set; }
    }
}
