import 'dart:convert';

enum QueuePriority { high, normal, low }

enum QueueCategory { userAction, sync, analytics, log }

class OfflineRequest {
  const OfflineRequest({
    required this.id,
    required this.idempotencyKey,
    required this.method,
    required this.path,
    this.query,
    this.body,
    this.headers,
    this.priority = QueuePriority.normal,
    this.category = QueueCategory.sync,
    this.retryCount = 0,
    this.maxRetry = 3,
  });

  final String id;
  final String idempotencyKey;
  final String method;
  final String path;
  final Map<String, dynamic>? query;
  final dynamic body;
  final Map<String, dynamic>? headers;
  final QueuePriority priority;
  final QueueCategory category;
  final int retryCount;
  final int maxRetry;

  bool get isDead => retryCount >= maxRetry;

  OfflineRequest copyWith({int? retryCount}) {
    return OfflineRequest(
      id: id,
      idempotencyKey: idempotencyKey,
      method: method,
      path: path,
      query: query,
      body: body,
      headers: headers,
      priority: priority,
      category: category,
      retryCount: retryCount ?? this.retryCount,
      maxRetry: maxRetry,
    );
  }

  factory OfflineRequest.fromJson(Map<String, dynamic> json) {
    return OfflineRequest(
      id: json['id'] as String,
      idempotencyKey: json['idempotencyKey'] as String,
      method: json['method'] as String,
      path: json['path'] as String,
      query: (json['query'] as Map?)?.cast<String, dynamic>(),
      body: json['body'],
      headers: (json['headers'] as Map?)?.cast<String, dynamic>(),
      priority: QueuePriority.values[(json['priority'] as num).toInt()],
      category: QueueCategory.values[(json['category'] as num).toInt()],
      retryCount: (json['retryCount'] as num).toInt(),
      maxRetry: (json['maxRetry'] as num).toInt(),
    );
  }

  Map<String, dynamic> toJson() {
    return {
      'id': id,
      'idempotencyKey': idempotencyKey,
      'method': method,
      'path': path,
      'query': query,
      'body': body,
      'headers': headers,
      'priority': priority.index,
      'category': category.index,
      'retryCount': retryCount,
      'maxRetry': maxRetry,
    };
  }

  String encode() => jsonEncode(toJson());

  static OfflineRequest decode(String raw) {
    return OfflineRequest.fromJson(jsonDecode(raw) as Map<String, dynamic>);
  }
}
