using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Autodesk.Navisworks.Api;
using Autodesk.Navisworks.Api.Clash;
using NavisworksTransport.Utils;
using NavisworksTransport.UI.WPF.Views;

namespace NavisworksTransport.Commands
{
    /// <summary>
    /// 碰撞报告参数类
    /// </summary>
    public class CollisionReportParameters
    {
        /// <summary>
        /// 报告类型
        /// </summary>
        public enum ReportType
        {
            /// <summary>动画碰撞报告</summary>
            Animation,
            /// <summary>独立碰撞检测报告</summary>
            Independent,
            /// <summary>综合报告（包含所有类型）</summary>
            Comprehensive
        }

        /// <summary>
        /// 要生成的报告类型
        /// </summary>
        public ReportType Type { get; set; } = ReportType.Comprehensive;

        /// <summary>
        /// 是否包含详细信息
        /// </summary>
        public bool IncludeDetails { get; set; } = true;

        /// <summary>
        /// 是否自动高亮报告中的碰撞对象
        /// </summary>
        public bool AutoHighlight { get; set; } = false;

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

    /// <summary>
    /// 碰撞数据收集结果
    /// </summary>
    public class CollisionDataResult
    {
        public List<CollisionResult> AllCollisions { get; set; } = new List<CollisionResult>();
        public int BoundingBoxTestCount { get; set; }    // 包围盒测试数量
        public int ClashDetectiveCollisionCount { get; set; } // Clash Detective结果数量
        public int AnimationCollisions { get; set; }       // 动画过程碰撞数量
        public string MovingObjectInfo { get; set; } = string.Empty;

        // 新增：被撞物体去重统计
        public HashSet<string> UniqueCollidedObjects { get; set; } = new HashSet<string>();
    }

    /// <summary>
    /// 碰撞报告结果类
    /// </summary>
    public class CollisionReportResult
    {
        public string ReportContent { get; set; }
        public int TotalCollisions { get; set; }
        public int AnimationCollisions { get; set; }    // 检测点数量
        public List<CollisionResult> AllCollisions { get; set; } = new List<CollisionResult>();
        public long GenerationTimeMs { get; set; }
        public string MovingObjectInfo { get; set; } = string.Empty;

        // 新增：被撞物体清单
        public List<string> CollidedObjectsList { get; set; } = new List<string>();
        public int UniqueCollidedObjectsCount { get; set; }

        // 新增：动画参数
        public string PathName { get; set; } = "未知路径";
        public int FrameRate { get; set; } = 30;
        public double Duration { get; set; } = 10.0;
        public double DetectionGap { get; set; } = 0.05;
    }

    /// <summary>
    /// 生成碰撞报告Command
    /// </summary>
    public class GenerateCollisionReportCommand : CommandBase
    {
        #region 静态缓存机制

        /// <summary>
        /// 碰撞报告结果缓存 - 使用测试名称作为键
        /// </summary>
        private static readonly Dictionary<string, CollisionReportResult> _reportCache = new Dictionary<string, CollisionReportResult>();

        /// <summary>
        /// 缓存操作锁对象
        /// </summary>
        private static readonly object _cacheLock = new object();

        #endregion

        private readonly CollisionReportParameters _parameters;

        public GenerateCollisionReportCommand(CollisionReportParameters parameters = null)
            : base("GenerateCollisionReport", "生成碰撞报告", "生成并显示详细的碰撞检测报告")
        {
            _parameters = parameters ?? new CollisionReportParameters();
        }

        protected override PathPlanningResult ValidateParameters()
        {
            return _parameters.ValidateParameters();
        }

