using System;
using System.Collections.Generic;
using System.Linq;
using Autodesk.Navisworks.Api;
using NavisworksTransport.Utils.CoordinateSystem;

namespace NavisworksTransport.PathPlanning
{
    /// <summary>
    /// 优化的高度计算器 - 解决网格生成时的性能问题
    /// 使用采样+插值的策略，而不是对每个网格点都进行View API调用
    /// </summary>
    public class OptimizedHeightCalculator
    {
        private readonly Dictionary<string, double> _heightSamples;
        private readonly double _sampleInterval;
        private readonly ChannelHeightDetector _heightDetector;
        private readonly ICoordinateSystem _coordinateSystem;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="sampleInterval">采样间隔（米）</param>
        public OptimizedHeightCalculator(double sampleInterval = 5.0)
        {
            _heightSamples = new Dictionary<string, double>();
            _sampleInterval = sampleInterval;
            _coordinateSystem = CoordinateSystemManager.Instance.Current;
            _heightDetector = new ChannelHeightDetector(_coordinateSystem);
            
            LogManager.Info($"[优化高度计算] 初始化完成，采样间隔: {sampleInterval}米");
        }

        /// <summary>
        /// 预计算指定区域的高度采样点
        /// </summary>
        /// <param name="bounds">计算边界</param>
        /// <param name="channelItems">通道模型集合</param>
        public void PrecomputeHeightSamples(BoundingBox3D bounds, IEnumerable<ModelItem> channelItems)
        {
            try
            {
                LogManager.Info("[优化高度计算] 开始预计算高度采样点...");
                _heightSamples.Clear();

                var channels = channelItems?.ToList() ?? new List<ModelItem>();
                if (!channels.Any())
                {
                    LogManager.Warning("[优化高度计算] 没有通道数据，跳过预计算");
                    return;
                }

                // 计算采样网格
                double sampleIntervalModel = _sampleInterval * 39.37; // 转换为模型单位
                
                var (minH1, maxH1, minH2, maxH2) = _coordinateSystem.GetHorizontalRange(bounds);
                int samplesX = (int)Math.Ceiling((maxH1 - minH1) / sampleIntervalModel);
                int samplesY = (int)Math.Ceiling((maxH2 - minH2) / sampleIntervalModel);
                
                LogManager.Info($"[优化高度计算] 采样网格: {samplesX}x{samplesY} = {samplesX * samplesY}个采样点");

                int processedSamples = 0;
                int totalSamples = samplesX * samplesY;

                // 对网格进行采样
                for (int x = 0; x < samplesX; x++)
                {
                    for (int y = 0; y < samplesY; y++)
                    {
                        double worldH1 = minH1 + x * sampleIntervalModel;
                        double worldH2 = minH2 + y * sampleIntervalModel;
                        
                        var sampleKey = GenerateSampleKey(worldH1, worldH2);
                        
                        // 只对通道区域进行精确计算
                        var position = _coordinateSystem.CreatePoint(worldH1, worldH2, 0);
                        var containingChannel = FindNearestChannel(position, channels);
                        
                        if (containingChannel != null)
                        {
                            // 这里使用几何分析而不是View API
                            var height = CalculateHeightFromGeometry(position, containingChannel);
                            _heightSamples[sampleKey] = height;
                        }
                        
                        processedSamples++;
                        
                        // 每处理1000个点输出一次进度
                        if (processedSamples % 1000 == 0)
                        {
                            double progress = (double)processedSamples / totalSamples * 100;
                            LogManager.Info($"[优化高度计算] 预计算进度: {progress:F1}% ({processedSamples}/{totalSamples})");
                        }
                    }
                }

                LogManager.Info($"[优化高度计算] 预计算完成，共采样 {_heightSamples.Count} 个有效点");
            }
            catch (Exception ex)
            {
                LogManager.Error($"[优化高度计算] 预计算失败: {ex.Message}");
            }
        }

