using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Autodesk.Navisworks.Api;
using Autodesk.Navisworks.Api.Clash;
using NavisworksTransport.Utils;

namespace NavisworksTransport
{
    /// <summary>
    /// Clash Detective 集成管理器
    /// 实现动态碰撞检测与Clash Detective窗口的联动
    /// </summary>
    public class ClashDetectiveIntegration
    {
        private static ClashDetectiveIntegration _instance;
        private const string CollisionHighlightsCategory = ModelHighlightHelper.CollisionResultsCategory;

        private DocumentClash _documentClash;
        private List<ClashResult> _currentCollisions;
        // 通道对象缓存，用于优化碰撞检测性能
        private static HashSet<ModelItem> _channelObjectsCache = null;
        private static readonly object _cacheLock = new object();

        // 几何对象列表缓存，用于避免重复获取对象列表
        // 使用 ModelItemCollection 而非 List<ModelItem> 以避免昂贵的 ToList() 转换
        private static ModelItemCollection _allGeometryItemsCache = null;

        // 已过滤通道对象的几何对象列表缓存（供空间索引使用）
        private static List<ModelItem> _nonChannelGeometryItemsCache = null;

        // 碰撞检测计数器
        private int _animationCollisionCount = 0;  // 动画过程中简单包围盒检测的碰撞数量
        private int _clashDetectiveCollisionCount = 0;  // Clash Detective最终检测的碰撞数量

        /// <summary>
        /// 动画过程中检测到的碰撞数量（仅供参考统计）
        /// </summary>
        public int AnimationCollisionCount
        {
            get { return _animationCollisionCount; }
        }

        /// <summary>
        /// Clash Detective检测到的权威碰撞数量
        /// </summary>
        public int ClashDetectiveCollisionCount
        {
            get { return _clashDetectiveCollisionCount; }
        }

        /// <summary>
        /// 当前ClashDetective测试名称
        /// </summary>
        public string CurrentTestName
        {
            get { return _currentTestName; }
        }

        private string _currentTestName;

        /// <summary>
        /// 单例实例
        /// </summary>
        public static ClashDetectiveIntegration Instance
        {
            get
            {
                if (_instance == null)
                {
                    _instance = new ClashDetectiveIntegration();
                }
                return _instance;
            }
        }

        /// <summary>
        /// 当前检测到的碰撞结果
        /// </summary>
        public List<ClashResult> CurrentCollisions
        {
            get { return _currentCollisions ?? new List<ClashResult>(); }
        }

        /// <summary>
        /// 碰撞检测结果变化事件
        /// </summary>
        public event EventHandler<CollisionDetectedEventArgs> CollisionDetected;

        /// <summary>
        /// ClashDetective结果保存到数据库事件
        /// </summary>
        public event EventHandler<ClashDetectiveResultSavedEventArgs> ClashDetectiveResultSaved;

        private ClashDetectiveIntegration()
        {
            _currentCollisions = new List<ClashResult>();
            _cachedResults = new List<CollisionResult>();

            // 自动初始化 Clash Detective 集成
            try
            {
                LogManager.Info("初始化Clash Detective集成（.NET API模式）...");

                // 直接使用.NET API获取Clash文档
                _documentClash = Application.ActiveDocument.GetClash();
                if (_documentClash != null)
                {
                    LogManager.Info("成功获取.NET API Clash文档");
                    LogManager.Info("Clash Detective集成初始化成功（.NET API模式）");
                }
                else
                {
                    LogManager.Warning("无法获取Clash文档，Clash Detective可能未安装");
                }
            }
            catch (Exception ex)
            {
                LogManager.Error($"初始化Clash Detective集成失败: {ex.Message}");
                _documentClash = null;
            }
        }

        /// <summary>
        /// 创建碰撞快照（动画结束后一次性更新结果）
        /// </summary>
        public void CreateCollisionSnapshot(List<CollisionResult> results)
        {
            try
            {
                if (_documentClash == null)
                    return;

                // 缓存结果，等动画结束后统一处理
                CacheCollisionResults(results);
            }
            catch (Exception ex)
            {
                LogManager.Error($"创建实时碰撞快照失败: {ex.Message}");
            }
        }

        private List<CollisionResult> _cachedResults = new List<CollisionResult>();
        private readonly object _resultsLock = new object();

        // ClashDetective测试结果缓存：pathName -> List<CollisionResult>
        // 使用自定义的CollisionResult类型，支持修改Item1和Item2
        private Dictionary<string, List<CollisionResult>> _clashDetectiveResultsCache = new Dictionary<string, List<CollisionResult>>();
        private readonly object _clashResultsCacheLock = new object();

        /// <summary>
        /// 缓存碰撞结果
        /// </summary>
        private void CacheCollisionResults(List<CollisionResult> results)
        {
            if (results != null && results.Count > 0)
            {
                _cachedResults.AddRange(results);
            }
        }

        /// <summary>
        /// 保存ClashDetective结果到数据库
        /// </summary>
        private void SaveClashDetectiveResultToDatabase(string pathName, string routeId, List<CollisionResult> clashResults,
                                                         int frameRate, double duration, double detectionGap, string animatedObjectName)
        {
            try
            {
                var pathDatabase = PathPlanningManager.Instance?.GetPathDatabase();
                if (pathDatabase != null)
                {
                    var record = new ClashDetectiveResultRecord
                    {
                        TestName = _currentTestName,
                        PathName = pathName,
                        RouteId = routeId ?? "",
                        TestTime = DateTime.Now,
                        CollisionCount = clashResults.Count,
                        AnimationCollisionCount = _animationCollisionCount,
                        FrameRate = frameRate,
                        Duration = duration,
                        DetectionGap = detectionGap,
                        AnimatedObjectName = animatedObjectName,
                        CreatedAt = DateTime.Now
                    };
                    pathDatabase.SaveClashDetectiveResult(record);
                    LogManager.Info($"ClashDetective结果已保存到数据库");

                    // 触发结果保存事件，通知UI刷新列表
                    ClashDetectiveResultSaved?.Invoke(this, new ClashDetectiveResultSavedEventArgs(pathName, _currentTestName, clashResults.Count));
                }
            }
            catch (Exception ex)
            {
                LogManager.Error($"保存ClashDetective结果到数据库失败: {ex.Message}");
                // 不影响主流程，继续执行
            }
        }

        /// <summary>
        /// 合并复合对象碰撞结果
        /// 将几何体级别的碰撞结果合并成复合对象级别的碰撞结果（去重）
        /// </summary>
        private List<CollisionResult> MergeCompositeCollisions(ClashResultGroup collisionGroup)
        {
            var clashResults = new List<CollisionResult>();
            var mergedKeys = new HashSet<string>();

            foreach (var child in collisionGroup.Children)
            {
                if (child is ClashResult clashResult)
                {
                    // 向上查找有意义的父级容器
                    var compositeItem1 = ModelItemAnalysisHelper.FindNamedParentContainer(clashResult.Item1);
                    var compositeItem2 = ModelItemAnalysisHelper.FindNamedParentContainer(clashResult.Item2);

                    // 使用复合对象的HashCode作为key去重
                    var key = $"{compositeItem1.GetHashCode()}_{compositeItem2.GetHashCode()}";

                    if (!mergedKeys.Contains(key))
                    {
                        // 创建自定义的CollisionResult对象
                        var collisionResult = new CollisionResult
                        {
                            ClashGuid = clashResult.Guid,
                            DisplayName = clashResult.DisplayName,
                            Status = clashResult.Status,
                            Item1 = compositeItem1,
                            Item2 = compositeItem2,
                            Center = clashResult.Center,
                            Distance = clashResult.Distance,
                            CreatedTime = DateTime.Now,
                            OriginalItem1 = clashResult.Item1,
                            OriginalItem2 = clashResult.Item2,
                            HasContainerMapping = true
                        };

                        clashResults.Add(collisionResult);
                        mergedKeys.Add(key);
                    }
                }
            }

            LogManager.Info($"复合对象处理完成：原始{collisionGroup.Children.Count}个碰撞，合并后{clashResults.Count}个碰撞");

            return clashResults;
        }