        protected override async Task<PathPlanningResult> ExecuteInternalAsync(CancellationToken cancellationToken)
        {
            var startTime = DateTime.UtcNow;

            UpdateProgress(10, "开始生成碰撞报告...");

            // 检查缓存
            var clashIntegration = ClashDetectiveIntegration.Instance;
            var currentTestName = clashIntegration?.CurrentTestName;

            if (!string.IsNullOrEmpty(currentTestName))
            {
                lock (_cacheLock)
                {
                    if (_reportCache.ContainsKey(currentTestName))
                    {
                        var cachedResult = _reportCache[currentTestName];
                        LogManager.Info($"使用缓存的碰撞报告: {currentTestName}");

                        UpdateProgress(100, "使用缓存报告");

                        // 显示缓存的报告
                        ShowReport(cachedResult);

                        var cachedMessage = cachedResult.TotalCollisions > 0 ?
                            $"碰撞报告显示完成（缓存）：发现 {cachedResult.TotalCollisions} 个碰撞" :
                            "碰撞报告显示完成（缓存）：未发现碰撞";

                        return PathPlanningResult<CollisionReportResult>.Success(cachedResult, cachedMessage);
                    }
                    else
                    {
                        LogManager.Debug($"缓存中未找到测试: {currentTestName}");
                    }
                }
            }
            else
            {
                LogManager.Warning("无法获取测试名称，跳过缓存检查");
            }

            var result = new CollisionReportResult();

            try
            {
                UpdateProgress(30, "收集碰撞数据...");

                // 收集所有碰撞数据及统计信息（同步执行，避免 COM 线程问题）
                var collisionData = CollectAllCollisionData();
                result.AllCollisions = collisionData.AllCollisions;

                // 修改统计数据
                result.AnimationCollisions = collisionData.AnimationCollisions;
                result.TotalCollisions = collisionData.ClashDetectiveCollisionCount;
                result.MovingObjectInfo = collisionData.MovingObjectInfo;

                // 新增：被撞物体清单
                result.CollidedObjectsList = collisionData.UniqueCollidedObjects.OrderBy(x => x).ToList();
                result.UniqueCollidedObjectsCount = collisionData.UniqueCollidedObjects.Count;

                // 新增：从动画管理器获取动画参数
                var animationManager = Core.Animation.PathAnimationManager.GetInstance();
                if (animationManager != null)
                {
                    result.FrameRate = animationManager.AnimationFrameRate;
                    result.Duration = animationManager.AnimationDuration;
                    result.DetectionGap = animationManager.DetectionGap;
                    // PathName需要从动画管理器获取
                    result.PathName = animationManager.PathName ?? "未知路径";
                }

                LogManager.Info($"碰撞报告计数 - 检查点: {result.AnimationCollisions}, Clash Detective: {result.TotalCollisions}");

                UpdateProgress(70, "生成报告内容...");

                // 生成报告内容
                result.ReportContent = GenerateReportContent(collisionData, _parameters.Type, _parameters.IncludeDetails);

                UpdateProgress(90, "处理报告显示...");

                // 自动高亮（如果启用）
                if (_parameters.AutoHighlight && collisionData.AllCollisions.Count > 0)
                {
                    try
                    {
                        var highlightIntegration = ClashDetectiveIntegration.Instance;
                        if (highlightIntegration != null)
                        {
                            var highlightColor = Color.Green; // 绿色 (Navisworks API中没有Orange)
                            highlightIntegration.ManageHighlightsByCategory(ModelHighlightHelper.CollisionResultsCategory, collisionData.AllCollisions, highlightColor, true);
                            LogManager.Info($"自动高亮显示报告中的 {collisionData.AllCollisions.Count} 个碰撞对象");
                        }
                    }
                    catch (Exception ex)
                    {
                        LogManager.Error($"自动高亮报告对象失败: {ex.Message}");
                    }
                }

                UpdateProgress(100, "报告生成完成");

                // 显示报告（UI线程）
                ShowReport(result);

                // 将报告结果缓存起来
                if (!string.IsNullOrEmpty(currentTestName))
                {
                    lock (_cacheLock)
                    {
                        _reportCache[currentTestName] = result;
                        LogManager.Info($"碰撞报告已缓存: {currentTestName}, 缓存总数: {_reportCache.Count}");
                    }
                }
            }
            catch (OperationCanceledException)
            {
                return PathPlanningResult.Failure("报告生成被取消");
            }
            catch (Exception ex)
            {
                LogManager.Error($"生成碰撞报告失败: {ex.Message}");
                return PathPlanningResult.Failure($"报告生成失败: {ex.Message}");
            }

            result.GenerationTimeMs = (long)(DateTime.UtcNow - startTime).TotalMilliseconds;

            var message = result.TotalCollisions > 0 ?
                $"碰撞报告生成完成：发现 {result.TotalCollisions} 个碰撞" :
                "碰撞报告生成完成：未发现碰撞";

            return PathPlanningResult<CollisionReportResult>.Success(result, message);
        }

        #region 缓存相关方法