        /// <summary>
        /// 获取指定位置的优化高度（使用插值）
        /// </summary>
        /// <param name="worldX">世界坐标X</param>
        /// <param name="worldY">世界坐标Y</param>
        /// <param name="fallbackZ">备用Z坐标</param>
        /// <returns>优化后的高度</returns>
        public double GetOptimizedHeight(double worldX, double worldY, double fallbackZ)
        {
            try
            {
                // 找到最近的采样点进行插值
                var nearestSamples = FindNearestSamples(worldX, worldY);
                
                if (nearestSamples.Count >= 2)
                {
                    // 使用距离加权插值
                    return InterpolateFromSamples(worldX, worldY, nearestSamples);
                }
                else if (nearestSamples.Count == 1)
                {
                    // 使用最近的单个采样点
                    return nearestSamples.First().Value;
                }
                else
                {
                    // 没有采样数据，使用备用值
                    return fallbackZ;
                }
            }
            catch (Exception ex)
            {
                LogManager.Debug($"[优化高度计算] 获取优化高度失败: {ex.Message}");
                return fallbackZ;
            }
        }

        /// <summary>
        /// 使用View API精确计算表面高度
        /// </summary>
        private double CalculateHeightFromGeometry(Point3D position, ModelItem channel)
        {
            try
            {
                // 尝试使用View API进行精确表面检测
                var preciseHeight = TryGetPreciseSurfaceHeight(position, channel);
                if (preciseHeight.HasValue)
                {
                    return preciseHeight.Value;
                }
                
                // 如果View API失败，使用几何分析作为备用
                if (channel?.Geometry?.BoundingBox != null)
                {
                    var bbox = channel.Geometry.BoundingBox;
                    
                    // 对于大多数建筑元素，表面接近顶面
                    double surfaceRatio = DetermineChannelSurfaceRatio(channel);
                    var (minElevation, maxElevation) = _coordinateSystem.GetHeightRange(bbox);
                    double height = minElevation + (maxElevation - minElevation) * surfaceRatio;
                    
                    return height;
                }
            }
            catch (Exception ex)
            {
                LogManager.Debug($"[优化高度计算] 几何高度计算失败: {ex.Message}");
            }
            
            return _coordinateSystem.GetElevation(position);
        }

        /// <summary>
        /// 尝试使用View API获取精确表面高度
        /// </summary>
        private double? TryGetPreciseSurfaceHeight(Point3D worldPosition, ModelItem channel)
        {
            try
            {
                var view = Application.ActiveDocument?.ActiveView;
                if (view == null) return null;

                // 将3D世界坐标转换为屏幕坐标
                var screenPoint = view.ProjectPoint(worldPosition, false, false);
                if (screenPoint != null)
                {
                    // 使用PickItemFromPoint获取精确表面点
                    var pickResult = view.PickItemFromPoint((int)screenPoint.X, (int)screenPoint.Y);
                    if (pickResult?.Point != null && pickResult.ModelItem == channel)
                    {
                        double detectedElevation = _coordinateSystem.GetElevation(pickResult.Point);
                        LogManager.Debug($"[优化高度计算] View API精确检测: {worldPosition} -> {detectedElevation:F3}");
                        return detectedElevation;
                    }
                }
            }
            catch (Exception ex)
            {
                LogManager.Debug($"[优化高度计算] View API检测失败: {ex.Message}");
            }
            
            return null;
        }

        /// <summary>
        /// 确定通道的表面比例
        /// </summary>
        private double DetermineChannelSurfaceRatio(ModelItem channel)
        {
            var displayName = channel.DisplayName?.ToLower() ?? "";
            var className = channel.ClassDisplayName?.ToLower() ?? "";
            
            // 根据元素类型确定表面位置
            if (displayName.Contains("楼板") || displayName.Contains("slab") || 
                className.Contains("楼板") || className.Contains("slab"))
            {
                return 1.0; // 楼板表面在顶部
            }
            else if (displayName.Contains("楼梯") || displayName.Contains("stair"))
            {
                return 0.95; // 楼梯表面略低于顶部
            }
            else if (displayName.Contains("坡道") || displayName.Contains("ramp"))
            {
                return 0.98; // 坡道表面接近顶部
            }
            else
            {
                return 0.9; // 一般情况下表面在90%高度
            }
        }

