using System; using System.Collections.Generic; using Knot.Shared.Kernel; namespace Knot.Contracts.Messaging.Domain; public abstract class Message : AggregateRoot { public Guid ChatId { get; protected set; } public Guid SenderId { get; protected set; } public DateTime CreatedAt { get; protected set; } public long SequenceId { get; protected set; } public void SetSequenceId(long sequenceId) => SequenceId = sequenceId; public Guid? ReplyToId { get; protected set; } public Guid? ForwardedFromId { get; protected set; } public MessageState State { get; protected set; } public abstract string Type { get; } public abstract string? Content { get; protected set; } public bool IsEdited => HasState(MessageState.IsEdited); public bool IsDeleted => HasState(MessageState.IsDeleted); protected List _deletedFor = new(); public IReadOnlyCollection DeletedFor => _deletedFor.AsReadOnly(); protected List _readByUsers = new(); public IReadOnlyCollection ReadByUsers => _readByUsers.AsReadOnly(); protected Message() : base(Guid.Empty) { } protected Message(Guid id, Guid chatId, Guid senderId, Guid? replyToId, Guid? forwardedFromId, DateTime createdAt, bool isImported) : base(id) { ChatId = chatId; SenderId = senderId; ReplyToId = replyToId; ForwardedFromId = forwardedFromId; CreatedAt = createdAt; if (isImported) AddState(MessageState.IsImported); } public void AddState(MessageState state) => State |= state; public void RemoveState(MessageState state) => State &= ~state; public bool HasState(MessageState state) => (State & state) == state; public bool IsDeletedForUser(Guid userId) => _deletedFor.Exists(d => d.UserId == userId); public virtual void Delete() => AddState(MessageState.IsDeleted); public virtual void Edit(string newContent) { Content = newContent; AddState(MessageState.IsEdited); } public void DeleteForUser(Guid userId) { if (!_deletedFor.Exists(x => x.UserId == userId)) _deletedFor.Add(new DeletedMessage(Id, userId)); } public void MarkAsRead(Guid userId) { if (!_readByUsers.Contains(userId)) { _readByUsers.Add(userId); } } public bool IsReadBy(Guid userId) => _readByUsers.Contains(userId); }