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

namespace NavisworksTransport
{
    /// <summary>
    /// 可见性管理器
    /// 负责ModelItem可见性控制的核心业务逻辑
    /// </summary>
    public static class VisibilityHelper
    {

        /// <summary>
        /// 显示所有项目
        /// </summary>
        /// <returns>操作是否成功</returns>
        public static bool ShowAllItems()
        {
            try
            {
                NavisApplication.ActiveDocument?.Models?.ResetAllHidden();
                return true;
            }
            catch (Exception ex)
            {
                LogManager.Error($"[VisibilityManager] 显示所有项目失败: {ex.Message}");
                return false;
            }
        }

        /// <summary>
        /// 仅显示指定的模型项集合，隐藏其他所有项（高性能版本）
        /// </summary>
        /// <param name="itemsToShow">要显示的模型项集合</param>
        /// <returns>操作是否成功</returns>
        public static bool IsolateSpecificItems(ModelItemCollection itemsToShow)
        {
            try
            {
                var stopwatch = System.Diagnostics.Stopwatch.StartNew();

                var document = NavisApplication.ActiveDocument;
                if (document == null || document.Models.Count == 0)
                {
                    LogManager.Warning("[VisibilityManager] 没有加载的模型");
                    return false;
                }

                if (itemsToShow == null || !itemsToShow.Any())
                {
                    LogManager.Warning("[VisibilityManager] 没有指定要显示的项目");
                    return false;
                }

                LogManager.Info($"[VisibilityManager] 开始隔离显示，共 {itemsToShow.Count} 个对象");

                // 1. 重置所有隐藏状态
                document.Models.ResetAllHidden();

                // 2. 使用 HashSet 收集需要显示的所有节点（包括祖先）
                var visibleSet = new HashSet<ModelItem>();
                foreach (ModelItem item in itemsToShow)
                {
                    var ancestors = item.AncestorsAndSelf;
                    if (ancestors != null)
                    {
                        foreach (var ancestor in ancestors)
                        {
                            visibleSet.Add(ancestor);
                        }
                    }
                }

                LogManager.Info($"[VisibilityManager] 收集祖先完成，visibleSet={visibleSet.Count}");

                // 3. 收集需要隐藏的节点（兄弟节点）
                // 优化：先收集唯一的父节点，避免重复遍历同一个Parent的Children
                var uniqueParents = new HashSet<ModelItem>();
                foreach (ModelItem visibleItem in visibleSet)
                {
                    if (visibleItem.Parent != null)
                    {
                        uniqueParents.Add(visibleItem.Parent);
                    }
                }

                LogManager.Info($"[VisibilityManager] 收集唯一父节点完成，uniqueParents={uniqueParents.Count}");

                // 然后只遍历唯一的父节点的Children
                var hiddenSet = new HashSet<ModelItem>();
                foreach (var parent in uniqueParents)
                {
                    foreach (var sibling in parent.Children)
                    {
                        hiddenSet.Add(sibling);
                    }
                }

                LogManager.Info($"[VisibilityManager] 收集兄弟完成，hiddenSet={hiddenSet.Count}");

                // 4. 从隐藏集合中移除可见项（HashSet.Remove 是 O(1)）
                hiddenSet.ExceptWith(visibleSet);

                LogManager.Info($"[VisibilityManager] 排除可见项后，hiddenSet={hiddenSet.Count}");

                // 5. 执行隐藏操作
                if (hiddenSet.Count > 0)
                {
                    var hiddenCollection = new ModelItemCollection();
                    foreach (var item in hiddenSet)
                    {
                        hiddenCollection.Add(item);
                    }
                    document.Models.SetHidden(hiddenCollection, true);
                }

                stopwatch.Stop();
                LogManager.Info($"[VisibilityManager] 隔离显示完成，耗时 {stopwatch.ElapsedMilliseconds}ms");

                return true;
            }
            catch (Exception ex)
            {
                LogManager.Error($"[VisibilityManager] 隔离显示失败: {ex.Message}");
                return false;
            }
        }

