using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Autodesk.Navisworks.Api;
using NavisworksTransport.PathPlanning;

namespace NavisworksTransport.Commands
{
    /// <summary>
    /// 体素网格路径规划测试命令
    /// 测试VoxelPathFinder的3D A*路径规划功能
    /// </summary>
    public class VoxelPathFindingTestCommand : CommandBase
    {
        private readonly Document _document;
        private readonly double _cellSize;
        private readonly double _objectRadius;
        private readonly double _objectHeight;
        private readonly Point3D _startPoint;
        private readonly Point3D _endPoint;

        public VoxelPathFindingTestCommand(
            Document document,
            double cellSize,
            double objectRadius,
            double objectHeight,
            Point3D startPoint,
            Point3D endPoint)
            : base("VoxelPathFindingTest", "体素路径规划测试", "测试VoxelPathFinder的3D A*路径规划")
        {
            _document = document ?? throw new ArgumentNullException(nameof(document));
            _cellSize = cellSize;
            _objectRadius = objectRadius;
            _objectHeight = objectHeight;
            _startPoint = startPoint;
            _endPoint = endPoint;
        }

        protected override PathPlanningResult ValidateParameters()
        {
            if (_document == null)
            {
                return PathPlanningResult.ValidationFailure("Navisworks 文档对象为空");
            }

            if (_cellSize <= 0)
            {
                return PathPlanningResult.ValidationFailure("体素大小必须大于0");
            }

            return PathPlanningResult.Success("参数验证通过");
        }

