namespace NavisworksTransport.UnitTests.Commands
{
    /// <summary>
    /// CommandBase抽象类的纯逻辑测试
    /// 通过创建测试实现类来测试基础功能，不依赖Navisworks环境
    /// </summary>
    [TestClass]
    public class CommandBaseTests
    {
        private TestCommand _testCommand;

        [TestInitialize]
        public void SetUp()
        {
            _testCommand = new TestCommand();
        }

        [TestCleanup]
        public void TearDown()
        {
            _testCommand?.Cancel();
        }

        #region 构造函数测试

        [TestMethod]
        public void Constructor_Default_SetsCorrectDefaults()
        {
            // Arrange & Act
            var command = new TestCommand();

            // Assert
            Assert.IsNotNull(command.CommandId, "CommandId不应该为空");
            Assert.IsTrue(Guid.TryParse(command.CommandId, out _), "CommandId应该是有效的GUID");
            Assert.AreEqual("TestCommand", command.DisplayName, "DisplayName应该默认为类名");
            Assert.AreEqual("路径规划命令", command.Description, "Description应该有默认值");
            Assert.AreEqual(CommandExecutionStatus.NotStarted, command.Status, "初始状态应该为NotStarted");
            Assert.AreEqual(0, command.Progress, "初始进度应该为0");
        }

        [TestMethod]
        public void Constructor_WithParameters_SetsCorrectValues()
        {
            // Arrange
            string expectedCommandId = "test-command-123";
            string expectedDisplayName = "测试命令";
            string expectedDescription = "这是一个测试命令";

            // Act
            var command = new TestCommand(expectedCommandId, expectedDisplayName, expectedDescription);

            // Assert
            Assert.AreEqual(expectedCommandId, command.CommandId, "CommandId应该设置为指定值");
            Assert.AreEqual(expectedDisplayName, command.DisplayName, "DisplayName应该设置为指定值");
            Assert.AreEqual(expectedDescription, command.Description, "Description应该设置为指定值");
        }

        [TestMethod]
        public void Constructor_WithNullParameters_SetsDefaults()
        {
            // Arrange & Act
            var command = new TestCommand(null, null, null);

            // Assert
            Assert.IsNotNull(command.CommandId, "CommandId不应该为空");
            Assert.IsTrue(Guid.TryParse(command.CommandId, out _), "CommandId应该是有效的GUID");
            Assert.AreEqual("TestCommand", command.DisplayName, "DisplayName应该默认为类名");
            Assert.AreEqual("路径规划命令", command.Description, "Description应该有默认值");
        }

        #endregion

        #region 状态管理测试

        [TestMethod]
        public void Status_MultipleThreadsAccess_ThreadSafe()
        {
            // Arrange
            var command = new TestCommand();
            var exceptions = new List<Exception>();
            var tasks = new List<Task>();

            // Act - 多线程并发访问Status
            for (int i = 0; i < 10; i++)
            {
                tasks.Add(Task.Run(() =>
                {
                    try
                    {
                        for (int j = 0; j < 100; j++)
                        {
                            var status = command.Status; // 读取状态
                        }
                    }
                    catch (Exception ex)
                    {
                        lock (exceptions)
                        {
                            exceptions.Add(ex);
                        }
                    }
                }));
            }

            Task.WaitAll(tasks.ToArray());

            // Assert
            Assert.AreEqual(0, exceptions.Count, "多线程访问Status不应该抛出异常");
        }

        [TestMethod]
        public void Progress_MultipleThreadsAccess_ThreadSafe()
        {
            // Arrange
            var command = new TestCommand();
            var exceptions = new List<Exception>();
            var tasks = new List<Task>();

            // Act - 多线程并发访问Progress
            for (int i = 0; i < 10; i++)
            {
                tasks.Add(Task.Run(() =>
                {
                    try
                    {
                        for (int j = 0; j < 100; j++)
                        {
                            var progress = command.Progress; // 读取进度
                        }
                    }
                    catch (Exception ex)
                    {
                        lock (exceptions)
                        {
                            exceptions.Add(ex);
                        }
                    }
                }));
            }

            Task.WaitAll(tasks.ToArray());

            // Assert
            Assert.AreEqual(0, exceptions.Count, "多线程访问Progress不应该抛出异常");
        }

        #endregion

        #region 事件测试

