// lib/services/retry_service.dart

import 'dart:convert';
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:path/path.dart' as p;

import 'package:environment_monitoring_app/models/in_situ_sampling_data.dart';
import 'package:environment_monitoring_app/services/marine_in_situ_sampling_service.dart';
import 'package:environment_monitoring_app/models/river_in_situ_sampling_data.dart';
import 'package:environment_monitoring_app/services/river_in_situ_sampling_service.dart';
import 'package:environment_monitoring_app/models/river_inves_manual_sampling_data.dart';
import 'package:environment_monitoring_app/services/river_investigative_sampling_service.dart';
import 'package:environment_monitoring_app/models/marine_inves_manual_sampling_data.dart';
import 'package:environment_monitoring_app/services/marine_investigative_sampling_service.dart';
import 'package:environment_monitoring_app/models/tarball_data.dart';
import 'package:environment_monitoring_app/services/marine_tarball_sampling_service.dart';

// --- MARINE REPORT IMPORTS ---
import 'package:environment_monitoring_app/models/marine_manual_npe_report_data.dart';
import 'package:environment_monitoring_app/services/marine_npe_report_service.dart';

import 'package:environment_monitoring_app/models/marine_manual_pre_departure_checklist_data.dart';
import 'package:environment_monitoring_app/services/marine_manual_pre_departure_service.dart';

import 'package:environment_monitoring_app/models/marine_manual_sonde_calibration_data.dart';
import 'package:environment_monitoring_app/services/marine_manual_sonde_calibration_service.dart';

import 'package:environment_monitoring_app/models/marine_manual_equipment_maintenance_data.dart';
import 'package:environment_monitoring_app/services/marine_manual_equipment_maintenance_service.dart';
// --- END MARINE REPORT IMPORTS ---

import 'package:environment_monitoring_app/services/database_helper.dart';
import 'package:environment_monitoring_app/services/base_api_service.dart';
import 'package:environment_monitoring_app/services/ftp_service.dart';
import 'package:environment_monitoring_app/services/server_config_service.dart';
import 'package:environment_monitoring_app/auth_provider.dart';
import 'package:environment_monitoring_app/services/user_preferences_service.dart'; // ADDED

/// A dedicated service to manage the queue of failed API, FTP, and complex submission tasks.
class RetryService {
  final DatabaseHelper _dbHelper = DatabaseHelper();
  final BaseApiService _baseApiService = BaseApiService();
  final FtpService _ftpService = FtpService();
  final ServerConfigService _serverConfigService = ServerConfigService();
  final UserPreferencesService _userPreferencesService = UserPreferencesService(); // ADDED
  bool _isProcessing = false;

  // Sampling Services
  MarineInSituSamplingService? _marineInSituService;
  RiverInSituSamplingService? _riverInSituService;
  MarineInvestigativeSamplingService? _marineInvestigativeService;
  RiverInvestigativeSamplingService? _riverInvestigativeService;
  MarineTarballSamplingService? _marineTarballService;

  // Report Services
  MarineNpeReportService? _marineNpeService;
  // *** ADDED: Other Marine Report Services ***
  MarineManualPreDepartureService? _marinePreDepartureService;
  MarineManualSondeCalibrationService? _marineSondeCalibrationService;
  MarineManualEquipmentMaintenanceService? _marineEquipmentMaintenanceService;
  // *** END ADDED ***

  AuthProvider? _authProvider;

  void initialize({
    required MarineInSituSamplingService marineInSituService,
    required RiverInSituSamplingService riverInSituService,
    required MarineInvestigativeSamplingService marineInvestigativeService,
    required RiverInvestigativeSamplingService riverInvestigativeService,
    required MarineTarballSamplingService marineTarballService,

    // Added Marine Report Services
    required MarineNpeReportService marineNpeService,
    required MarineManualPreDepartureService marinePreDepartureService,
    required MarineManualSondeCalibrationService marineSondeCalibrationService,
    required MarineManualEquipmentMaintenanceService marineEquipmentMaintenanceService,

    required AuthProvider authProvider,
  }) {
    _marineInSituService = marineInSituService;
    _riverInSituService = riverInSituService;
    _marineInvestigativeService = marineInvestigativeService;
    _riverInvestigativeService = riverInvestigativeService;
    _marineTarballService = marineTarballService;

    _marineNpeService = marineNpeService;
    _marinePreDepartureService = marinePreDepartureService;
    _marineSondeCalibrationService = marineSondeCalibrationService;
    _marineEquipmentMaintenanceService = marineEquipmentMaintenanceService;

    _authProvider = authProvider;
  }

