using FluentAssertions;
using SocialService.Domain.AggregatesModel.UserBlockAggregate;
using SocialService.Domain.Events;
using SocialService.Domain.Exceptions;
using Xunit;

namespace SocialService.UnitTests.Domain;

/// <summary>
/// EN: Unit tests for UserBlock aggregate root.
/// VI: Unit tests cho UserBlock aggregate root.
/// </summary>
public class UserBlockAggregateTests
{
    private readonly Guid _blockerId = Guid.NewGuid();
    private readonly Guid _blockedId = Guid.NewGuid();

    #region Constructor Tests

    [Fact]
    public void Create_ValidBlock_SetsProperties()
    {
        // Act
        var block = new UserBlock(_blockerId, _blockedId);

        // Assert
        block.Id.Should().NotBeEmpty();
        block.BlockerId.Should().Be(_blockerId);
        block.BlockedId.Should().Be(_blockedId);
        block.Reason.Should().BeNull();
        block.CreatedAt.Should().BeCloseTo(DateTime.UtcNow, TimeSpan.FromSeconds(1));
    }

    [Fact]
    public void Create_WithReason_StoresReason()
    {
        // Arrange
        const string reason = "Spam content";

        // Act
        var block = new UserBlock(_blockerId, _blockedId, reason);

        // Assert
        block.Reason.Should().Be(reason);
    }

    [Fact]
    public void Create_RaisesUserBlockedEvent()
    {
        // Act
        var block = new UserBlock(_blockerId, _blockedId);

        // Assert
        block.DomainEvents.Should().ContainSingle(e => e is UserBlockedDomainEvent);
    }

    [Fact]
    public void Create_WithSameUserId_ThrowsException()
    {
        // Act
        var act = () => new UserBlock(_blockerId, _blockerId);

        // Assert
        act.Should().Throw<SocialDomainException>()
            .WithMessage("*yourself*");
    }

    [Fact]
    public void Create_WithEmptyBlockerId_ThrowsException()
    {
        // Act
        var act = () => new UserBlock(Guid.Empty, _blockedId);

        // Assert
        act.Should().Throw<SocialDomainException>()
            .WithMessage("*Blocker ID*");
    }

    [Fact]
    public void Create_WithEmptyBlockedId_ThrowsException()
    {
        // Act
        var act = () => new UserBlock(_blockerId, Guid.Empty);

        // Assert
        act.Should().Throw<SocialDomainException>()
            .WithMessage("*Blocked ID*");
    }

    #endregion
}