        /// <summary>
        /// 清理过期缓存（可选功能）
        /// </summary>
        public static void ClearReportCache()
        {
            lock (_cacheLock)
            {
                var count = _reportCache.Count;
                _reportCache.Clear();
                LogManager.Info($"已清理碰撞报告缓存，共清理 {count} 个缓存项");
            }
        }

        #endregion

        /// <summary>
        /// 收集所有碰撞数据及统计信息
        /// </summary>
        private CollisionDataResult CollectAllCollisionData()
        {
            var result = new CollisionDataResult();
            var allCollisions = new List<CollisionResult>();

            try
            {
                LogManager.Info("开始收集所有碰撞数据及统计信息...");

                var clashIntegration = ClashDetectiveIntegration.Instance;
                if (clashIntegration == null)
                {
                    throw new InvalidOperationException("无法获取ClashDetectiveIntegration实例");
                }

                // 从动画管理器获取当前路径名称
                var animationManager = Core.Animation.PathAnimationManager.GetInstance();
                var currentPathName = animationManager?.PathName;
                var currentTestName = clashIntegration?.CurrentTestName;

                if (string.IsNullOrEmpty(currentTestName))
                {
                    throw new InvalidOperationException("无法获取当前测试名称，请先运行碰撞检测");
                }

                // 直接从缓存获取ClashDetective结果
                var testCollisionsRaw = clashIntegration.GetCurrentPathClashResults(currentTestName);

                if (testCollisionsRaw == null || testCollisionsRaw.Count == 0)
                {
                    throw new InvalidOperationException($"未找到测试 '{currentTestName}' 的ClashDetective碰撞结果");
                }

                LogManager.Info($"从缓存获取ClashDetective结果: {testCollisionsRaw.Count}个碰撞，测试名称：{currentTestName}");

                // 直接使用缓存中的CollisionResult对象（已经过复合对象处理和去重）
                allCollisions.AddRange(testCollisionsRaw);

                // 统计碰撞总数
                result.ClashDetectiveCollisionCount = testCollisionsRaw.Count;
                LogManager.Debug($"测试 '{currentTestName}' 包含 {testCollisionsRaw.Count} 个碰撞");

                // 统计被撞物体（缓存中已经是复合对象，不需要再去重）
                var nameCountDict = new Dictionary<string, int>();
                var uniqueCollidedObjectsList = new List<string>();

                foreach (var collision in testCollisionsRaw)
                {
                    if (collision.Item2 != null)
                    {
                        // Item2已经是容器对象（在创建CollisionResult时已用FindNamedParentContainer处理）
                        var item2Name = ModelItemAnalysisHelper.GetSafeDisplayName(collision.Item2) ?? "未知对象";

                        // 为相同名称的对象添加编号区分
                        if (nameCountDict.ContainsKey(item2Name))
                        {
                            nameCountDict[item2Name]++;
                            uniqueCollidedObjectsList.Add($"{item2Name} #{nameCountDict[item2Name]}");
                        }
                        else
                        {
                            nameCountDict[item2Name] = 1;
                            uniqueCollidedObjectsList.Add(item2Name);
                        }
                    }
                }

                result.AllCollisions = allCollisions;
                result.UniqueCollidedObjects = new HashSet<string>(uniqueCollidedObjectsList);
                result.BoundingBoxTestCount = 0;

                // 设置动画碰撞数量
                result.AnimationCollisions = clashIntegration?.AnimationCollisionCount ?? 0;

                // 从碰撞结果的Item1中获取运动构件信息
                if (allCollisions.Count > 0 && allCollisions[0].Item1 != null)
                {
                    // Item1已经是容器对象（在创建CollisionResult时已用FindNamedParentContainer处理）
                    var movingItemName = ModelItemAnalysisHelper.GetSafeDisplayName(allCollisions[0].Item1) ?? "未知运动构件";
                    result.MovingObjectInfo = $"运动构件: {movingItemName}";
                }
                else
                {
                    result.MovingObjectInfo = "运动构件: 未知";
                }

                LogManager.Info($"收集完成 - Clash Detective权威结果: {result.ClashDetectiveCollisionCount}个, 碰撞对象: {allCollisions.Count}个, 被撞构件: {uniqueCollidedObjectsList.Count}个");

                return result;
            }
            catch (Exception ex)
            {
                LogManager.Error($"收集碰撞数据失败: {ex.Message}");
                result.AllCollisions = allCollisions;
                return result;
            }
        }

