using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using NavisworksTransport.Core;

namespace NavisworksTransport.Commands
{
    /// <summary>
    /// 命令管理器
    /// 提供命令注册、创建、执行的统一管理，与UIStateManager深度集成
    /// </summary>
    public class CommandManager
    {
        #region 字段和属性

        private static CommandManager _instance;
        private static readonly object _instanceLock = new object();

        private readonly ConcurrentDictionary<string, Func<IPathPlanningCommand>> _commandFactories;
        private readonly CommandExecutor _commandExecutor;
        private readonly UIStateManager _uiStateManager;
        private volatile bool _isDisposed = false;

        /// <summary>
        /// 获取CommandManager的单例实例
        /// </summary>
        public static CommandManager Instance
        {
            get
            {
                if (_instance == null)
                {
                    lock (_instanceLock)
                    {
                        if (_instance == null)
                        {
                            _instance = new CommandManager();
                        }
                    }
                }
                return _instance;
            }
        }

        /// <summary>
        /// 命令执行器
        /// </summary>
        public CommandExecutor Executor => _commandExecutor;

        #endregion

        #region 事件

        /// <summary>
        /// 命令注册事件
        /// </summary>
        public event EventHandler<CommandRegistrationEventArgs> CommandRegistered;

        /// <summary>
        /// 命令执行开始事件
        /// </summary>
        public event EventHandler<CommandExecutionEventArgs> CommandExecutionStarted;

        /// <summary>
        /// 命令执行完成事件
        /// </summary>
        public event EventHandler<CommandCompletedEventArgs> CommandExecutionCompleted;

        #endregion

        #region 构造函数

        private CommandManager()
        {
            _commandFactories = new ConcurrentDictionary<string, Func<IPathPlanningCommand>>();
            _commandExecutor = CommandExecutor.Instance;
            _uiStateManager = UIStateManager.Instance;

            // 订阅CommandExecutor事件
            _commandExecutor.CommandStarted += OnCommandStarted;
            _commandExecutor.CommandCompleted += OnCommandCompleted;

            // 注册默认命令
            RegisterDefaultCommands();

            LogManager.Info("CommandManager 初始化完成");
        }

        #endregion

        #region 命令注册

        /// <summary>
        /// 注册命令工厂
        /// </summary>
        public void RegisterCommand<T>(string commandKey, Func<T> factory) where T : IPathPlanningCommand
        {
            if (string.IsNullOrEmpty(commandKey))
                throw new ArgumentException("命令键不能为空", nameof(commandKey));

            if (factory == null)
                throw new ArgumentNullException(nameof(factory));

            _commandFactories.AddOrUpdate(commandKey, () => factory(), (key, oldFactory) => () => factory());
            
            OnCommandRegistered(commandKey, typeof(T));
            LogManager.Info($"命令已注册: {commandKey} -> {typeof(T).Name}");
        }

        /// <summary>
        /// 注册命令工厂（带参数）
        /// </summary>
        public void RegisterCommand<T>(string commandKey, Func<object[], T> factory) where T : IPathPlanningCommand
        {
            if (string.IsNullOrEmpty(commandKey))
                throw new ArgumentException("命令键不能为空", nameof(commandKey));

            if (factory == null)
                throw new ArgumentNullException(nameof(factory));

            // 存储一个包装函数，在创建时会需要参数
            _commandFactories.AddOrUpdate(commandKey, 
                () => throw new InvalidOperationException($"命令 {commandKey} 需要参数，请使用 CreateCommand(string, params object[]) 方法"),
                (key, oldFactory) => () => throw new InvalidOperationException($"命令 {commandKey} 需要参数，请使用 CreateCommand(string, params object[]) 方法"));

            // 单独存储参数化工厂
            _parameterizedFactories.AddOrUpdate(commandKey, factory, (key, oldFactory) => factory);
            
            OnCommandRegistered(commandKey, typeof(T));
            LogManager.Info($"参数化命令已注册: {commandKey} -> {typeof(T).Name}");
        }

        private readonly ConcurrentDictionary<string, Delegate> _parameterizedFactories = new ConcurrentDictionary<string, Delegate>();

