using System;
using System.Collections.Generic;
using System.Linq;
using Autodesk.Navisworks.Api;
using ComApi = Autodesk.Navisworks.Api.Interop.ComApi;
using ComApiBridge = Autodesk.Navisworks.Api.ComApi.ComApiBridge;

namespace NavisworksTransport.Utils
{
    /// <summary>
    /// 节点分析工具类
    /// 提供用于节点归属分析的静态方法
    /// </summary>
    public static class ModelItemAnalysisHelper
    {

        #region 辅助方法

        /// <summary>
        /// 获取ModelItem的完整路径
        /// </summary>
        /// <param name="modelItem">模型项</param>
        /// <returns>路径列表</returns>
        public static List<string> GetModelItemIndexPaths(ModelItem modelItem)
        {
            var paths = new List<string>();
            
            // 转换为COM选择
            var modelCollection = new ModelItemCollection
            {
                modelItem
            };
            var comSelection = ComApiBridge.ToInwOpSelection(modelCollection);
            
            // 遍历完整路径
            foreach (ComApi.InwOaPath3 path in comSelection.Paths())
            {
                var pathArray = ((Array)path.ArrayData).ToArray<int>();
                var pathKey = string.Join(",", pathArray);
                paths.Add(pathKey);
            }
            
            return paths;
        }

        /// <summary>
        /// 检查一个ModelItem是否是另一个ModelItem的子节点
        /// </summary>
        /// <param name="child">子节点</param>
        /// <param name="parent">父节点</param>
        /// <returns>如果child是parent的子节点返回true</returns>
        public static bool IsChildOf(ModelItem child, ModelItem parent)
        {
            if (child == null || parent == null)
                return false;
                
            var currentParent = child.Parent;
            while (currentParent != null)
            {
                if (currentParent.Equals(parent))
                    return true;
                currentParent = currentParent.Parent;
            }
            return false;
        }


        /// <summary>
        /// 检查ModelItem是否仍然有效
        /// </summary>
        /// <param name="item">要检查的ModelItem</param>
        /// <returns>如果ModelItem有效返回true</returns>
        public static 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>
        /// 比较两个ModelItem是否是同一个对象（使用底层原生对象比较）
        /// 这是项目中推荐的ModelItem比较方式，比使用InstanceGuid或引用比较更可靠
        /// </summary>
        /// <param name="item1">第一个ModelItem</param>
        /// <param name="item2">第二个ModelItem</param>
        /// <returns>如果是同一个对象返回true</returns>
        public static bool ModelItemEquals(ModelItem item1, ModelItem item2)
        {
            if (item1 == null && item2 == null)
                return true;
            if (item1 == null || item2 == null)
                return false;
            
            // 使用ModelItem.Equals比较底层原生对象
            // 这是Navisworks API提供的正确比较方式
            return item1.Equals(item2);
        }

        /// <summary>
        /// 智能查找有意义的父级容器
        /// 基于节点类型进行判断：纯几何体或空节点向上查找，有意义的节点直接返回
        /// </summary>
        /// <param name="geometryItem">几何体对象</param>
        /// <returns>有意义的容器，如果没找到则返回原对象</returns>
        public static ModelItem FindNamedParentContainer(ModelItem geometryItem)
        {
            if (geometryItem == null) return null;
            
            try
            {
                var current = geometryItem;
                int levels = 0; // 防止无限递归
                
                while (current != null && levels < 10) // 最多向上查找10层
                {
                    var nodeType = GetModelItemType(current);
                    var displayName = GetSafeDisplayName(current);
                                        
                    // 根据节点类型决策
                    switch (nodeType)
                    {
                        case ModelItemType.GroupNode:
                        case ModelItemType.HybridNode:
                            // 集合节点或混合节点：有意义的容器，停止查找
                            if (!string.IsNullOrEmpty(displayName))
                            {
                                return current;
                            }
                            break;
                        case ModelItemType.PureGeometry:
                        case ModelItemType.EmptyNode:
                            break;
                    }
                    
                    // 继续向上查找
                    current = current.Parent;
                    levels++;
                }
                
                // 如果没有找到合适的容器，返回原对象
                LogManager.Warning($"[智能容器映射] 未找到有意义的父级容器，使用原对象: {GetSafeDisplayName(geometryItem)}");
                return geometryItem;
            }
            catch (Exception ex)
            {
                LogManager.Warning($"[智能容器映射] 查找父级容器时出错: {ex.Message}");
                return geometryItem; // 出错时返回原对象
            }
        }

