/// Message Envelope for wrapping all WebSocket messages with metadata
/// 
/// This provides reliable message delivery with acknowledgment mechanism
class MessageEnvelope {
  /// Unique message identifier (UUID)
  final String messageId;

  /// Timestamp when the message was created
  final DateTime timestamp;

  /// Target topic
  final String topic;

  /// Original message payload (can be Map or List)
  final dynamic payload;

  /// Whether this message requires acknowledgment
  final bool requiresAck;

  /// Number of retry attempts (for tracking)
  final int retryCount;

  /// Optional expiration timestamp
  final DateTime? expiresAt;

  MessageEnvelope({
    required this.messageId,
    required this.timestamp,
    required this.topic,
    required this.payload,
    this.requiresAck = true,
    this.retryCount = 0,
    this.expiresAt,
  });

  /// Create MessageEnvelope from JSON
  factory MessageEnvelope.fromJson(Map<String, dynamic> json) {
    return MessageEnvelope(
      messageId: json['messageId'] as String,
      timestamp: DateTime.parse(json['timestamp'] as String),
      topic: json['topic'] as String,
      payload: json['payload'],
      requiresAck: json['requiresAck'] as bool? ?? true,
      retryCount: json['retryCount'] as int? ?? 0,
      expiresAt: json['expiresAt'] != null
          ? DateTime.parse(json['expiresAt'] as String)
          : null,
    );
  }

  /// Convert MessageEnvelope to JSON
  Map<String, dynamic> toJson() {
    return {
      'messageId': messageId,
      'timestamp': timestamp.toIso8601String(),
      'topic': topic,
      'payload': payload,
      'requiresAck': requiresAck,
      'retryCount': retryCount,
      if (expiresAt != null) 'expiresAt': expiresAt!.toIso8601String(),
    };
  }

  /// Create a copy with updated fields
  MessageEnvelope copyWith({
    String? messageId,
    DateTime? timestamp,
    String? topic,
    dynamic payload,
    bool? requiresAck,
    int? retryCount,
    DateTime? expiresAt,
  }) {
    return MessageEnvelope(
      messageId: messageId ?? this.messageId,
      timestamp: timestamp ?? this.timestamp,
      topic: topic ?? this.topic,
      payload: payload ?? this.payload,
      requiresAck: requiresAck ?? this.requiresAck,
      retryCount: retryCount ?? this.retryCount,
      expiresAt: expiresAt ?? this.expiresAt,
    );
  }

  @override
  String toString() {
    return 'MessageEnvelope(messageId: $messageId, topic: $topic, requiresAck: $requiresAck, retryCount: $retryCount)';
  }
}

