using System;
using System.Collections.Generic;
using System.Linq;
using Autodesk.Navisworks.Api;
using NavisApplication = Autodesk.Navisworks.Api.Application;
using NavisworksTransport.Core;
using NavisworksTransport.Core.Config;
using NavisworksTransport.Utils;

namespace NavisworksTransport.UI.WPF.ViewModels
{
    /// <summary>
    /// 物流控制面板主ViewModel
    /// </summary>
    public class LogisticsControlViewModel : ViewModelBase
    {
        private enum ClipBoxFocusMode
        {
            None,
            Path,
            Selection
        }

        #region 私有字段

        private string _statusText;
        private bool _isProcessing = false;
        private bool _showControlVisualization = true;
        
        // UI状态管理和命令框架
        private readonly UIStateManager _uiStateManager;
        private readonly NavisworksTransport.Commands.CommandManager _commandManager;
        private readonly PathPlanningManager _pathPlanningManager;

        #endregion

        #region 公共属性


        /// <summary>
        /// 状态文本
        /// </summary>
        public string StatusText
        {
            get => _statusText;
            set => SetProperty(ref _statusText, value);
        }

        /// <summary>
        /// 是否正在处理中（用于统一状态栏进度条显示）
        /// </summary>
        public bool IsProcessing
        {
            get => _isProcessing;
            set => SetProperty(ref _isProcessing, value);
        }

        private double _progressPercentage = 0;
        
        /// <summary>
        /// 进度百分比（0-100，-1表示不确定进度）
        /// </summary>
        public double ProgressPercentage
        {
            get => _progressPercentage;
            set 
            { 
                if (SetProperty(ref _progressPercentage, value))
                {
                    OnPropertyChanged(nameof(IsIndeterminateProgress));
                }
            }
        }

        /// <summary>
        /// 是否使用不确定进度模式
        /// </summary>
        public bool IsIndeterminateProgress => ProgressPercentage < 0;

        /// <summary>
        /// 是否显示控制点连线
        /// </summary>
        public bool ShowControlVisualization
        {
            get => _showControlVisualization;
            set
            {
                if (SetProperty(ref _showControlVisualization, value))
                {
                    // 更新所有路径的控制点显示
                    var renderPlugin = PathPointRenderPlugin.Instance;
                    if (renderPlugin != null)
                    {
                        lock (typeof(PathPointRenderPlugin))
                        {
                            var allVisualizations = renderPlugin.GetAllPathVisualizations();
                            foreach (var visualization in allVisualizations)
                            {
                                visualization.ShowControlVisualization = value;
                            }
                        }
                        // 触发视图刷新
                        if (NavisApplication.ActiveDocument?.ActiveView != null)
                        {
                            NavisApplication.ActiveDocument.ActiveView.RequestDelayedRedraw(ViewRedrawRequests.Render);
                        }
                    }
                }
            }
        }

        private bool _showPathLines = true;
        private bool _showObjectSpace = false;

        /// <summary>
        /// 是否显示路径线/地面连线
        /// </summary>
        public bool ShowPathLines
        {
            get => _showPathLines;
            set
            {
                if (SetProperty(ref _showPathLines, value))
                {
                    var renderPlugin = PathPointRenderPlugin.Instance;
                    if (renderPlugin != null)
                    {
                        renderPlugin.ShowPathLines = value;
                    }
                }
            }
        }

        /// <summary>
        /// 是否显示通行空间
        /// </summary>
        public bool ShowObjectSpace
        {
            get => _showObjectSpace;
            set
            {
                if (SetProperty(ref _showObjectSpace, value))
                {
                    var renderPlugin = PathPointRenderPlugin.Instance;
                    if (renderPlugin != null)
                    {
                        renderPlugin.ShowObjectSpace = value;
                    }
                }
            }
        }

        private bool _isClipBoxEnabled;
        private bool _isSelectionClipBoxEnabled;
        private bool _isUpdatingClipBoxState;
        private ClipBoxFocusMode _clipBoxFocusMode = ClipBoxFocusMode.None;
        private readonly SelectionClipBoxLockState _selectionClipBoxLockState = new SelectionClipBoxLockState();
        private string _savedClipStateJson;

