using WorkClub.Domain.Entities;
using WorkClub.Domain.Enums;

namespace WorkClub.Tests.Unit.Domain;

public class WorkItemStatusTests
{
    private static WorkItem CreateWorkItem(WorkItemStatus status = WorkItemStatus.Open)
    {
        return new WorkItem
        {
            Id = Guid.NewGuid(),
            TenantId = "test-tenant",
            Title = "Test Work Item",
            Status = status,
            CreatedById = Guid.NewGuid(),
            ClubId = Guid.NewGuid(),
            CreatedAt = DateTimeOffset.UtcNow,
            UpdatedAt = DateTimeOffset.UtcNow
        };
    }

    [Fact]
    public void Open_ToAssigned_Succeeds()
    {
        // Arrange
        var workItem = CreateWorkItem(WorkItemStatus.Open);

        // Act
        workItem.TransitionTo(WorkItemStatus.Assigned);

        // Assert
        Assert.Equal(WorkItemStatus.Assigned, workItem.Status);
    }

    [Fact]
    public void Assigned_ToInProgress_Succeeds()
    {
        // Arrange
        var workItem = CreateWorkItem(WorkItemStatus.Assigned);

        // Act
        workItem.TransitionTo(WorkItemStatus.InProgress);

        // Assert
        Assert.Equal(WorkItemStatus.InProgress, workItem.Status);
    }

    [Fact]
    public void InProgress_ToReview_Succeeds()
    {
        // Arrange
        var workItem = CreateWorkItem(WorkItemStatus.InProgress);

        // Act
        workItem.TransitionTo(WorkItemStatus.Review);

        // Assert
        Assert.Equal(WorkItemStatus.Review, workItem.Status);
    }

    [Fact]
    public void Review_ToDone_Succeeds()
    {
        // Arrange
        var workItem = CreateWorkItem(WorkItemStatus.Review);

        // Act
        workItem.TransitionTo(WorkItemStatus.Done);

        // Assert
        Assert.Equal(WorkItemStatus.Done, workItem.Status);
    }

    [Fact]
    public void Review_ToInProgress_Succeeds()
    {
        // Arrange
        var workItem = CreateWorkItem(WorkItemStatus.Review);

        // Act
        workItem.TransitionTo(WorkItemStatus.InProgress);

        // Assert
        Assert.Equal(WorkItemStatus.InProgress, workItem.Status);
    }

    [Fact]
    public void Open_ToDone_Throws()
    {
        // Arrange
        var workItem = CreateWorkItem(WorkItemStatus.Open);

        // Act & Assert
        Assert.Throws<InvalidOperationException>(() =>
            workItem.TransitionTo(WorkItemStatus.Done));
    }

    [Fact]
    public void Open_ToInProgress_Throws()
    {
        // Arrange
        var workItem = CreateWorkItem(WorkItemStatus.Open);

        // Act & Assert
        Assert.Throws<InvalidOperationException>(() =>
            workItem.TransitionTo(WorkItemStatus.InProgress));
    }

    [Fact]
    public void Assigned_ToDone_Throws()
    {
        // Arrange
        var workItem = CreateWorkItem(WorkItemStatus.Assigned);

        // Act & Assert
        Assert.Throws<InvalidOperationException>(() =>
            workItem.TransitionTo(WorkItemStatus.Done));
    }

    [Fact]
    public void InProgress_ToOpen_Throws()
    {
        // Arrange
        var workItem = CreateWorkItem(WorkItemStatus.InProgress);

        // Act & Assert
        Assert.Throws<InvalidOperationException>(() =>
            workItem.TransitionTo(WorkItemStatus.Open));
    }

    [Fact]
    public void Done_ToAnyStatus_Throws()
    {
        // Arrange
        var workItem = CreateWorkItem(WorkItemStatus.Done);

        // Act & Assert
        Assert.Throws<InvalidOperationException>(() =>
            workItem.TransitionTo(WorkItemStatus.Open));
        Assert.Throws<InvalidOperationException>(() =>
            workItem.TransitionTo(WorkItemStatus.Assigned));
        Assert.Throws<InvalidOperationException>(() =>
            workItem.TransitionTo(WorkItemStatus.InProgress));
        Assert.Throws<InvalidOperationException>(() =>
            workItem.TransitionTo(WorkItemStatus.Review));
    }

    [Fact]
    public void CanTransitionTo_ValidTransition_ReturnsTrue()
    {
        // Arrange
        var workItem = CreateWorkItem(WorkItemStatus.Open);

        // Act & Assert
        Assert.True(workItem.CanTransitionTo(WorkItemStatus.Assigned));
    }

    [Fact]
    public void CanTransitionTo_InvalidTransition_ReturnsFalse()
    {
        // Arrange
        var workItem = CreateWorkItem(WorkItemStatus.Open);

        // Act & Assert
        Assert.False(workItem.CanTransitionTo(WorkItemStatus.Done));
    }
}
