import '../../core/constants/env_config.dart'; import '../../core/utils/app_logger.dart'; import '../../domain/entities/story.dart'; /// Modèle de données pour les stories (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 [Story]. class StoryModel extends Story { /// Crée une nouvelle instance de [StoryModel]. const StoryModel({ required super.id, required super.userId, required super.userFirstName, required super.userLastName, required super.userProfileImageUrl, required super.userIsVerified, required super.mediaType, required super.mediaUrl, required super.createdAt, required super.expiresAt, super.thumbnailUrl, super.durationSeconds, super.isActive, super.viewsCount, super.hasViewed, }); /// Crée un [StoryModel] à partir d'un JSON reçu depuis l'API. factory StoryModel.fromJson(Map json) { try { return StoryModel( id: json['id']?.toString() ?? '', userId: json['userId']?.toString() ?? '', userFirstName: json['userFirstName']?.toString() ?? '', userLastName: json['userLastName']?.toString() ?? '', userProfileImageUrl: json['userProfileImageUrl']?.toString() ?? '', userIsVerified: json['userIsVerified'] as bool? ?? false, mediaType: _parseMediaType(json['mediaType']), mediaUrl: json['mediaUrl']?.toString() ?? '', thumbnailUrl: json['thumbnailUrl']?.toString(), durationSeconds: json['durationSeconds'] as int?, createdAt: _parseDateTime(json['createdAt']), expiresAt: _parseDateTime(json['expiresAt']), isActive: json['isActive'] as bool? ?? true, viewsCount: json['viewsCount'] as int? ?? 0, hasViewed: json['hasViewed'] as bool? ?? false, ); } catch (e, stackTrace) { AppLogger.e('Erreur lors du parsing JSON', error: e, stackTrace: stackTrace, tag: 'StoryModel'); AppLogger.d('JSON reçu: $json', tag: 'StoryModel'); rethrow; } } /// Convertit le modèle en JSON pour l'envoi à l'API. Map toJson() { return { 'id': id, 'userId': userId, 'userFirstName': userFirstName, 'userLastName': userLastName, 'userProfileImageUrl': userProfileImageUrl, 'userIsVerified': userIsVerified, 'mediaType': _mediaTypeToString(mediaType), 'mediaUrl': mediaUrl, 'thumbnailUrl': thumbnailUrl, 'durationSeconds': durationSeconds, 'createdAt': createdAt.toIso8601String(), 'expiresAt': expiresAt.toIso8601String(), 'isActive': isActive, 'viewsCount': viewsCount, 'hasViewed': hasViewed, }; } /// Convertit le modèle en entité de domaine. Story toEntity() { return Story( id: id, userId: userId, userFirstName: userFirstName, userLastName: userLastName, userProfileImageUrl: userProfileImageUrl, userIsVerified: userIsVerified, mediaType: mediaType, mediaUrl: mediaUrl, thumbnailUrl: thumbnailUrl, durationSeconds: durationSeconds, createdAt: createdAt, expiresAt: expiresAt, isActive: isActive, viewsCount: viewsCount, hasViewed: hasViewed, ); } /// Parse le type de média depuis une string. static StoryMediaType _parseMediaType(dynamic value) { if (value == null) return StoryMediaType.image; final stringValue = value.toString().toUpperCase(); switch (stringValue) { case 'IMAGE': return StoryMediaType.image; case 'VIDEO': return StoryMediaType.video; default: AppLogger.w('Type de média inconnu: $value, utilisation de IMAGE par défaut', tag: 'StoryModel'); return StoryMediaType.image; } } /// Convertit le type de média en string pour l'API. static String _mediaTypeToString(StoryMediaType type) { switch (type) { case StoryMediaType.image: return 'IMAGE'; case StoryMediaType.video: return 'VIDEO'; } } /// Parse une DateTime depuis différents formats possibles. static DateTime _parseDateTime(dynamic value) { if (value == null) return DateTime.now(); try { // Si c'est déjà une DateTime if (value is DateTime) return value; // Si c'est une string ISO 8601 if (value is String) { return DateTime.parse(value); } // Si c'est un timestamp en millisecondes if (value is int) { return DateTime.fromMillisecondsSinceEpoch(value); } AppLogger.w('Format de date non reconnu: $value', tag: 'StoryModel'); return DateTime.now(); } catch (e, stackTrace) { AppLogger.e('Erreur parsing DateTime', error: e, stackTrace: stackTrace, tag: 'StoryModel'); return DateTime.now(); } } }