        /// <summary>
        /// 是否启用剖面盒（聚焦当前路径）
        /// </summary>
        public bool IsClipBoxEnabled
        {
            get => _isClipBoxEnabled;
            set
            {
                if (SetProperty(ref _isClipBoxEnabled, value))
                {
                    if (_isUpdatingClipBoxState)
                    {
                        return;
                    }

                    if (value)
                    {
                        ActivatePathClipBox();
                    }
                    else if (_clipBoxFocusMode == ClipBoxFocusMode.Path)
                    {
                        ClearActiveClipBox();
                    }
                }
            }
        }

        /// <summary>
        /// 是否启用剖面盒（聚焦当前选择对象）
        /// </summary>
        public bool IsSelectionClipBoxEnabled
        {
            get => _isSelectionClipBoxEnabled;
            set
            {
                if (SetProperty(ref _isSelectionClipBoxEnabled, value))
                {
                    if (_isUpdatingClipBoxState)
                    {
                        return;
                    }

                    if (value)
                    {
                        ActivateSelectionClipBox();
                    }
                    else if (_clipBoxFocusMode == ClipBoxFocusMode.Selection)
                    {
                        ClearActiveClipBox();
                    }
                }
            }
        }

        /// <summary>
        /// 从 PathPointRenderPlugin 同步渲染状态
        /// </summary>
        private void SyncVisualizationStateFromPlugin()
        {
            var renderPlugin = PathPointRenderPlugin.Instance;
            if (renderPlugin != null)
            {
                _showPathLines = renderPlugin.ShowPathLines;
                _showObjectSpace = renderPlugin.ShowObjectSpace;
                OnPropertyChanged(nameof(ShowPathLines));
                OnPropertyChanged(nameof(ShowObjectSpace));
            }
        }

        /// <summary>
        /// 当前路径是否可以使用路径线（仅地面路径）
        /// </summary>
        public bool CanUsePathLines
        {
            get
            {
                var currentRoute = _pathPlanningManager?.CurrentRoute;
                if (currentRoute == null) return true;
                return currentRoute.PathType == PathType.Ground;
            }
        }

        #endregion

        #region 构造函数

        public LogisticsControlViewModel() : base()
        {
            try
            {
                // 获取UI状态管理器和命令管理器实例
                _uiStateManager = UIStateManager.Instance;
                _commandManager = NavisworksTransport.Commands.CommandManager.Instance;
                _pathPlanningManager = PathPlanningManager.Instance;
                
                // 验证关键组件是否正常初始化
                if (_uiStateManager == null)
                {
                    LogManager.Error("UIStateManager初始化失败");
                    throw new InvalidOperationException("UIStateManager初始化失败");
                }
                
                if (_commandManager == null)
                {
                    LogManager.Error("CommandManager初始化失败");
                    throw new InvalidOperationException("CommandManager初始化失败");
                }

                // 订阅可视化状态变更事件，同步按钮状态
                if (_pathPlanningManager != null)
                {
                    _pathPlanningManager.VisualizationStateChanged += (s, e) =>
                    {
                        // 通知 CanUsePathLines 变更（影响LN按钮的启用状态）
                        OnPropertyChanged(nameof(CanUsePathLines));
                        
                        // 从 PathPointRenderPlugin 同步最新的渲染状态
                        SyncVisualizationStateFromPlugin();
                    };

                    // 订阅当前路径切换事件（总是触发，包括UI调用SetCurrentRoute时）
                    // 用于剖面盒自动跟随路径切换
                    _pathPlanningManager.CurrentRouteSwitched += (s, e) =>
                    {
                        if (_clipBoxFocusMode == ClipBoxFocusMode.Path)
                        {
                            if (_pathPlanningManager.PathEditState == PathEditState.Creating)
                            {
                                LogManager.Info("[剖面盒] 当前处于新建路径流程，跳过自动跟随");
                                return;
                            }

                            LogManager.Info("[剖面盒] 路径已切换，重新设置剖面盒聚焦到新路径");
                            EnableClipBoxForCurrentRoute();
                        }
                    };
                }

                if (NavisApplication.ActiveDocument?.CurrentSelection != null)
                {
                    NavisApplication.ActiveDocument.CurrentSelection.Changed += OnCurrentSelectionChanged;
                }

                // 初始化状态
                StatusText = "插件已就绪";
                
                LogManager.Info("LogisticsControlViewModel构造函数执行完成");
            }
            catch (Exception ex)
            {
                LogManager.Error($"LogisticsControlViewModel构造函数异常: {ex.Message}", ex);
                
                // 在构造函数中尽量保证对象处于可用状态
                StatusText = "初始化失败，请检查日志";
                throw;
            }
        }

