using SocialService.Domain.Events;
using SocialService.Domain.Exceptions;
using SocialService.Domain.SeedWork;

namespace SocialService.Domain.AggregatesModel.UserBlockAggregate;

/// <summary>
/// EN: Aggregate root for managing user blocks.
/// VI: Aggregate root để quản lý việc block user.
/// </summary>
public class UserBlock : Entity, IAggregateRoot
{
    // EN: Private fields for encapsulation
    // VI: Fields private để đóng gói
    private Guid _blockerId;
    private Guid _blockedId;
    private string? _reason;
    private DateTime _createdAt;

    /// <summary>
    /// EN: ID of the user who blocked.
    /// VI: ID của user đã block.
    /// </summary>
    public Guid BlockerId => _blockerId;

    /// <summary>
    /// EN: ID of the user who was blocked.
    /// VI: ID của user bị block.
    /// </summary>
    public Guid BlockedId => _blockedId;

    /// <summary>
    /// EN: Optional reason for blocking.
    /// VI: Lý do block (tùy chọn).
    /// </summary>
    public string? Reason => _reason;

    /// <summary>
    /// EN: Creation timestamp.
    /// VI: Thời gian tạo.
    /// </summary>
    public DateTime CreatedAt => _createdAt;

    /// <summary>
    /// EN: Private constructor for EF Core.
    /// VI: Constructor private cho EF Core.
    /// </summary>
    protected UserBlock() { }

    /// <summary>
    /// EN: Create a new user block.
    /// VI: Tạo một block user mới.
    /// </summary>
    /// <param name="blockerId">EN: Blocker user ID / VI: ID user block</param>
    /// <param name="blockedId">EN: Blocked user ID / VI: ID user bị block</param>
    /// <param name="reason">EN: Optional reason / VI: Lý do (tùy chọn)</param>
    public UserBlock(Guid blockerId, Guid blockedId, string? reason = null) : this()
    {
        if (blockerId == Guid.Empty)
            throw new SocialDomainException("Blocker ID cannot be empty");
        if (blockedId == Guid.Empty)
            throw new SocialDomainException("Blocked ID cannot be empty");
        if (blockerId == blockedId)
            throw new SocialDomainException("Cannot block yourself");

        Id = Guid.NewGuid();
        _blockerId = blockerId;
        _blockedId = blockedId;
        _reason = reason;
        _createdAt = DateTime.UtcNow;

        AddDomainEvent(new UserBlockedDomainEvent(this));
    }
}