        /// <summary>
        /// 缓存碰撞结果（动画过程中使用）- 现在包含位置信息用于恢复测试
        /// 使用精确的碰撞检测算法替代简化检测
        /// </summary>
        public void CacheCollisionDuringAnimation(ModelItem animatedObject, Point3D animatedObjectPosition, ModelItem collisionObject, Point3D collisionObjectPosition = null)
        {
            try
            {
                if (!IsModelItemValid(animatedObject) || !IsModelItemValid(collisionObject))
                {
                    LogManager.Warning($"[诊断-无效对象] 对象验证失败，退出缓存过程");
                    return;
                }

                // 🔧 智能容器映射：将几何体子对象映射到有名称的容器对象
                var mappedAnimatedObject = GetCollisionObjectWithValidIdentity(animatedObject);
                var mappedCollisionObject = GetCollisionObjectWithValidIdentity(collisionObject);

                // 检查是否进行了容器映射
                bool hasMapping1 = !mappedAnimatedObject.Equals(animatedObject);
                bool hasMapping2 = !mappedCollisionObject.Equals(collisionObject);

                // 使用包围盒碰撞检测算法
                var animatedBoundingBox = animatedObject.BoundingBox();
                var collisionBoundingBox = collisionObject.BoundingBox();

                if (BoundingBoxGeometryUtils.BoundingBoxesIntersect(animatedBoundingBox, collisionBoundingBox))
                {
                    // 🔍 计算并验证位置信息
                    var finalCollisionPosition = collisionObjectPosition ?? GetObjectPosition(collisionObject);

                    // 创建碰撞结果
                    var collisionDistance = BoundingBoxGeometryUtils.CalculateDistance(animatedBoundingBox, collisionBoundingBox);
                    var collisionCenter = BoundingBoxGeometryUtils.CalculateCenter(animatedBoundingBox, collisionBoundingBox);

                    var collision = new CollisionResult
                    {
                        ClashGuid = Guid.NewGuid(),
                        DisplayName = $"精确碰撞: {mappedAnimatedObject.DisplayName} <-> {mappedCollisionObject.DisplayName}",
                        Status = ClashResultStatus.New,
                        Item1 = mappedAnimatedObject,  // 记录容器对象
                        Item2 = mappedCollisionObject, // 记录容器对象
                        OriginalItem1 = animatedObject, // 保存原始几何体对象
                        OriginalItem2 = collisionObject, // 保存原始几何体对象
                        HasContainerMapping = hasMapping1 || hasMapping2, // 标记是否进行了映射
                        CreatedTime = DateTime.Now,
                        Distance = collisionDistance,
                        Center = collisionCenter,
                        Item1Position = animatedObjectPosition,
                        Item2Position = finalCollisionPosition,
                        HasPositionInfo = true
                    };

                    // 去重处理：避免重复缓存相同的碰撞对（基于容器对象）
                    var existing = _cachedResults.FirstOrDefault(r =>
                        r.Item1.Equals(mappedAnimatedObject) && r.Item2.Equals(mappedCollisionObject));

                    if (existing == null)
                    {
                        _cachedResults.Add(collision);
                    }
                }
            }
            catch (Exception ex)
            {
                LogManager.Error($"缓存碰撞失败: {ex.Message}");
                LogManager.Error($"[诊断-异常堆栈] {ex.StackTrace}");
            }
        }

        /// <summary>
        /// 获取对象当前位置
        /// </summary>
        private Point3D GetObjectPosition(ModelItem item)
        {
            try
            {
                if (item == null) return new Point3D(0, 0, 0);

                var bounds = item.BoundingBox();
                if (bounds != null)
                {
                    return new Point3D(
                        (bounds.Min.X + bounds.Max.X) / 2,
                        (bounds.Min.Y + bounds.Max.Y) / 2,
                        (bounds.Min.Z + bounds.Max.Z) / 2
                    );
                }
                return new Point3D(0, 0, 0);
            }
            catch (Exception ex)
            {
                LogManager.Error($"获取对象位置失败: {ex.Message}");
                return new Point3D(0, 0, 0);
            }
        }