        /// <summary>
        /// 查找最近的通道
        /// </summary>
        private ModelItem FindNearestChannel(Point3D position, List<ModelItem> channels)
        {
            ModelItem nearestChannel = null;
            double minDistance = double.MaxValue;

            foreach (var channel in channels)
            {
                try
                {
                    if (channel?.Geometry?.BoundingBox != null)
                    {
                        var bbox = channel.Geometry.BoundingBox;
                        
                        // 检查位置是否在通道边界内（带容差）
                        var (positionH1, positionH2) = _coordinateSystem.GetHorizontalCoords(position);
                        var (minH1, maxH1, minH2, maxH2) = _coordinateSystem.GetHorizontalRange(bbox);
                        if (positionH1 >= minH1 - 50 && positionH1 <= maxH1 + 50 &&
                            positionH2 >= minH2 - 50 && positionH2 <= maxH2 + 50)
                        {
                            // 计算到边界中心的距离
                            double centerH1 = (minH1 + maxH1) / 2;
                            double centerH2 = (minH2 + maxH2) / 2;
                            double distance = Math.Sqrt(Math.Pow(positionH1 - centerH1, 2) + Math.Pow(positionH2 - centerH2, 2));
                            
                            if (distance < minDistance)
                            {
                                minDistance = distance;
                                nearestChannel = channel;
                            }
                        }
                    }
                }
                catch
                {
                    // 忽略单个通道的错误
                }
            }

            return nearestChannel;
        }

        /// <summary>
        /// 查找最近的采样点
        /// </summary>
        private Dictionary<string, double> FindNearestSamples(double worldX, double worldY)
        {
            var nearestSamples = new Dictionary<string, double>();
            double searchRadius = _sampleInterval * 39.37 * 2; // 搜索半径为2倍采样间隔

            foreach (var sample in _heightSamples)
            {
                var coords = ParseSampleKey(sample.Key);
                if (coords.HasValue)
                {
                    double distance = Math.Sqrt(Math.Pow(worldX - coords.Value.X, 2) + Math.Pow(worldY - coords.Value.Y, 2));
                    if (distance <= searchRadius)
                    {
                        nearestSamples[sample.Key] = sample.Value;
                    }
                }
            }

            return nearestSamples.Take(4).ToDictionary(x => x.Key, x => x.Value); // 最多取4个最近点
        }

        /// <summary>
        /// 从采样点进行插值
        /// </summary>
        private double InterpolateFromSamples(double worldX, double worldY, Dictionary<string, double> samples)
        {
            double totalWeight = 0;
            double weightedHeight = 0;

            foreach (var sample in samples)
            {
                var coords = ParseSampleKey(sample.Key);
                if (coords.HasValue)
                {
                    double distance = Math.Sqrt(Math.Pow(worldX - coords.Value.X, 2) + Math.Pow(worldY - coords.Value.Y, 2));
                    double weight = distance > 0 ? 1.0 / distance : 1000.0; // 避免除零
                    
                    weightedHeight += sample.Value * weight;
                    totalWeight += weight;
                }
            }

            return totalWeight > 0 ? weightedHeight / totalWeight : samples.Values.Average();
        }

        /// <summary>
        /// 生成采样键
        /// </summary>
        private string GenerateSampleKey(double worldX, double worldY)
        {
            // 对坐标进行网格对齐
            double sampleIntervalModel = _sampleInterval * 39.37;
            int gridX = (int)Math.Floor(worldX / sampleIntervalModel);
            int gridY = (int)Math.Floor(worldY / sampleIntervalModel);
            return $"{gridX}_{gridY}";
        }

        /// <summary>
        /// 解析采样键获取世界坐标
        /// </summary>
        private (double X, double Y)? ParseSampleKey(string key)
        {
            try
            {
                var parts = key.Split('_');
                if (parts.Length == 2 && int.TryParse(parts[0], out int gridX) && int.TryParse(parts[1], out int gridY))
                {
                    double sampleIntervalModel = _sampleInterval * 39.37;
                    return (gridX * sampleIntervalModel, gridY * sampleIntervalModel);
                }
            }
            catch
            {
                // 忽略解析错误
            }
            return null;
        }

        /// <summary>
        /// 清除采样缓存
        /// </summary>
        public void ClearSamples()
        {
            _heightSamples.Clear();
            LogManager.Info("[优化高度计算] 采样缓存已清除");
        }

        /// <summary>
        /// 获取统计信息
        /// </summary>
        public string GetStats()
        {
            return $"采样点数: {_heightSamples.Count}, 采样间隔: {_sampleInterval}米";
        }
    }
}