        #endregion

        #region 统一状态栏方法

        /// <summary>
        /// 更新统一状态栏信息（简单版本，不显示进度条）
        /// </summary>
        /// <param name="message">状态消息</param>
        public void UpdateStatus(string message)
        {
            SafeExecute(() =>
            {
                StatusText = message ?? "就绪";
                IsProcessing = false; // 简单状态更新不显示进度条
            }, "更新统一状态栏", runOnUIThread: true);
        }

        /// <summary>
        /// 更新统一状态栏信息（完整版本）
        /// </summary>
        /// <param name="message">状态消息</param>
        /// <param name="progress">进度值 (0-100)，默认不显示进度条</param>
        /// <param name="isProcessing">是否正在处理中（显示进度条动画）</param>
        public void UpdateStatus(string message, double progress = -1, bool? isProcessing = null)
        {
            SafeExecute(() =>
            {
                StatusText = message ?? "就绪";
                if (progress >= 0)
                {
                    ProgressPercentage = Math.Max(0, Math.Min(100, progress));
                }
                if (isProcessing.HasValue)
                {
                    IsProcessing = isProcessing.Value;
                }
            }, "更新统一状态栏", runOnUIThread: true);
        }

        /// <summary>
        /// 更新统一状态栏信息（支持百分比进度）
        /// </summary>
        /// <param name="message">状态消息</param>
        /// <param name="percentage">进度百分比 (0-100)</param>
        public void UpdateStatus(string message, double percentage)
        {
            SafeExecute(() =>
            {
                StatusText = message ?? "就绪";
                ProgressPercentage = Math.Max(0, Math.Min(100, percentage));
                IsProcessing = true; // 有百分比进度时显示进度条
            }, "更新统一状态栏（百分比模式）", runOnUIThread: true);
        }

        /// <summary>
        /// 重置状态栏到默认状态
        /// </summary>
        public void ResetStatus()
        {
            UpdateStatus("插件已就绪");
        }

        #endregion

        #region 剖面盒功能

        private void ActivatePathClipBox()
        {
            var currentRoute = _pathPlanningManager?.CurrentRoute;
            if (currentRoute?.Points == null || currentRoute.Points.Count == 0)
            {
                LogManager.Warning("[剖面盒] 当前没有路径，无法设置剖面盒");
                SetClipBoxState(ClipBoxFocusMode.None);
                return;
            }

            // 开启前保存当前剖面状态（包括 Box/Plane 模式）
            if (_clipBoxFocusMode == ClipBoxFocusMode.None)
            {
                _savedClipStateJson = SectionClipHelper.SaveClipState();
                LogManager.Debug("[剖面盒] 已保存开启前的剖面状态");
            }
            SetClipBoxState(ClipBoxFocusMode.Path);
            EnableClipBoxForCurrentRoute();
        }

        private void ActivateSelectionClipBox()
        {
            var document = NavisApplication.ActiveDocument;
            var selectedItems = document?.CurrentSelection?.SelectedItems?.Cast<ModelItem>().Where(item => item != null).ToList();
            if (selectedItems == null || selectedItems.Count == 0)
            {
                LogManager.Warning("[剖面盒] 当前没有选中的模型对象，无法设置剖面盒");
                SetClipBoxState(ClipBoxFocusMode.None);
                return;
            }

            // 开启前保存当前剖面状态（包括 Box/Plane 模式）
            if (_clipBoxFocusMode == ClipBoxFocusMode.None)
            {
                _savedClipStateJson = SectionClipHelper.SaveClipState();
                LogManager.Debug("[剖面盒] 已保存开启前的剖面状态");
            }
            SetClipBoxState(ClipBoxFocusMode.Selection);
            EnableClipBoxForCurrentSelection();
        }