        /// <summary>
        /// 动画结束后统一创建和运行ClashDetective碰撞测试
        /// </summary>
        /// <param name="precomputedCollisions">预计算碰撞结果</param>
        /// <param name="detectionGap">检测间隙容差</param>
        /// <param name="pathName">路径名称</param>
        /// <param name="routeId">路由ID</param>
        /// <param name="animatedObjectName">动画对象名称</param>
        /// <param name="frameRate">帧率</param>
        /// <param name="duration">动画时长</param>
        public void CreateAllAnimationCollisionTests(List<CollisionResult> precomputedCollisions, double detectionGap = 0.05,
            string pathName = "未知路径", string routeId = null, string animatedObjectName = null,
            int frameRate = 30, double duration = 10.0)
        {
            try
            {
                LogManager.Info($"=== 使用预计算碰撞数据创建ClashDetective测试（容差: {detectionGap}米） ===");

                if (_documentClash == null || precomputedCollisions == null || precomputedCollisions.Count == 0)
                {
                    LogManager.Info($"无预计算碰撞数据需要处理 - _documentClash: {_documentClash != null}, precomputedCollisions: {precomputedCollisions?.Count ?? 0}");
                    return;
                }

                LogManager.Info($"[预计算数据] 共有 {precomputedCollisions.Count} 个碰撞记录");

                // 直接使用所有预计算结果，只过滤有效对象（不去重）
                var collisionResults = precomputedCollisions
                    .Where(result => IsModelItemValid(result.Item1) && IsModelItemValid(result.Item2))
                    .ToList();

                if (collisionResults.Count == 0)
                {
                    LogManager.Warning("没有有效的预计算碰撞可以创建测试");
                    return;
                }

                // 记录动画过程中的碰撞数量
                _animationCollisionCount = collisionResults.Count;
                LogManager.Info($"[预计算处理] 原始记录: {precomputedCollisions.Count}，有效碰撞: {_animationCollisionCount}");

                // 获取动画对象和当前动画终点位置（用于后续恢复）
                ModelItem animatedObject = null;
                Point3D animationEndPosition = new Point3D(0, 0, 0);

                if (collisionResults.Count > 0)
                {
                    animatedObject = collisionResults[0].Item1;

                    // 记录当前位置（应该是动画终点）
                    if (animatedObject != null && IsModelItemValid(animatedObject))
                    {
                        var bounds = animatedObject.BoundingBox();
                        animationEndPosition = new Point3D(
                            (bounds.Min.X + bounds.Max.X) / 2,
                            (bounds.Min.Y + bounds.Max.Y) / 2,
                            (bounds.Min.Z + bounds.Max.Z) / 2
                        );
                        LogManager.Info($"记录动画终点位置: ({animationEndPosition.X:F2},{animationEndPosition.Y:F2},{animationEndPosition.Z:F2})");
                    }
                }

                var doc = Application.ActiveDocument;

                // 使用分组方案：创建一个主测试和一个包含所有碰撞结果的组
                LogManager.Info("=== 开始分组方案：创建主测试和碰撞分组 ===");

                // 过滤有效的碰撞
                var validCollisions = collisionResults.Where(collision =>
                    collision.HasPositionInfo &&
                    IsModelItemValid(collision.Item1) &&
                    IsModelItemValid(collision.Item2)
                ).ToList();

                if (validCollisions.Count == 0)
                {
                    LogManager.Warning("没有有效的碰撞可以创建测试");
                    return;
                }

                LogManager.Info($"[分组测试] 有效碰撞数量: {validCollisions.Count}");

                // 创建主测试名称
                var mainTestName = $"物流碰撞检测_{pathName}_{DateTime.Now:yyyyMMdd_HHmmss}";
                _currentTestName = mainTestName;
                LogManager.Info($"[分组测试] 创建主测试: {mainTestName}");

                Progress progress = null;
                try
                {
                    // 开始进度条（ClashDetective本身会显示进度，这里只提供提示信息）
                    progress = Application.BeginProgress(
                        "碰撞检测数据分析中，请稍候..."
                    );

                    // 使用事务确保操作的原子性
                    using (var transaction = doc.BeginTransaction("创建分组碰撞测试"))
                    {
                        // 第一步：创建主测试（不包含选择集，纯容器）
                        var mainTest = new ClashTest
                        {
                            DisplayName = mainTestName,
                            // HardConservative 模式的缺点是性能低。如果要提高性能，可以用Hard模式
                            TestType = ClashTestType.Hard,
                            Tolerance = detectionGap,
                            Guid = Guid.Empty,
                            MergeComposites = true
                        };

                        // 添加主测试到文档
                        _documentClash.TestsData.TestsAddCopy(mainTest);
                        LogManager.Info($"[分组测试] 主测试已添加到文档");

                        // 获取添加后的测试对象引用
                        var addedMainTest = _documentClash.TestsData.Tests.FirstOrDefault(t => t.DisplayName == mainTestName) as ClashTest;
                        if (addedMainTest == null)
                        {
                            LogManager.Error("无法获取添加后的主测试对象");
                            return;
                        }


                        // 第二步：创建分组并添加碰撞结果（应用智能去重）
                        // 1. 分组：按碰撞对象对分组
                        var groupedCollisions = validCollisions
                            .GroupBy(c => new { Item1 = c.Item1, Item2 = c.Item2 })
                            .ToList();

                        LogManager.Info($"[分组测试] 智能去重: {validCollisions.Count} 个检测点 -> {groupedCollisions.Count} 个唯一碰撞对");

                        var collisionGroup = new ClashResultGroup
                        {
                            DisplayName = $"物流碰撞检测组 ({groupedCollisions.Count} 个唯一碰撞对)"
                        };

                        LogManager.Info($"[分组测试] 创建碰撞分组: {collisionGroup.DisplayName}");

                        int confirmedCount = 0;
                        int skippedCount = 0;

                        // 2. 遍历每一组
                        for (int groupIndex = 0; groupIndex < groupedCollisions.Count; groupIndex++)
                        {
                            // 检查用户是否取消
                            if (progress.IsCanceled)
                            {
                                LogManager.Info($"[分组测试] 用户取消操作，已处理 {groupIndex}/{groupedCollisions.Count} 组");
                                break;
                            }

                            var group = groupedCollisions[groupIndex];

                            // 3. 排序：按距离/重叠深度排序，优先检测最严重的碰撞
                            // 注意：Distance通常越小（或负值越大）表示碰撞越深，具体取决于计算方式
                            // 这里假设Distance越小越严重
                            var sortedCandidates = group.OrderBy(c => c.Distance).ToList();

                            bool pairConfirmed = false;

                            // 4. 验证即止：逐个检测候选帧
                            for (int i = 0; i < sortedCandidates.Count; i++)
                            {
                                var candidate = sortedCandidates[i];

                                try
                                {
                                    // 临时移动动画对象到碰撞位置以执行测试
                                    var testAnimatedObject = candidate.Item1;
                                    var modelItems = new ModelItemCollection { testAnimatedObject };
                                    var targetPosition = candidate.Item1Position;

                                    // 计算移动偏移
                                    var currentBounds = testAnimatedObject.BoundingBox();
                                    var currentPos = new Point3D(
                                        (currentBounds.Min.X + currentBounds.Max.X) / 2,
                                        (currentBounds.Min.Y + currentBounds.Max.Y) / 2,
                                        (currentBounds.Min.Z + currentBounds.Max.Z) / 2
                                    );

                                    var offset = new Vector3D(
                                        targetPosition.X - currentPos.X,
                                        targetPosition.Y - currentPos.Y,
                                        targetPosition.Z - currentPos.Z
                                    );

                                    var transform = Transform3D.CreateTranslation(offset);
                                    doc.Models.OverridePermanentTransform(modelItems, transform, false);

                                    // 创建临时测试以获取真实碰撞结果
                                    var tempTestName = $"临时验证_{confirmedCount + 1}_{i}_{DateTime.Now:HHmmss_fff}";
                                    var tempTest = new ClashTest
                                    {
                                        DisplayName = tempTestName,
                                        TestType = ClashTestType.HardConservative,
                                        Tolerance = detectionGap,
                                        Guid = Guid.Empty,
                                        MergeComposites = true
                                    };

                                    // 设置选择集
                                    var selectionA = new ModelItemCollection { candidate.Item1 };
                                    var selectionB = new ModelItemCollection { candidate.Item2 };

                                    tempTest.SelectionA.Selection.CopyFrom(selectionA);
                                    tempTest.SelectionB.Selection.CopyFrom(selectionB);

                                    // 添加并运行临时测试
                                    _documentClash.TestsData.TestsAddCopy(tempTest);
                                    var addedTempTest = _documentClash.TestsData.Tests.FirstOrDefault(t => t.DisplayName == tempTestName) as ClashTest;

                                    if (addedTempTest != null)
                                    {
                                        // 使用正确的PrimitiveTypes设置模式
                                        try
                                        {
                                            var copyTest = addedTempTest.CreateCopy() as ClashTest;
                                            copyTest.SelectionA.PrimitiveTypes = PrimitiveTypes.Triangles | PrimitiveTypes.Lines | PrimitiveTypes.Points;
                                            copyTest.SelectionB.PrimitiveTypes = PrimitiveTypes.Triangles | PrimitiveTypes.Lines | PrimitiveTypes.Points;
                                            _documentClash.TestsData.TestsEditTestFromCopy(addedTempTest, copyTest);
                                        }
                                        catch (Exception geomEx)
                                        {
                                            LogManager.Warning($"设置几何类型失败: {geomEx.Message}");
                                        }

                                        // 运行测试
                                        _documentClash.TestsData.TestsRunTest(addedTempTest);

                                        // 获取刷新后的测试结果
                                        var refreshedTempTest = _documentClash.TestsData.Tests.FirstOrDefault(t => t.DisplayName == tempTestName) as ClashTest;
                                        if (refreshedTempTest != null && refreshedTempTest.Children.Count > 0)
                                        {
                                            // ！！！发现真实碰撞！！！
                                            pairConfirmed = true;
                                            confirmedCount++;
                                            skippedCount += (sortedCandidates.Count - 1 - i); // 记录跳过的数量

                                            // 将碰撞结果复制到分组中
                                            int subResultIndex = 1;
                                            foreach (var child in refreshedTempTest.Children)
                                            {
                                                if (child is ClashResult result)
                                                {
                                                    var copiedResult = result.CreateCopy() as ClashResult;
                                                    copiedResult.Guid = Guid.NewGuid(); // 生成新的GUID

                                                    // 设置唯一且有意义的碰撞名称
                                                    // 先找到有意义的容器对象，再获取其名称
                                                    var container1 = ModelItemAnalysisHelper.FindNamedParentContainer(result.Item1);
                                                    var container2 = ModelItemAnalysisHelper.FindNamedParentContainer(result.Item2);
                                                    var object1Name = ModelItemAnalysisHelper.GetSafeDisplayName(container1);
                                                    var object2Name = ModelItemAnalysisHelper.GetSafeDisplayName(container2);

                                                    var timeStamp = DateTime.Now.ToString("HHmmss");
                                                    copiedResult.DisplayName = $"物流碰撞#{confirmedCount:00}-{subResultIndex:00}_{timeStamp}: {object1Name} ↔ {object2Name}";

                                                    collisionGroup.Children.Add(copiedResult);
                                                    subResultIndex++;
                                                }
                                            }
                                        }

                                        // 删除临时测试
                                        try
                                        {
                                            _documentClash.TestsData.TestsRemove(refreshedTempTest ?? addedTempTest);
                                        }
                                        catch (Exception cleanEx)
                                        {
                                            LogManager.Warning($"清理临时测试失败: {cleanEx.Message}");
                                        }

                                        // 如果已确认碰撞，跳出当前候选循环，不再检测该组剩余帧
                                        if (pairConfirmed)
                                        {
                                            break;
                                        }
                                    }
                                }
                                catch (Exception itemEx)
                                {
                                    LogManager.Error($"候选检测失败: {itemEx.Message}");
                                }
                            }
                        }

                        LogManager.Info($"[分组测试] ClashDetective检测完成: 确认碰撞 {confirmedCount} 组, 跳过 {skippedCount} 个冗余检测点");

                        // 第三步：处理碰撞结果
                        var clashResults = MergeCompositeCollisions(collisionGroup);

                        // 缓存结果
                        lock (_clashResultsCacheLock)
                        {
                            _clashDetectiveResultsCache[_currentTestName] = clashResults;
                        }
                        LogManager.Info($"已缓存ClashDetective结果：{clashResults.Count}个碰撞，测试名称：{_currentTestName}");

                        // 更新碰撞计数器
                        _clashDetectiveCollisionCount = clashResults.Count;

                        // 保存到数据库
                        SaveClashDetectiveResultToDatabase(pathName, routeId, clashResults, frameRate, duration, detectionGap, animatedObjectName);

                        // 第四步：将分组添加到主测试
                        if (collisionGroup.Children.Count > 0)
                        {
                            _documentClash.TestsData.TestsAddCopy(addedMainTest, collisionGroup);
                        }
                        else
                        {
                            LogManager.Warning("[分组测试] 分组为空（未检测到真实几何碰撞），未添加到主测试");
                        }

                        // 提交事务
                        transaction.Commit();
                    }
                }
                catch (Exception groupEx)
                {
                    LogManager.Error($"[分组测试] 创建分组测试失败: {groupEx.Message}");
                }
                finally
                {
                    // 确保关闭进度条
                    if (progress != null)
                    {
                        Application.EndProgress();
                    }
                }

                // 碰撞测试完成后，将物体恢复到动画终点位置
                if (animatedObject != null && IsModelItemValid(animatedObject))
                {
                    try
                    {
                        var modelItems = new ModelItemCollection { animatedObject };

                        // 计算当前位置到动画终点的偏移
                        var currentBounds = animatedObject.BoundingBox();
                        var currentPos = new Point3D(
                            (currentBounds.Min.X + currentBounds.Max.X) / 2,
                            (currentBounds.Min.Y + currentBounds.Max.Y) / 2,
                            (currentBounds.Min.Z + currentBounds.Max.Z) / 2
                        );

                        var restoreOffset = new Vector3D(
                            animationEndPosition.X - currentPos.X,
                            animationEndPosition.Y - currentPos.Y,
                            animationEndPosition.Z - currentPos.Z
                        );

                        var restoreTransform = Transform3D.CreateTranslation(restoreOffset);
                        doc.Models.OverridePermanentTransform(modelItems, restoreTransform, false);

                        LogManager.Info($"已将 {animatedObject.DisplayName} 恢复到动画终点位置: ({animationEndPosition.X:F2},{animationEndPosition.Y:F2},{animationEndPosition.Z:F2})");
                    }
                    catch (Exception restoreEx)
                    {
                        LogManager.Error($"恢复物体到动画终点失败: {restoreEx.Message}");
                    }
                }

                // 检查是否成功创建了主测试
                var finalMainTest = _documentClash.TestsData.Tests.FirstOrDefault(t => t.DisplayName.Contains("物流碰撞检测")) as ClashTest;
                if (finalMainTest != null)
                {
                    // 刷新Clash Detective窗口
                    RefreshClashDetectiveUI();

                    // 自动高亮ClashDetective结果
                    try
                    {
                        HighlightClashDetectiveResults(_currentTestName);
                        LogManager.Info("自动高亮ClashDetective检测结果完成");
                    }
                    catch (Exception clashHighlightEx)
                    {
                        LogManager.Error($"自动高亮ClashDetective结果失败: {clashHighlightEx.Message}");
                    }

                    LogManager.Info($"=== 碰撞统计最终结果 ===");
                    LogManager.Info($"动画过程包围盒检测: {_animationCollisionCount}个碰撞 (参考值)");
                    LogManager.Info($"Clash Detective权威结果: {_clashDetectiveCollisionCount}个碰撞 (权威数据)");

                    // 触发碰撞检测完成事件，通知生成报告
                    if (validCollisions.Count > 0)
                    {
                        LogManager.Info($"触发CollisionDetected事件，通知生成报告（{validCollisions.Count}个碰撞）");
                        var eventArgs = new CollisionDetectedEventArgs(validCollisions);
                        OnCollisionDetected(eventArgs);
                    }
                    else
                    {
                        LogManager.Info("没有碰撞，不生成报告，不保存数据库");
                    }
                }
            }
            catch (Exception ex)
            {
                LogManager.Error($"动画结束后创建测试失败: {ex.Message}");
            }
        }

