using ColaFlow.Modules.ProjectManagement.Domain.ValueObjects;
using FluentAssertions;

namespace ColaFlow.Domain.Tests.ValueObjects;

/// <summary>
/// Unit tests for ProjectId value object
/// </summary>
public class ProjectIdTests
{
    [Fact]
    public void Create_WithoutParameter_ShouldGenerateNewGuid()
    {
        // Act
        var projectId = ProjectId.Create();

        // Assert
        projectId.Should().NotBeNull();
        projectId.Value.Should().NotBe(Guid.Empty);
    }

    [Fact]
    public void Create_WithGuid_ShouldCreateProjectIdWithGivenValue()
    {
        // Arrange
        var guid = Guid.NewGuid();

        // Act
        var projectId = ProjectId.Create(guid);

        // Assert
        projectId.Value.Should().Be(guid);
    }

    [Fact]
    public void From_WithGuid_ShouldCreateProjectId()
    {
        // Arrange
        var guid = Guid.NewGuid();

        // Act
        var projectId = ProjectId.From(guid);

        // Assert
        projectId.Value.Should().Be(guid);
    }

    [Fact]
    public void Create_MultipleCalls_ShouldGenerateDifferentGuids()
    {
        // Act
        var projectId1 = ProjectId.Create();
        var projectId2 = ProjectId.Create();

        // Assert
        projectId1.Value.Should().NotBe(projectId2.Value);
    }

    [Fact]
    public void Equals_WithSameValue_ShouldReturnTrue()
    {
        // Arrange
        var guid = Guid.NewGuid();
        var projectId1 = ProjectId.Create(guid);
        var projectId2 = ProjectId.Create(guid);

        // Act & Assert
        projectId1.Should().Be(projectId2);
        projectId1.Equals(projectId2).Should().BeTrue();
    }

    [Fact]
    public void Equals_WithDifferentValue_ShouldReturnFalse()
    {
        // Arrange
        var projectId1 = ProjectId.Create();
        var projectId2 = ProjectId.Create();

        // Act & Assert
        projectId1.Should().NotBe(projectId2);
        projectId1.Equals(projectId2).Should().BeFalse();
    }

    [Fact]
    public void GetHashCode_WithSameValue_ShouldReturnSameHashCode()
    {
        // Arrange
        var guid = Guid.NewGuid();
        var projectId1 = ProjectId.Create(guid);
        var projectId2 = ProjectId.Create(guid);

        // Act & Assert
        projectId1.GetHashCode().Should().Be(projectId2.GetHashCode());
    }

    [Fact]
    public void ToString_ShouldReturnGuidString()
    {
        // Arrange
        var guid = Guid.NewGuid();
        var projectId = ProjectId.Create(guid);

        // Act
        var result = projectId.ToString();

        // Assert
        result.Should().Be(guid.ToString());
    }

    [Fact]
    public void ValueObject_ShouldBeImmutable()
    {
        // Arrange
        var guid = Guid.NewGuid();
        var projectId = ProjectId.Create(guid);
        var originalValue = projectId.Value;

        // Act - Try to get the value multiple times
        var value1 = projectId.Value;
        var value2 = projectId.Value;

        // Assert
        value1.Should().Be(originalValue);
        value2.Should().Be(originalValue);
    }
}
