using FluentAssertions;
using Workflow.Domain.Enums;
using Workflow.Domain.Exceptions;
using Workflow.Domain.StateMachine;
using Xunit;
using TaskStatus = Workflow.Domain.Enums.TaskStatus;

namespace Workflow.Tests.StateMachine;

/// <summary>
/// TaskStateMachine TDD 红灯阶段测试
/// 测试任务状态机的所有合法转换与非法转换
///
/// 任务状态: Pending, Approved, Rejected, Transferred, Delegated
/// 操作: Approve, Reject, Transfer, Delegate, DelegateComplete, TimeoutAutoProcess
/// </summary>
public class TaskStateMachineTests
{
    private readonly TaskStateMachine _machine = new();

    #region Pending → Approved

    [Fact]
    public void Transition_Pending_To_Approved()
    {
        // Arrange - 正常审批通过
        var currentState = TaskStatus.Pending;
        var operation = TaskOperation.Approve;
        var context = new TaskTransitionContext();

        // Act
        var newState = _machine.Transition(currentState, operation, context);

        // Assert
        newState.Should().Be(TaskStatus.Approved);
    }

    #endregion

    #region Pending → Rejected

    [Fact]
    public void Transition_Pending_To_Rejected()
    {
        // Arrange - 正常审批驳回
        var currentState = TaskStatus.Pending;
        var operation = TaskOperation.Reject;
        var context = new TaskTransitionContext();

        // Act
        var newState = _machine.Transition(currentState, operation, context);

        // Assert
        newState.Should().Be(TaskStatus.Rejected);
    }

    #endregion

    #region Pending → Transferred

    [Fact]
    public void Transition_Pending_To_Transferred()
    {
        // Arrange - 转办：关闭原任务，为目标人创建新任务
        var currentState = TaskStatus.Pending;
        var operation = TaskOperation.Transfer;
        var context = new TaskTransitionContext();

        // Act
        var newState = _machine.Transition(currentState, operation, context);

        // Assert
        newState.Should().Be(TaskStatus.Transferred);
    }

    #endregion

    #region Pending → Delegated

    [Fact]
    public void Transition_Pending_To_Delegated()
    {
        // Arrange - 委派：临时分配给他人处理，完成后归还
        var currentState = TaskStatus.Pending;
        var operation = TaskOperation.Delegate;
        var context = new TaskTransitionContext();

        // Act
        var newState = _machine.Transition(currentState, operation, context);

        // Assert
        newState.Should().Be(TaskStatus.Delegated);
    }

    #endregion

    #region Delegated → Pending

    [Fact]
    public void Transition_Delegated_To_Pending_On_DelegateComplete()
    {
        // Arrange - 被委派人处理完毕，任务归还给委派人
        var currentState = TaskStatus.Delegated;
        var operation = TaskOperation.DelegateComplete;
        var context = new TaskTransitionContext();

        // Act
        var newState = _machine.Transition(currentState, operation, context);

        // Assert
        newState.Should().Be(TaskStatus.Pending);
    }

    #endregion

    #region Pending → Approved/Rejected (Timeout Auto Process)

    [Fact]
    public void Transition_Pending_To_Approved_On_Timeout_With_AutoApprove_Config()
    {
        // Arrange - 超时自动审批通过（配置为自动通过）
        var currentState = TaskStatus.Pending;
        var operation = TaskOperation.TimeoutAutoProcess;
        var context = new TaskTransitionContext
        {
            AutoApproveOnTimeout = true,
        };

        // Act
        var newState = _machine.Transition(currentState, operation, context);

        // Assert
        newState.Should().Be(TaskStatus.Approved);
    }

    [Fact]
    public void Transition_Pending_To_Rejected_On_Timeout_With_AutoReject_Config()
    {
        // Arrange - 超时自动审批驳回（配置为自动驳回）
        var currentState = TaskStatus.Pending;
        var operation = TaskOperation.TimeoutAutoProcess;
        var context = new TaskTransitionContext
        {
            AutoApproveOnTimeout = false,
        };

        // Act
        var newState = _machine.Transition(currentState, operation, context);

        // Assert
        newState.Should().Be(TaskStatus.Rejected);
    }

    #endregion

    #region Illegal Transitions - Terminal States Cannot Transition

    [Fact]
    public void Transition_Approved_To_Pending_Should_Throw()
    {
        // Arrange - 已通过的任务不能回到待处理
        var currentState = TaskStatus.Approved;
        var operation = TaskOperation.Reject;
        var context = new TaskTransitionContext();

        // Act
        var act = () => _machine.Transition(currentState, operation, context);

        // Assert
        act.Should().Throw<InvalidStateTransitionException>();
    }

    [Fact]
    public void Transition_Rejected_To_Approved_Should_Throw()
    {
        // Arrange - 已驳回的任务不能变为通过
        var currentState = TaskStatus.Rejected;
        var operation = TaskOperation.Approve;
        var context = new TaskTransitionContext();

        // Act
        var act = () => _machine.Transition(currentState, operation, context);

        // Assert
        act.Should().Throw<InvalidStateTransitionException>();
    }