        /// <summary>
        /// 安全获取ModelItem的DisplayName，避免访问已释放对象的警告
        /// </summary>
        /// <param name="item">ModelItem对象</param>
        /// <returns>安全的显示名称</returns>
        public static string GetSafeDisplayName(ModelItem item)
        {
            try
            {
                if (item == null)
                {
                    return "NULL";
                }
                
                // 尝试访问DisplayName，如果对象已被释放会抛出异常
                return item.DisplayName ?? "未命名对象";
            }
            catch (System.ObjectDisposedException)
            {
                return "已释放对象";
            }
            catch (System.Runtime.InteropServices.COMException)
            {
                return "COM对象已释放";
            }
            catch (Exception ex)
            {
                return $"访问失败({ex.GetType().Name})";
            }
        }

        #endregion

        #region 节点归属分析方法

        /// <summary>
        /// 收集与选中对象相关的所有节点
        /// 基于节点类型的智能收集策略：
        /// - 纯几何体：找父节点，收集父节点及其所有子节点
        /// - 集合节点/混合节点：收集自身及所有子节点
        /// - 空节点：仅收集自身
        /// </summary>
        /// <param name="selectedObject">选中的对象</param>
        /// <returns>相关节点列表</returns>
        public static List<ModelItem> CollectRelatedNodes(ModelItem selectedObject)
        {
            try
            {
                var relatedNodes = new List<ModelItem>
                {
                    // 添加自身
                    selectedObject
                };
                
                // 判断节点类型
                var itemType = GetModelItemType(selectedObject);
                LogManager.Debug($"[收集相关节点] 开始收集，节点类型: {itemType}");
                
                // 根据节点类型执行不同的收集策略
                switch (itemType)
                {
                    case ModelItemType.PureGeometry:
                        // 纯几何体：找父节点，收集父节点及其所有子节点
                        CollectFromParentNode(selectedObject, relatedNodes);
                        break;
                        
                    case ModelItemType.GroupNode:
                    case ModelItemType.HybridNode:
                        // 集合节点或混合节点：收集自身及所有子节点
                        CollectFromCurrentNode(selectedObject, relatedNodes);
                        break;
                        
                    case ModelItemType.EmptyNode:
                        // 空节点：仅收集自身（已在开头添加）
                        LogManager.Debug($"[收集相关节点] 空节点，仅收集自身");
                        break;
                }
                
                // 去重
                relatedNodes = relatedNodes.Distinct().ToList();
                
                LogManager.Debug($"[收集相关节点] 总共收集到 {relatedNodes.Count} 个节点");
                return relatedNodes;
            }
            catch (Exception ex)
            {
                LogManager.Warning($"[收集相关节点] 收集过程异常: {ex.Message}");
                return new List<ModelItem> { selectedObject }; // 异常时返回最基本的列表
            }
        }

