import 'package:intl/intl.dart';

/// Classe utilitaire pour formater les dates et heures.
///
/// Cette classe fournit des méthodes statiques pour formater les dates
/// dans différents formats selon les besoins de l'application.
///
/// **Usage:**
/// ```dart
/// final formatted = DateFormatter.formatDate(DateTime.now());
/// // Résultat: "lundi 05 janvier 2026, à 14:30"
/// ```
class DateFormatter {
  /// Constructeur privé pour empêcher l'instanciation
  DateFormatter._();

  /// Formate une date avec l'heure incluse en français.
  ///
  /// [date] La date à formater
  ///
  /// Returns une chaîne formatée (ex: "lundi 05 janvier 2026, à 14:30").
  ///
  /// **Exemple:**
  /// ```dart
  /// final formatted = DateFormatter.formatDate(DateTime(2026, 1, 5, 14, 30));
  /// // Résultat: "lundi 05 janvier 2026, à 14:30"
  /// ```
  static String formatDate(DateTime date) {
    return DateFormat('EEEE dd MMMM yyyy, à HH:mm', 'fr_FR').format(date);
  }

  /// Formate une date sans l'heure en français.
  ///
  /// [date] La date à formater
  ///
  /// Returns une chaîne formatée (ex: "lundi 05 janvier 2026").
  static String formatDateOnly(DateTime date) {
    return DateFormat('EEEE dd MMMM yyyy', 'fr_FR').format(date);
  }

  /// Formate uniquement l'heure.
  ///
  /// [date] La date contenant l'heure à formater
  ///
  /// Returns une chaîne formatée (ex: "14:30").
  static String formatTime(DateTime date) {
    return DateFormat('HH:mm', 'fr_FR').format(date);
  }

  /// Formate une date de manière courte (ex: "05/01/2026").
  ///
  /// [date] La date à formater
  ///
  /// Returns une chaîne formatée (ex: "05/01/2026").
  static String formatDateShort(DateTime date) {
    return DateFormat('dd/MM/yyyy', 'fr_FR').format(date);
  }

  /// Formate une date avec l'heure de manière courte (ex: "05/01/2026 14:30").
  ///
  /// [date] La date à formater
  ///
  /// Returns une chaîne formatée (ex: "05/01/2026 14:30").
  static String formatDateTimeShort(DateTime date) {
    return DateFormat('dd/MM/yyyy HH:mm', 'fr_FR').format(date);
  }

  /// Formate une date de manière relative (ex: "il y a 2 heures").
  ///
  /// [date] La date à formater
  ///
  /// Returns une chaîne formatée relative.
  static String formatDateRelative(DateTime date) {
    final now = DateTime.now();
    final difference = now.difference(date);

    if (difference.inDays > 365) {
      final years = (difference.inDays / 365).floor();
      return 'il y a $years an${years > 1 ? 's' : ''}';
    } else if (difference.inDays > 30) {
      final months = (difference.inDays / 30).floor();
      return 'il y a $months mois';
    } else if (difference.inDays > 0) {
      return 'il y a ${difference.inDays} jour${difference.inDays > 1 ? 's' : ''}';
    } else if (difference.inHours > 0) {
      return 'il y a ${difference.inHours} heure${difference.inHours > 1 ? 's' : ''}';
    } else if (difference.inMinutes > 0) {
      return 'il y a ${difference.inMinutes} minute${difference.inMinutes > 1 ? 's' : ''}';
    } else {
      return 'à l\'instant';
    }
  }

  /// Formate une date pour l'affichage dans une liste (ex: "Aujourd'hui, 14:30").
  ///
  /// [date] La date à formater
  ///
  /// Returns une chaîne formatée.
  static String formatDateForList(DateTime date) {
    final now = DateTime.now();
    final today = DateTime(now.year, now.month, now.day);
    final dateOnly = DateTime(date.year, date.month, date.day);

    if (dateOnly == today) {
      return 'Aujourd\'hui, ${formatTime(date)}';
    } else if (dateOnly == today.subtract(const Duration(days: 1))) {
      return 'Hier, ${formatTime(date)}';
    } else if (dateOnly == today.add(const Duration(days: 1))) {
      return 'Demain, ${formatTime(date)}';
    } else {
      return formatDateTimeShort(date);
    }
  }

