using System;
using System.IO;
using System.Linq;
using System.Reflection;
using Autodesk.Navisworks.Api;
using NavisworksTransport.Utils;
using NavisworksTransport.Utils.CoordinateSystem;

namespace NavisworksTransport.Core
{
    /// <summary>
    /// 虚拟物体管理器 - 负责创建和管理虚拟物体几何体
    /// 设计原则：
    /// 1. 虚拟物体只创建一次（创建会载入模型，开销大）
    /// 2. 不用时可以隐藏，或移动到CAD原始位置（不改变尺寸）
    /// 3. 移动位置和朝向时，只使用变换，不修改尺寸
    /// 4. 修改尺寸只在创建或尺寸参数变更时进行（会触发文档更新事件）
    /// </summary>
    public class VirtualObjectManager
    {
        private static readonly ModelAxisConvention VirtualObjectAxisConvention = ModelAxisConvention.CreateVirtualObjectAssetConvention();
        private static VirtualObjectManager _instance;
        private static readonly object _lock = new object();

        public static VirtualObjectManager Instance
        {
            get
            {
                if (_instance == null)
                {
                    lock (_lock)
                    {
                        if (_instance == null)
                        {
                            _instance = new VirtualObjectManager();
                        }
                    }
                }
                return _instance;
            }
        }

        private ModelItem _virtualObjectModelItem;
        private Model _virtualObjectModel;
        private bool _isVirtualObjectActive;
        private bool _isUpdatingVirtualObject = false;
        public bool IsUpdatingVirtualObject => _isUpdatingVirtualObject;

        private double _currentLengthMeters = 0;
        private double _currentWidthMeters = 0;
        private double _currentHeightMeters = 0;

        public ModelItem CurrentVirtualObject => _virtualObjectModelItem;
        public bool IsVirtualObjectActive => _isVirtualObjectActive;

        private VirtualObjectManager()
        {
            _isVirtualObjectActive = false;
        }

        #region 1. 创建（只执行一次，开销大）

        public ModelItem CreateVirtualObject(double lengthMeters, double widthMeters, double heightMeters)
        {
            _isUpdatingVirtualObject = true;

            try
            {
                // 检查是否已存在且尺寸相同
                if (_virtualObjectModel != null && 
                    Application.ActiveDocument.Models.IndexOf(_virtualObjectModel) >= 0 &&
                    Math.Abs(_currentLengthMeters - lengthMeters) < 0.001 &&
                    Math.Abs(_currentWidthMeters - widthMeters) < 0.001 &&
                    Math.Abs(_currentHeightMeters - heightMeters) < 0.001)
                {
                    LogManager.Info($"虚拟物体已存在且尺寸相同，直接返回");
                    _isVirtualObjectActive = true;
                    return _virtualObjectModelItem;
                }

                // 检查是否已存在但尺寸不同
                if (_virtualObjectModel != null && 
                    Application.ActiveDocument.Models.IndexOf(_virtualObjectModel) >= 0)
                {
                    LogManager.Info($"虚拟物体已存在但尺寸不同，更新尺寸");
                    UpdateVirtualObjectSize(lengthMeters, widthMeters, heightMeters);
                    _isVirtualObjectActive = true;
                    return _virtualObjectModelItem;
                }

                // 创建新的虚拟物体
                LogManager.Info($"=== 创建虚拟物体 ===");
                LogManager.Info($"目标尺寸: {lengthMeters:F2}m x {widthMeters:F2}m x {heightMeters:F2}m");

                var doc = Application.ActiveDocument;
                var unitCubePath = GetUnitCubeFilePath();
                if (string.IsNullOrEmpty(unitCubePath) || !File.Exists(unitCubePath))
                {
                    throw new FileNotFoundException($"找不到单位立方体文件: {unitCubePath}");
                }

                int modelCountBefore = doc.Models.Count;
                if (!doc.TryAppendFile(unitCubePath))
                {
                    throw new InvalidOperationException($"无法追加文件: {unitCubePath}");
                }

                int modelCountAfter = doc.Models.Count;
                if (modelCountAfter <= modelCountBefore)
                {
                    throw new InvalidOperationException("追加文件后模型数量未增加");
                }

                _virtualObjectModel = doc.Models.Last();
                _virtualObjectModelItem = _virtualObjectModel.RootItem;
                
                var geometryItem = FindFirstGeometryItem(_virtualObjectModelItem);
                if (geometryItem != null && !geometryItem.Equals(_virtualObjectModelItem))
                {
                    _virtualObjectModelItem = geometryItem;
                }

                LogVirtualObjectGeometry("[虚拟物体创建] Append后缩放前");

                _currentLengthMeters = lengthMeters;
                _currentWidthMeters = widthMeters;
                _currentHeightMeters = heightMeters;
                ScaleVirtualObject(lengthMeters, widthMeters, heightMeters);

                _isVirtualObjectActive = true;
                LogManager.Info($"虚拟物体创建成功");
                
                return _virtualObjectModelItem;
            }
            catch (Exception ex)
            {
                LogManager.Error($"创建虚拟物体失败: {ex.Message}");
                throw;
            }
            finally
            {
                _isUpdatingVirtualObject = false;
            }
        }

