import 'dart:async';
import 'package:dio/dio.dart';
import 'package:flutter/foundation.dart';
import '../storage/telemetry_storage.dart';

class TelemetryUploader {
  final String apiBaseUrl;
  final TelemetryStorage storage;
  final Dio _dio;

  Timer? _uploadTimer;
  bool _isUploading = false;

  Map<String, String> Function()? getAuthHeaders;

  TelemetryUploader({
    required this.apiBaseUrl,
    required this.storage,
    this.getAuthHeaders,
  }) : _dio = Dio(BaseOptions(
          baseUrl: apiBaseUrl,
          connectTimeout: const Duration(seconds: 10),
          receiveTimeout: const Duration(seconds: 10),
        ));

  void startPeriodicUpload({
    Duration interval = const Duration(seconds: 30),
    int batchSize = 20,
  }) {
    _uploadTimer?.cancel();
    _uploadTimer = Timer.periodic(interval, (_) {
      uploadIfNeeded(batchSize: batchSize);
    });
  }

  void stopPeriodicUpload() {
    _uploadTimer?.cancel();
    _uploadTimer = null;
  }

  Future<void> uploadIfNeeded({int batchSize = 20}) async {
    if (_isUploading) return;
    if (storage.getQueueSize() < 10) return;
    await uploadBatch(batchSize: batchSize);
  }

  Future<bool> uploadBatch({int batchSize = 20}) async {
    if (_isUploading) return false;
    _isUploading = true;
    try {
      final events = storage.dequeueEvents(batchSize);
      if (events.isEmpty) return true;

      final response = await _dio.post(
        '/api/v1/analytics/events',
        data: {'events': events.map((e) => e.toServerJson()).toList()},
        options: Options(headers: getAuthHeaders?.call()),
      );

      if (response.statusCode == 200) {
        await storage.removeEvents(events.length);
        debugPrint('[TelemetryUploader] Uploaded ${events.length} events');
        return true;
      }
      return false;
    } on DioException catch (e) {
      debugPrint('[TelemetryUploader] Upload error: ${e.message}');
      return false;
    } catch (e) {
      debugPrint('[TelemetryUploader] Upload error: $e');
      return false;
    } finally {
      _isUploading = false;
    }
  }

  Future<void> forceUploadAll() async {
    stopPeriodicUpload();
    int retries = 0;
    while (storage.getQueueSize() > 0 && retries < 3) {
      final success = await uploadBatch(batchSize: 50);
      if (!success) {
        retries++;
        await Future.delayed(const Duration(seconds: 1));
      }
    }
  }
}