        /// <summary>
        /// 刷新Clash Detective UI - 安全版本
        /// </summary>
        private void RefreshClashDetectiveUI()
        {
            try
            {
                // 检查文档是否有效
                var doc = Application.ActiveDocument;
                if (doc == null || doc.IsClear)
                {
                    LogManager.Warning("文档无效，跳过UI刷新");
                    return;
                }

                // 检查视图是否有效
                if (doc.ActiveView != null)
                {
                    try
                    {
                        doc.ActiveView.RequestDelayedRedraw(ViewRedrawRequests.All);
                        LogManager.Info("Clash Detective UI已刷新");
                    }
                    catch (ObjectDisposedException)
                    {
                        LogManager.Warning("视图对象已释放，跳过重绘");
                    }
                    catch (Exception ex)
                    {
                        LogManager.Error($"重绘视图失败: {ex.Message}");
                    }
                }
                else
                {
                    LogManager.Warning("活动视图无效，跳过UI刷新");
                }
            }
            catch (ObjectDisposedException)
            {
                LogManager.Warning("文档或视图对象已释放，跳过UI刷新");
            }
            catch (Exception ex)
            {
                LogManager.Error($"刷新Clash Detective UI失败: {ex.Message}");
            }
        }

        /// <summary>
        /// 检查ModelItem是否仍然有效
        /// </summary>
        private bool IsModelItemValid(ModelItem item)
        {
            try
            {
                if (item == null)
                    return false;

                // 尝试访问对象的属性来检查是否有效
                var displayName = item.DisplayName;
                var hasGeometry = item.HasGeometry;

                // 额外检查：确保对象没有被释放
                var boundingBox = item.BoundingBox();
                return true;
            }
            catch (Exception ex)
            {
                LogManager.Debug($"ModelItem无效: {ex.Message}");
                return false;
            }
        }

