/// Domain Entity: Message
///
/// Represents a chat message in a conversation.
library;

/// Content type enum
enum ContentType {
  /// Plain text message
  text,

  /// Image message
  image,

  /// File attachment
  file,

  /// Product reference
  product,

  /// System notification
  system;

  /// Get display name for content type
  String get displayName {
    switch (this) {
      case ContentType.text:
        return 'Text';
      case ContentType.image:
        return 'Image';
      case ContentType.file:
        return 'File';
      case ContentType.product:
        return 'Product';
      case ContentType.system:
        return 'System';
    }
  }
}

/// Message Entity
///
/// Contains information about a chat message:
/// - Message content
/// - Sender information
/// - Attachments
/// - Read status
/// - Edit history
class Message {
  /// Unique message identifier
  final String messageId;

  /// Chat room ID this message belongs to
  final String chatRoomId;

  /// Sender user ID
  final String senderId;

  /// Content type
  final ContentType contentType;

  /// Message content/text
  final String content;

  /// Attachment URL (for images/files)
  final String? attachmentUrl;

  /// Product reference ID (if product message)
  final String? productReference;

  /// Message is read
  final bool isRead;

  /// Message has been edited
  final bool isEdited;

  /// Message has been deleted
  final bool isDeleted;

  /// User IDs who have read this message
  final List<String> readBy;

  /// Message timestamp
  final DateTime timestamp;

  /// Edit timestamp
  final DateTime? editedAt;

  const Message({
    required this.messageId,
    required this.chatRoomId,
    required this.senderId,
    required this.contentType,
    required this.content,
    this.attachmentUrl,
    this.productReference,
    required this.isRead,
    required this.isEdited,
    required this.isDeleted,
    required this.readBy,
    required this.timestamp,
    this.editedAt,
  });

  /// Check if message is text
  bool get isText => contentType == ContentType.text;

  /// Check if message is image
  bool get isImage => contentType == ContentType.image;

  /// Check if message is file
  bool get isFile => contentType == ContentType.file;

  /// Check if message is product reference
  bool get isProductReference => contentType == ContentType.product;

  /// Check if message is system notification
  bool get isSystemMessage => contentType == ContentType.system;

  /// Check if message has attachment
  bool get hasAttachment => attachmentUrl != null && attachmentUrl!.isNotEmpty;

  /// Check if message references a product
  bool get hasProductReference =>
      productReference != null && productReference!.isNotEmpty;

  /// Get number of readers
  int get readerCount => readBy.length;

  /// Check if user has read this message
  bool isReadBy(String userId) {
    return readBy.contains(userId);
  }

  /// Check if message is sent by user
  bool isSentBy(String userId) {
    return senderId == userId;
  }

  /// Get time since message was sent
  Duration get timeSinceSent {
    return DateTime.now().difference(timestamp);
  }

  /// Copy with method for immutability
  Message copyWith({
    String? messageId,
    String? chatRoomId,
    String? senderId,
    ContentType? contentType,
    String? content,
    String? attachmentUrl,
    String? productReference,
    bool? isRead,
    bool? isEdited,
    bool? isDeleted,
    List<String>? readBy,
    DateTime? timestamp,
    DateTime? editedAt,
  }) {
    return Message(
      messageId: messageId ?? this.messageId,
      chatRoomId: chatRoomId ?? this.chatRoomId,
      senderId: senderId ?? this.senderId,
      contentType: contentType ?? this.contentType,
      content: content ?? this.content,
      attachmentUrl: attachmentUrl ?? this.attachmentUrl,
      productReference: productReference ?? this.productReference,
      isRead: isRead ?? this.isRead,
      isEdited: isEdited ?? this.isEdited,
      isDeleted: isDeleted ?? this.isDeleted,
      readBy: readBy ?? this.readBy,
      timestamp: timestamp ?? this.timestamp,
      editedAt: editedAt ?? this.editedAt,
    );
  }

  @override
  bool operator ==(Object other) {
    if (identical(this, other)) return true;

    return other is Message &&
        other.messageId == messageId &&
        other.chatRoomId == chatRoomId &&
        other.senderId == senderId &&
        other.contentType == contentType &&
        other.content == content &&
        other.isRead == isRead &&
        other.isEdited == isEdited &&
        other.isDeleted == isDeleted;
  }

  @override
  int get hashCode {
    return Object.hash(
      messageId,
      chatRoomId,
      senderId,
      contentType,
      content,
      isRead,
      isEdited,
      isDeleted,
    );
  }

  @override
  String toString() {
    return 'Message(messageId: $messageId, senderId: $senderId, '
        'contentType: $contentType, isRead: $isRead, timestamp: $timestamp)';
  }
}