  /// Adds a generic, complex task to the queue, to be handled by a background processor.
  Future<void> queueTask({
    required String type,
    required Map<String, dynamic> payload,
  }) async {
    await _dbHelper.queueFailedRequest({
      'type': type,
      'endpoint_or_path': 'N/A',
      'payload': jsonEncode(payload),
      'timestamp': DateTime.now().toIso8601String(),
      'status': 'pending',
    });
    debugPrint("Task of type '$type' has been queued for background processing.");
  }

  /// Adds a failed API request to the local database queue.
  Future<void> addApiToQueue({
    required String endpoint,
    required String method,
    Map<String, dynamic>? body,
    Map<String, String>? fields,
    Map<String, File>? files,
  }) async {
    final serializableFiles = files?.map((key, value) => MapEntry(key, value.path));
    final payload = {
      'method': method,
      'body': body,
      'fields': fields,
      'files': serializableFiles,
    };
    await _dbHelper.queueFailedRequest({
      'type': 'api',
      'endpoint_or_path': endpoint,
      'payload': jsonEncode(payload),
      'timestamp': DateTime.now().toIso8601String(),
      'status': 'pending',
    });
    debugPrint("API request for endpoint '$endpoint' has been queued for retry.");
  }

  /// Adds a failed FTP upload to the local database queue.
  Future<void> addFtpToQueue({
    required String localFilePath,
    required String remotePath,
    required int ftpConfigId,
  }) async {
    final payload = {
      'localFilePath': localFilePath,
      'ftpConfigId': ftpConfigId,
    };
    await _dbHelper.queueFailedRequest({
      'type': 'ftp',
      'endpoint_or_path': remotePath,
      'payload': jsonEncode(payload),
      'timestamp': DateTime.now().toIso8601String(),
      'status': 'pending',
    });
    debugPrint("FTP upload for file '$localFilePath' to config ID $ftpConfigId has been queued for retry.");
  }


  Future<List<Map<String, dynamic>>> getPendingTasks() {
    return _dbHelper.getPendingRequests();
  }

  Future<void> processRetryQueue() async {
    if (_isProcessing) {
      debugPrint("[RetryService] ⏳ Queue is already being processed. Skipping.");
      return;
    }
    _isProcessing = true;
    debugPrint("[RetryService] ▶️ Starting to process main retry queue...");

    final pendingTasks = await getPendingTasks();
    if (pendingTasks.isEmpty) {
      debugPrint("[RetryService] ⏹️ Queue is empty. Nothing to process.");
      _isProcessing = false;
      return;
    }

    if (_authProvider == null || !await _authProvider!.isConnected()) {
      debugPrint("[RetryService] ❌ No internet connection. Aborting queue processing.");
      _isProcessing = false;
      return;
    }

    debugPrint("[RetryService] 🔎 Found ${pendingTasks.length} pending tasks.");
    for (final task in pendingTasks) {
      if (await _dbHelper.getRequestById(task['id'] as int) != null) {
        await retryTask(task['id'] as int);
      }
    }

    debugPrint("[RetryService] ⏹️ Finished processing retry queue.");
    _isProcessing = false;
  }