        protected override async Task<PathPlanningResult> ExecuteInternalAsync(CancellationToken cancellationToken)
        {
            try
            {
                LogInfo("=== 开始体素路径规划测试 ===");
                LogInfo($"体素大小: {_cellSize}米");
                LogInfo($"物体半径: {_objectRadius}米");
                LogInfo($"物体高度: {_objectHeight}米");
                LogInfo($"起点: ({_startPoint.X:F2}, {_startPoint.Y:F2}, {_startPoint.Z:F2})");
                LogInfo($"终点: ({_endPoint.X:F2}, {_endPoint.Y:F2}, {_endPoint.Z:F2})");

                UpdateProgress(5, "正在获取模型空间范围...");

                // 步骤1: 获取模型空间包围盒
                BoundingBox3D spaceBounds = GetSpaceBounds(_document);
                if (spaceBounds == null)
                {
                    return PathPlanningResult.Failure("无法获取模型空间范围");
                }

                LogInfo($"空间范围: Min={spaceBounds.Min}, Max={spaceBounds.Max}");

                UpdateProgress(15, "正在收集模型对象...");

                // 步骤2: 收集所有模型对象
                var allModelItems = GetAllModelItems(_document);
                LogInfo($"场景中共有 {allModelItems.Count} 个带几何信息的模型对象");

                if (allModelItems.Count == 0)
                {
                    return PathPlanningResult.Failure("场景中没有找到任何带几何信息的模型对象");
                }

                UpdateProgress(25, "正在生成体素网格...");

                // 步骤3: 生成体素网格
                var generator = new VoxelGridGenerator();
                var voxelGrid = generator.GenerateFromBIMWithSDF(
                    spaceBounds,
                    _cellSize,
                    _objectRadius,
                    _objectHeight,
                    allModelItems);

                LogInfo($"体素网格生成完成: {voxelGrid.SizeX}×{voxelGrid.SizeY}×{voxelGrid.SizeZ} = {voxelGrid.TotalVoxels:N0} 个体素");

                var (total, passable, obstacle) = voxelGrid.GetStatistics();
                LogInfo($"体素统计: 总数={total:N0}, 可通行={passable:N0} ({passable*100.0/total:F1}%), 障碍物={obstacle:N0} ({obstacle*100.0/total:F1}%)");

                // 打印一些可通行体素的世界坐标样本，帮助选择合适的起点终点
                LogInfo("=== 可通行体素样本（优先中间区域和较高楼层）===");
                int sampleCount = 0;
                int maxSamples = 30;

                // 从中间区域和较高楼层开始采样
                int midX = voxelGrid.SizeX / 2;
                int midY = voxelGrid.SizeY / 2;

                // 从高到低遍历楼层
                for (int z = voxelGrid.SizeZ - 1; z >= 0 && sampleCount < maxSamples; z--)
                {
                    // 以中心为起点螺旋采样
                    for (int radius = 0; radius < Math.Max(voxelGrid.SizeX, voxelGrid.SizeY) / 2 && sampleCount < maxSamples; radius += 15)
                    {
                        // 上下左右4个方向采样
                        int[][] offsets = new int[][]
                        {
                            new int[] {radius, 0},    // 右
                            new int[] {-radius, 0},   // 左
                            new int[] {0, radius},    // 上
                            new int[] {0, -radius},   // 下
                            new int[] {radius, radius}, // 右上
                            new int[] {-radius, radius}, // 左上
                            new int[] {radius, -radius}, // 右下
                            new int[] {-radius, -radius}  // 左下
                        };

                        foreach (var offset in offsets)
                        {
                            if (sampleCount >= maxSamples) break;

                            int x = midX + offset[0];
                            int y = midY + offset[1];

                            if (x >= 0 && x < voxelGrid.SizeX && y >= 0 && y < voxelGrid.SizeY)
                            {
                                if (voxelGrid.IsPassable(x, y, z))
                                {
                                    var worldPos = voxelGrid.VoxelToWorld(x, y, z);
                                    LogInfo($"  体素({x,3}, {y,3}, {z,2}) -> 世界({worldPos.X,8:F2}, {worldPos.Y,8:F2}, {worldPos.Z,8:F2})");
                                    sampleCount++;
                                }
                            }
                        }
                    }
                }
                LogInfo($"已打印 {sampleCount} 个可通行体素样本（优先中间区域和高楼层）");
                LogInfo("=====================================");

                UpdateProgress(50, "正在规划路径...");

                // 步骤4: 创建路径查找器
                var pathFinder = new VoxelPathFinder(voxelGrid);

                // 步骤5: 配置路径规划参数
                var config = new VoxelPathFinder.PathFindingConfig
                {
                    NeighborType = VoxelPathFinder.NeighborType.TwentySix, // 26邻域
                    HeuristicType = VoxelPathFinder.HeuristicType.Euclidean, // 欧几里得距离
                    HeuristicWeight = 1.0, // 不加权
                    VerticalCostFactor = 1.5, // 垂直移动成本1.5倍
                    DiagonalCostFactor = Math.Sqrt(2), // 对角线移动成本√2
                    MaxSearchNodes = 100000 // 最大搜索10万个节点
                };

                // 步骤6: 执行路径规划
                LogInfo("开始A*路径搜索...");
                var pathStartTime = System.Diagnostics.Stopwatch.StartNew();

                var path = pathFinder.FindPath(_startPoint, _endPoint, config);

                pathStartTime.Stop();

                if (path == null || path.Count == 0)
                {
                    LogError("路径规划失败：未找到有效路径");
                    return PathPlanningResult.Failure("未找到从起点到终点的路径");
                }

                LogInfo($"✓ 路径规划成功！");
                LogInfo($"  路径点数: {path.Count}");
                LogInfo($"  规划耗时: {pathStartTime.ElapsedMilliseconds} ms");

                UpdateProgress(70, "正在计算路径统计信息...");

                // 步骤7: 计算路径统计
                double pathLength = CalculatePathLength(path);
                double directDistance = CalculateDistance(_startPoint, _endPoint);
                double pathRatio = pathLength / directDistance;

                LogInfo($"路径统计:");
                LogInfo($"  路径总长: {pathLength:F2} 模型单位");
                LogInfo($"  直线距离: {directDistance:F2} 模型单位");
                LogInfo($"  路径比率: {pathRatio:F2} (越接近1越优)");

                UpdateProgress(80, "正在可视化路径...");

                // 步骤8: 可视化路径
                var visualRoute = CreatePathRoute(path, "VoxelPath_Test");
                var renderPlugin = PathPointRenderPlugin.Instance;
                if (renderPlugin != null)
                {
                    renderPlugin.SetGridSize(_cellSize);
                    renderPlugin.RenderPointOnly(visualRoute);
                    LogInfo("✓ 路径已渲染到3D视图");
                }
                else
                {
                    LogWarning("PathPointRenderPlugin 实例不可用，无法渲染路径");
                }

                UpdateProgress(100, "体素路径规划测试完成");

                string report = GenerateReport(voxelGrid, path, pathLength, directDistance, pathStartTime.ElapsedMilliseconds);

                return PathPlanningResult.Success($"体素路径规划测试完成\n\n{report}");
            }
            catch (Exception ex)
            {
                LogError($"体素路径规划测试失败: {ex.Message}", ex);
                return PathPlanningResult.Failure($"体素路径规划测试失败: {ex.Message}", ex);
            }
        }

