import 'package:dio/dio.dart';
import 'package:recording_tool/core/network/network_monitor.dart';
import 'package:recording_tool/core/network/offline_queue/offline_queue_manager.dart';
import 'package:recording_tool/core/network/offline_queue/offline_request.dart';
import 'package:uuid/uuid.dart';

class OfflineQueueInterceptor extends Interceptor {
  OfflineQueueInterceptor({
    required this.monitor,
    required this.manager,
    this.enabled = false,
  });

  final NetworkMonitor monitor;
  final OfflineQueueManager manager;
  final bool enabled;

  @override
  void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
    if (!enabled || options.extra['offline'] != true) {
      handler.next(options);
      return;
    }

    if (options.extra['replay'] == true || monitor.current.isUnknown) {
      handler.next(options);
      return;
    }

    if (monitor.current.isOffline) {
      final extra = options.extra;
      final request = OfflineRequest(
        id: const Uuid().v4(),
        idempotencyKey: (extra['idempotencyKey'] ?? const Uuid().v4())
            .toString(),
        method: options.method,
        path: options.path,
        query: options.queryParameters,
        body: options.data,
        headers: Map<String, dynamic>.from(options.headers),
        priority: QueuePriority
            .values[(extra['priority'] as int?) ?? QueuePriority.normal.index],
        category:
            QueueCategory.values[(extra['category'] as int?) ??
                QueueCategory.userAction.index],
      );

      manager.enqueue(request);
      handler.reject(
        DioException(
          requestOptions: options,
          type: DioExceptionType.cancel,
          message: 'OFFLINE_QUEUED',
        ),
      );
      return;
    }

    handler.next(options);
  }
}