        /// <summary>
        /// 高亮显示碰撞对象
        /// </summary>
        /// <param name="results">碰撞结果</param>
        /// <param name="clearPrevious">是否清除之前的高亮</param>
        public void HighlightCollisions(List<CollisionResult> results, bool clearPrevious = true)
        {
            HighlightCollisions(results, Color.Red, clearPrevious);
        }

        /// <summary>
        /// 高亮显示碰撞对象（支持自定义颜色）
        /// </summary>
        /// <param name="results">碰撞结果</param>
        /// <param name="highlightColor">高亮颜色</param>
        /// <param name="clearPrevious">是否清除之前的高亮</param>
        public void HighlightCollisions(List<CollisionResult> results, Color highlightColor, bool clearPrevious = true)
        {
            try
            {
                var validResults = results?.Where(r => r != null).ToList() ?? new List<CollisionResult>();

                if (validResults.Count == 0)
                {
                    if (clearPrevious)
                    {
                        ModelHighlightHelper.ClearCategory(CollisionHighlightsCategory);
                    }
                    return;
                }

                if (clearPrevious)
                {
                    ModelHighlightHelper.ClearCategory(CollisionHighlightsCategory);
                }

                var highlightItems = new List<ModelItem>();
                foreach (var collision in validResults)
                {
                    var item1 = collision.GetValidItem1();
                    var item2 = collision.GetValidItem2();

                    if (IsModelItemValid(item1) && !highlightItems.Contains(item1))
                    {
                        highlightItems.Add(item1);
                    }

                    if (IsModelItemValid(item2) && !highlightItems.Contains(item2))
                    {
                        highlightItems.Add(item2);
                    }
                }

                ModelHighlightHelper.HighlightItems(CollisionHighlightsCategory, highlightItems, highlightColor);
            }
            catch (Exception ex)
            {
                LogManager.Error($"高亮显示碰撞对象失败: {ex.Message}");
            }
        }

        /// <summary>
        /// 高亮ClashDetective测试结果
        /// </summary>
        public void HighlightClashDetectiveResults(string testName)
        {
            try
            {
                // 使用公共方法获取指定测试的碰撞结果
                var clashResults = GetCurrentPathClashResults(testName);

                if (clashResults.Count == 0)
                {
                    LogManager.Info("[ClashDetective高亮] 指定测试中未找到碰撞结果");
                    return;
                }

                // 提取碰撞对象
                var highlightItems = new List<ModelItem>();
                foreach (var clash in clashResults)
                {
                    if (clash.Item1 != null && !highlightItems.Contains(clash.Item1) &&
                        ModelItemAnalysisHelper.IsModelItemValid(clash.Item1))
                    {
                        highlightItems.Add(clash.Item1);
                    }

                    if (clash.Item2 != null && !highlightItems.Contains(clash.Item2) &&
                        ModelItemAnalysisHelper.IsModelItemValid(clash.Item2))
                    {
                        highlightItems.Add(clash.Item2);
                    }
                }

                if (highlightItems.Count > 0)
                {
                    ModelHighlightHelper.HighlightItems(
                        ModelHighlightHelper.ClashDetectiveResultsCategory,
                        highlightItems,
                        Color.Red
                    );
                    LogManager.Info($"[ClashDetective高亮] 已高亮 {highlightItems.Count} 个对象，来自 {clashResults.Count} 个碰撞结果");
                }
                else
                {
                    LogManager.Info("[ClashDetective高亮] 没有有效的碰撞对象可高亮");
                }
            }
            catch (Exception ex)
            {
                LogManager.Error($"[ClashDetective高亮] 高亮失败: {ex.Message}");
            }
        }

        /// <summary>
        /// 清除ClashDetective高亮
        /// </summary>
        public void ClearClashDetectiveHighlights()
        {
            try
            {
                ModelHighlightHelper.ClearCategory(ModelHighlightHelper.ClashDetectiveResultsCategory);
                LogManager.Info("[ClashDetective高亮] 已清除高亮");
            }
            catch (Exception ex)
            {
                LogManager.Error($"[ClashDetective高亮] 清除高亮失败: {ex.Message}");
            }
        }

        /// <summary>
        /// 获取所有物流碰撞检测测试
        /// </summary>
        /// <returns>物流碰撞检测测试列表</returns>
        public List<ClashTest> GetLogisticsClashTests()
        {
            if (_documentClash == null)
            {
                throw new InvalidOperationException("ClashDetective文档未初始化");
            }

            return _documentClash.TestsData.Tests.Cast<ClashTest>()
                .Where(t => t.DisplayName.Contains("物流碰撞检测") ||
                           t.DisplayName.Contains("物流碰撞"))
                .ToList();
        }

        /// <summary>
        /// 获取当前路径的Clash测试
        /// </summary>
        /// <param name="pathName">路径名称</param>
        /// <returns>当前路径的测试</returns>
        public ClashTest GetCurrentPathClashTest(string pathName)
        {
            if (_documentClash == null)
            {
                throw new InvalidOperationException("ClashDetective文档未初始化");
            }

            if (string.IsNullOrEmpty(pathName))
            {
                throw new ArgumentException("路径名称不能为空", nameof(pathName));
            }

            // 获取所有物流碰撞检测测试
            var logisticsTests = GetLogisticsClashTests();

            if (logisticsTests.Count == 0)
            {
                throw new InvalidOperationException("未找到任何物流碰撞检测测试");
            }

            // 精确匹配当前路径的测试
            var matchedTest = logisticsTests
                .Where(t => t.DisplayName.StartsWith("物流碰撞检测_") &&
                           t.DisplayName.Contains(pathName))
                .OrderByDescending(t => t.DisplayName)
                .FirstOrDefault();

            if (matchedTest != null)
            {
                LogManager.Info($"[获取当前路径测试] 找到路径 '{pathName}' 的测试: {matchedTest.DisplayName}");
            }
            else
            {
                LogManager.Info($"[获取当前路径测试] 未找到路径 '{pathName}' 的碰撞测试");
            }

            return matchedTest;
        }

        /// <summary>
        /// 获取当前路径的Clash结果
        /// </summary>
        /// <param name="pathName">路径名称</param>
        /// <returns>当前路径的碰撞结果列表</returns>
        public List<CollisionResult> GetCurrentPathClashResults(string testName)
        {
            lock (_clashResultsCacheLock)
            {
                if (_clashDetectiveResultsCache.TryGetValue(testName, out var cachedResults))
                {
                    LogManager.Debug($"[ClashDetective结果] 从缓存获取 '{testName}' 的结果：{cachedResults.Count}个碰撞");
                    return cachedResults;
                }
            }

            throw new InvalidOperationException($"未找到测试 '{testName}' 的ClashDetective缓存结果，请先运行碰撞检测");
        }

        /// <summary>
        /// 获取当前测试的碰撞结果（便捷方法）
        /// </summary>
        /// <returns>当前测试的碰撞结果列表</returns>
        public List<CollisionResult> GetCurrentTestResults()
        {
            return GetCurrentPathClashResults(_currentTestName);
        }

        /// <summary>
        /// 从测试中提取碰撞结果
        /// </summary>
        /// <param name="clashTest">测试</param>
        /// <returns>碰撞结果列表</returns>
        public List<ClashResult> ExtractClashResultsFromTest(ClashTest clashTest)
        {
            var results = new List<ClashResult>();
            ExtractClashResultsFromTestRecursive(clashTest, results);
            return results;
        }