        /// <summary>
        /// 注册默认命令
        /// </summary>
        private void RegisterDefaultCommands()
        {
            // 注册基本路径规划命令 - 暂时移除，避免构造函数参数问题
            // RegisterCommand("SelectChannels", () => new SelectChannelsCommand());
            // RegisterCommand("CreatePathRoute", () => new CreatePathRouteCommand());

            // 注册自动路径规划命令
            RegisterCommand("AutoPathPlanning", (object[] args) =>
            {
                if (args.Length < 2)
                    throw new ArgumentException("AutoPathPlanning 需要至少起点和终点参数");
                
                var startPoint = args[0] as Autodesk.Navisworks.Api.Point3D;
                var endPoint = args[1] as Autodesk.Navisworks.Api.Point3D;
                
                if (startPoint == null || endPoint == null)
                    throw new ArgumentException("起点和终点必须是 Point3D 类型");
                
                var parameters = new AutoPathPlanningParameters
                {
                    StartPoint = startPoint,
                    EndPoint = endPoint,
                    ObjectWidthMeters = args.Length > 2 && args[2] is double v ? v : 1.0,
                    SafetyMarginMeters = args.Length > 3 && args[3] is double v1 ? v1 : 0.5,
                    GridSizeMeters = args.Length > 4 && args[4] is double v2 ? v2 : -1,
                    PathName = args.Length > 5 ? args[5]?.ToString() : null,
                    AutoDrawVisualization = args.Length <= 6 || !(args[6] is bool v3) || v3
                };
                
                return new AutoPathPlanningCommand(parameters);
            });
            
            // 注册快捷自动路径规划命令
            RegisterCommand("AutoPathPlanningQuick", (object[] args) =>
            {
                if (args.Length < 2)
                    throw new ArgumentException("AutoPathPlanningQuick 需要至少起点和终点参数");
                
                var startPoint = args[0] as Autodesk.Navisworks.Api.Point3D;
                var endPoint = args[1] as Autodesk.Navisworks.Api.Point3D;
                
                if (startPoint == null || endPoint == null)
                    throw new ArgumentException("起点和终点必须是 Point3D 类型");
                
                var objectSize = args.Length > 2 && args[2] is double v ? v : 1.0;
                var pathName = args.Length > 3 ? args[3]?.ToString() : null;
                
                return AutoPathPlanningCommand.CreateQuick(startPoint, endPoint, objectSize, pathName);
            });

            // 注册模拟路径规划命令（保留用于测试）- 暂时注释掉避免类型推断问题
            // RegisterCommand("MockAutoPathPlanning", (object[] args) => { return null; });

            // 注册新的业务Commands
            RegisterNewBusinessCommands();
        }

        /// <summary>
        /// 注册新的业务Commands
        /// </summary>
        private void RegisterNewBusinessCommands()
        {
            LogManager.Info("开始注册新的业务Commands");

            // 1. 注册设置物流属性命令
            RegisterCommand("SetLogisticsAttribute", (object[] args) =>
            {
                if (args.Length < 2)
                    throw new ArgumentException("SetLogisticsAttribute 需要目标模型项和元素类型参数");
                
                var targetItems = args[0] as Autodesk.Navisworks.Api.ModelItemCollection;
                var elementType = args[1];
                
                if (targetItems == null)
                    throw new ArgumentException("第一个参数必须是 ModelItemCollection 类型");
                
                if (!Enum.TryParse<CategoryAttributeManager.LogisticsElementType>(elementType.ToString(), out var logisticsType))
                    throw new ArgumentException("第二个参数必须是有效的 LogisticsElementType");
                
                var parameters = new SetLogisticsAttributeParameters
                {
                    TargetItems = targetItems,
                    ElementType = logisticsType,
                    IsTraversable = args.Length > 2 && args[2] is bool ? (bool?)args[2] : null,
                    OverwriteExisting = args.Length <= 3 || !(args[3] is bool v) || v
                };
                
                return new SetLogisticsAttributeCommand(parameters);
            });

            // 2. 注册删除路径命令
            RegisterCommand("DeletePath", (object[] args) =>
            {
                var parameters = new DeletePathParameters();
                
                if (args.Length > 0)
                {
                    if (args[0] is PathRoute route)
                    {
                        parameters.PathsToDelete.Add(route);
                    }
                    else if (args[0] is string pathId)
                    {
                        parameters.PathIds.Add(pathId);
                    }
                    else if (args[0] is bool deleteAll && deleteAll)
                    {
                        parameters.DeleteAll = true;
                    }
                }
                
                parameters.CreateBackup = args.Length <= 1 || !(args[1] is bool v) || v;
                parameters.ForceDelete = args.Length > 2 && args[2] is bool v1 && v1;
                
                return new DeletePathCommand(parameters);
            });

            // 3. 注册导入路径命令
            RegisterCommand("ImportPath", (object[] args) =>
            {
                if (args.Length < 1)
                    throw new ArgumentException("ImportPath 需要文件路径参数");
                
                var filePath = args[0]?.ToString();
                if (string.IsNullOrEmpty(filePath))
                    throw new ArgumentException("文件路径不能为空");
                
                var parameters = new ImportPathParameters
                {
                    FilePath = filePath,
                    ImportFormat = args.Length > 1 && args[1] is ExportFormat format ? format : ExportFormat.Xml,
                    MergeWithExisting = args.Length <= 2 || !(args[2] is bool v) || v,
                    CreateBackup = args.Length <= 3 || !(args[3] is bool v1) || v1
                };
                
                return new ImportPathCommand(parameters);
            });

            // 4. 注册导出路径命令
            RegisterCommand("ExportPath", (object[] args) =>
            {
                if (args.Length < 1)
                    throw new ArgumentException("ExportPath 需要输出文件路径参数");
                
                var outputPath = args[0]?.ToString();
                if (string.IsNullOrEmpty(outputPath))
                    throw new ArgumentException("输出文件路径不能为空");
                
                var parameters = new ExportPathParameters
                {
                    OutputFilePath = outputPath,
                    ExportAll = args.Length <= 1 || !(args[1] is bool v) || v,
                    ExportFormat = args.Length > 2 && args[2] is ExportFormat format ? format : ExportFormat.Xml,
                    OverwriteExisting = args.Length > 3 && args[3] is bool v1 && v1
                };
                
                return new ExportPathCommand(parameters);
            });

            // 5. 注册启动动画命令（原第6项）
            RegisterCommand("StartAnimation", (object[] args) =>
            {
                if (args.Length < 1 || !(args[0] is PathRoute route))
                    throw new ArgumentException("StartAnimation 需要 PathRoute 参数");

                var parameters = new StartAnimationParameters
                {
                    TargetRoute = route,
                    AnimationSpeed = args.Length > 1 && args[1] is double v ? v : 1.0,
                    Loop = args.Length > 2 && args[2] is bool v1 && v1,
                    AutoStart = args.Length <= 3 || !(args[3] is bool v2) || v2
                };

                return new StartAnimationCommand(parameters);
            });

            LogManager.Info("新的业务Commands注册完成");
        }