  /// Parse une chaîne de date au format ISO 8601.
  ///
  /// [dateString] La chaîne à parser
  ///
  /// Returns un [DateTime] ou `null` si le parsing échoue.
  static DateTime? parseIso8601(String dateString) {
    try {
      return DateTime.parse(dateString);
    } catch (e) {
      return null;
    }
  }

  /// Formate une date au format ISO 8601.
  ///
  /// [date] La date à formater
  ///
  /// Returns une chaîne au format ISO 8601 (ex: "2026-01-05T14:30:00.000Z").
  static String formatIso8601(DateTime date) {
    return date.toIso8601String();
  }
}

/// Classe utilitaire spécifique pour formater les dates dans la messagerie.
///
/// Cette classe fournit des méthodes pour formater les timestamps de messages
/// de manière intelligente et moderne (style WhatsApp/Telegram).
class ChatDateFormatter {
  /// Constructeur privé pour empêcher l'instanciation
  ChatDateFormatter._();

  /// Formate un timestamp pour affichage dans une bulle de message.
  ///
  /// Exemples :
  /// - Aujourd'hui : "14:30"
  /// - Hier : "Hier 14:30"
  /// - Cette semaine : "Lun 14:30"
  /// - Plus ancien : "12/01 14:30"
  ///
  /// [timestamp] Le timestamp du message
  ///
  /// Returns une chaîne formatée optimisée pour les bulles de message.
  static String formatMessageTimestamp(DateTime timestamp) {
    final now = DateTime.now();
    final today = DateTime(now.year, now.month, now.day);
    final messageDate = DateTime(timestamp.year, timestamp.month, timestamp.day);

    final difference = today.difference(messageDate).inDays;
    final timeFormat = DateFormat.Hm('fr_FR'); // HH:mm
    final time = timeFormat.format(timestamp);

    if (difference == 0) {
      // Aujourd'hui : juste l'heure
      return time;
    } else if (difference == 1) {
      // Hier
      return 'Hier $time';
    } else if (difference < 7) {
      // Cette semaine : jour de la semaine
      final dayName = DateFormat.E('fr_FR').format(timestamp);
      return '$dayName $time';
    } else {
      // Plus ancien : date courte
      final dateFormat = DateFormat('dd/MM', 'fr_FR');
      return '${dateFormat.format(timestamp)} $time';
    }
  }

  /// Formate pour les séparateurs de date entre groupes de messages.
  ///
  /// Exemples :
  /// - Aujourd'hui : "Aujourd'hui"
  /// - Hier : "Hier"
  /// - Cette semaine : "Lundi"
  /// - Cette année : "12 janvier"
  /// - Année précédente : "12 janvier 2024"
  ///
  /// [date] La date à formater
  ///
  /// Returns une chaîne formatée pour les séparateurs de date.
  static String formatDateSeparator(DateTime date) {
    final now = DateTime.now();
    final today = DateTime(now.year, now.month, now.day);
    final messageDate = DateTime(date.year, date.month, date.day);

    final difference = today.difference(messageDate).inDays;

    if (difference == 0) {
      return "Aujourd'hui";
    } else if (difference == 1) {
      return 'Hier';
    } else if (difference < 7) {
      return DateFormat.EEEE('fr_FR').format(date);
    } else if (date.year == now.year) {
      return DateFormat('d MMMM', 'fr_FR').format(date);
    } else {
      return DateFormat('d MMMM yyyy', 'fr_FR').format(date);
    }
  }

  /// Formate un temps relatif (optionnel, pour liste de conversations).
  ///
  /// Exemples :
  /// - "À l'instant"
  /// - "Il y a 5 min"
  /// - "Il y a 2 h"
  /// - "Hier"
  /// - "12/01"
  ///
  /// [timestamp] Le timestamp à formater
  ///
  /// Returns une chaîne formatée relative.
  static String formatRelativeTime(DateTime timestamp) {
    final now = DateTime.now();
    final difference = now.difference(timestamp);

    if (difference.inSeconds < 60) {
      return "À l'instant";
    } else if (difference.inMinutes < 60) {
      return 'Il y a ${difference.inMinutes} min';
    } else if (difference.inHours < 24) {
      return 'Il y a ${difference.inHours} h';
    } else if (difference.inDays == 1) {
      return 'Hier';
    } else if (difference.inDays < 7) {
      return DateFormat.E('fr_FR').format(timestamp);
    } else {
      return DateFormat('dd/MM', 'fr_FR').format(timestamp);
    }
  }
}