        /// <summary>
        /// 递归提取测试中的碰撞结果
        /// </summary>
        /// <param name="clashTest">测试</param>
        /// <param name="results">结果列表</param>
        private void ExtractClashResultsFromTestRecursive(ClashTest clashTest, List<ClashResult> results)
        {
            foreach (var child in clashTest.Children)
            {
                if (child is ClashResult clashResult)
                {
                    results.Add(clashResult);
                }
                else if (child is ClashResultGroup resultGroup)
                {
                    ExtractClashResultsFromGroupRecursive(resultGroup, results);
                }
            }
        }

        /// <summary>
        /// 递归提取分组中的碰撞结果
        /// </summary>
        /// <param name="group">分组</param>
        /// <param name="results">结果列表</param>
        private void ExtractClashResultsFromGroupRecursive(ClashResultGroup group, List<ClashResult> results)
        {
            foreach (var child in group.Children)
            {
                if (child is ClashResult result)
                {
                    results.Add(result);
                }
                else if (child is ClashResultGroup subGroup)
                {
                    ExtractClashResultsFromGroupRecursive(subGroup, results);
                }
            }
        }

        /// <summary>
        /// 获取所有物流碰撞检测的碰撞结果
        /// </summary>
        /// <returns>碰撞结果列表</returns>
        public List<ClashResult> GetAllLogisticsClashResults()
        {
            var tests = GetLogisticsClashTests();
            var allResults = new List<ClashResult>();

            foreach (var test in tests)
            {
                var results = ExtractClashResultsFromTest(test);
                allResults.AddRange(results);
            }

            return allResults;
        }

        /// <summary>
        /// 按类别管理高亮显示
        /// </summary>
        /// <param name="category">高亮类别（如"animation", "independent", "report"等）</param>
        /// <param name="results">碰撞结果</param>
        /// <param name="highlightColor">高亮颜色</param>
        /// <param name="clearOtherCategories">是否在高亮前清除该类别以避免叠加</param>
        public void ManageHighlightsByCategory(string category, List<CollisionResult> results,
            Color highlightColor, bool clearOtherCategories = false)
        {
            try
            {
                var collidingItems = new List<ModelItem>();

                if (results != null)
                {
                    foreach (var result in results)
                    {
                        if (result?.Item1 != null && !collidingItems.Contains(result.Item1) && IsModelItemValid(result.Item1))
                        {
                            collidingItems.Add(result.Item1);
                        }

                        if (result?.Item2 != null && !collidingItems.Contains(result.Item2) && IsModelItemValid(result.Item2))
                        {
                            collidingItems.Add(result.Item2);
                        }
                    }
                }

                if (clearOtherCategories)
                {
                    ModelHighlightHelper.ClearCategory(category);
                }

                ModelHighlightHelper.HighlightItems(category, collidingItems, highlightColor);
            }
            catch (Exception ex)
            {
                LogManager.Error($"按类别管理高亮失败 [{category}]: {ex.Message}");
            }
        }

        /// <summary>
        /// 获取当前活跃高亮信息
        /// </summary>
        public string GetActiveHighlightInfo()
        {
            try
            {
                var snapshot = ModelHighlightHelper.GetActiveHighlightSnapshot();
                if (snapshot.Count == 0)
                {
                    return "当前无活跃高亮";
                }

                var info = new StringBuilder();
                info.AppendLine("=== 当前活跃高亮 ===");
                foreach (var entry in snapshot)
                {
                    info.AppendLine($"类别: {entry.Category}");
                    info.AppendLine($"  对象数量: {entry.Count}");
                    info.AppendLine($"  颜色: {entry.Color}");
                    info.AppendLine();
                }

                return info.ToString();
            }
            catch (Exception ex)
            {
                LogManager.Error($"获取高亮信息失败: {ex.Message}");
                return "获取高亮信息失败";
            }
        }

        /// <summary>
        /// 构建通道对象缓存，一次性扫描所有对象，避免重复的属性查询
        /// </summary>
        /// <summary>
        /// 构建通道对象缓存，一次性扫描所有对象，避免重复的属性查询
        /// </summary>
        public void BuildChannelObjectsCache()
        {
            lock (_cacheLock)
            {
                if (_channelObjectsCache != null) return; // 双重检查锁定

                var cacheStopwatch = new System.Diagnostics.Stopwatch();
                cacheStopwatch.Start();

                _channelObjectsCache = new HashSet<ModelItem>();

                try
                {
                    var document = Application.ActiveDocument;

                    // 获取所有可通行的物流模型项
                    var allChannelItems = CategoryAttributeManager.GetAllTraversableLogisticsItems();

                    if (allChannelItems.Count == 0)
                    {
                        LogManager.Warning("[通道缓存] ⚠️ 未找到任何可通行的物流元素，请检查模型中的物流属性设置");
                        cacheStopwatch.Stop();
                        return;
                    }

                    // 智能收集通道相关节点（包括父节点、同级节点、子节点等）
                    foreach (var channelItem in allChannelItems)
                    {
                        try
                        {
                            var itemRelatedNodes = ModelItemAnalysisHelper.CollectRelatedNodes(channelItem);

                            // 将结果添加到缓存中
                            foreach (var node in itemRelatedNodes)
                            {
                                _channelObjectsCache.Add(node);
                            }
                        }
                        catch (Exception ex)
                        {
                            LogManager.Warning($"[通道收集] 处理通道节点 '{channelItem?.DisplayName ?? "NULL"}' 时出错: {ex.Message}");
                            // 出错时至少保证通道本身被添加
                            _channelObjectsCache.Add(channelItem);
                        }
                    }

                    cacheStopwatch.Stop();
                    LogManager.Info($"通道对象缓存构建完成，耗时: {cacheStopwatch.ElapsedMilliseconds}ms");
                    LogManager.Info($"  - 可通行物流根对象: {allChannelItems.Count} 个");
                    LogManager.Info($"  - 缓存总对象数: {_channelObjectsCache.Count} 个");
                }
                catch (Exception ex)
                {
                    LogManager.Error($"构建通道对象缓存时发生错误: {ex.Message}", ex);
                    _channelObjectsCache = new HashSet<ModelItem>(); // 创建空缓存，避免重复构建
                }
            }
        }

        /// <summary>
        /// 清除通道对象缓存，在模型变化时调用
        /// </summary>
        public static void ClearChannelObjectsCache()
        {
            lock (_cacheLock)
            {
                _channelObjectsCache = null;
                LogManager.Debug("通道对象缓存已清除");
            }
        }

        /// <summary>
        /// 获取通道对象缓存（供外部使用）
        /// </summary>
        /// <returns>通道对象集合，如果缓存不存在则返回null</returns>
        public static HashSet<ModelItem> GetChannelObjectsCache()
        {
            lock (_cacheLock)
            {
                return _channelObjectsCache;
            }
        }

