import 'package:hive/hive.dart';

part 'pending_request.g.dart';

/// Modèle pour stocker les requêtes API en attente quand l'application est hors ligne
/// Ces requêtes seront traitées automatiquement au retour de la connexion
@HiveType(typeId: 100)
class PendingRequest extends HiveObject {
  /// ID unique de la requête (UUID)
  @HiveField(0)
  final String id;
  
  /// Méthode HTTP (POST, GET, PUT, DELETE)
  @HiveField(1)
  final String method;
  
  /// Path de l'API (ex: /chat/rooms/xxx/messages)
  @HiveField(2)
  final String path;
  
  /// Body de la requête (données JSON)
  @HiveField(3)
  final Map<String, dynamic>? data;
  
  /// Query parameters
  @HiveField(4)
  final Map<String, dynamic>? queryParams;
  
  /// Timestamp de création - UTILISÉ POUR L'ORDRE FIFO
  @HiveField(5)
  final DateTime createdAt;
  
  /// ID temporaire associé (ex: temp_msg_xxx, temp_user_xxx)
  @HiveField(6)
  final String? tempId;
  
  /// Contexte de la requête (chat, user, operation, passage, etc.)
  @HiveField(7)
  final String context;
  
  /// Nombre de tentatives de retry
  @HiveField(8)
  final int retryCount;
  
  /// Message de la dernière erreur
  @HiveField(9)
  final String? errorMessage;
  
  /// Métadonnées additionnelles (userId, amicaleId, etc.)
  @HiveField(10)
  final Map<String, dynamic>? metadata;
  
  /// Priorité de la requête (0 = normale, 1 = haute pour passages)
  @HiveField(11)
  final int priority;
  
  /// Headers spécifiques pour cette requête
  @HiveField(12)
  final Map<String, String>? headers;

  PendingRequest({
    required this.id,
    required this.method,
    required this.path,
    this.data,
    this.queryParams,
    required this.createdAt,
    this.tempId,
    required this.context,
    this.retryCount = 0,
    this.errorMessage,
    this.metadata,
    this.priority = 0,
    this.headers,
  });

  /// Créer une copie avec des modifications
  PendingRequest copyWith({
    String? id,
    String? method,
    String? path,
    Map<String, dynamic>? data,
    Map<String, dynamic>? queryParams,
    DateTime? createdAt,
    String? tempId,
    String? context,
    int? retryCount,
    String? errorMessage,
    Map<String, dynamic>? metadata,
    int? priority,
    Map<String, String>? headers,
  }) {
    return PendingRequest(
      id: id ?? this.id,
      method: method ?? this.method,
      path: path ?? this.path,
      data: data ?? this.data,
      queryParams: queryParams ?? this.queryParams,
      createdAt: createdAt ?? this.createdAt,
      tempId: tempId ?? this.tempId,
      context: context ?? this.context,
      retryCount: retryCount ?? this.retryCount,
      errorMessage: errorMessage ?? this.errorMessage,
      metadata: metadata ?? this.metadata,
      priority: priority ?? this.priority,
      headers: headers ?? this.headers,
    );
  }

  /// Calculer le prochain délai de retry basé sur le nombre de tentatives
  Duration getNextRetryDelay() {
    switch (retryCount) {
      case 0:
        return Duration.zero; // Immédiat
      case 1:
        return const Duration(seconds: 30);
      case 2:
        return const Duration(minutes: 2);
      default:
        return const Duration(minutes: 5);
    }
  }

  /// Vérifier si la requête a expiré (>24h)
  bool isExpired() {
    final age = DateTime.now().difference(createdAt);
    return age.inHours >= 24;
  }

  /// Obtenir une description lisible pour les logs
  String toLogString() {
    return '[$context] $method $path (ID: $id, TempID: $tempId, Priority: $priority, Retry: $retryCount)';
  }

  @override
  String toString() {
    return 'PendingRequest{id: $id, method: $method, path: $path, context: $context, priority: $priority, retryCount: $retryCount}';
  }
}