        [TestMethod]
        public void StatusChanged_EventRaised_WhenStatusChanges()
        {
            // Arrange
            var command = new TestCommand();
            CommandStatusChangedEventArgs receivedEventArgs = null;
            command.StatusChanged += (sender, args) => receivedEventArgs = args;

            // Act
            command.SimulateStatusChangeEvent(CommandExecutionStatus.NotStarted, CommandExecutionStatus.Executing);

            // Assert
            Assert.IsNotNull(receivedEventArgs, "StatusChanged事件应该被触发");
            Assert.AreEqual(CommandExecutionStatus.NotStarted, receivedEventArgs.OldStatus, "旧状态应该正确");
            Assert.AreEqual(CommandExecutionStatus.Executing, receivedEventArgs.NewStatus, "新状态应该正确");
        }

        [TestMethod]
        public void ProgressChanged_EventRaised_WhenProgressChanges()
        {
            // Arrange
            var command = new TestCommand();
            CommandProgressChangedEventArgs receivedEventArgs = null;
            command.ProgressChanged += (sender, args) => receivedEventArgs = args;

            // Act
            command.SimulateProgressChange(50, "进度50%");

            // Assert
            Assert.IsNotNull(receivedEventArgs, "ProgressChanged事件应该被触发");
            Assert.AreEqual(50, receivedEventArgs.Progress, "进度值应该正确");
            Assert.AreEqual("进度50%", receivedEventArgs.StatusMessage, "状态消息应该正确");
        }

        #endregion

        #region 执行测试

        [TestMethod]
        public async Task ExecuteAsync_Success_ReturnsSuccessResult()
        {
            // Arrange
            var command = new TestCommand();
            command.SetShouldSucceed(true);

            // Act
            var result = await command.ExecuteAsync();

            // Assert
            Assert.IsTrue(result.IsSuccess, "执行应该成功");
            Assert.AreEqual(CommandExecutionStatus.Completed, command.Status, "状态应该为Completed");
            Assert.AreEqual(100, command.Progress, "进度应该为100");
        }

        [TestMethod]
        public async Task ExecuteAsync_Failure_ReturnsFailureResult()
        {
            // Arrange
            var command = new TestCommand();
            command.SetShouldSucceed(false);

            // Act
            var result = await command.ExecuteAsync();

            // Assert
            Assert.IsFalse(result.IsSuccess, "执行应该失败");
            Assert.AreEqual(CommandExecutionStatus.Failed, command.Status, "状态应该为Failed");
        }

        [TestMethod]
        public async Task ExecuteAsync_ValidationFailure_ReturnsValidationFailure()
        {
            // Arrange
            var command = new TestCommand();
            command.SetValidationShouldFail(true);

            // Act
            var result = await command.ExecuteAsync();

            // Assert
            Assert.IsFalse(result.IsSuccess, "执行应该失败");
            Assert.AreEqual(CommandExecutionStatus.Failed, command.Status, "状态应该为Failed");
            Assert.IsTrue(result.ErrorMessage.Contains("验证失败"), "错误消息应该包含验证失败信息");
        }

        [TestMethod]
        public async Task ExecuteAsync_CancellationRequested_ReturnsCancelledResult()
        {
            // Arrange
            var command = new TestCommand();
            command.SetExecutionDelay(TimeSpan.FromSeconds(2)); // 设置较长的执行时间
            var cts = new CancellationTokenSource();

            // Act
            var executeTask = command.ExecuteAsync(cts.Token);
            cts.CancelAfter(100); // 100ms后取消
            var result = await executeTask;

            // Assert
            Assert.IsFalse(result.IsSuccess, "执行应该失败");
            Assert.AreEqual(CommandExecutionStatus.Cancelled, command.Status, "状态应该为Cancelled");
            Assert.IsTrue(result.ErrorMessage.Contains("取消"), "错误消息应该包含取消信息");
        }

        [TestMethod]
        public async Task ExecuteAsync_AlreadyExecuting_ReturnsFailure()
        {
            // Arrange
            var command = new TestCommand();
            command.SetExecutionDelay(TimeSpan.FromSeconds(1));

            // Act
            var task1 = command.ExecuteAsync();
            await Task.Delay(50); // 确保第一个任务开始执行
            var result2 = await command.ExecuteAsync(); // 尝试重复执行

            // Assert
            Assert.IsFalse(result2.IsSuccess, "重复执行应该失败");
            Assert.IsTrue(result2.ErrorMessage.Contains("正在执行中"), "错误消息应该指示命令正在执行");

            // 等待第一个任务完成
            await task1;
        }