        /// <summary>
        /// 构建几何对象列表缓存，一次性获取非隐藏几何对象
        /// </summary>
        public static void BuildNonHidddenGeometryItemsCache()
        {
            lock (_cacheLock)
            {
                if (_allGeometryItemsCache != null) return; // 双重检查锁定

                var cacheStopwatch = new System.Diagnostics.Stopwatch();
                cacheStopwatch.Start();

                try
                {
                    // 优化方案：递归遍历 (Top-Down Traversal)
                    // 原因：Search API 的 Hidden 属性不检查父级可见性，且 IsHidden 属性检查自身。
                    // 解决方案：使用堆栈进行深度优先搜索(DFS)，如果遭遇 Hidden 节点则停止深入该分支。
                    // 这天然地利用了 Navisworks 的层级可见性规则。
                    _allGeometryItemsCache = new ModelItemCollection();
                    int visibleCount = 0;

                    // 使用 Stack 模拟递归避免栈溢出，并保持对 .NET 版本的兼容性
                    // Stack 初始容量设为 1000 以减少扩容
                    var stack = new Stack<ModelItem>(1000);

                    // 将所有模型的根节点压入栈
                    foreach (var model in Application.ActiveDocument.Models)
                    {
                        stack.Push(model.RootItem);
                    }

                    while (stack.Count > 0)
                    {
                        var item = stack.Pop();

                        // 关键剪枝：如果节点显式隐藏，则跳过其整个分支（它的所有子节点都不可见）
                        if (item.IsHidden)
                            continue;

                        // 收集：如果是几何体，加入缓存
                        // 注意：这里我们假设只有几何体(HasGeometry)才是我们需要碰撞检测的对象
                        // 如果父组没有Geometry但子节点有，我们会继续遍历子节点
                        if (item.HasGeometry)
                        {
                            _allGeometryItemsCache.Add(item);
                            visibleCount++;
                        }

                        // 将子节点压入栈 (倒序压入以保持遍历顺序，虽不 strictly necessary)
                        foreach (var child in item.Children)
                        {
                            stack.Push(child);
                        }
                    }

                    cacheStopwatch.Stop();
                    LogManager.Info($"几何对象列表缓存构建完成 (DFS遍历 + 自动剪枝)，耗时: {cacheStopwatch.ElapsedMilliseconds}ms");
                    LogManager.Info($"  - 缓存可见对象: {visibleCount}");
                    LogManager.Info($"  - 策略: 深度优先搜索 (父节点隐藏则跳过分支)");
                }
                catch (Exception ex)
                {
                    LogManager.Error($"构建几何对象列表缓存时发生错误: {ex.Message}", ex);
                    _allGeometryItemsCache = new ModelItemCollection(); // 创建空缓存，避免重复构建
                }
            }
        }

        /// <summary>
        /// 获取几何对象缓存（供外部使用）
        /// </summary>
        /// <returns>几何对象集合，如果缓存不存在则返回null</returns>
        public static ModelItemCollection GetAllGeometryItemsCache()
        {
            lock (_cacheLock)
            {
                return _allGeometryItemsCache; // 直接返回 ModelItemCollection，避免 ToList() 转换
            }
        }

        /// <summary>
        /// 获取已排除通道对象的几何对象缓存（供空间索引使用）
        /// </summary>
        /// <returns>排除通道后的几何对象列表，如果缓存不存在则返回null</returns>
        public static List<ModelItem> GetNonChannelGeometryItemsCache()
        {
            lock (_cacheLock)
            {
                // 如果已经有过滤后的缓存，直接返回
                if (_nonChannelGeometryItemsCache != null)
                {
                    return _nonChannelGeometryItemsCache;
                }

                // 如果原始缓存不存在，返回 null
                if (_allGeometryItemsCache == null || _channelObjectsCache == null)
                {
                    return null;
                }

                // 第一次调用：构建并缓存过滤后的列表
                LogManager.Info($"[空间索引] 构建非通道几何对象缓存...");
                var sw = System.Diagnostics.Stopwatch.StartNew();

                _nonChannelGeometryItemsCache = _allGeometryItemsCache
                    .Where(item => !_channelObjectsCache.Contains(item))
                    .ToList();

                sw.Stop();
                LogManager.Info($"[空间索引] 非通道几何对象缓存构建完成，耗时: {sw.ElapsedMilliseconds}ms，对象数: {_nonChannelGeometryItemsCache.Count}");

                return _nonChannelGeometryItemsCache;
            }
        }

        /// <summary>
        /// 清除所有缓存，在模型变化时调用
        /// </summary>
        public static void ClearAllCaches()
        {
            lock (_cacheLock)
            {
                _channelObjectsCache = null;
                _allGeometryItemsCache = null;
                _nonChannelGeometryItemsCache = null;
                LogManager.Debug("所有对象缓存已清除");
            }
        }

        /// <summary>
        /// 清理碰撞缓存
        /// </summary>
        public void ClearCollisionCache()
        {
            try
            {
                LogManager.Info("[ClashDetectiveIntegration] 清理碰撞缓存");

                // 清空当前碰撞列表
                _currentCollisions?.Clear();

                // 清空缓存的结果
                lock (_resultsLock)
                {
                    _cachedResults?.Clear();
                }

                // 清除对象缓存
                ClearAllCaches();

                // 重置计数器
                _animationCollisionCount = 0;
                _clashDetectiveCollisionCount = 0;

                LogManager.Info("[ClashDetectiveIntegration] 碰撞缓存已清理");
            }
            catch (Exception ex)
            {
                LogManager.Error($"[ClashDetectiveIntegration] 清理碰撞缓存失败: {ex.Message}");
            }
        }

        /// <summary>
        /// 增强的碰撞对象信息，包含容器映射
        /// </summary>
        /// <param name="originalItem">原始碰撞对象（可能是几何体子对象）</param>
        /// <returns>包含完整标识信息的对象</returns>
        private static ModelItem GetCollisionObjectWithValidIdentity(ModelItem originalItem)
        {
            if (originalItem == null) return null;

            // 如果原对象已经有有效名称，直接返回
            if (!string.IsNullOrEmpty(originalItem.DisplayName) && originalItem.DisplayName.Trim().Length > 0)
            {
                return originalItem;
            }

            // 否则查找有名称的父级容器
            var containerObject = ModelItemAnalysisHelper.FindNamedParentContainer(originalItem);

            return containerObject ?? originalItem;
        }

        /// <summary>
        /// 测试容器映射功能是否正常工作
        /// </summary>
        public void TestContainerMapping()
        {
            try
            {
                LogManager.Info("=== [容器映射测试] 开始测试容器映射功能 ===");

                var testResults = new List<string>();

                // 获取一些测试对象
                var allItems = Application.ActiveDocument.Models.RootItemDescendantsAndSelf
                    .Where(item => item.HasGeometry).Take(10).ToList();

                LogManager.Info($"[容器映射测试] 找到 {allItems.Count} 个几何体对象进行测试");

                foreach (var item in allItems)
                {
                    try
                    {
                        var originalName = item.DisplayName ?? "无名称";
                        var mappedObject = GetCollisionObjectWithValidIdentity(item);
                        var mappedName = mappedObject?.DisplayName ?? "无名称";

                        bool hasMapping = !mappedObject.Equals(item);

                        testResults.Add($"原始: '{originalName}' -> 映射: '{mappedName}' (映射: {hasMapping})");

                        LogManager.Info($"[容器映射测试] {testResults.Last()}");

                        // 验证映射对象的有效性
                        if (hasMapping)
                        {
                            var isValidOriginal = IsModelItemValid(item);
                            var isValidMapped = IsModelItemValid(mappedObject);
                            LogManager.Info($"  - 原始对象有效性: {isValidOriginal}");
                            LogManager.Info($"  - 映射对象有效性: {isValidMapped}");
                            LogManager.Info($"  - 原始对象GUID: {item.InstanceGuid}");
                            LogManager.Info($"  - 映射对象GUID: {mappedObject.InstanceGuid}");
                        }
                    }
                    catch (Exception itemEx)
                    {
                        LogManager.Warning($"[容器映射测试] 测试单个对象失败: {itemEx.Message}");
                    }
                }

                LogManager.Info("=== [容器映射测试] 测试结果汇总 ===");
                int mappingCount = testResults.Count(r => r.Contains("映射: True"));
                LogManager.Info($"测试对象总数: {testResults.Count}");
                LogManager.Info($"发生映射的对象: {mappingCount}");
                LogManager.Info($"映射成功率: {(mappingCount * 100.0 / Math.Max(testResults.Count, 1)):F1}%");

                // 测试碰撞结果数据结构
                var testCollision = new CollisionResult
                {
                    ClashGuid = Guid.NewGuid(),
                    DisplayName = "测试碰撞",
                    Item1 = allItems.FirstOrDefault(),
                    Item2 = allItems.Skip(1).FirstOrDefault(),
                    OriginalItem1 = allItems.FirstOrDefault(),
                    OriginalItem2 = allItems.Skip(1).FirstOrDefault(),
                    HasContainerMapping = true,
                    HasPositionInfo = true
                };

                LogManager.Info($"[容器映射测试] CollisionResult数据结构测试:");
                LogManager.Info($"  - GetValidItem1: {testCollision.GetValidItem1()?.DisplayName ?? "NULL"}");
                LogManager.Info($"  - GetValidItem2: {testCollision.GetValidItem2()?.DisplayName ?? "NULL"}");
                LogManager.Info($"  - GetOriginalItem1: {testCollision.GetOriginalItem1()?.DisplayName ?? "NULL"}");
                LogManager.Info($"  - GetOriginalItem2: {testCollision.GetOriginalItem2()?.DisplayName ?? "NULL"}");
                LogManager.Info($"  - HasContainerMapping: {testCollision.HasContainerMapping}");

                LogManager.Info("=== [容器映射测试] 测试完成 ===");
            }
            catch (Exception ex)
            {
                LogManager.Error($"[容器映射测试] 测试失败: {ex.Message}");
                LogManager.Error($"[容器映射测试] 堆栈跟踪: {ex.StackTrace}");
            }
        }