        /// <summary>
        /// 生成报告内容
        /// </summary>
        private string GenerateReportContent(CollisionDataResult collisionData, 
            CollisionReportParameters.ReportType reportType, bool includeDetails)
        {
            var report = new StringBuilder();
            var now = DateTime.Now;
            var collisions = collisionData.AllCollisions;

            // 报告头部
            report.AppendLine("========================================");
            report.AppendLine("       NavisworksTransport 碰撞检测报告");
            report.AppendLine("========================================");
            report.AppendLine($"生成时间: {now:yyyy年MM月dd日 HH:mm:ss}");
            report.AppendLine($"报告类型: {GetReportTypeName(reportType)}");

            // 运动构件信息（原运动物体信息）
            if (!string.IsNullOrEmpty(collisionData.MovingObjectInfo))
            {
                var movingInfo = collisionData.MovingObjectInfo.Replace("运动对象", "运动构件");
                report.AppendLine($"{movingInfo}");
            }
            report.AppendLine();

            // 总体统计
            report.AppendLine("=== 总体统计 ===");
            var clashIntegration = ClashDetectiveIntegration.Instance;
            var animationCollisionCount = clashIntegration?.AnimationCollisionCount ?? 0;

            report.AppendLine($"总碰撞数: {collisionData.ClashDetectiveCollisionCount}个");
            report.AppendLine($"碰撞构件: {collisionData.UniqueCollidedObjects.Count}个");
            report.AppendLine($"检测点: {animationCollisionCount}个");
            report.AppendLine();

            // 碰撞构件清单（新增）
            if (collisionData.UniqueCollidedObjects?.Count > 0)
            {
                report.AppendLine("=== 碰撞构件清单 ===");
                int index = 1;
                foreach (var objName in collisionData.UniqueCollidedObjects.OrderBy(x => x).Take(20)) // 限制显示前20个
                {
                    report.AppendLine($"  {index}. {objName}");
                    index++;
                }
                if (collisionData.UniqueCollidedObjects.Count > 20)
                {
                    report.AppendLine($"  ... 还有 {collisionData.UniqueCollidedObjects.Count - 20} 个构件");
                }
                report.AppendLine();
            }

            // 详细信息
            if (includeDetails && collisions.Count > 0)
            {
                report.AppendLine("=== 详细碰撞信息 ===");
                
                report.AppendLine("--- 碰撞详情 ---");
                foreach (var collision in collisions.Take(10)) // 限制显示数量
                {
                    AppendCollisionDetail(report, collision);
                }
                if (collisions.Count > 10)
                {
                    report.AppendLine($"... 还有 {collisions.Count - 10} 个碰撞未显示");
                }
                report.AppendLine();
            }

            // 建议和结论
            report.AppendLine("=== 建议与结论 ===");
            if (collisions.Count == 0)
            {
                report.AppendLine("✅ 未发现碰撞问题，路径规划良好。");
            }
            else
            {
                report.AppendLine($"⚠️ 发现 {collisions.Count} 个碰撞问题，建议采取以下措施：");
                report.AppendLine("   1. 调整路径规划，避开碰撞区域");
                report.AppendLine("   2. 检查车辆尺寸和安全边距设置");
                report.AppendLine("   3. 考虑增加临时障碍物标记");
                report.AppendLine("   4. 重新评估物流流程设计");
                
                report.AppendLine("   5. 建议进行更详细的碰撞检测分析");
            }

            report.AppendLine();
            report.AppendLine("========================================");
            report.AppendLine($"报告生成完成 - {now:HH:mm:ss}");
            report.AppendLine("========================================");

            return report.ToString();
        }

        /// <summary>
        /// 添加碰撞详细信息到报告中
        /// </summary>
        private void AppendCollisionDetail(StringBuilder report, CollisionResult collision)
        {
            var item1Name = collision.Item1?.DisplayName ?? "未知对象";
            var item2Name = collision.Item2?.DisplayName ?? "未知对象";
            
            // 转换距离单位为米
            var distanceInMeters = ConvertDistanceToMeters(collision.Distance);
            
            report.AppendLine($"• {item1Name} ↔ {item2Name}");
            report.AppendLine($"  状态: {GetStatusName(collision.Status)}, 距离: {distanceInMeters:F3}m");
            
            // 转换位置坐标单位为米
            var centerInMeters = ConvertPointToMeters(collision.Center);
            report.AppendLine($"  位置: ({centerInMeters.X:F2}, {centerInMeters.Y:F2}, {centerInMeters.Z:F2})m");
            report.AppendLine($"  GUID: {collision.ClashGuid}");
            report.AppendLine();
        }