        #endregion

        #region 2. 显示/隐藏

        public void ShowVirtualObject(double lengthMeters, double widthMeters, double heightMeters)
        {
            if (_virtualObjectModel == null || 
                Application.ActiveDocument.Models.IndexOf(_virtualObjectModel) < 0)
            {
                CreateVirtualObject(lengthMeters, widthMeters, heightMeters);
                return;
            }

            var modelItems = new ModelItemCollection { _virtualObjectModelItem };
            Application.ActiveDocument.Models.SetHidden(modelItems, false);
            _isVirtualObjectActive = true;
            LogManager.Info("虚拟物体已显示");
        }

        public void HideVirtualObject()
        {
            if (_virtualObjectModelItem == null) return;

            try
            {
                var modelItems = new ModelItemCollection { _virtualObjectModelItem };
                Application.ActiveDocument.Models.SetHidden(modelItems, true);
                _isVirtualObjectActive = false;
                LogManager.Info("虚拟物体已隐藏");
            }
            catch (Exception ex)
            {
                LogManager.Error($"隐藏虚拟物体失败: {ex.Message}");
            }
        }

        #endregion

        #region 3. 移动位置和朝向

        public void MoveVirtualObject(Point3D position, double yawRadians)
        {
            if (_virtualObjectModelItem == null) return;

            try
            {
                var adapter = CoordinateSystemManager.Instance.CreateHostAdapter();
                var hostForward = adapter.FromCanonicalVector(new Vector3D(Math.Cos(yawRadians), Math.Sin(yawRadians), 0));
                var hostUp = adapter.FromCanonicalVector(new Vector3D(
                    HostCoordinateAdapter.CanonicalUpVector3.X,
                    HostCoordinateAdapter.CanonicalUpVector3.Y,
                    HostCoordinateAdapter.CanonicalUpVector3.Z));
                var rotation = VirtualObjectAxisConvention.CreateRotation(hostForward, hostUp);
                MoveVirtualObject(position, rotation);
                LogManager.Debug($"虚拟物体已按Canonical平面yaw应用完整姿态");
            }
            catch (Exception ex)
            {
                LogManager.Error($"移动虚拟物体失败: {ex.Message}");
            }
        }

        public void MoveVirtualObject(Point3D position, Rotation3D rotation)
        {
            if (_virtualObjectModelItem == null) return;

            try
            {
                LogVirtualObjectGeometry("[虚拟物体姿态] 应用前");
                ModelItemTransformHelper.MoveItemToPositionAndRotation(_virtualObjectModelItem, position, rotation);
                var actualBounds = _virtualObjectModelItem.BoundingBox();
                Point3D actualCenter = actualBounds?.Center ?? new Point3D(0, 0, 0);
                LogManager.Debug(
                    $"[虚拟物体姿态] 应用后中心=({actualCenter.X:F3},{actualCenter.Y:F3},{actualCenter.Z:F3}), " +
                    $"目标中心=({position.X:F3},{position.Y:F3},{position.Z:F3}), " +
                    $"偏差=({actualCenter.X - position.X:F3},{actualCenter.Y - position.Y:F3},{actualCenter.Z - position.Z:F3})");
                LogVirtualObjectGeometry("[虚拟物体姿态] 应用后");
                LogManager.Debug("虚拟物体已应用完整三维姿态");
            }
            catch (Exception ex)
            {
                LogManager.Error($"移动虚拟物体并应用完整三维姿态失败: {ex.Message}");
            }
        }