    [Fact]
    public void Transition_Transferred_To_Approved_Should_Throw()
    {
        // Arrange - 已转办的任务不能再审批
        var currentState = TaskStatus.Transferred;
        var operation = TaskOperation.Approve;
        var context = new TaskTransitionContext();

        // Act
        var act = () => _machine.Transition(currentState, operation, context);

        // Assert
        act.Should().Throw<InvalidStateTransitionException>();
    }

    [Fact]
    public void Transition_Transferred_To_Rejected_Should_Throw()
    {
        // Arrange - 已转办的任务不能再驳回
        var currentState = TaskStatus.Transferred;
        var operation = TaskOperation.Reject;
        var context = new TaskTransitionContext();

        // Act
        var act = () => _machine.Transition(currentState, operation, context);

        // Assert
        act.Should().Throw<InvalidStateTransitionException>();
    }

    [Fact]
    public void Transition_Approved_To_Approved_Should_Throw()
    {
        // Arrange - 已通过的任务不能再次通过
        var currentState = TaskStatus.Approved;
        var operation = TaskOperation.Approve;
        var context = new TaskTransitionContext();

        // Act
        var act = () => _machine.Transition(currentState, operation, context);

        // Assert
        act.Should().Throw<InvalidStateTransitionException>();
    }

    [Fact]
    public void Transition_Rejected_To_Rejected_Should_Throw()
    {
        // Arrange - 已驳回的任务不能再次驳回
        var currentState = TaskStatus.Rejected;
        var operation = TaskOperation.Reject;
        var context = new TaskTransitionContext();

        // Act
        var act = () => _machine.Transition(currentState, operation, context);

        // Assert
        act.Should().Throw<InvalidStateTransitionException>();
    }

    #endregion

    #region Illegal Transitions - DelegateComplete Only From Delegated

    [Fact]
    public void Transition_Pending_DelegateComplete_Should_Throw()
    {
        // Arrange - 非委派状态不能完成委派
        var currentState = TaskStatus.Pending;
        var operation = TaskOperation.DelegateComplete;
        var context = new TaskTransitionContext();

        // Act
        var act = () => _machine.Transition(currentState, operation, context);

        // Assert
        act.Should().Throw<InvalidStateTransitionException>();
    }

    [Fact]
    public void Transition_Approved_DelegateComplete_Should_Throw()
    {
        // Arrange - 已通过的任务不能完成委派
        var currentState = TaskStatus.Approved;
        var operation = TaskOperation.DelegateComplete;
        var context = new TaskTransitionContext();

        // Act
        var act = () => _machine.Transition(currentState, operation, context);

        // Assert
        act.Should().Throw<InvalidStateTransitionException>();
    }

    #endregion

    #region Illegal Transitions - Timeout Only From Pending

    [Fact]
    public void Transition_Delegated_TimeoutAutoProcess_Should_Throw()
    {
        // Arrange - 委派状态不支持超时自动处理
        var currentState = TaskStatus.Delegated;
        var operation = TaskOperation.TimeoutAutoProcess;
        var context = new TaskTransitionContext
        {
            AutoApproveOnTimeout = true,
        };

        // Act
        var act = () => _machine.Transition(currentState, operation, context);

        // Assert
        act.Should().Throw<InvalidStateTransitionException>();
    }

    [Fact]
    public void Transition_Approved_TimeoutAutoProcess_Should_Throw()
    {
        // Arrange - 已通过的任务不支持超时处理
        var currentState = TaskStatus.Approved;
        var operation = TaskOperation.TimeoutAutoProcess;
        var context = new TaskTransitionContext
        {
            AutoApproveOnTimeout = true,
        };

        // Act
        var act = () => _machine.Transition(currentState, operation, context);

        // Assert
        act.Should().Throw<InvalidStateTransitionException>();
    }

    #endregion

    #region Illegal Transitions - Delegated State Restrictions

    [Fact]
    public void Transition_Delegated_To_Approved_Should_Throw()
    {
        // Arrange - 委派中的任务不能直接审批通过，需先归还
        var currentState = TaskStatus.Delegated;
        var operation = TaskOperation.Approve;
        var context = new TaskTransitionContext();

        // Act
        var act = () => _machine.Transition(currentState, operation, context);

        // Assert
        act.Should().Throw<InvalidStateTransitionException>();
    }

    [Fact]
    public void Transition_Delegated_To_Rejected_Should_Throw()
    {
        // Arrange - 委派中的任务不能直接驳回，需先归还
        var currentState = TaskStatus.Delegated;
        var operation = TaskOperation.Reject;
        var context = new TaskTransitionContext();

        // Act
        var act = () => _machine.Transition(currentState, operation, context);

        // Assert
        act.Should().Throw<InvalidStateTransitionException>();
    }

    #endregion
}
