using System;
using System.Collections.Generic;
using System.Linq;
using Autodesk.Navisworks.Api;
using g4;

namespace NavisworksTransport
{
    /// <summary>
    /// Navisworks 几何体到 geometry4Sharp DMesh3 的转换器
    /// 用于将 Navisworks 提取的三角形数据转换为 geometry4Sharp 可以处理的网格格式
    /// </summary>
    public static class NavisworksToDMesh3Converter
    {
        /// <summary>
        /// 将 Navisworks 三角形列表转换为 geometry4Sharp 的 DMesh3 格式
        /// </summary>
        /// <param name="triangles">从 Navisworks 提取的三角形列表</param>
        /// <returns>DMesh3 网格对象</returns>
        public static DMesh3 Convert(List<Triangle3D> triangles)
        {
            if (triangles == null || triangles.Count == 0)
            {
                LogManager.Warning("[DMesh3转换] 输入三角形列表为空");
                return new DMesh3();
            }

            LogManager.Info($"[DMesh3转换] 开始转换 {triangles.Count} 个三角形");

            var mesh = new DMesh3();

            // 使用字典进行顶点去重（基于坐标的精确匹配）
            var vertexMap = new Dictionary<Vector3d, int>();
            const double epsilon = 1e-6; // 顶点合并容差（很小，几乎是精确匹配）

            int trianglesAdded = 0;
            int verticesAdded = 0;

            foreach (var triangle in triangles)
            {
                try
                {
                    // 转换三个顶点坐标（Navisworks Point3D → geometry4Sharp Vector3d）
                    var v1 = new Vector3d(triangle.Point1.X, triangle.Point1.Y, triangle.Point1.Z);
                    var v2 = new Vector3d(triangle.Point2.X, triangle.Point2.Y, triangle.Point2.Z);
                    var v3 = new Vector3d(triangle.Point3.X, triangle.Point3.Y, triangle.Point3.Z);

                    // 获取或创建顶点索引（带去重）
                    int vid1 = GetOrAddVertex(mesh, v1, vertexMap, epsilon, ref verticesAdded);
                    int vid2 = GetOrAddVertex(mesh, v2, vertexMap, epsilon, ref verticesAdded);
                    int vid3 = GetOrAddVertex(mesh, v3, vertexMap, epsilon, ref verticesAdded);

                    // 跳过退化三角形（三个顶点重合或共线）
                    if (vid1 == vid2 || vid2 == vid3 || vid3 == vid1)
                    {
                        continue;
                    }

                    // 添加三角形到网格
                    int triangleId = mesh.AppendTriangle(vid1, vid2, vid3);
                    if (triangleId >= 0)
                    {
                        trianglesAdded++;
                    }
                }
                catch (Exception ex)
                {
                    LogManager.Warning($"[DMesh3转换] 处理三角形失败: {ex.Message}");
                }
            }

            LogManager.Info($"[DMesh3转换] 转换完成:");
            LogManager.Info($"  - 输入三角形数: {triangles.Count}");
            LogManager.Info($"  - 输出三角形数: {trianglesAdded}");
            LogManager.Info($"  - 唯一顶点数: {verticesAdded}");
            LogManager.Info($"  - 顶点去重率: {(triangles.Count * 3 - verticesAdded) * 100.0 / (triangles.Count * 3):F1}%");

            // 验证网格完整性
            if (mesh.TriangleCount > 0)
            {
                LogManager.Info($"[DMesh3转换] 网格统计:");
                LogManager.Info($"  - 顶点数: {mesh.VertexCount}");
                LogManager.Info($"  - 三角形数: {mesh.TriangleCount}");
                LogManager.Info($"  - 边数: {mesh.EdgeCount}");
                LogManager.Info($"  - 是否封闭: {mesh.IsClosed()}");

                var bounds = mesh.GetBounds();
                LogManager.Info($"  - 包围盒: ({bounds.Min.x:F2}, {bounds.Min.y:F2}, {bounds.Min.z:F2}) ~ ({bounds.Max.x:F2}, {bounds.Max.y:F2}, {bounds.Max.z:F2})");
                LogManager.Info($"  - 尺寸: {bounds.Width:F2} × {bounds.Height:F2} × {bounds.Depth:F2}");
            }
            else
            {
                LogManager.Warning("[DMesh3转换] 警告：生成的网格为空（没有有效三角形）");
            }

            return mesh;
        }

        /// <summary>
        /// 获取或添加顶点（带去重）
        /// </summary>
        private static int GetOrAddVertex(
            DMesh3 mesh,
            Vector3d vertex,
            Dictionary<Vector3d, int> vertexMap,
            double epsilon,
            ref int verticesAdded)
        {
            // 尝试在已有顶点中查找（精确匹配）
            if (vertexMap.TryGetValue(vertex, out int existingId))
            {
                return existingId;
            }

            // 如果需要更宽松的去重，可以遍历现有顶点查找接近的点
            // 但这会降低性能，所以这里使用精确匹配

            // 添加新顶点
            int newId = mesh.AppendVertex(vertex);
            vertexMap[vertex] = newId;
            verticesAdded++;

            return newId;
        }

        /// <summary>
        /// 从多个 ModelItem 提取三角形并转换为 DMesh3（批量转换）
        /// </summary>
        /// <param name="items">Navisworks 模型项列表</param>
        /// <returns>合并后的 DMesh3 网格</returns>
        public static DMesh3 ConvertFromModelItems(IEnumerable<ModelItem> items)
        {
            if (items == null)
            {
                LogManager.Warning("[DMesh3转换] 输入模型项列表为空");
                return new DMesh3();
            }

            LogManager.Info("[DMesh3转换] 开始从 ModelItem 批量提取和转换");

            // 批量提取所有三角形 - 性能优化
            var extractStopwatch = System.Diagnostics.Stopwatch.StartNew();

            var itemsList = items.ToList();
            int itemCount = itemsList.Count;

            LogManager.Info($"[DMesh3转换] 共 {itemCount} 个模型项，使用批量提取方式");

            var allTriangles = GeometryHelper.ExtractTriangles(itemsList);

            extractStopwatch.Stop();
            LogManager.Info($"[DMesh3转换] 从 {itemCount} 个模型项共提取 {allTriangles.Count} 个三角形，耗时: {extractStopwatch.ElapsedMilliseconds} ms ({extractStopwatch.Elapsed.TotalSeconds:F2}秒)");

            // 转换为 DMesh3
            return Convert(allTriangles);
        }

        /// <summary>
        /// 转换单个 ModelItem 为 DMesh3
        /// </summary>
        /// <param name="item">Navisworks 模型项</param>
        /// <returns>DMesh3 网格</returns>
        public static DMesh3 ConvertFromModelItem(ModelItem item)
        {
            if (item == null)
            {
                LogManager.Warning("[DMesh3转换] 输入 ModelItem 为空");
                return new DMesh3();
            }

            LogManager.Info($"[DMesh3转换] 转换单个 ModelItem: {item.DisplayName}");

            try
            {
                var triangles = GeometryHelper.ExtractTriangles(new[] { item });
                return Convert(triangles);
            }
            catch (Exception ex)
            {
                LogManager.Error($"[DMesh3转换] 转换失败: {ex.Message}");
                return new DMesh3();
            }
        }
    }
}