        /// <summary>
        /// 设置指定模型项集合的可见性
        /// </summary>
        /// <param name="items">要设置的模型项集合</param>
        /// <param name="isHidden">是否隐藏（true=隐藏，false=显示）</param>
        /// <returns>操作是否成功</returns>
        public static bool SetItemsVisibility(ModelItemCollection items, bool isHidden)
        {
            try
            {
                var document = NavisApplication.ActiveDocument;
                if (document == null || document.Models.Count == 0)
                {
                    LogManager.Warning("[VisibilityManager] 没有加载的模型");
                    return false;
                }

                if (items == null || !items.Any())
                {
                    LogManager.Warning("[VisibilityManager] 没有指定要操作的项目");
                    return false;
                }

                // 设置可见性状态
                document.Models.SetHidden(items, isHidden);

                var action = isHidden ? "隐藏" : "显示";
                LogManager.Info($"[VisibilityManager] 已{action} {items.Count} 个模型项");
                return true;
            }
            catch (Exception ex)
            {
                var action = isHidden ? "隐藏" : "显示";
                LogManager.Error($"[VisibilityManager] {action}指定项目失败: {ex.Message}");
                return false;
            }
        }

        // 可见性状态栈（支持嵌套隔离）
        private static readonly Stack<Dictionary<ModelItem, bool>> _visibilityStateStack = new Stack<Dictionary<ModelItem, bool>>();

        /// <summary>
        /// 进入隔离模式：保存当前可见性状态，并隔离显示指定项目
        /// </summary>
        /// <param name="itemsToShow">要显示的项目集合</param>
        /// <returns>操作是否成功</returns>
        public static bool EnterIsolation(ModelItemCollection itemsToShow)
        {
            try
            {
                var document = NavisApplication.ActiveDocument;
                if (document == null)
                {
                    LogManager.Warning("[VisibilityHelper] 进入隔离模式失败：没有活动文档");
                    return false;
                }

                // 保存当前状态到栈
                var state = SaveVisibilityStateInternal(document);
                _visibilityStateStack.Push(state);

                // 执行隔离显示
                bool success = IsolateSpecificItems(itemsToShow);
                if (!success)
                {
                    // 隔离失败，弹出状态
                    _visibilityStateStack.Pop();
                    return false;
                }

                LogManager.Info($"[VisibilityHelper] 进入隔离模式，当前栈深度: {_visibilityStateStack.Count}");
                return true;
            }
            catch (Exception ex)
            {
                LogManager.Error($"[VisibilityHelper] 进入隔离模式失败: {ex.Message}");
                return false;
            }
        }

        /// <summary>
        /// 退出隔离模式：恢复之前保存的可见性状态
        /// </summary>
        /// <returns>操作是否成功</returns>
        public static bool ExitIsolation()
        {
            try
            {
                if (_visibilityStateStack.Count == 0)
                {
                    LogManager.Warning("[VisibilityHelper] 退出隔离模式失败：没有保存的状态");
                    return false;
                }

                var document = NavisApplication.ActiveDocument;
                if (document == null)
                {
                    LogManager.Warning("[VisibilityHelper] 退出隔离模式失败：没有活动文档");
                    return false;
                }

                // 弹出并恢复状态
                var state = _visibilityStateStack.Pop();
                RestoreVisibilityStateInternal(document, state);

                LogManager.Info($"[VisibilityHelper] 退出隔离模式，当前栈深度: {_visibilityStateStack.Count}");
                return true;
            }
            catch (Exception ex)
            {
                LogManager.Error($"[VisibilityHelper] 退出隔离模式失败: {ex.Message}");
                return false;
            }
        }

        /// <summary>
        /// 【新增】应用预计算的隐藏节点列表，并保存当前状态用于后续恢复
        /// 用于优化场景：遍历和计算隐藏节点已经完成，只需直接应用
        /// </summary>
        /// <param name="itemsToHide">预计算的隐藏节点集合</param>
        /// <param name="action">在应用隐藏后执行的操作</param>
        /// <param name="operationName">操作名称（用于日志）</param>
        /// <returns>操作结果</returns>
        public static T ExecuteWithPrecomputedHiddenItems<T>(ModelItemCollection itemsToHide, Func<T> action, string operationName = "预计算隐藏")
        {
            var document = NavisApplication.ActiveDocument;
            if (document == null)
            {
                LogManager.Warning($"[VisibilityHelper] {operationName}失败：没有活动文档");
                return default(T);
            }

            // 保存可见性状态
            var savedState = SaveVisibilityStateInternal(document);

            // 保存剖面盒状态（Navisworks ExportToNwd 会内部关闭剖分）
            bool clipWasEnabled = SectionClipHelper.IsClipBoxEnabled;
            string savedClipJson = SectionClipHelper.SaveClipState();

            try
            {
                // 1. 全部显示
                document.Models.ResetAllHidden();

                // 2. 直接应用预计算的隐藏节点
                if (itemsToHide != null && itemsToHide.Count > 0)
                {
                    document.Models.SetHidden(itemsToHide, true);
                    LogManager.Debug($"[VisibilityHelper] {operationName}：应用 {itemsToHide.Count} 个预计算隐藏节点");
                }

                // 3. 执行操作
                return action.Invoke();
            }
            finally
            {
                // 4. 恢复可见性状态
                RestoreVisibilityStateInternal(document, savedState);

                // 5. 恢复剖面盒（Navisworks 导出时会关闭）
                if (clipWasEnabled && !SectionClipHelper.IsClipBoxEnabled && !string.IsNullOrEmpty(savedClipJson))
                {
                    SectionClipHelper.RestoreClipState(savedClipJson);
                }
            }
        }