        /// <summary>
        /// 判断模型节点的类型
        /// </summary>
        /// <param name="item">模型节点</param>
        /// <returns>节点类型</returns>
        private static ModelItemType GetModelItemType(ModelItem item)
        {
            try
            {
                bool hasGeometry = item.HasGeometry;
                int childCount = item.Children?.Count() ?? 0;
                
                if (hasGeometry && childCount == 0)
                {
                    return ModelItemType.PureGeometry;
                }
                else if (!hasGeometry && childCount > 0)
                {
                    return ModelItemType.GroupNode;
                }
                else if (hasGeometry && childCount > 0)
                {
                    return ModelItemType.HybridNode;
                }
                else
                {
                    return ModelItemType.EmptyNode;
                }
            }
            catch (Exception ex)
            {
                LogManager.Warning($"[节点类型判断] 判断节点类型时异常 '{item.DisplayName}': {ex.Message}");
                return ModelItemType.EmptyNode; // 异常时返回最保守的类型
            }
        }

        
        /// <summary>
        /// 从父节点收集相关节点（用于纯几何体节点）
        /// </summary>
        /// <param name="pureGeometryNode">纯几何体节点</param>
        /// <param name="analysis">分析结果对象</param>
        /// <summary>
        /// 从父节点收集相关节点（用于纯几何体节点）
        /// </summary>
        /// <param name="pureGeometryNode">纯几何体节点</param>
        /// <param name="relatedNodes">相关节点列表</param>
        private static void CollectFromParentNode(ModelItem pureGeometryNode, List<ModelItem> relatedNodes)
        {
            try
            {
                if (pureGeometryNode.Parent != null)
                {
                    var parent = pureGeometryNode.Parent;
                    LogManager.Debug($"[父节点收集] 找到父节点: '{parent.DisplayName}'");
                    
                    // 添加父节点
                    relatedNodes.Add(parent);
                    
                    // 收集父节点的所有子节点（包含几何体的）
                    if (parent.Children != null)
                    {
                        var siblings = parent.Children.Where(child => child.HasGeometry).ToList();
                        relatedNodes.AddRange(siblings);
                        
                        LogManager.Debug($"[父节点收集] 从父节点 '{parent.DisplayName}' 收集了 {siblings.Count} 个有几何体的子节点");
                    }
                }
                else
                {
                    // 没有父节点，可能是根节点，只收集自己的后代
                    LogManager.Debug($"[父节点收集] '{pureGeometryNode.DisplayName}' 没有父节点，收集自身后代");
                    CollectFromCurrentNode(pureGeometryNode, relatedNodes);
                }
            }
            catch (Exception ex)
            {
                LogManager.Warning($"[父节点收集] 收集过程异常: {ex.Message}");
            }
        }

        
        /// <summary>
        /// 从当前节点收集相关节点（用于集合节点和混合节点）
        /// </summary>
        /// <param name="currentNode">当前节点（集合节点或混合节点）</param>
        /// <param name="analysis">分析结果对象</param>
        /// <summary>
        /// 从当前节点收集相关节点（用于集合节点和混合节点）
        /// </summary>
        /// <param name="currentNode">当前节点（集合节点或混合节点）</param>
        /// <param name="relatedNodes">相关节点列表</param>
        private static void CollectFromCurrentNode(ModelItem currentNode, List<ModelItem> relatedNodes)
        {
            try
            {
                // 收集当前节点的所有后代节点（包含几何体的）
                var descendants = currentNode.DescendantsAndSelf.Where(d => d.HasGeometry).ToList();
                relatedNodes.AddRange(descendants);
                
                LogManager.Debug($"[当前节点收集] 从节点 '{currentNode.DisplayName}' 收集了 {descendants.Count} 个有几何体的后代节点");
            }
            catch (Exception ex)
            {
                LogManager.Warning($"[当前节点收集] 收集过程异常: {ex.Message}");
            }
        }

        #endregion

        #region 几何体获取方法