        private void ClearActiveClipBox()
        {
            SetClipBoxState(ClipBoxFocusMode.None);
            _selectionClipBoxLockState.Clear();
            // 重建保存的剖面状态（自动识别 Box/Planes 模式），
            // 同时确保 Navisworks 剖面 UI 指示器显示。
            if (!string.IsNullOrEmpty(_savedClipStateJson))
            {
                bool reconstructed = SectionClipHelper.ReconstructClipStateWithIndicator(_savedClipStateJson);
                if (!reconstructed)
                {
                    SectionClipHelper.ClearClipBox();
                }
                _savedClipStateJson = null;
            }
            else
            {
                SectionClipHelper.ClearClipBox();
            }
            LogManager.Info("[剖面盒] 已关闭");
        }

        private void SetClipBoxState(ClipBoxFocusMode mode)
        {
            _clipBoxFocusMode = mode;
            bool pathEnabled = mode == ClipBoxFocusMode.Path;
            bool selectionEnabled = mode == ClipBoxFocusMode.Selection;

            _isUpdatingClipBoxState = true;
            try
            {
                if (_isClipBoxEnabled != pathEnabled)
                {
                    _isClipBoxEnabled = pathEnabled;
                    OnPropertyChanged(nameof(IsClipBoxEnabled));
                }

                if (_isSelectionClipBoxEnabled != selectionEnabled)
                {
                    _isSelectionClipBoxEnabled = selectionEnabled;
                    OnPropertyChanged(nameof(IsSelectionClipBoxEnabled));
                }
            }
            finally
            {
                _isUpdatingClipBoxState = false;
            }
        }

        private void OnCurrentSelectionChanged(object sender, EventArgs e)
        {
            if (_clipBoxFocusMode != ClipBoxFocusMode.Selection)
            {
                return;
            }

            if (!_selectionClipBoxLockState.ShouldRefreshOnSelectionChanged(isSelectionClipBoxMode: true))
            {
                LogManager.Info($"[剖面盒] 选择已变化，但当前剖面盒保持锁定，锁定对象数: {_selectionClipBoxLockState.LockedSelectionCount}");
                return;
            }

            LogManager.Info("[剖面盒] 选择已变化，重新聚焦到当前选择对象");
            EnableClipBoxForCurrentSelection();
        }

        /// <summary>
        /// 启用剖面盒并聚焦到当前路径
        /// </summary>
        private void EnableClipBoxForCurrentRoute()
        {
            try
            {
                var currentRoute = _pathPlanningManager?.CurrentRoute;
                if (currentRoute?.Points == null || currentRoute.Points.Count == 0)
                {
                    LogManager.Warning("[剖面盒] 当前没有路径，无法设置剖面盒");
                    SectionClipHelper.ClearClipBox();
                    SetClipBoxState(ClipBoxFocusMode.None);
                    return;
                }

                // 获取虚拟物体默认高度（米）
                double objectHeightInMeters = ConfigManager.Instance.Current.PathEditing.ObjectHeightMeters;
                
                // ========== 第1步：处理路径，计算包含虚拟物体高度的包围盒 ==========
                
                // 转换路径点，并根据路径类型调整Z值范围（包含虚拟物体高度）
                var adjustedPoints = currentRoute.Points.Select(p => new Point3D(p.X, p.Y, p.Z)).ToList();
                
                // 根据路径类型，添加包含虚拟物体高度的额外点
                if (currentRoute.PathType == PathType.Ground)
                {
                    // 地面路径：在路径点上方添加物体高度点
                    foreach (var p in currentRoute.Points)
                    {
                        adjustedPoints.Add(new Point3D(p.X, p.Y, p.Z + objectHeightInMeters));
                    }
                }
                else
                {
                    // 空中路径：在路径点下方添加物体高度点
                    foreach (var p in currentRoute.Points)
                    {
                        adjustedPoints.Add(new Point3D(p.X, p.Y, p.Z - objectHeightInMeters));
                    }
                }

                // ========== 第2步：先清除旧的剖面盒，再设置新的 ==========
                SectionClipHelper.ClearClipBox();
                
                // ========== 第3步：统一扩展（水平4米，高度2米）==========
                bool success = SectionClipHelper.SetClipBoxByPath(adjustedPoints, 
                    marginInMeters: 4.0,      // 水平方向扩展4米
                    heightMarginInMeters: 2.0 // 高度方向上下各扩展2米
                );

                if (success)
                {
                    LogManager.Info($"[剖面盒] 已启用，路径点数量: {currentRoute.Points.Count}, 各方向扩展: 2m");
                }
                else
                {
                    LogManager.Warning("[剖面盒] 设置失败");
                    SectionClipHelper.ClearClipBox();
                    SetClipBoxState(ClipBoxFocusMode.None);
                }
            }
            catch (Exception ex)
            {
                LogManager.Error($"[剖面盒] 启用失败: {ex.Message}");
                SectionClipHelper.ClearClipBox();
                SetClipBoxState(ClipBoxFocusMode.None);
            }
        }