        public void ResetToCADPosition()
        {
            if (_virtualObjectModelItem == null) return;

            try
            {
                var doc = Application.ActiveDocument;
                var modelItems = new ModelItemCollection { _virtualObjectModelItem };
                doc.Models.ResetPermanentTransform(modelItems);
                LogManager.Info("虚拟物体已恢复到CAD原始位置（仅清除Item姿态，保留Model尺寸）");
            }
            catch (Exception ex)
            {
                LogManager.Error($"恢复虚拟物体失败: {ex.Message}");
            }
        }

        #endregion

        #region 4. 修改尺寸

        public void UpdateVirtualObjectSize(double lengthMeters, double widthMeters, double heightMeters)
        {
            if (_virtualObjectModel == null) return;

            _isUpdatingVirtualObject = true;

            try
            {
                _currentLengthMeters = lengthMeters;
                _currentWidthMeters = widthMeters;
                _currentHeightMeters = heightMeters;
                ScaleVirtualObject(lengthMeters, widthMeters, heightMeters);
                LogManager.Info("虚拟物体尺寸已更新（仅更新Model尺寸）");
            }
            finally
            {
                _isUpdatingVirtualObject = false;
            }
        }

        #endregion

        #region 辅助方法

        private void ScaleVirtualObject(double lengthMeters, double widthMeters, double heightMeters)
        {
            if (_virtualObjectModel == null || _virtualObjectModelItem == null) return;

            var doc = Application.ActiveDocument;
            double baseSizeMeters = 0.01;

            var currentTransform = _virtualObjectModel.Transform;
            var transformComponents = currentTransform.Factor();
            transformComponents.Scale = VirtualObjectAxisConvention.CreateScaleVector(
                lengthMeters / baseSizeMeters,
                widthMeters / baseSizeMeters,
                heightMeters / baseSizeMeters);
            Transform3D newTransform = transformComponents.Combine();
            doc.Models.SetModelUnitsAndTransform(_virtualObjectModel, _virtualObjectModel.Units, newTransform, false);

            LogVirtualObjectGeometry("[虚拟物体缩放] 完成后");
        }

        private void LogVirtualObjectGeometry(string prefix)
        {
            if (_virtualObjectModelItem == null)
            {
                return;
            }

            try
            {
                var itemBounds = _virtualObjectModelItem.BoundingBox();

                if (itemBounds != null)
                {
                    LogManager.Debug(
                        $"{prefix} Item包围盒: Min=({itemBounds.Min.X:F3},{itemBounds.Min.Y:F3},{itemBounds.Min.Z:F3}), " +
                        $"Max=({itemBounds.Max.X:F3},{itemBounds.Max.Y:F3},{itemBounds.Max.Z:F3}), " +
                        $"Center=({itemBounds.Center.X:F3},{itemBounds.Center.Y:F3},{itemBounds.Center.Z:F3})");
                }
            }
            catch (Exception ex)
            {
                LogManager.Warning($"{prefix} 记录虚拟物体几何失败: {ex.Message}");
            }
        }

        /// <summary>
        /// 清理虚拟物体（用于程序退出或切换文档时）
        /// </summary>
        public void Cleanup()
        {
            try
            {
                if (_virtualObjectModel != null)
                {
                    var doc = Application.ActiveDocument;
                    int index = doc.Models.IndexOf(_virtualObjectModel);
                    if (index >= 0)
                    {
                        doc.TryRemoveFile(index);
                    }
                }
            }
            catch (Exception ex)
            {
                LogManager.Error($"清理虚拟物体失败: {ex.Message}");
            }
            finally
            {
                _virtualObjectModel = null;
                _virtualObjectModelItem = null;
                _isVirtualObjectActive = false;
            }
        }

        private ModelItem FindFirstGeometryItem(ModelItem item)
        {
            if (item == null) return null;
            if (item.HasGeometry) return item;
            foreach (var child in item.Children)
            {
                var result = FindFirstGeometryItem(child);
                if (result != null) return result;
            }
            return item;
        }

        private string GetUnitCubeFilePath()
        {
            string pluginDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
            string[] possiblePaths = new[]
            {
                Path.Combine(pluginDir, "resources", "unit_cube.nwc"),
                Path.Combine(pluginDir, "..", "..", "resources", "unit_cube.nwc")
            };

            foreach (var path in possiblePaths)
            {
                if (File.Exists(path))
                    return path;
            }
            return possiblePaths[0];
        }

        #endregion
    }
}