  Future<bool> retryTask(int taskId) async {
    final task = await _dbHelper.getRequestById(taskId);
    if (task == null) {
      debugPrint("Retry failed: Task with ID $taskId not found in the queue.");
      return false;
    }

    bool success = false;
    Map<String, dynamic> payload;
    final String taskType = task['type'] as String;

    try {
      payload = jsonDecode(task['payload'] as String);
    } catch (e) {
      debugPrint("Error decoding payload for task $taskId (Type: $taskType): $e. Removing invalid task.");
      await _dbHelper.deleteRequestFromQueue(taskId);
      return false;
    }

    try {
      if (_authProvider == null) {
        debugPrint("RetryService has not been initialized. Cannot process task $taskId.");
        return false;
      }

      // --- Complex Task Handlers ---
      if (taskType == 'insitu_submission') {
        if (_marineInSituService == null) return false;
        final String logDirectoryPath = payload['localLogPath'];
        final jsonFilePath = p.join(logDirectoryPath, 'data.json');
        final file = File(jsonFilePath);
        if (!await file.exists()) {
          await _dbHelper.deleteRequestFromQueue(taskId);
          return false;
        }
        final content = await file.readAsString();
        final result = await _marineInSituService!.submitInSituSample(
          data: InSituSamplingData.fromJson(jsonDecode(content)),
          appSettings: _authProvider!.appSettings,
          authProvider: _authProvider!,
          logDirectory: logDirectoryPath,
        );
        success = result['success'];

      } else if (taskType == 'river_insitu_submission') {
        if (_riverInSituService == null) return false;
        final String jsonFilePath = payload['localLogPath'];
        final file = File(jsonFilePath);
        if (!await file.exists()) {
          await _dbHelper.deleteRequestFromQueue(taskId);
          return false;
        }
        final result = await _riverInSituService!.submitData(
          data: RiverInSituSamplingData.fromJson(jsonDecode(await file.readAsString())),
          appSettings: _authProvider!.appSettings,
          authProvider: _authProvider!,
          logDirectory: p.dirname(jsonFilePath),
        );
        success = result['success'];

      } else if (taskType == 'river_investigative_submission') {
        if (_riverInvestigativeService == null) return false;
        final String jsonFilePath = payload['localLogPath'];
        final file = File(jsonFilePath);
        if (!await file.exists()) {
          await _dbHelper.deleteRequestFromQueue(taskId);
          return false;
        }
        final result = await _riverInvestigativeService!.submitData(
          data: RiverInvesManualSamplingData.fromJson(jsonDecode(await file.readAsString())),
          appSettings: _authProvider!.appSettings,
          authProvider: _authProvider!,
          logDirectory: p.dirname(jsonFilePath),
        );
        success = result['success'];

      } else if (taskType == 'investigative_submission') {
        if (_marineInvestigativeService == null) return false;
        final String logDirectoryPath = payload['localLogPath'];
        final jsonFilePath = p.join(logDirectoryPath, 'data.json');
        final file = File(jsonFilePath);
        if (!await file.exists()) {
          await _dbHelper.deleteRequestFromQueue(taskId);
          return false;
        }
        final result = await _marineInvestigativeService!.submitInvestigativeSample(
          data: MarineInvesManualSamplingData.fromJson(jsonDecode(await file.readAsString())),
          appSettings: _authProvider!.appSettings,
          authProvider: _authProvider!,
          logDirectory: logDirectoryPath,
        );
        success = result['success'];

      } else if (taskType == 'tarball_submission') {
        if (_marineTarballService == null) return false;
        final String logDirectoryPath = payload['localLogPath'];
        final jsonFilePath = p.join(logDirectoryPath, 'data.json');
        final file = File(jsonFilePath);
        if (!await file.exists()) {
          await _dbHelper.deleteRequestFromQueue(taskId);
          return false;
        }
        final jsonData = jsonDecode(await file.readAsString());

        // --- START: Manual Reconstruction of Tarball Data (Fixing .fromJson error) ---
        final TarballSamplingData dataToResubmit = TarballSamplingData();
        dataToResubmit.firstSampler = jsonData['firstSampler'];
        dataToResubmit.firstSamplerUserId = jsonData['firstSamplerUserId'];
        dataToResubmit.secondSampler = jsonData['secondSampler'];
        dataToResubmit.samplingDate = jsonData['samplingDate'];
        dataToResubmit.samplingTime = jsonData['samplingTime'];
        dataToResubmit.selectedStateName = jsonData['selectedStateName'];
        dataToResubmit.selectedCategoryName = jsonData['selectedCategoryName'];
        dataToResubmit.selectedStation = jsonData['selectedStation'];
        dataToResubmit.stationLatitude = jsonData['stationLatitude'];
        dataToResubmit.stationLongitude = jsonData['stationLongitude'];
        dataToResubmit.currentLatitude = jsonData['currentLatitude'];
        dataToResubmit.currentLongitude = jsonData['currentLongitude'];
        dataToResubmit.distanceDifference = (jsonData['distanceDifference'] as num?)?.toDouble();
        dataToResubmit.distanceDifferenceRemarks = jsonData['distanceDifferenceRemarks'];
        dataToResubmit.classificationId = jsonData['classificationId'];
        dataToResubmit.selectedClassification = jsonData['selectedClassification'];
        dataToResubmit.optionalRemark1 = jsonData['optionalRemark1'];
        dataToResubmit.optionalRemark2 = jsonData['optionalRemark2'];
        dataToResubmit.optionalRemark3 = jsonData['optionalRemark3'];
        dataToResubmit.optionalRemark4 = jsonData['optionalRemark4'];
        dataToResubmit.reportId = jsonData['reportId'];
        dataToResubmit.submissionStatus = jsonData['submissionStatus'];
        dataToResubmit.submissionMessage = jsonData['submissionMessage'];

        // Helper to create File from path if it exists
        File? fileFromPath(dynamic path) => (path is String && path.isNotEmpty) ? File(path) : null;

        dataToResubmit.leftCoastalViewImage = fileFromPath(jsonData['leftCoastalViewImage']);
        dataToResubmit.rightCoastalViewImage = fileFromPath(jsonData['rightCoastalViewImage']);
        dataToResubmit.verticalLinesImage = fileFromPath(jsonData['verticalLinesImage']);
        dataToResubmit.horizontalLineImage = fileFromPath(jsonData['horizontalLineImage']);
        dataToResubmit.optionalImage1 = fileFromPath(jsonData['optionalImage1']);
        dataToResubmit.optionalImage2 = fileFromPath(jsonData['optionalImage2']);
        dataToResubmit.optionalImage3 = fileFromPath(jsonData['optionalImage3']);
        dataToResubmit.optionalImage4 = fileFromPath(jsonData['optionalImage4']);
        // --- END: Manual Reconstruction ---

        final result = await _marineTarballService!.submitTarballSample(
          data: dataToResubmit,
          appSettings: _authProvider!.appSettings,
          context: null,
          logDirectory: logDirectoryPath,
        );
        success = result['success'];

        // =======================================================================
        // MARINE REPORT HANDLERS
        // =======================================================================

      } else if (taskType == 'marine_npe_submission' || taskType == 'npe_submission') {
        if (_marineNpeService == null) return false;
        final String logDirectoryPath = payload['localLogPath'];
        final jsonFilePath = p.join(logDirectoryPath, 'data.json');
        final file = File(jsonFilePath);
        if (!await file.exists()) {
          await _dbHelper.deleteRequestFromQueue(taskId);
          return false;
        }

        final content = await file.readAsString();
        final jsonData = jsonDecode(content) as Map<String, dynamic>;
        final MarineManualNpeReportData dataToResubmit = MarineManualNpeReportData();

        // Reconstruction logic
        dataToResubmit.firstSamplerName = jsonData['firstSamplerName'];
        dataToResubmit.firstSamplerUserId = jsonData['firstSamplerUserId'];
        dataToResubmit.eventDate = jsonData['eventDate'];
        dataToResubmit.eventTime = jsonData['eventTime'];
        dataToResubmit.sourceOrigin = jsonData['sourceOrigin'];
        dataToResubmit.locationDescription = jsonData['locationDescription'];
        dataToResubmit.stateName = jsonData['stateName'];
        dataToResubmit.selectedStation = jsonData['selectedStation'];
        dataToResubmit.latitude = jsonData['latitude'];
        dataToResubmit.longitude = jsonData['longitude'];
        dataToResubmit.oxygenSaturation = jsonData['oxygenSaturation'];
        dataToResubmit.electricalConductivity = jsonData['electricalConductivity'];
        dataToResubmit.oxygenConcentration = jsonData['oxygenConcentration'];
        dataToResubmit.turbidity = jsonData['turbidity'];
        dataToResubmit.ph = jsonData['ph'];
        dataToResubmit.temperature = jsonData['temperature'];
        if (jsonData['fieldObservations'] != null) {
          dataToResubmit.fieldObservations = Map<String, bool>.from(jsonData['fieldObservations']);
        }
        dataToResubmit.othersObservationRemark = jsonData['othersObservationRemark'];
        dataToResubmit.possibleSource = jsonData['possibleSource'];
        dataToResubmit.image1Remark = jsonData['image1Remark'];
        dataToResubmit.image2Remark = jsonData['image2Remark'];
        dataToResubmit.image3Remark = jsonData['image3Remark'];
        dataToResubmit.image4Remark = jsonData['image4Remark'];
        dataToResubmit.tarballClassificationId = jsonData['tarballClassificationId'];
        dataToResubmit.selectedTarballClassification = jsonData['selectedTarballClassification'];
        dataToResubmit.reportId = jsonData['reportId'];

        if (jsonData['npe_image_1'] != null) dataToResubmit.image1 = File(jsonData['npe_image_1']);
        if (jsonData['npe_image_2'] != null) dataToResubmit.image2 = File(jsonData['npe_image_2']);
        if (jsonData['npe_image_3'] != null) dataToResubmit.image3 = File(jsonData['npe_image_3']);
        if (jsonData['npe_image_4'] != null) dataToResubmit.image4 = File(jsonData['npe_image_4']);

        final result = await _marineNpeService!.submitNpeReport(
          data: dataToResubmit,
          authProvider: _authProvider!,
          logDirectory: logDirectoryPath,
        );
        success = result['success'];

        // *** START: ADDED Pre-Departure Checklist ***
      } else if (taskType == 'pre_departure_submission') {
        if (_marinePreDepartureService == null) return false;
        final String logDirectoryPath = payload['localLogPath'];
        final jsonFilePath = p.join(logDirectoryPath, 'data.json');
        final file = File(jsonFilePath);
        if (!await file.exists()) {
          await _dbHelper.deleteRequestFromQueue(taskId);
          return false;
        }

        final content = await file.readAsString();
        final jsonData = jsonDecode(content) as Map<String, dynamic>;
        final MarineManualPreDepartureChecklistData dataToResubmit = MarineManualPreDepartureChecklistData();

        // Reconstruct Data from JSON
        dataToResubmit.reporterName = jsonData['reporterName'];
        dataToResubmit.reporterUserId = jsonData['reporterUserId'];
        dataToResubmit.submissionDate = jsonData['submissionDate'];
        dataToResubmit.location = jsonData['location'];
        if (jsonData['checklistItems'] != null) {
          dataToResubmit.checklistItems = Map<String, bool>.from(jsonData['checklistItems']);
        }
        if (jsonData['remarks'] != null) {
          dataToResubmit.remarks = Map<String, String>.from(jsonData['remarks']);
        }
        dataToResubmit.reportId = jsonData['reportId'];

        final result = await _marinePreDepartureService!.submitChecklist(
          data: dataToResubmit,
          authProvider: _authProvider!,
          appSettings: _authProvider!.appSettings,
          logDirectory: logDirectoryPath,
        );
        success = result['success'];
        // *** END: ADDED Pre-Departure Checklist ***

        // *** START: ADDED Sonde Calibration ***
      } else if (taskType == 'sonde_calibration_submission') {
        if (_marineSondeCalibrationService == null) return false;
        final String logDirectoryPath = payload['localLogPath'];
        final jsonFilePath = p.join(logDirectoryPath, 'data.json');
        final file = File(jsonFilePath);
        if (!await file.exists()) {
          await _dbHelper.deleteRequestFromQueue(taskId);
          return false;
        }

        final content = await file.readAsString();
        final jsonData = jsonDecode(content) as Map<String, dynamic>;
        final MarineManualSondeCalibrationData dataToResubmit = MarineManualSondeCalibrationData();

        // Reconstruct Data
        dataToResubmit.calibratedByUserId = jsonData['calibratedByUserId'];
        dataToResubmit.calibratedByUserName = jsonData['calibratedByUserName'];
        dataToResubmit.sondeSerialNumber = jsonData['sondeSerialNumber'];
        dataToResubmit.firmwareVersion = jsonData['firmwareVersion'];
        dataToResubmit.korVersion = jsonData['korVersion'];
        dataToResubmit.location = jsonData['location'];
        dataToResubmit.startDateTime = jsonData['startDateTime'];
        dataToResubmit.endDateTime = jsonData['endDateTime'];

        // Cast to double as JSON decodes numbers as int if no decimal places
        dataToResubmit.ph7Mv = (jsonData['ph_7_mv'] as num?)?.toDouble();
        dataToResubmit.ph7Before = (jsonData['ph_7_before'] as num?)?.toDouble();
        dataToResubmit.ph7After = (jsonData['ph_7_after'] as num?)?.toDouble();
        dataToResubmit.ph10Mv = (jsonData['ph_10_mv'] as num?)?.toDouble();
        dataToResubmit.ph10Before = (jsonData['ph_10_before'] as num?)?.toDouble();
        dataToResubmit.ph10After = (jsonData['ph_10_after'] as num?)?.toDouble();
        dataToResubmit.condBefore = (jsonData['cond_before'] as num?)?.toDouble();
        dataToResubmit.condAfter = (jsonData['cond_after'] as num?)?.toDouble();
        dataToResubmit.doBefore = (jsonData['do_before'] as num?)?.toDouble();
        dataToResubmit.doAfter = (jsonData['do_after'] as num?)?.toDouble();
        dataToResubmit.turbidity0Before = (jsonData['turbidity_0_before'] as num?)?.toDouble();
        dataToResubmit.turbidity0After = (jsonData['turbidity_0_after'] as num?)?.toDouble();
        dataToResubmit.turbidity124Before = (jsonData['turbidity_124_before'] as num?)?.toDouble();
        dataToResubmit.turbidity124After = (jsonData['turbidity_124_after'] as num?)?.toDouble();

        dataToResubmit.calibrationStatus = jsonData['calibration_status'];
        dataToResubmit.remarks = jsonData['remarks'];
        dataToResubmit.reportId = jsonData['reportId'];

        final result = await _marineSondeCalibrationService!.submitCalibration(
          data: dataToResubmit,
          authProvider: _authProvider!,
          appSettings: _authProvider!.appSettings,
          logDirectory: logDirectoryPath,
        );
        success = result['success'];
        // *** END: ADDED Sonde Calibration ***

        // *** START: ADDED Equipment Maintenance ***
      } else if (taskType == 'equipment_maintenance_submission') {
        if (_marineEquipmentMaintenanceService == null) return false;
        final String logDirectoryPath = payload['localLogPath'];
        final jsonFilePath = p.join(logDirectoryPath, 'data.json');
        final file = File(jsonFilePath);
        if (!await file.exists()) {
          await _dbHelper.deleteRequestFromQueue(taskId);
          return false;
        }

        final content = await file.readAsString();
        final jsonData = jsonDecode(content) as Map<String, dynamic>;
        final MarineManualEquipmentMaintenanceData dataToResubmit = MarineManualEquipmentMaintenanceData();

        // Reconstruct Data
        dataToResubmit.conductedByUserId = jsonData['conductedByUserId'];
        dataToResubmit.conductedByUserName = jsonData['conductedByUserName'];
        dataToResubmit.maintenanceDate = jsonData['maintenanceDate'];
        dataToResubmit.lastMaintenanceDate = jsonData['lastMaintenanceDate'];
        dataToResubmit.scheduleMaintenance = jsonData['scheduleMaintenance'];
        dataToResubmit.isReplacement = jsonData['isReplacement'] ?? false;
        dataToResubmit.timeStart = jsonData['timeStart'];
        dataToResubmit.timeEnd = jsonData['timeEnd'];
        dataToResubmit.location = jsonData['location'];

        if (jsonData['ysiSondeChecks'] != null) {
          dataToResubmit.ysiSondeChecks = Map<String, bool>.from(jsonData['ysiSondeChecks']);
        }
        dataToResubmit.ysiSondeComments = jsonData['ysiSondeComments'];

        // Handle nested maps for Sensor Checks
        if (jsonData['ysiSensorChecks'] != null) {
          dataToResubmit.ysiSensorChecks = (jsonData['ysiSensorChecks'] as Map<String, dynamic>).map(
                (key, value) => MapEntry(key, Map<String, bool>.from(value)),
          );
        }
        dataToResubmit.ysiSensorComments = jsonData['ysiSensorComments'];

        // Handle nested maps for Replacements
        if (jsonData['ysiReplacements'] != null) {
          dataToResubmit.ysiReplacements = (jsonData['ysiReplacements'] as Map<String, dynamic>).map(
                (key, value) => MapEntry(key, Map<String, String>.from(value)),
          );
        }

        if (jsonData['vanDornChecks'] != null) {
          dataToResubmit.vanDornChecks = (jsonData['vanDornChecks'] as Map<String, dynamic>).map(
                (key, value) => MapEntry(key, Map<String, bool>.from(value)),
          );
        }
        dataToResubmit.vanDornComments = jsonData['vanDornComments'];
        dataToResubmit.vanDornCurrentSerial = jsonData['vanDornCurrentSerial'];
        dataToResubmit.vanDornNewSerial = jsonData['vanDornNewSerial'];

        if (jsonData['vanDornReplacements'] != null) {
          dataToResubmit.vanDornReplacements = (jsonData['vanDornReplacements'] as Map<String, dynamic>).map(
                (key, value) => MapEntry(key, Map<String, String>.from(value)),
          );
        }
        dataToResubmit.reportId = jsonData['reportId'];

        final result = await _marineEquipmentMaintenanceService!.submitMaintenanceReport(
          data: dataToResubmit,
          authProvider: _authProvider!,
          appSettings: _authProvider!.appSettings,
          logDirectory: logDirectoryPath,
        );
        success = result['success'];
        // *** END: ADDED Equipment Maintenance ***

        // =======================================================================
        // SIMPLE API / FTP HANDLERS
        // =======================================================================

      } else if (taskType == 'api') {
        final endpoint = task['endpoint_or_path'] as String;
        final method = payload['method'] as String;
        final baseUrl = await _serverConfigService.getActiveApiUrl();

        if (method == 'POST_MULTIPART') {
          final Map<String, String> fields = Map<String, String>.from(payload['fields'] ?? {});
          final Map<String, File> files = (payload['files'] as Map<String, dynamic>?)
              ?.map((key, value) => MapEntry(key, File(value as String))) ?? {};

          bool allFilesExist = true;
          for (var entry in files.entries) {
            if (!await entry.value.exists()) {
              allFilesExist = false;
            }
          }
          if (!allFilesExist) {
            await _dbHelper.deleteRequestFromQueue(taskId);
            return false;
          }
          final result = await _baseApiService.postMultipart(baseUrl: baseUrl, endpoint: endpoint, fields: fields, files: files);
          success = result['success'];
        } else {
          final Map<String, dynamic> body = Map<String, dynamic>.from(payload['body'] ?? {});
          final result = await _baseApiService.post(baseUrl, endpoint, body);
          success = result['success'];
        }

      } else if (taskType == 'ftp') {
        final remotePath = task['endpoint_or_path'] as String;
        final localFile = File(payload['localFilePath'] as String);
        final int? ftpConfigId = payload['ftpConfigId'] as int?;

        if (ftpConfigId == null) {
          await _dbHelper.deleteRequestFromQueue(taskId);
          return false;
        }

        // --- START FIX: Check if this FTP module is enabled in preferences ---
        final ftpConfigs = await _dbHelper.loadFtpConfigs() ?? [];
        final config = ftpConfigs.firstWhere(
              (c) => c['ftp_config_id'] == ftpConfigId,
          orElse: () => <String, dynamic>{},
        );

        if (config.isNotEmpty) {
          String? moduleKey = config['ftp_module'];
          // Map legacy module names if needed (e.g., river_manual -> river_in_situ)
          if (moduleKey == 'river_manual') {
            moduleKey = 'river_in_situ';
          } else if (moduleKey == 'marine_manual') {
            moduleKey = 'marine_in_situ';
          }
          // Add other mappings if needed for consistency with user preferences keys

          if (moduleKey != null) {
            final pref = await _userPreferencesService.getModulePreference(moduleKey);
            final bool isFtpEnabled = pref?['is_ftp_enabled'] ?? true;

            if (!isFtpEnabled) {
              debugPrint("RetryService: FTP upload for module '$moduleKey' is disabled by user. Removing task $taskId.");
              await _dbHelper.deleteRequestFromQueue(taskId);
              return false;
            }
          }
        }
        // --- END FIX ---

        if (await localFile.exists()) {
          if (config.isEmpty) return false; // Config missing

          final result = await _ftpService.uploadFile(config: config, fileToUpload: localFile, remotePath: remotePath);
          success = result['success'];
        } else {
          await _dbHelper.deleteRequestFromQueue(taskId);
          return false;
        }

      } else {
        debugPrint("Unknown task type '$taskType' for task ID $taskId. Cannot retry. Removing task.");
        await _dbHelper.deleteRequestFromQueue(taskId);
      }

    } on SessionExpiredException catch (e) {
      debugPrint("Session expired during retry attempt: $e");
      success = false;
    } catch (e, stacktrace) {
      debugPrint("A critical error occurred while retrying task $taskId: $e");
      debugPrint("Stacktrace: $stacktrace");
      success = false;
    }

    if (success) {
      debugPrint("Task $taskId (Type: $taskType) completed successfully. Removing from queue.");
      await _dbHelper.deleteRequestFromQueue(taskId);

      if (taskType.endsWith('_submission') && payload['localLogPath'] != null) {
        String pathToCheck = payload['localLogPath'];
        bool isDirectory = await Directory(pathToCheck).exists();
        if (!isDirectory && pathToCheck.endsWith('.json')) {
          pathToCheck = p.dirname(pathToCheck);
          isDirectory = true;
        }
        _cleanUpTemporaryZipFiles(pathToCheck, isDirectory: isDirectory);
      }

      if (taskType == 'ftp' && payload['localFilePath'] != null && (payload['localFilePath'] as String).endsWith('.zip')) {
        _cleanUpTemporaryZipFiles(payload['localFilePath'], isDirectory: false);
      }

    } else {
      debugPrint("Retry attempt for task $taskId (Type: $taskType) failed. It will remain in the queue.");
    }

    return success;
  }

  void _cleanUpTemporaryZipFiles(String path, {required bool isDirectory}) async {
    try {
      if (isDirectory) {
        final dir = Directory(path);
        if (await dir.exists()) {
          final filesInDir = dir.listSync();
          for (var entity in filesInDir) {
            if (entity is File && entity.path.endsWith('.zip')) {
              debugPrint("Deleting temporary zip file from directory: ${entity.path}");
              await entity.delete();
            }
          }
        }
      } else {
        final file = File(path);
        if (await file.exists() && path.endsWith('.zip')) {
          debugPrint("Deleting temporary zip file: ${file.path}");
          await file.delete();
        }
      }
    } catch (e) {
      debugPrint("Error cleaning up temporary zip file(s) for path $path: $e");
    }
  }

}