        #region 辅助方法

        private BoundingBox3D GetSpaceBounds(Document document)
        {
            try
            {
                BoundingBox3D totalBounds = null;

                foreach (var model in document.Models)
                {
                    if (model.RootItem != null)
                    {
                        var modelBounds = model.RootItem.BoundingBox();
                        if (modelBounds != null)
                        {
                            if (totalBounds == null)
                            {
                                totalBounds = modelBounds;
                            }
                            else
                            {
                                totalBounds = ExpandBounds(totalBounds, modelBounds);
                            }
                        }
                    }
                }

                return totalBounds;
            }
            catch (Exception ex)
            {
                LogError($"获取空间范围失败: {ex.Message}", ex);
                return null;
            }
        }

        private BoundingBox3D ExpandBounds(BoundingBox3D bounds1, BoundingBox3D bounds2)
        {
            var min = new Point3D(
                Math.Min(bounds1.Min.X, bounds2.Min.X),
                Math.Min(bounds1.Min.Y, bounds2.Min.Y),
                Math.Min(bounds1.Min.Z, bounds2.Min.Z)
            );
            var max = new Point3D(
                Math.Max(bounds1.Max.X, bounds2.Max.X),
                Math.Max(bounds1.Max.Y, bounds2.Max.Y),
                Math.Max(bounds1.Max.Z, bounds2.Max.Z)
            );
            return new BoundingBox3D(min, max);
        }

        private List<ModelItem> GetAllModelItems(Document document)
        {
            var items = new List<ModelItem>();

            foreach (var model in document.Models)
            {
                if (model.RootItem != null)
                {
                    CollectAllItems(model.RootItem, items);
                }
            }

            return items;
        }

        private void CollectAllItems(ModelItem item, List<ModelItem> result)
        {
            if (item.HasGeometry)
            {
                result.Add(item);
            }

            foreach (var child in item.Children)
            {
                CollectAllItems(child, result);
            }
        }

        private double CalculatePathLength(List<Point3D> path)
        {
            if (path == null || path.Count < 2)
                return 0;

            double length = 0;
            for (int i = 1; i < path.Count; i++)
            {
                length += CalculateDistance(path[i - 1], path[i]);
            }

            return length;
        }

        private double CalculateDistance(Point3D p1, Point3D p2)
        {
            double dx = p2.X - p1.X;
            double dy = p2.Y - p1.Y;
            double dz = p2.Z - p1.Z;
            return Math.Sqrt(dx * dx + dy * dy + dz * dz);
        }

        private PathRoute CreatePathRoute(List<Point3D> path, string routeName)
        {
            // 将Point3D列表转换为PathPoint列表
            var pathPoints = new List<PathPoint>();
            foreach (var pt in path)
            {
                pathPoints.Add(new PathPoint
                {
                    Position = pt
                });
            }

            var route = new PathRoute
            {
                Id = Guid.NewGuid().ToString(),
                Name = routeName,
                Points = pathPoints,
                IsComplete = true,
                CreatedTime = DateTime.Now
            };

            return route;
        }

        private string GenerateReport(VoxelGrid voxelGrid, List<Point3D> path, double pathLength, double directDistance, long planningTimeMs)
        {
            var (total, passable, obstacle) = voxelGrid.GetStatistics();

            return $@"================================
  体素路径规划测试报告
================================

【体素网格信息】
网格尺寸: {voxelGrid.SizeX} × {voxelGrid.SizeY} × {voxelGrid.SizeZ}
体素大小: {voxelGrid.VoxelSize:F4} 模型单位
总体素数: {total:N0}
可通行体素: {passable:N0} ({passable*100.0/total:F1}%)
障碍物体素: {obstacle:N0} ({obstacle*100.0/total:F1}%)

【路径规划结果】
路径点数: {path.Count}
路径总长: {pathLength:F2} 模型单位
直线距离: {directDistance:F2} 模型单位
路径比率: {pathLength/directDistance:F2} (1.0为最优直线)
规划耗时: {planningTimeMs} ms

【性能评估】
✅ 路径规划成功
✅ 性能: {(planningTimeMs < 1000 ? "优秀" : planningTimeMs < 5000 ? "良好" : "需优化")} ({planningTimeMs}ms)
✅ 路径质量: {(pathLength/directDistance < 1.5 ? "优秀" : pathLength/directDistance < 2.0 ? "良好" : "一般")}

================================";
        }

        #endregion
    }
}
