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

// 使用命名空间引用以避免类名冲突
using ClashIntegration = NavisworksTransport.ClashDetectiveIntegration;

namespace NavisworksTransport.Core.Spatial
{
    /// <summary>
    /// 全局空间索引管理器
    /// 单例模式，为所有动画提供高效的空间查询服务
    /// </summary>
    public class SpatialIndexManager
    {
        private static SpatialIndexManager _instance;
        private static readonly object _lockObj = new object();

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

        private SpatialHashGrid<ModelItem> _globalSpatialIndex;
        private double _cellSize = 1.0;  // 默认格子大小（模型单位）
        private bool _isInitialized = false;
        private int _indexedObjectCount = 0;

        // 缓存对象位置，避免重复计算
        private readonly Dictionary<ModelItem, Vector3d> _objectPositions = new Dictionary<ModelItem, Vector3d>();

        private SpatialIndexManager()
        {
        }

        /// <summary>
        /// 空间索引是否已初始化
        /// </summary>
        public bool IsInitialized => _isInitialized;

        /// <summary>
        /// 格子大小（模型单位）
        /// </summary>
        public double CellSize => _cellSize;

        /// <summary>
        /// 已索引的对象数量
        /// </summary>
        public int IndexedObjectCount => _indexedObjectCount;

        /// <summary>
        /// 构建全局空间索引
        /// </summary>
        /// <param name="cellSizeInModelUnits">格子大小（模型单位），建议设置为物体半径的2倍</param>
        public void BuildGlobalIndex(double cellSizeInModelUnits = 1.0)
        {
            var sw = Stopwatch.StartNew();
            LogManager.Info("[空间索引] 开始构建全局空间索引");
            LogManager.Info($"[空间索引] 格子大小: {cellSizeInModelUnits:F2} 模型单位");

            try
            {
                _cellSize = cellSizeInModelUnits;

                // 1. 从缓存获取已过滤通道的几何对象列表
                var nonChannelItems = ClashIntegration.GetNonChannelGeometryItemsCache();

                if (nonChannelItems == null)
                {
                    LogManager.Error("[空间索引] 几何对象缓存不存在！调用方应在动画生成阶段构建缓存。");
                    throw new InvalidOperationException("空间索引构建失败：几何对象缓存未初始化。请先调用 BuildAllGeometryItemsCache()。");
                }

                LogManager.Info($"[空间索引] 使用缓存的非通道几何对象: {nonChannelItems.Count} 个");

                // 2. 创建空间哈希网格
                _globalSpatialIndex = new SpatialHashGrid<ModelItem>(cellSizeInModelUnits);
                _objectPositions.Clear();

                // 3. 索引所有非通道对象
                int indexedCount = 0;
                int failedCount = 0;

                foreach (var item in nonChannelItems)
                {
                    try
                    {
                        // 获取包围盒
                        var bbox = item.BoundingBox();
                        var center = new Vector3d(
                            (bbox.Min.X + bbox.Max.X) / 2.0,
                            (bbox.Min.Y + bbox.Max.Y) / 2.0,
                            (bbox.Min.Z + bbox.Max.Z) / 2.0
                        );

                        // 使用边界框插入到空间索引（支持大型对象覆盖多个格子）
                        _globalSpatialIndex.Insert(item, bbox);

                        // 缓存位置（用于快速查询）
                        _objectPositions[item] = center;

                        indexedCount++;
                    }
                    catch (Exception ex)
                    {
                        LogManager.Warning($"[空间索引] 索引对象失败: {item.DisplayName}, 错误: {ex.Message}");
                        failedCount++;
                    }
                }

                _indexedObjectCount = indexedCount;
                _isInitialized = true;

                sw.Stop();

                LogManager.Info("[空间索引] 构建完成");
                LogManager.Info($"  - 成功索引: {indexedCount} 个对象");
                LogManager.Info($"  - 失败: {failedCount} 个对象");
                LogManager.Info($"  - 格子数量: {_globalSpatialIndex.CellCount} 个");
                LogManager.Info($"  - 耗时: {sw.ElapsedMilliseconds} ms");

                // 输出统计信息
                LogManager.Debug("[空间索引] " + _globalSpatialIndex.GetStatistics());
            }
            catch (Exception ex)
            {
                LogManager.Error($"[空间索引] 构建失败: {ex.Message}");
                LogManager.Error($"[空间索引] 堆栈跟踪: {ex.StackTrace}");
                _isInitialized = false;
                throw;
            }
        }