        /// <summary>
        /// 获取所有可见的几何体项目（DFS遍历 + 隐藏项过滤 + 几何体类型过滤）
        /// 统一的几何体获取接口，供自动路径规划和动画检测预计算共同使用
        /// </summary>
        /// <returns>可见的几何体项目列表（只保留包含 Triangles 的几何体）</returns>
        public static List<ModelItem> GetAllVisibleGeometryItems()
        {
            try
            {
                LogManager.Info("[几何体获取] 开始获取所有可见几何体项目");
                var startTime = DateTime.Now;

                // 统计模型总数
                var totalModelItems = Application.ActiveDocument.Models.RootItemDescendantsAndSelf.Count();
                LogManager.Info($"[几何体获取] 模型总数统计: {totalModelItems} 个模型项");

                // 使用 Stack 模拟递归避免栈溢出
                // Stack 初始容量设为 1000 以减少扩容
                var stack = new Stack<ModelItem>(1000);
                var visibleItems = new List<ModelItem>();

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

                // 统计信息
                int hiddenSkipped = 0;          // 跳过的隐藏节点（包括其子节点）
                int visibleCount = 0;           // 可见节点总数
                int triangleCount = 0;          // 纯三角形几何体
                int lineOnlyCount = 0;          // 纯线条几何体（过滤）
                int pointOnlyCount = 0;         // 纯点几何体（过滤）
                int snapPointOnlyCount = 0;     // 纯捕捉点几何体（过滤）
                int textOnlyCount = 0;          // 纯文本几何体（过滤）
                int mixedCount = 0;             // 混合类型几何体
                int noGeometryCount = 0;        // 无几何体节点

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

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

                    visibleCount++;

                    // 🔥 优化：只提取复合对象（IsComposite = true）或独立实体节点（HasGeometry）
                    // 原因：复合对象（如窗户）包含多个实体节点（玻璃、框架、把手）
                    // 我们只需要检测复合对象，不需要检测其子节点
                    bool isComposite = item.IsComposite;
                    bool hasGeometry = item.HasGeometry;

                    if (isComposite || hasGeometry)
                    {
                        bool addedCurrentItem = false;

                        // 复合对象或独立实体节点：检查几何体类型
                        var geometry = item.Geometry;

                        if (geometry != null)
                        {
                            var primitiveTypes = geometry.PrimitiveTypes;

                            // 统计各种图元类型
                            if (primitiveTypes.HasFlag(PrimitiveTypes.Triangles))
                            {
                                if (primitiveTypes == PrimitiveTypes.Triangles)
                                    triangleCount++;
                                else
                                    mixedCount++;
                                visibleItems.Add(item); // 只保留包含三角形的几何体
                                addedCurrentItem = true;
                            }
                            else if (primitiveTypes == PrimitiveTypes.Lines)
                            {
                                lineOnlyCount++;
                                // 不添加：纯线条几何体过滤掉
                            }
                            else if (primitiveTypes == PrimitiveTypes.Points)
                            {
                                pointOnlyCount++;
                                // 不添加：纯点几何体过滤掉
                            }
                            else if (primitiveTypes == PrimitiveTypes.SnapPoints)
                            {
                                snapPointOnlyCount++;
                                // 不添加：纯捕捉点几何体过滤掉
                            }
                            else if (primitiveTypes == PrimitiveTypes.Text)
                            {
                                textOnlyCount++;
                                // 不添加：纯文本几何体过滤掉
                            }
                            else
                            {
                                mixedCount++;
                                visibleItems.Add(item); // 其他混合类型保留
                                addedCurrentItem = true;
                            }
                        }
                        else
                        {
                            noGeometryCount++;
                            // 不添加：无几何体数据
                        }

                        // 只有当前节点已经可直接作为几何候选时，才截断子树。
                        // 如果当前节点本身没有可用三角几何，则继续向下遍历，避免把真实几何子节点整棵截断。
                        if (!addedCurrentItem)
                        {
                            foreach (var child in item.Children)
                            {
                                stack.Push(child);
                            }
                        }
                    }
                    else
                    {
                        // 空节点：继续遍历子节点
                        foreach (var child in item.Children)
                        {
                            stack.Push(child);
                        }
                    }
                }

                var elapsed = (DateTime.Now - startTime).TotalMilliseconds;

                // 输出详细统计信息
                LogManager.Info($"[几何体获取] DFS遍历完成，总耗时: {elapsed:F1}ms");
                LogManager.Info($"[几何体获取] 隐藏项过滤效果: 跳过 {hiddenSkipped} 个隐藏节点（包括其子节点）");
                LogManager.Info($"[几何体获取] 可见节点统计: {visibleCount} 个可见节点");
                LogManager.Info($"[几何体获取] 图元类型统计 - 纯三角形: {triangleCount}, 纯线条: {lineOnlyCount}, 纯点: {pointOnlyCount}, 纯捕捉点: {snapPointOnlyCount}, 纯文本: {textOnlyCount}, 混合类型: {mixedCount}, 无几何体: {noGeometryCount}");
                LogManager.Info($"[几何体获取] 最终结果: {visibleItems.Count} 个几何体项目（只保留包含 Triangles 的几何体）");

                return visibleItems;
            }
            catch (Exception ex)
            {
                LogManager.Error($"[几何体获取] 获取失败: {ex.Message}");
                throw;
            }
        }

        #endregion
    }

    #region 数据结构定义
    
    /// <summary>
    /// 模型节点类型枚举
    /// </summary>
    public enum ModelItemType
    {
        /// <summary>
        /// 纯几何体节点：HasGeometry = true, Children.Count = 0
        /// </summary>
        PureGeometry,
        
        /// <summary>
        /// 集合节点：HasGeometry = false, Children.Count > 0
        /// </summary>
        GroupNode,
        
        /// <summary>
        /// 混合节点：HasGeometry = true, Children.Count > 0
        /// </summary>
        HybridNode,
        
        /// <summary>
        /// 空节点：HasGeometry = false, Children.Count = 0
        /// </summary>
        EmptyNode
    }

    #endregion
}