        // 已删除：ForceShowTestResults 和 CreateDemoTest - 不再需要这些已废弃的方法

        /// <summary>
        /// 递归计算测试中的碰撞结果总数（包括分组内的结果）
        /// </summary>
        /// <param name="test">要统计的测试</param>
        /// <returns>碰撞结果总数</returns>
        private int GetTotalClashResultCount(ClashTest test)
        {
            if (test == null) return 0;

            int totalCount = 0;
            foreach (var child in test.Children)
            {
                if (child is ClashResult)
                {
                    totalCount++;
                }
                else if (child is ClashResultGroup group)
                {
                    // 递归统计分组内的结果
                    totalCount += CountClashResultsInGroup(group);
                }
            }

            return totalCount;
        }

        /// <summary>
        /// 递归统计分组内的碰撞结果数量
        /// </summary>
        /// <param name="group">分组</param>
        /// <returns>分组内的碰撞结果总数</returns>
        private int CountClashResultsInGroup(ClashResultGroup group)
        {
            if (group == null) return 0;

            int count = 0;
            foreach (var child in group.Children)
            {
                if (child is ClashResult)
                {
                    count++;
                }
                else if (child is ClashResultGroup nestedGroup)
                {
                    // 递归处理嵌套分组
                    count += CountClashResultsInGroup(nestedGroup);
                }
            }

            return count;
        }

        /// <summary>
        /// 清理资源
        /// </summary>
        public void Cleanup()
        {
            try
            {
                LogManager.Info("开始Clash Detective集成资源清理...");

                // 检查文档是否仍然有效，如果无效则跳过操作
                var document = Application.ActiveDocument;
                if (document == null || document.IsClear)
                {
                    LogManager.Info("文档已无效，跳过资源清理操作");
                    return;
                }

                try
                {
                    ModelHighlightHelper.ClearAllHighlights();
                    LogManager.Info("已清除临时材质高亮");
                }
                catch (Exception ex)
                {
                    LogManager.Warning($"清除临时材质失败: {ex.Message}");
                }

                // 清空内存中的结果
                _currentCollisions?.Clear();
                lock (_resultsLock)
                {
                    _cachedResults?.Clear();
                }

                // 清理.NET API引用
                _documentClash = null;

                LogManager.Info("Clash Detective集成资源清理完成");
            }
            catch (Exception ex)
            {
                LogManager.Error($"清理Clash Detective资源时发生异常: {ex.Message}");
            }
        }

        /// <summary>
        /// 触发碰撞检测事件
        /// </summary>
        private void OnCollisionDetected(CollisionDetectedEventArgs e)
        {
            CollisionDetected?.Invoke(this, e);
        }
    }

    /// <summary>
    /// 碰撞结果数据结构
    /// </summary>
    public class CollisionResult : IEquatable<CollisionResult>
    {
        public Guid ClashGuid { get; set; }
        public string DisplayName { get; set; }
        public ClashResultStatus Status { get; set; }
        public string GridLocation { get; set; }
        public ModelItem Item1 { get; set; }
        public ModelItem Item2 { get; set; }
        public Point3D Center { get; set; }
        public double Distance { get; set; }
        public DateTime CreatedTime { get; set; }

        // 位置信息用于恢复测试
        public Point3D Item1Position { get; set; }
        public Point3D Item2Position { get; set; }
        public bool HasPositionInfo { get; set; }

        // 📦 容器映射信息：记录原始几何体对象引用
        public ModelItem OriginalItem1 { get; set; }  // 原始几何体对象
        public ModelItem OriginalItem2 { get; set; }  // 原始几何体对象
        public bool HasContainerMapping { get; set; } // 标识是否进行了容器映射

        // 📍 获取最终用于ClashDetective的有效对象
        public ModelItem GetValidItem1() => Item1;    // 容器对象，用于ClashDetective选择集
        public ModelItem GetValidItem2() => Item2;    // 容器对象，用于ClashDetective选择集

        // 📍 获取原始几何体对象（用于精确位置信息）
        public ModelItem GetOriginalItem1() => OriginalItem1 ?? Item1;
        public ModelItem GetOriginalItem2() => OriginalItem2 ?? Item2;

        // IEquatable<CollisionResult> 实现：基于碰撞对象进行去重
        public bool Equals(CollisionResult other)
        {
            if (other == null) return false;

            // 使用 ModelItem.Equals 比较底层原生对象
            bool item1Equal = (Item1 == null && other.Item1 == null) ||
                              (Item1 != null && Item1.Equals(other.Item1));
            bool item2Equal = (Item2 == null && other.Item2 == null) ||
                              (Item2 != null && Item2.Equals(other.Item2));

            return item1Equal && item2Equal;
        }

        public override bool Equals(object obj)
        {
            return Equals(obj as CollisionResult);
        }

        public override int GetHashCode()
        {
            unchecked
            {
                int hash = 17;
                hash = hash * 31 + (Item1?.GetHashCode() ?? 0);
                hash = hash * 31 + (Item2?.GetHashCode() ?? 0);
                return hash;
            }
        }
    }

    /// <summary>
    /// 碰撞检测事件参数
    /// </summary>
    public class CollisionDetectedEventArgs : EventArgs
    {
        public List<CollisionResult> Results { get; private set; }
        public int CollisionCount { get; private set; }

        public CollisionDetectedEventArgs(List<CollisionResult> results)
        {
            Results = results;
            CollisionCount = results.Count;
        }
    }

    /// <summary>
    /// ClashDetective结果保存事件参数
    /// </summary>
    public class ClashDetectiveResultSavedEventArgs : EventArgs
    {
        public string PathName { get; private set; }
        public string TestName { get; private set; }
        public int CollisionCount { get; private set; }

        public ClashDetectiveResultSavedEventArgs(string pathName, string testName, int collisionCount)
        {
            PathName = pathName;
            TestName = testName;
            CollisionCount = collisionCount;
        }
    }
}