// lib/services/ftp_service.dart import 'dart:io'; import 'package:flutter/foundation.dart'; import 'package:ftpconnect/ftpconnect.dart'; import 'package:environment_monitoring_app/services/server_config_service.dart'; // --- ADDED: Import for the new service that manages the retry queue --- import 'package:environment_monitoring_app/services/retry_service.dart'; // --- ADDED: Import for the local database helper --- import 'package:environment_monitoring_app/services/api_service.dart'; class FtpService { final ServerConfigService _serverConfigService = ServerConfigService(); // --- REMOVED: This creates an infinite loop with RetryService --- // final RetryService _retryService = RetryService(); final DatabaseHelper _dbHelper = DatabaseHelper(); // --- ADDED: Instance of DatabaseHelper to get all configs --- /// Uploads a single file to the active server's FTP. /// /// [fileToUpload] The local file to be uploaded. /// [remotePath] The destination path on the FTP server (e.g., '/uploads/images/'). /// Returns a map with 'success' and 'message' keys. // --- MODIFIED: Method now attempts to upload to multiple servers --- Future> uploadFile(File fileToUpload, String remotePath) async { final configs = await _dbHelper.loadFtpConfigs() ?? []; // Get all FTP configs final latestConfigs = configs.take(2).toList(); // Limit to the two latest configs if (latestConfigs.isEmpty) { return {'success': false, 'message': 'FTP credentials are not configured or selected.'}; } // Loop through each of the two latest configurations and attempt to upload for (final configMap in latestConfigs) { final config = configMap['config_json']; // The data is nested under this key final ftpHost = config?['ftp_host'] as String?; final ftpUser = config?['ftp_user'] as String?; final ftpPass = config?['ftp_pass'] as String?; final ftpPort = config?['ftp_port'] as int? ?? 21; if (ftpHost == null || ftpUser == null || ftpPass == null) { debugPrint('FTP: Configuration is incomplete. Skipping to next server if available.'); continue; } final ftpConnect = FTPConnect( ftpHost, user: ftpUser, pass: ftpPass, port: ftpPort, showLog: kDebugMode, // Show logs only in debug mode timeout: 60, // --- MODIFIED: Set the timeout to 60 seconds --- ); try { debugPrint('FTP: Connecting to $ftpHost...'); await ftpConnect.connect(); debugPrint('FTP: Uploading file ${fileToUpload.path} to $remotePath...'); bool res = await ftpConnect.uploadFileWithRetry( fileToUpload, pRemoteName: remotePath, pRetryCount: 3, // --- MODIFIED: Retry three times on failure --- ); await ftpConnect.disconnect(); // Disconnect immediately upon success if (res) { debugPrint('FTP upload to $ftpHost succeeded.'); return {'success': true, 'message': 'File uploaded successfully via FTP.'}; } else { debugPrint('FTP upload to $ftpHost failed after retries. Trying next server.'); continue; // Move to the next configuration in the loop } } catch (e) { debugPrint('FTP upload to $ftpHost failed with an exception. Trying next server. Error: $e'); try { // Attempt to disconnect even if an error occurred during connect/upload await ftpConnect.disconnect(); } catch (_) { // Ignore errors during disconnect } continue; // Move to the next configuration in the loop } } // If the loop completes and no server was successful, queue for manual retry. final retryService = RetryService(); debugPrint('All FTP upload attempts failed. Queueing for manual retry.'); await retryService.addFtpToQueue( localFilePath: fileToUpload.path, remotePath: remotePath ); return {'success': false, 'message': 'All FTP upload attempts failed and have been queued for manual retry.'}; } }