        /// <summary>
        /// 【新增】应用预计算的隐藏节点列表（无返回值版本）
        /// </summary>
        public static void ExecuteWithPrecomputedHiddenItems(ModelItemCollection itemsToHide, Action action, string operationName = "预计算隐藏")
        {
            ExecuteWithPrecomputedHiddenItems<object>(itemsToHide, () =>
            {
                action?.Invoke();
                return null;
            }, operationName);
        }

        /// <summary>
        /// 在隔离模式下执行操作，自动恢复可见性
        /// </summary>
        /// <param name="itemsToShow">要显示的项目集合</param>
        /// <param name="action">要执行的操作</param>
        public static void ExecuteInIsolation(ModelItemCollection itemsToShow, Action action)
        {
            bool entered = EnterIsolation(itemsToShow);
            try
            {
                action?.Invoke();
            }
            finally
            {
                if (entered)
                {
                    ExitIsolation();
                }
            }
        }

        /// <summary>
        /// 在隔离模式下执行操作（带返回值），自动恢复可见性
        /// </summary>
        /// <typeparam name="T">返回值类型</typeparam>
        /// <param name="itemsToShow">要显示的项目集合</param>
        /// <param name="func">要执行的函数</param>
        /// <returns>函数执行结果</returns>
        public static T ExecuteInIsolation<T>(ModelItemCollection itemsToShow, Func<T> func)
        {
            bool entered = EnterIsolation(itemsToShow);
            try
            {
                return func.Invoke();
            }
            finally
            {
                if (entered)
                {
                    ExitIsolation();
                }
            }
        }

        /// <summary>
        /// 获取当前隔离栈深度（用于调试）
        /// </summary>
        public static int IsolationDepth => _visibilityStateStack.Count;

        /// <summary>
        /// 清空所有保存的可见性状态（谨慎使用）
        /// </summary>
        public static void ClearIsolationStack()
        {
            _visibilityStateStack.Clear();
            LogManager.Warning("[VisibilityHelper] 已清空所有隔离状态");
        }

        #region 内部实现

        /// <summary>
        /// 保存当前可见性状态（内部实现）
        /// </summary>
        private static Dictionary<ModelItem, bool> SaveVisibilityStateInternal(Document document)
        {
            var visibilityState = new Dictionary<ModelItem, bool>();

            try
            {
                if (document?.Models == null)
                    return visibilityState;

                foreach (Model model in document.Models)
                {
                    if (model.RootItem?.Children == null)
                        continue;

                    foreach (ModelItem topLevelItem in model.RootItem.Children)
                    {
                        try
                        {
                            visibilityState[topLevelItem] = !topLevelItem.IsHidden;
                        }
                        catch
                        {
                            visibilityState[topLevelItem] = true;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                LogManager.Error($"[VisibilityHelper] 保存可见性状态失败: {ex.Message}");
            }

            return visibilityState;
        }

        /// <summary>
        /// 恢复可见性状态（内部实现）
        /// </summary>
        private static void RestoreVisibilityStateInternal(Document document, Dictionary<ModelItem, bool> visibilityState)
        {
            try
            {
                if (document?.Models == null)
                    return;

                if (visibilityState == null || visibilityState.Count == 0)
                {
                    document.Models.ResetAllHidden();
                    return;
                }

                var itemsToHide = new ModelItemCollection();

                foreach (var kvp in visibilityState)
                {
                    try
                    {
                        if (!kvp.Value) // 原来是隐藏的
                        {
                            itemsToHide.Add(kvp.Key);
                        }
                    }
                    catch { }
                }

                document.Models.ResetAllHidden();

                if (itemsToHide.Count > 0)
                {
                    document.Models.SetHidden(itemsToHide, true);
                }
            }
            catch (Exception ex)
            {
                LogManager.Error($"[VisibilityHelper] 恢复可见性状态失败: {ex.Message}");
                try
                {
                    document.Models.ResetAllHidden();
                }
                catch { }
            }
        }

        #endregion
    }
}