        /// <summary>
        /// 获取报告类型名称
        /// </summary>
        private string GetReportTypeName(CollisionReportParameters.ReportType reportType)
        {
            switch (reportType)
            {
                case CollisionReportParameters.ReportType.Animation:
                    return "动画碰撞报告";
                case CollisionReportParameters.ReportType.Independent:
                    return "独立检测报告";
                case CollisionReportParameters.ReportType.Comprehensive:
                    return "综合碰撞报告";
                default:
                    return "未知类型";
            }
        }

        /// <summary>
        /// 获取碰撞状态名称
        /// </summary>
        private string GetStatusName(ClashResultStatus status)
        {
            switch (status)
            {
                case ClashResultStatus.New:
                    return "新发现";
                case ClashResultStatus.Active:
                    return "活跃";
                case ClashResultStatus.Reviewed:
                    return "已审阅";
                case ClashResultStatus.Approved:
                    return "已批准";
                case ClashResultStatus.Resolved:
                    return "已解决";
                default:
                    return "未知";
            }
        }

        /// <summary>
        /// 显示报告
        /// </summary>
        private void ShowReport(CollisionReportResult reportResult)
        {
            try
            {
                // 确保在UI线程中执行
                if (System.Windows.Application.Current != null)
                {
                    if (System.Windows.Application.Current.Dispatcher.CheckAccess())
                    {
                        // 已在UI线程上
                        ShowReportInternal(reportResult);
                    }
                    else
                    {
                        // 切换到UI线程
                        System.Windows.Application.Current.Dispatcher.Invoke(() => ShowReportInternal(reportResult));
                    }
                }
                else
                {
                    // 如果WPF Application不存在，回退到原来的方式
                    ShowReportInternal(reportResult);
                }
            }
            catch (Exception ex)
            {
                LogManager.Error($"显示报告失败: {ex.Message}");
                System.Windows.MessageBox.Show($"显示报告失败: {ex.Message}", "错误", 
                    System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error);
            }
        }

        /// <summary>
        /// 内部报告显示方法
        /// </summary>
        private void ShowReportInternal(CollisionReportResult reportResult)
        {
            try
            {
                // 使用新的WPF碰撞报告对话框
                var reportDialog = CollisionReportDialog.ShowReport(reportResult);
                
                if (reportDialog != null)
                {
                    LogManager.Info("WPF碰撞报告对话框显示成功");
                }
            }
            catch (Exception ex)
            {
                LogManager.Error($"显示WPF报告对话框失败: {ex.Message}");
            }
        }

        /// <summary>
        /// 创建综合报告命令
        /// </summary>
        public static GenerateCollisionReportCommand CreateComprehensive(bool autoHighlight = false)
        {
            return new GenerateCollisionReportCommand(new CollisionReportParameters
            {
                Type = CollisionReportParameters.ReportType.Comprehensive,
                IncludeDetails = true,
                AutoHighlight = autoHighlight
            });
        }

        /// <summary>
        /// 将距离转换为米
        /// </summary>
        private double ConvertDistanceToMeters(double distance)
        {
            try
            {
                var conversionFactor = UnitsConverter.GetUnitsToMetersConversionFactor();
                return distance * conversionFactor;
            }
            catch (Exception ex)
            {
                LogManager.Warning($"距离单位转换失败: {ex.Message}，使用原始值");
                return distance;
            }
        }

        /// <summary>
        /// 将3D点坐标转换为米
        /// </summary>
        private Point3D ConvertPointToMeters(Point3D point)
        {
            try
            {
                var conversionFactor = UnitsConverter.GetUnitsToMetersConversionFactor();
                return new Point3D(
                    point.X * conversionFactor,
                    point.Y * conversionFactor,
                    point.Z * conversionFactor
                );
            }
            catch (Exception ex)
            {
                LogManager.Warning($"坐标单位转换失败: {ex.Message}，使用原始值");
                return point;
            }
        }
    }
}