        [TestMethod]
        public void Cancel_WhileExecuting_CancelsExecution()
        {
            // Arrange
            var command = new TestCommand();
            command.SetExecutionDelay(TimeSpan.FromSeconds(2));

            // Act
            var executeTask = command.ExecuteAsync();
            command.Cancel(); // 取消执行

            // Assert - 由于是异步操作，我们只验证Cancel方法不抛出异常
            Assert.IsTrue(true, "Cancel方法应该能够正常调用");
        }

        #endregion

        #region CanExecute测试

        [TestMethod]
        public void CanExecute_DefaultImplementation_ReturnsSuccess()
        {
            // Arrange
            var command = new TestCommand();

            // Act
            var result = command.CanExecute();

            // Assert
            Assert.IsTrue(result.IsSuccess, "默认的CanExecute应该返回成功");
        }

        [TestMethod]
        public void CanExecute_WhileExecuting_ReturnsFailure()
        {
            // Arrange
            var command = new TestCommand();
            command.SetExecutionDelay(TimeSpan.FromSeconds(1));

            // Act
            var executeTask = command.ExecuteAsync();
            var canExecuteResult = command.CanExecute();

            // Assert
            Assert.IsFalse(canExecuteResult.IsSuccess, "执行中的命令CanExecute应该返回失败");

            // 清理
            command.Cancel();
        }

        #endregion

        #region 性能测试

        [TestMethod]
        public async Task ExecuteAsync_TracksElapsedTime()
        {
            // Arrange
            var command = new TestCommand();
            command.SetExecutionDelay(TimeSpan.FromMilliseconds(100));

            // Act
            var result = await command.ExecuteAsync();

            // Assert
            Assert.IsTrue(result.ElapsedMilliseconds >= 90, "执行时间应该被正确记录"); // 允许一些时间误差
            Assert.IsTrue(result.ElapsedMilliseconds < 500, "执行时间不应该过长");
        }

        #endregion
    }

    #region 测试用Command实现

    /// <summary>
    /// 用于测试的Command实现类
    /// </summary>
    internal class TestCommand : CommandBase
    {
        private bool _shouldSucceed = true;
        private bool _validationShouldFail = false;
        private TimeSpan _executionDelay = TimeSpan.Zero;

        public TestCommand() : base() { }

        public TestCommand(string commandId, string displayName, string description) 
            : base(commandId, displayName, description) { }

        public void SetShouldSucceed(bool shouldSucceed)
        {
            _shouldSucceed = shouldSucceed;
        }

        public void SetValidationShouldFail(bool shouldFail)
        {
            _validationShouldFail = shouldFail;
        }

        public void SetExecutionDelay(TimeSpan delay)
        {
            _executionDelay = delay;
        }

        // 暴露受保护的方法用于测试
        public void SimulateProgressChange(int progress, string message)
        {
            UpdateProgress(progress, message);
        }

        public void SimulateStatusChangeEvent(CommandExecutionStatus oldStatus, CommandExecutionStatus newStatus)
        {
            OnStatusChanged(oldStatus, newStatus, "测试状态变化");
        }

        protected override async Task<PathPlanningResult> ValidateAsync(CancellationToken cancellationToken)
        {
            if (_validationShouldFail)
            {
                return PathPlanningResult.ValidationFailure("测试验证失败");
            }
            return PathPlanningResult.Success("验证成功");
        }

        protected override async Task<PathPlanningResult> ExecuteInternalAsync(CancellationToken cancellationToken)
        {
            // 模拟执行延迟
            if (_executionDelay > TimeSpan.Zero)
            {
                await Task.Delay(_executionDelay, cancellationToken);
            }

            // 模拟进度更新
            for (int i = 10; i <= 90; i += 20)
            {
                if (cancellationToken.IsCancellationRequested)
                    break;
                    
                UpdateProgress(i, $"执行进度 {i}%");
                await Task.Delay(10, cancellationToken); // 短暂延迟以模拟工作
            }

            if (_shouldSucceed)
            {
                return PathPlanningResult.Success("测试执行成功");
            }
            else
            {
                return PathPlanningResult.Failure("测试执行失败");
            }
        }
    }

    #endregion
}