using System;
using System.Collections.Generic;
using System.IO;
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 class GeometryCacheManager
    {
        // 缓存根节点
        private PathTreeNode cacheRoot;
        
        // 当前文档路径
        private string documentPath;
        
        // 缓存文件路径
        private string cacheFilePath;
        
        // 缓存加载状态
        private bool _isCacheLoaded = false;
        private bool _cacheLoadResult = false;
        
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="docPath">文档路径</param>
        public GeometryCacheManager(string docPath)
        {
            documentPath = docPath;
            cacheRoot = new PathTreeNode("", "");
            
            // 生成缓存文件路径
            var docDir = Path.GetDirectoryName(documentPath);
            var docName = Path.GetFileNameWithoutExtension(documentPath);
            cacheFilePath = Path.Combine(docDir, $"{docName}.geometrycache");
            
            LogManager.Info($"[几何体缓存] 缓存文件路径: {cacheFilePath}");
        }
        
        /// <summary>
        /// 从模型项列表提取所有片段并构建缓存
        /// </summary>
        /// <param name="modelItems">模型项列表</param>
        public void BuildCache(IEnumerable<ModelItem> modelItems)
        {
            var itemCount = modelItems?.Count() ?? 0;
            LogManager.Info($"[几何体缓存] 开始构建几何体缓存，模型项数量: {itemCount}");
            
            // 清空现有缓存
            cacheRoot = new PathTreeNode("", "");
            
            ComApi.InwOpSelection comSelection = null;
            try
            {
                // 转换为 COM 选择
                var modelCollection = new ModelItemCollection();
                foreach (var item in modelItems)
                {
                    modelCollection.Add(item);
                }
                
                comSelection = ComApiBridge.ToInwOpSelection(modelCollection);
                
                // 获取所有片段
                var allFragments = GeometryHelper.GetAllFragments(comSelection);
                
                int processedFragments = 0;
                int totalTriangles = 0;
                int skippedDuplicates = 0;
                
                // 处理每个片段
                foreach (var fragmentInfo in allFragments)
                {
                    try
                    {
                        var callback = new OptimizedGeometryCallback(fragmentInfo.TransformMatrix);
                        fragmentInfo.Fragment.GenerateSimplePrimitives(
                            ComApi.nwEVertexProperty.eNORMAL,
                            callback);
                        
                        var fragmentTriangles = callback.GetTriangles();
                        totalTriangles += fragmentTriangles.Count;
                        
                        // 创建缓存片段数据
                        var cachedFragment = new CachedFragmentData
                        {
                            PathKey = fragmentInfo.PathKey,
                            Triangles = fragmentTriangles.Select(t => new NavisworksTransport.CachedTriangle3D(t.Point1, t.Point2, t.Point3)).ToList()
                        };
                        
                        // 插入到树形结构中
                        InsertFragment(fragmentInfo.PathKey, cachedFragment);
                        
                        processedFragments++;
                    }
                    catch (Exception ex)
                    {
                        LogManager.Error($"[几何体缓存] 处理片段失败: {ex.Message}");
                    }
                }
                
                // 统计最终缓存中的片段数量
                int totalCachedFragments = CountFragments(cacheRoot);
                LogManager.Info($"[几何体缓存] 几何体缓存构建完成，处理片段数: {processedFragments}，总三角形数: {totalTriangles}，最终缓存片段数: {totalCachedFragments}，跳过重复: {skippedDuplicates}");
            }
            finally
            {
                // 释放COM对象
                if (comSelection != null)
                {
                    System.Runtime.InteropServices.Marshal.ReleaseComObject(comSelection);
                }
            }
        }
        
        /// <summary>
        /// 将片段插入到树形结构中
        /// </summary>
        /// <param name="pathKey">片段路径</param>
        /// <param name="fragment">片段数据</param>
        private void InsertFragment(string pathKey, CachedFragmentData fragment)
        {
            var pathParts = pathKey.Split(',');
            var currentNode = cacheRoot;
            
            // 逐级创建或导航到目标节点
            for (int i = 0; i < pathParts.Length; i++)
            {
                var currentPath = string.Join(",", pathParts.Take(i + 1));
                var nodeKey = pathParts[i];
                
                currentNode = currentNode.AddChild(nodeKey, currentPath);
            }
            
            // 检查是否已存在相同PathKey的片段（避免完全重复）
            bool isDuplicate = currentNode.Fragments.Any(f => f.PathKey == pathKey && 
                f.Triangles.Count == fragment.Triangles.Count &&
                f.Triangles.SequenceEqual(fragment.Triangles, new CachedTriangleComparer()));
            
            if (!isDuplicate)
            {
                // 只有当片段不完全相同时才添加
                currentNode.Fragments.Add(fragment);
            }
            else
            {
                LogManager.Debug($"[几何体缓存] 跳过重复片段，PathKey: {pathKey}");
            }
        }
        
        /// <summary>
        /// 获取指定ModelItem的所有三角形数据
        /// 如果缓存不存在，则自动生成缓存
        /// </summary>
        /// <param name="modelItem">模型项</param>
        /// <returns>三角形列表</returns>
        public List<Triangle3D> GetTrianglesForModelItem(ModelItem modelItem)
        {
            // 确保缓存已加载（只加载一次）
            if (!_isCacheLoaded)
            {
                if (CacheExists())
                {
                    _cacheLoadResult = LoadCache();
                }
                else
                {
                    LogManager.Info("[几何体缓存] 缓存不存在，开始自动生成缓存...");
                    GenerateCacheAutomatically();
                    // 重新尝试加载新生成的缓存
                    if (CacheExists())
                    {
                        _cacheLoadResult = LoadCache();
                    }
                }
                _isCacheLoaded = true;
            }
            
            // 如果缓存加载失败，则使用传统方法
            if (!_cacheLoadResult)
            {
                LogManager.Warning("[几何体缓存] 无法加载缓存，使用传统方法提取几何体");
                return GeometryHelper.ExtractTriangles(new[] { modelItem });
            }
            
            var result = new List<Triangle3D>();
            
            // 获取ModelItem的完整路径
            var itemPaths = ModelItemAnalysisHelper.GetModelItemIndexPaths(modelItem);
            
            // 收集所有路径下的片段
            foreach (var pathKey in itemPaths)
            {
                var fragments = GetFragmentsForPath(pathKey);
                foreach (var fragment in fragments)
                {
                    // 将CachedTriangle3D转换为Triangle3D
                    foreach (var cachedTriangle in fragment.Triangles)
                    {
                        result.Add(new Triangle3D(
                            cachedTriangle.Point1.ToNavisworksPoint3D(),
                            cachedTriangle.Point2.ToNavisworksPoint3D(),
                            cachedTriangle.Point3.ToNavisworksPoint3D()
                        ));
                    }
                }
            }
            
            return result;
        }
        
        /// <summary>
        /// 获取指定ModelItem的所有三角形数据（自动缓存版本）
        /// 如果缓存不存在，则自动生成缓存
        /// </summary>
        /// <param name="modelItem">模型项</param>
        /// <returns>三角形列表</returns>
        public List<Triangle3D> GetTrianglesForModelItemWithAutoCache(ModelItem modelItem)
        {
            // 检查缓存是否存在，如果不存在则自动生成
            if (!CacheExists())
            {
                LogManager.Info("[几何体缓存] 缓存不存在，开始自动生成缓存...");
                GenerateCacheAutomatically();
            }
            
            // 如果缓存仍然不存在或加载失败，则使用传统方法
            if (!CacheExists() || !LoadCache())
            {
                LogManager.Warning("[几何体缓存] 无法加载缓存，使用传统方法提取几何体");
                return GeometryHelper.ExtractTriangles(new[] { modelItem });
            }
            
            return GetTrianglesForModelItem(modelItem);
        }
        
        /// <summary>
        /// 递归统计缓存中的片段数量
        /// </summary>
        /// <param name="node">当前节点</param>
        /// <returns>片段总数</returns>
        private int CountFragments(PathTreeNode node)
        {
            if (node == null) return 0;
            
            int count = node.Fragments?.Count ?? 0;
            
            if (node.Children != null)
            {
                foreach (var child in node.Children)
                {
                    count += CountFragments(child);
                }
            }
            
            return count;
        }
        
        /// <summary>
        /// 获取指定路径下的所有片段
        /// </summary>
        /// <param name="targetPath">目标路径</param>
        /// <returns>片段列表</returns>
        private List<CachedFragmentData> GetFragmentsForPath(string targetPath)
        {
            var result = new List<CachedFragmentData>();
            var pathParts = targetPath.Split(',');
            var currentNode = cacheRoot;
            
            // 逐级导航到目标节点
            for (int i = 0; i < pathParts.Length; i++)
            {
                var nodeKey = pathParts[i];
                var childNode = currentNode.FindChild(nodeKey);
                if (childNode != null)
                {
                    currentNode = childNode;
                }
                else
                {
                    // 路径不存在，返回空结果
                    return result;
                }
            }
            
            // 只返回目标节点的片段
            if (currentNode.Fragments != null)
            {
                result.AddRange(currentNode.Fragments);
            }
            
            return result;
        }
        
        /// <summary>
        /// 保存缓存到文件
        /// </summary>
        public void SaveCache()
        {
            try
            {
                // 统计缓存中的数据量
                int fragmentCount = 0;
                int nodeCount = 0;
                CountCacheNodes(cacheRoot, ref fragmentCount, ref nodeCount);
                
                LogManager.Info($"[几何体缓存] 保存缓存到文件: {cacheFilePath}，节点数: {nodeCount}, 片段数: {fragmentCount}");
                
                // 使用XML序列化
                var serializer = new System.Xml.Serialization.XmlSerializer(typeof(PathTreeNode));
                using (var writer = new System.IO.StreamWriter(cacheFilePath, false, System.Text.Encoding.UTF8))
                {
                    serializer.Serialize(writer, cacheRoot);
                }
                
                // 检查文件是否成功创建
                if (File.Exists(cacheFilePath))
                {
                    var fileInfo = new FileInfo(cacheFilePath);
                    LogManager.Info($"[几何体缓存] 缓存保存完成，文件大小: {fileInfo.Length} 字节");
                }
                else
                {
                    LogManager.Warning($"[几何体缓存] 缓存保存完成，但文件未找到: {cacheFilePath}");
                }
            }
            catch (Exception ex)
            {
                LogManager.Error($"[几何体缓存] 保存缓存失败: {ex.Message}");
            }
        }
        
        /// <summary>
        /// 从文件加载缓存
        /// </summary>
        /// <returns>是否加载成功</returns>
        public bool LoadCache()
        {
            try
            {
                if (!File.Exists(cacheFilePath))
                {
                    LogManager.Info($"[几何体缓存] 缓存文件不存在: {cacheFilePath}");
                    return false;
                }
                
                LogManager.Info($"[几何体缓存] 从文件加载缓存: {cacheFilePath}");
                
                // 使用XML反序列化
                var serializer = new System.Xml.Serialization.XmlSerializer(typeof(PathTreeNode));
                using (var reader = new System.IO.StreamReader(cacheFilePath, System.Text.Encoding.UTF8))
                {
                    cacheRoot = (PathTreeNode)serializer.Deserialize(reader);
                }
                
                // 统计缓存中的数据量
                int fragmentCount = 0;
                int nodeCount = 0;
                CountCacheNodes(cacheRoot, ref fragmentCount, ref nodeCount);
                
                LogManager.Info($"[几何体缓存] 缓存加载完成，节点数: {nodeCount}, 片段数: {fragmentCount}");
                return true;
            }
            catch (Exception ex)
            {
                LogManager.Error($"[几何体缓存] 加载缓存失败: {ex.Message}");
                return false;
            }
        }
        
        /// <summary>
        /// 递归统计缓存中的节点和片段数量
        /// </summary>
        private void CountCacheNodes(PathTreeNode node, ref int fragmentCount, ref int nodeCount)
        {
            if (node == null) return;
            
            nodeCount++;
            fragmentCount += node.Fragments?.Count ?? 0;
            
            if (node.Children != null)
            {
                foreach (var child in node.Children)
                {
                    CountCacheNodes(child, ref fragmentCount, ref nodeCount);
                }
            }
        }
        
        /// <summary>
        /// 检查缓存文件是否存在
        /// </summary>
        /// <returns>是否存在</returns>
        public bool CacheExists()
        {
            bool exists = File.Exists(cacheFilePath);
            LogManager.Info($"[几何体缓存] 检查缓存文件是否存在: {cacheFilePath}, 结果: {(exists ? "存在" : "不存在")}");
            return exists;
        }
        
        /// <summary>
        /// 自动生成缓存文件
        /// </summary>
        private void GenerateCacheAutomatically()
        {
            try
            {
                LogManager.Info("[几何体缓存] 开始自动生成缓存文件");
                
                // 获取当前文档
                var document = Autodesk.Navisworks.Api.Application.ActiveDocument;
                if (document == null)
                {
                    LogManager.Error("[几何体缓存] 无法获取活动文档");
                    return;
                }
                
                // 开始进度条
                var progress = Autodesk.Navisworks.Api.Application.BeginProgress("生成几何体缓存", 
                    $"正在为 {Path.GetFileName(document.FileName)} 生成几何体缓存...");
                
                try
                {
                    // 收集场景中所有带几何信息的对象
                    var allModelItems = GetAllModelItems(document);
                    LogManager.Info($"[几何体缓存] 场景中共有 {allModelItems.Count} 个带几何信息的模型对象");
                    
                    if (allModelItems.Count == 0)
                    {
                        LogManager.Warning("[几何体缓存] 场景中没有找到任何带几何信息的模型对象");
                        return;
                    }
                    
                    // 更新进度
                    progress.Update(0.25); // 只传递进度值，不传递消息
                    
                    // 构建缓存
                    BuildCache(allModelItems);
                    
                    // 更新进度
                    progress.Update(0.75); // 只传递进度值，不传递消息
                    
                    // 保存缓存到文件
                    SaveCache();
                    
                    // 更新进度
                    progress.Update(1.0); // 只传递进度值，不传递消息
                    
                    LogManager.Info("[几何体缓存] 几何体缓存自动生成完成");
                }
                finally
                {
                    // 确保进度条被关闭
                    Autodesk.Navisworks.Api.Application.EndProgress();
                }
            }
            catch (Exception ex)
            {
                LogManager.Error($"[几何体缓存] 自动生成缓存失败: {ex.Message}");
            }
        }
        
        /// <summary>
        /// 获取场景中所有带几何信息的模型对象
        /// </summary>
        private List<ModelItem> GetAllModelItems(Autodesk.Navisworks.Api.Document document)
        {
            var items = new List<ModelItem>();
            
            // 遍历文档中的所有模型
            foreach (var model in document.Models)
            {
                if (model.RootItem != null)
                {
                    CollectAllItems(model.RootItem, items);
                }
            }
            
            return items;
        }
        
        /// <summary>
        /// 递归收集所有带几何信息的对象
        /// </summary>
        private void CollectAllItems(ModelItem item, List<ModelItem> result)
        {
            // 如果当前对象有几何信息，加入结果
            if (item.HasGeometry)
            {
                result.Add(item);
            }
            
            // 递归处理所有子对象
            foreach (var child in item.Children)
            {
                CollectAllItems(child, result);
            }
        }
    }
    
    /// <summary>
    /// 路径树节点
    /// </summary>
    [Serializable]
    public class PathTreeNode
    {
        public string NodeKey { get; set; }
        public string FullPath { get; set; }
        public List<CachedFragmentData> Fragments { get; set; }
        
        // 使用List存储子节点，避免Dictionary序列化问题
        public List<PathTreeNode> Children { get; set; }
        
        // 用于查找子节点的辅助方法
        public PathTreeNode FindChild(string nodeKey)
        {
            return Children?.FirstOrDefault(child => child.NodeKey == nodeKey);
        }
        
        // 用于添加子节点的辅助方法
        public PathTreeNode AddChild(string nodeKey, string fullPath)
        {
            if (Children == null)
                Children = new List<PathTreeNode>();
                
            var existingChild = FindChild(nodeKey);
            if (existingChild != null)
                return existingChild;
                
            var newChild = new PathTreeNode
            {
                NodeKey = nodeKey,
                FullPath = fullPath,
                Fragments = new List<CachedFragmentData>(),
                Children = new List<PathTreeNode>()
            };
            
            Children.Add(newChild);
            return newChild;
        }
        
        public PathTreeNode()
        {
            Fragments = new List<CachedFragmentData>();
            Children = new List<PathTreeNode>();
        }
        
        public PathTreeNode(string nodeKey, string fullPath)
        {
            NodeKey = nodeKey;
            FullPath = fullPath;
            Fragments = new List<CachedFragmentData>();
            Children = new List<PathTreeNode>();
        }
    }
    
    /// <summary>
    /// 缓存片段数据
    /// </summary>
    [Serializable]
    [System.Xml.Serialization.XmlType("CachedFragmentData")]
    public class CachedFragmentData
    {
        [System.Xml.Serialization.XmlAttribute("PathKey")]
        public string PathKey { get; set; }
        
        [System.Xml.Serialization.XmlArray("Triangles")]
        [System.Xml.Serialization.XmlArrayItem("Triangle")]
        public List<CachedTriangle3D> Triangles { get; set; }
        
        public CachedFragmentData()
        {
            Triangles = new List<CachedTriangle3D>();
        }
    }
    
    /// <summary>
    /// 三角形比较器，用于检测重复的三角形数据
    /// </summary>
    public class CachedTriangleComparer : IEqualityComparer<CachedTriangle3D>
    {
        public bool Equals(CachedTriangle3D x, CachedTriangle3D y)
        {
            if (x.Point1.X != y.Point1.X || x.Point1.Y != y.Point1.Y || x.Point1.Z != y.Point1.Z)
                return false;
            if (x.Point2.X != y.Point2.X || x.Point2.Y != y.Point2.Y || x.Point2.Z != y.Point2.Z)
                return false;
            if (x.Point3.X != y.Point3.X || x.Point3.Y != y.Point3.Y || x.Point3.Z != y.Point3.Z)
                return false;
            return true;
        }

        public int GetHashCode(CachedTriangle3D obj)
        {
            // 简单的哈希实现
            return obj.Point1.GetHashCode() ^ obj.Point2.GetHashCode() ^ obj.Point3.GetHashCode();
        }
    }
}