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<String, dynamic> 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<String, dynamic> 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();
    }
  }
}