        /// <summary>
        /// 范围查询：查找指定位置附近的对象
        /// </summary>
        /// <param name="position">查询中心位置（Navisworks Point3D）</param>
        /// <param name="searchRadiusInModelUnits">查询半径（模型单位）</param>
        /// <param name="excludeObject">要排除的对象（通常是移动物体本身）</param>
        /// <returns>范围内的对象列表</returns>
        public List<ModelItem> FindNearbyObjects(
            Point3D position,
            double searchRadiusInModelUnits,
            ModelItem excludeObject = null)
        {
            if (!_isInitialized)
            {
                throw new InvalidOperationException(
                    "[空间索引] 空间索引未初始化，请先调用 BuildGlobalIndex()");
            }

            var sw = Stopwatch.StartNew();

            try
            {
                // 转换为 geometry4Sharp 的 Vector3d
                var centerVec = new Vector3d(position.X, position.Y, position.Z);

                // 使用空间哈希网格进行范围查询（带精确距离检查）
                var nearbyObjects = _globalSpatialIndex.FindInRadiusExact(
                    centerVec,
                    searchRadiusInModelUnits,
                    getPositionFunc: item =>
                    {
                        // 从缓存中获取对象位置
                        if (_objectPositions.TryGetValue(item, out var pos))
                        {
                            return pos;
                        }

                        // 缓存未命中，重新计算（理论上不应该发生）
                        var bbox = item.BoundingBox();
                        return new Vector3d(
                            (bbox.Min.X + bbox.Max.X) / 2.0,
                            (bbox.Min.Y + bbox.Max.Y) / 2.0,
                            (bbox.Min.Z + bbox.Max.Z) / 2.0
                        );
                    }
                );

                // 排除指定对象
                if (excludeObject != null)
                {
                    nearbyObjects = nearbyObjects.Where(obj => !obj.Equals(excludeObject)).ToList();
                }

                sw.Stop();

                return nearbyObjects;
            }
            catch (Exception ex)
            {
                LogManager.Error($"[空间索引] 范围查询失败: {ex.Message}");
                throw;
            }
        }

        /// <summary>
        /// 范围查询（带排除列表）
        /// </summary>
        /// <param name="position">查询中心位置</param>
        /// <param name="searchRadiusInModelUnits">查询半径</param>
        /// <param name="excludeObjects">要排除的对象列表</param>
        /// <returns>范围内的对象列表</returns>
        public List<ModelItem> FindNearbyObjects(
            Point3D position,
            double searchRadiusInModelUnits,
            IEnumerable<ModelItem> excludeObjects)
        {
            var results = FindNearbyObjects(position, searchRadiusInModelUnits, excludeObject: null);

            if (excludeObjects != null)
            {
                var excludeSet = new HashSet<ModelItem>(excludeObjects);
                results = results.Where(obj => !excludeSet.Contains(obj)).ToList();
            }

            return results;
        }

        /// <summary>
        /// AABB范围查询：查找与指定AABB相交的对象
        /// 比球形查询更精确，避免球体扩大的无效范围
        /// </summary>
        /// <param name="bounds">查询AABB（Navisworks BoundingBox3D）</param>
        /// <param name="excludeObject">要排除的对象</param>
        /// <returns>与AABB相交格子中的对象列表</returns>
        public List<ModelItem> FindInAABB(
            BoundingBox3D bounds,
            ModelItem excludeObject = null)
        {
            if (!_isInitialized)
            {
                throw new InvalidOperationException(
                    "[空间索引] 空间索引未初始化，请先调用 BuildGlobalIndex()");
            }

            try
            {
                // 直接使用AABB查询（更精确）
                var nearbyObjects = _globalSpatialIndex.FindInAABB(bounds);

                // 排除指定对象
                if (excludeObject != null)
                {
                    nearbyObjects = nearbyObjects.Where(obj => !obj.Equals(excludeObject)).ToList();
                }

                return nearbyObjects;
            }
            catch (Exception ex)
            {
                LogManager.Error($"[空间索引] AABB查询失败: {ex.Message}");
                throw;
            }
        }

        /// <summary>
        /// 获取对象的缓存位置
        /// </summary>
        /// <param name="item">模型对象</param>
        /// <returns>对象的3D位置（Vector3d）</returns>
        public Vector3d? GetObjectPosition(ModelItem item)
        {
            if (_objectPositions.TryGetValue(item, out var pos))
            {
                return pos;
            }
            return null;
        }

        /// <summary>
        /// 清除空间索引
        /// </summary>
        public void Clear()
        {
            LogManager.Info("[空间索引] 清除空间索引");

            _globalSpatialIndex?.Clear();
            _objectPositions.Clear();
            _isInitialized = false;
            _indexedObjectCount = 0;

            LogManager.Info("[空间索引] 空间索引已清除");
        }

        /// <summary>
        /// 获取空间索引统计信息
        /// </summary>
        /// <returns>统计信息字符串</returns>
        public string GetStatistics()
        {
            if (!_isInitialized)
            {
                return "[空间索引] 未初始化";
            }

            return $"[空间索引] 统计信息:\n" +
                   $"  - 已索引对象: {_indexedObjectCount} 个\n" +
                   $"  - 格子大小: {_cellSize:F2} 模型单位\n" +
                   $"  - 格子数量: {_globalSpatialIndex.CellCount} 个\n" +
                   $"{_globalSpatialIndex.GetStatistics()}";
        }
    }
}
