namespace ChatService.Domain.AggregatesModel.ConversationAggregate;

using ChatService.Domain.Exceptions;
using ChatService.Domain.SeedWork;

/// <summary>
/// EN: Message entity - stores encrypted message content.
/// VI: Message entity - lưu trữ nội dung tin nhắn đã mã hóa.
/// </summary>
/// <remarks>
/// EN: The server stores ONLY encrypted content - cannot decrypt without client's private key.
/// VI: Server CHỈ lưu nội dung đã mã hóa - không thể giải mã mà không có private key của client.
/// </remarks>
public class Message : Entity
{
    private Guid _conversationId;
    private Guid _senderId;
    private string _encryptedContent;
    private string _nonce;
    private string? _authTag;
#pragma warning disable CS0169 // Fields are used by EF Core
    private int _typeId;
#pragma warning restore CS0169
    private MessageType _type;
#pragma warning disable CS0169 // Fields are used by EF Core
    private int _statusId;
#pragma warning restore CS0169
    private MessageStatus _status;
    private DateTime _createdAt;
    private DateTime? _updatedAt;
    private DateTime? _deliveredAt;
    private DateTime? _readAt;
    private string? _metadata;
    private Guid? _replyToMessageId;

    /// <summary>
    /// EN: The conversation this message belongs to.
    /// VI: Cuộc hội thoại mà tin nhắn này thuộc về.
    /// </summary>
    public Guid ConversationId => _conversationId;

    /// <summary>
    /// EN: The sender's chat user ID.
    /// VI: Chat user ID của người gửi.
    /// </summary>
    public Guid SenderId => _senderId;

    /// <summary>
    /// EN: Encrypted message content (Base64 encoded).
    /// VI: Nội dung tin nhắn đã mã hóa (mã hóa Base64).
    /// </summary>
    /// <remarks>
    /// EN: Encrypted using AES-256-GCM with session key derived from X3DH.
    /// VI: Mã hóa bằng AES-256-GCM với session key được derive từ X3DH.
    /// </remarks>
    public string EncryptedContent => _encryptedContent;

    /// <summary>
    /// EN: Nonce/IV for AES-GCM decryption (Base64 encoded).
    /// VI: Nonce/IV cho giải mã AES-GCM (mã hóa Base64).
    /// </summary>
    public string Nonce => _nonce;

    /// <summary>
    /// EN: Authentication tag for AES-GCM (Base64 encoded).
    /// VI: Authentication tag cho AES-GCM (mã hóa Base64).
    /// </summary>
    public string? AuthTag => _authTag;

    /// <summary>
    /// EN: Type of message content.
    /// VI: Loại nội dung tin nhắn.
    /// </summary>
    public MessageType Type => _type;

    /// <summary>
    /// EN: Current status of the message.
    /// VI: Trạng thái hiện tại của tin nhắn.
    /// </summary>
    public MessageStatus Status => _status;

    /// <summary>
    /// EN: When the message was sent.
    /// VI: Thời điểm tin nhắn được gửi.
    /// </summary>
    public DateTime CreatedAt => _createdAt;

    /// <summary>
    /// EN: When the message was last updated.
    /// VI: Thời điểm tin nhắn được cập nhật lần cuối.
    /// </summary>
    public DateTime? UpdatedAt => _updatedAt;

    /// <summary>
    /// EN: When the message was delivered.
    /// VI: Thời điểm tin nhắn được gửi đến.
    /// </summary>
    public DateTime? DeliveredAt => _deliveredAt;

    /// <summary>
    /// EN: When the message was read.
    /// VI: Thời điểm tin nhắn được đọc.
    /// </summary>
    public DateTime? ReadAt => _readAt;

    /// <summary>
    /// EN: Optional metadata (e.g., file name, size for file messages).
    /// VI: Metadata tùy chọn (vd: tên file, kích thước cho tin nhắn file).
    /// </summary>
    public string? Metadata => _metadata;

    /// <summary>
    /// EN: ID of the message this is replying to (if any).
    /// VI: ID của tin nhắn đang trả lời (nếu có).
    /// </summary>
    public Guid? ReplyToMessageId => _replyToMessageId;

    protected Message()
    {
        // EN: Required by EF Core
        // VI: Yêu cầu bởi EF Core
        _encryptedContent = string.Empty;
        _nonce = string.Empty;
        _type = MessageType.Text;
        _status = MessageStatus.Sent;
    }

    public Message(
        Guid conversationId,
        Guid senderId,
        string encryptedContent,
        string nonce,
        MessageType? type = null,
        string? authTag = null,
        string? metadata = null,
        Guid? replyToMessageId = null)
    {
        if (string.IsNullOrWhiteSpace(encryptedContent))
            throw new ChatDomainException("Encrypted content is required");
        if (string.IsNullOrWhiteSpace(nonce))
            throw new ChatDomainException("Nonce is required for decryption");

        Id = Guid.NewGuid();
        _conversationId = conversationId;
        _senderId = senderId;
        _encryptedContent = encryptedContent;
        _nonce = nonce;
        _authTag = authTag;
        _type = type ?? MessageType.Text;
        _status = MessageStatus.Sent;
        _metadata = metadata;
        _replyToMessageId = replyToMessageId;
        _createdAt = DateTime.UtcNow;
    }

    /// <summary>
    /// EN: Mark message as delivered.
    /// VI: Đánh dấu tin nhắn đã được gửi đến.
    /// </summary>
    public void MarkAsDelivered()
    {
        if (_status == MessageStatus.Read)
            return; // EN: Already read, no need to mark delivered / VI: Đã đọc, không cần đánh dấu đã gửi

        _status = MessageStatus.Delivered;
        _deliveredAt = DateTime.UtcNow;
        _updatedAt = DateTime.UtcNow;
    }

    /// <summary>
    /// EN: Mark message as read.
    /// VI: Đánh dấu tin nhắn đã được đọc.
    /// </summary>
    public void MarkAsRead()
    {
        _status = MessageStatus.Read;
        _readAt = DateTime.UtcNow;
        _updatedAt = DateTime.UtcNow;
        
        if (_deliveredAt == null)
            _deliveredAt = _readAt;
    }

    /// <summary>
    /// EN: Mark message as failed.
    /// VI: Đánh dấu tin nhắn gửi thất bại.
    /// </summary>
    public void MarkAsFailed()
    {
        _status = MessageStatus.Failed;
        _updatedAt = DateTime.UtcNow;
    }
}
