import '../../domain/entities/notification.dart';

/// Modèle de données pour les notifications (Data Transfer Object).
///
/// Cette classe est responsable de la sérialisation/désérialisation
/// avec l'API backend et convertit vers/depuis l'entité de domaine Notification.
class NotificationModel {
  NotificationModel({
    required this.id,
    required this.title,
    required this.message,
    required this.type,
    required this.timestamp,
    this.isRead = false,
    this.eventId,
    this.userId,
    this.metadata,
  });

  /// Factory pour créer un [NotificationModel] à partir d'un JSON.
  factory NotificationModel.fromJson(Map<String, dynamic> json) {
    return NotificationModel(
      id: _parseIdRequired(json, 'id', ''),
      title: _parseString(json, 'title', 'Notification'),
      message: _parseString(json, 'message', ''),
      type: _parseNotificationType(json['type'] as String?),
      timestamp: _parseTimestamp(json['timestamp']),
      isRead: json['isRead'] as bool? ?? false,
      eventId: _parseId(json, 'eventId'),
      userId: _parseId(json, 'userId'),
      metadata: _parseMetadata(json['metadata']),
    );
  }

  /// Crée un [NotificationModel] depuis une entité de domaine [Notification].
  factory NotificationModel.fromEntity(Notification notification) {
    return NotificationModel(
      id: notification.id,
      title: notification.title,
      message: notification.message,
      type: notification.type,
      timestamp: notification.timestamp,
      isRead: notification.isRead,
      eventId: notification.eventId,
      userId: notification.userId,
      metadata: notification.metadata,
    );
  }

  final String id;
  final String title;
  final String message;
  final NotificationType type;
  final DateTime timestamp;
  bool isRead;
  final String? eventId;
  final String? userId;
  final Map<String, dynamic>? metadata;

  /// Convertit ce modèle en JSON pour l'envoi vers l'API.
  Map<String, dynamic> toJson() {
    return {
      'id': id,
      'title': title,
      'message': message,
      'type': type.toString().split('.').last,
      'timestamp': timestamp.toIso8601String(),
      'isRead': isRead,
      if (eventId != null) 'eventId': eventId,
      if (userId != null) 'userId': userId,
      if (metadata != null) 'metadata': metadata,
    };
  }

  /// Convertit ce modèle vers une entité de domaine [Notification].
  Notification toEntity() {
    return Notification(
      id: id,
      title: title,
      message: message,
      type: type,
      timestamp: timestamp,
      isRead: isRead,
      eventId: eventId,
      userId: userId,
      metadata: metadata,
    );
  }

  /// Parse une valeur string depuis le JSON avec valeur par défaut.
  static String _parseString(
    Map<String, dynamic> json,
    String key,
    String defaultValue,
  ) {
    return json[key] as String? ?? defaultValue;
  }

  /// Parse le type de notification depuis le JSON.
  static NotificationType _parseNotificationType(String? type) {
    if (type == null) return NotificationType.other;

    switch (type.toLowerCase()) {
      case 'event':
      case 'événement':
        return NotificationType.event;
      case 'friend':
      case 'ami':
        return NotificationType.friend;
      case 'reminder':
      case 'rappel':
        return NotificationType.reminder;
      default:
        return NotificationType.other;
    }
  }

  /// Parse un timestamp depuis le JSON.
  static DateTime _parseTimestamp(dynamic timestamp) {
    if (timestamp == null) return DateTime.now();

    if (timestamp is String) {
      try {
        return DateTime.parse(timestamp);
      } catch (e) {
        return DateTime.now();
      }
    }

    if (timestamp is int) {
      return DateTime.fromMillisecondsSinceEpoch(timestamp);
    }

    return DateTime.now();
  }

  /// Parse un ID (UUID) depuis le JSON.
  ///
  /// [json] Le JSON à parser
  /// [key] La clé de l'ID
  /// [defaultValue] La valeur par défaut si l'ID est null
  ///
  /// Returns l'ID parsé ou la valeur par défaut
  static String _parseIdRequired(
    Map<String, dynamic> json,
    String key,
    String defaultValue,
  ) {
    final value = json[key];
    if (value == null) return defaultValue;
    return value.toString();
  }

  /// Parse un ID (UUID) optionnel depuis le JSON.
  ///
  /// [json] Le JSON à parser
  /// [key] La clé de l'ID
  ///
  /// Returns l'ID parsé ou null
  static String? _parseId(Map<String, dynamic> json, String key) {
    final value = json[key];
    if (value == null) return null;
    return value.toString();
  }

  /// Parse les métadonnées depuis le JSON.
  static Map<String, dynamic>? _parseMetadata(dynamic metadata) {
    if (metadata == null) return null;
    if (metadata is Map<String, dynamic>) return metadata;
    if (metadata is String) {
      try {
        // Tenter de parser si c'est une chaîne JSON
        return {'raw': metadata};
      } catch (e) {
        return null;
      }
    }
    return null;
  }
}