        #endregion

        #region 命令创建和执行

        /// <summary>
        /// 创建命令实例
        /// </summary>
        public IPathPlanningCommand CreateCommand(string commandKey)
        {
            if (!_commandFactories.TryGetValue(commandKey, out var factory))
            {
                throw new ArgumentException($"未注册的命令: {commandKey}");
            }

            try
            {
                return factory();
            }
            catch (Exception ex)
            {
                LogManager.Error($"创建命令失败: {commandKey}", ex);
                throw new InvalidOperationException($"创建命令失败: {commandKey}", ex);
            }
        }

        /// <summary>
        /// 创建命令实例（带参数）
        /// </summary>
        public IPathPlanningCommand CreateCommand(string commandKey, params object[] parameters)
        {
            if (!_parameterizedFactories.TryGetValue(commandKey, out var factory))
            {
                // 尝试无参数创建
                return CreateCommand(commandKey);
            }

            try
            {
                return (IPathPlanningCommand)factory.DynamicInvoke(new object[] { parameters });
            }
            catch (Exception ex)
            {
                LogManager.Error($"创建参数化命令失败: {commandKey}", ex);
                throw new InvalidOperationException($"创建参数化命令失败: {commandKey}", ex);
            }
        }

        /// <summary>
        /// 执行命令（异步）
        /// </summary>
        public async Task<PathPlanningResult> ExecuteCommandAsync(string commandKey, CancellationToken cancellationToken = default)
        {
            try
            {
                var command = CreateCommand(commandKey);
                return await _commandExecutor.ExecuteAsync(command, cancellationToken);
            }
            catch (Exception ex)
            {
                LogManager.Error($"执行命令失败: {commandKey}", ex);
                return PathPlanningResult.Failure($"执行命令失败: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 执行命令（带参数，异步）
        /// </summary>
        public async Task<PathPlanningResult> ExecuteCommandAsync(string commandKey, object[] parameters, CancellationToken cancellationToken = default)
        {
            try
            {
                var command = CreateCommand(commandKey, parameters);
                return await _commandExecutor.ExecuteAsync(command, cancellationToken);
            }
            catch (Exception ex)
            {
                LogManager.Error($"执行参数化命令失败: {commandKey}", ex);
                return PathPlanningResult.Failure($"执行参数化命令失败: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 将命令加入队列执行
        /// </summary>
        public Task<PathPlanningResult> EnqueueCommandAsync(string commandKey, 
                                                          CommandPriority priority = CommandPriority.Normal,
                                                          CancellationToken cancellationToken = default)
        {
            try
            {
                var command = CreateCommand(commandKey);
                return _commandExecutor.EnqueueAsync(command, priority, cancellationToken);
            }
            catch (Exception ex)
            {
                LogManager.Error($"将命令加入队列失败: {commandKey}", ex);
                return Task.FromResult(PathPlanningResult.Failure($"将命令加入队列失败: {ex.Message}", ex));
            }
        }

        /// <summary>
        /// 将命令加入队列执行（带参数）
        /// </summary>
        public Task<PathPlanningResult> EnqueueCommandAsync(string commandKey, 
                                                          object[] parameters,
                                                          CommandPriority priority = CommandPriority.Normal,
                                                          CancellationToken cancellationToken = default)
        {
            try
            {
                var command = CreateCommand(commandKey, parameters);
                return _commandExecutor.EnqueueAsync(command, priority, cancellationToken);
            }
            catch (Exception ex)
            {
                LogManager.Error($"将参数化命令加入队列失败: {commandKey}", ex);
                return Task.FromResult(PathPlanningResult.Failure($"将参数化命令加入队列失败: {ex.Message}", ex));
            }
        }

        #endregion

        #region 管理功能

        /// <summary>
        /// 获取已注册的命令列表
        /// </summary>
        public IEnumerable<string> GetRegisteredCommands()
        {
            return _commandFactories.Keys.ToArray();
        }

        /// <summary>
        /// 检查命令是否已注册
        /// </summary>
        public bool IsCommandRegistered(string commandKey)
        {
            return _commandFactories.ContainsKey(commandKey);
        }

        /// <summary>
        /// 取消注册命令
        /// </summary>
        public bool UnregisterCommand(string commandKey)
        {
            var removed = _commandFactories.TryRemove(commandKey, out _);
            _parameterizedFactories.TryRemove(commandKey, out _);
            
            if (removed)
            {
                LogManager.Info($"命令已取消注册: {commandKey}");
            }
            
            return removed;
        }

        /// <summary>
        /// 获取运行状态统计
        /// </summary>
        public CommandManagerStatus GetStatus()
        {
            return new CommandManagerStatus
            {
                RegisteredCommandCount = _commandFactories.Count,
                RunningCommandCount = _commandExecutor.RunningCommandCount,
                QueuedCommandCount = _commandExecutor.QueuedCommandCount,
                RegisteredCommands = GetRegisteredCommands().ToArray(),
                RunningCommands = _commandExecutor.GetRunningCommands().ToArray()
            };
        }

        #endregion

        #region 事件处理

        private void OnCommandStarted(object sender, CommandExecutionEventArgs e)
        {
            // 使用UIStateManager安全地更新UI
            _uiStateManager.QueueUIUpdate(() =>
            {
                CommandExecutionStarted?.Invoke(this, e);
            }, UIUpdatePriority.Normal);
        }

        private void OnCommandCompleted(object sender, CommandCompletedEventArgs e)
        {
            // 使用UIStateManager安全地更新UI
            _uiStateManager.QueueUIUpdate(() =>
            {
                CommandExecutionCompleted?.Invoke(this, e);
            }, UIUpdatePriority.Normal);
        }

        private void OnCommandRegistered(string commandKey, Type commandType)
        {
            try
            {
                CommandRegistered?.Invoke(this, new CommandRegistrationEventArgs(commandKey, commandType));
            }
            catch (Exception ex)
            {
                LogManager.Error("触发命令注册事件时出现异常", ex);
            }
        }

        #endregion

        #region 资源清理

        /// <summary>
        /// 释放资源
        /// </summary>
        public void Dispose()
        {
            if (_isDisposed) return;

            _isDisposed = true;

            // 取消订阅事件
            _commandExecutor.CommandStarted -= OnCommandStarted;
            _commandExecutor.CommandCompleted -= OnCommandCompleted;

            // 释放CommandExecutor
            _commandExecutor?.Dispose();

            LogManager.Info("CommandManager 已释放");
        }

        #endregion
    }

    #region 辅助类

    /// <summary>
    /// 命令管理器状态
    /// </summary>
    public class CommandManagerStatus
    {
        public int RegisteredCommandCount { get; set; }
        public int RunningCommandCount { get; set; }
        public int QueuedCommandCount { get; set; }
        public string[] RegisteredCommands { get; set; }
        public CommandInfo[] RunningCommands { get; set; }
    }

    /// <summary>
    /// 命令注册事件参数
    /// </summary>
    public class CommandRegistrationEventArgs : EventArgs
    {
        public string CommandKey { get; }
        public Type CommandType { get; }

        public CommandRegistrationEventArgs(string commandKey, Type commandType)
        {
            CommandKey = commandKey;
            CommandType = commandType;
        }
    }

    #endregion
}