        /// <summary>
        /// 启用剖面盒并聚焦到当前选择对象
        /// </summary>
        private void EnableClipBoxForCurrentSelection()
        {
            try
            {
                var document = NavisApplication.ActiveDocument;
                var selectedItems = document?.CurrentSelection?.SelectedItems?.Cast<ModelItem>().Where(item => item != null).ToList();
                if (selectedItems == null || selectedItems.Count == 0)
                {
                    LogManager.Warning("[剖面盒] 当前没有选中的模型对象，无法设置剖面盒");
                    SetClipBoxState(ClipBoxFocusMode.None);
                    return;
                }

                _selectionClipBoxLockState.LockSelection(selectedItems);
                SectionClipHelper.ClearClipBox();

                bool success = SectionClipHelper.SetClipBoxByModelItems(
                    selectedItems,
                    marginInMeters: 2.0,
                    heightMarginInMeters: 2.0);

                if (success)
                {
                    ViewpointHelper.FocusOnModelItems(selectedItems, ViewpointHelper.ViewpointStrategy.ModelFocus);
                    LogManager.Info($"[剖面盒] 已按当前选择对象启用，选择数量: {selectedItems.Count}");
                }
                else
                {
                    LogManager.Warning("[剖面盒] 按选择对象设置失败");
                    _selectionClipBoxLockState.Clear();
                    SectionClipHelper.ClearClipBox();
                    SetClipBoxState(ClipBoxFocusMode.None);
                }
            }
            catch (Exception ex)
            {
                LogManager.Error($"[剖面盒] 按选择对象启用失败: {ex.Message}");
                _selectionClipBoxLockState.Clear();
                SectionClipHelper.ClearClipBox();
                SetClipBoxState(ClipBoxFocusMode.None);
            }
        }

        /// <summary>
        /// 计算点列表的包围盒
        /// </summary>
        private (Point3D Center, double SizeX, double SizeY, double SizeZ) CalculatePointsBoundingBox(List<Point3D> points)
        {
            double minX = double.MaxValue, minY = double.MaxValue, minZ = double.MaxValue;
            double maxX = double.MinValue, maxY = double.MinValue, maxZ = double.MinValue;

            foreach (var p in points)
            {
                minX = Math.Min(minX, p.X);
                minY = Math.Min(minY, p.Y);
                minZ = Math.Min(minZ, p.Z);
                maxX = Math.Max(maxX, p.X);
                maxY = Math.Max(maxY, p.Y);
                maxZ = Math.Max(maxZ, p.Z);
            }

            var center = new Point3D((minX + maxX) / 2, (minY + maxY) / 2, (minZ + maxZ) / 2);
            return (center, maxX - minX, maxY - minY, maxZ - minZ);
        }

        #endregion
    }
}
