// lib/services/marine_npe_report_service.dart

import 'dart:async';
import 'dart:io';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:path/path.dart' as p;

import '../auth_provider.dart';
import '../models/marine_manual_npe_report_data.dart';
import 'local_storage_service.dart';
import 'server_config_service.dart';
import 'zipping_service.dart';
import 'submission_api_service.dart';
import 'submission_ftp_service.dart';
import 'telegram_service.dart';
import 'retry_service.dart';
import 'package:environment_monitoring_app/services/database_helper.dart';
import 'user_preferences_service.dart'; // ADDED

class MarineNpeReportService {
  final SubmissionApiService _submissionApiService = SubmissionApiService();
  final SubmissionFtpService _submissionFtpService = SubmissionFtpService();
  final ZippingService _zippingService = ZippingService();
  final LocalStorageService _localStorageService = LocalStorageService();
  final ServerConfigService _serverConfigService = ServerConfigService();
  final UserPreferencesService _userPreferencesService = UserPreferencesService(); // ADDED
  final DatabaseHelper _dbHelper = DatabaseHelper();
  final RetryService _retryService = RetryService();
  final TelegramService _telegramService;

  MarineNpeReportService(this._telegramService);

  Future<List<Map<String, dynamic>>> getLocalNpeLogs() async {
    return await _localStorageService.getAllNpeLogs();
  }

  Future<Map<String, dynamic>> submitNpeReport({
    required MarineManualNpeReportData data,
    required AuthProvider authProvider,
    String? logDirectory,
  }) async {
    const String moduleName = 'marine_report';

    final connectivityResult = await Connectivity().checkConnectivity();
    bool isOnline = !connectivityResult.contains(ConnectivityResult.none);
    bool isOfflineSession = authProvider.isLoggedIn && (authProvider.profileData?['token']?.startsWith("offline-session-") ?? false);

    if (isOnline && isOfflineSession) {
      final bool transitionSuccess = await authProvider.checkAndTransitionToOnlineSession();
      if (transitionSuccess) isOfflineSession = false; else isOnline = false;
    }

    if (isOnline && !isOfflineSession) {
      return await _performNpeOnlineSubmission(
        data: data,
        moduleName: moduleName,
        authProvider: authProvider,
        logDirectory: logDirectory,
      );
    } else {
      return await _performNpeOfflineQueuing(
        data: data,
        moduleName: moduleName,
      );
    }
  }

  Future<Map<String, dynamic>> _performNpeOnlineSubmission({
    required MarineManualNpeReportData data,
    required String moduleName,
    required AuthProvider authProvider,
    String? logDirectory,
  }) async {
    final serverName = (await _serverConfigService.getActiveApiConfig())?['config_name'] as String? ?? 'Default';
    final imageFilesWithNulls = data.toApiImageFiles();
    imageFilesWithNulls.removeWhere((key, value) => value == null);
    final Map<String, File> finalImageFiles = imageFilesWithNulls.cast<String, File>();

    bool anyApiSuccess = false;
    Map<String, dynamic> apiDataResult = {};
    Map<String, dynamic> apiImageResult = {};

    // 1. API Submission
    // Check if API is enabled in preferences
    final pref = await _userPreferencesService.getModulePreference(moduleName);
    bool isApiEnabled = pref?['is_api_enabled'] ?? true;

    if (isApiEnabled) {
      try {
        apiDataResult = await _submissionApiService.submitPost(
          moduleName: moduleName,
          endpoint: 'marine/npe/report',
          body: data.toApiFormData(),
        );

        if (apiDataResult['success'] == false && (apiDataResult['message'] as String?)?.contains('Unauthorized') == true) {
          if (await authProvider.attemptSilentRelogin()) {
            apiDataResult = await _submissionApiService.submitPost(
              moduleName: moduleName,
              endpoint: 'marine/npe/report',
              body: data.toApiFormData(),
            );
          }
        }

        if (apiDataResult['success'] == true) {
          anyApiSuccess = true;
          data.reportId = apiDataResult['data']?['npe_id']?.toString();

          if (data.reportId != null && finalImageFiles.isNotEmpty) {
            apiImageResult = await _submissionApiService.submitMultipart(
              moduleName: moduleName,
              endpoint: 'marine/npe/images',
              fields: {'npe_id': data.reportId!},
              files: finalImageFiles,
            );
            if (apiImageResult['success'] != true) anyApiSuccess = false;
          }
        }
      } on SocketException catch (e) {
        anyApiSuccess = false;
        apiDataResult = {'success': false, 'message': "API Network Error: $e"};
        await _retryService.addApiToQueue(endpoint: 'marine/npe/report', method: 'POST', body: data.toApiFormData());
      } on TimeoutException catch (e) {
        anyApiSuccess = false;
        apiDataResult = {'success': false, 'message': "API Timeout: $e"};
        await _retryService.addApiToQueue(endpoint: 'marine/npe/report', method: 'POST', body: data.toApiFormData());
      }
    } else {
      anyApiSuccess = true; // Treated as success if disabled by user
    }

    // 2. FTP Submission
    Map<String, dynamic> ftpResults = {'statuses': []};
    bool anyFtpSuccess = false;

    bool isFtpEnabled = pref?['is_ftp_enabled'] ?? true;
    // Check if this record was already successfully sent to FTP (L4 or S4 status)
    bool previousFtpSuccess = data.submissionStatus == 'L4' || data.submissionStatus == 'S4';
    // Check if there are any active FTP configs for this module
    final enabledFtpConfigs = await _userPreferencesService.getEnabledFtpConfigsForModule(moduleName);

    if (!isFtpEnabled) {
      ftpResults = {'statuses': [{'status': 'Skipped', 'message': 'FTP disabled by user.', 'success': true}]};
      anyFtpSuccess = true;
    } else if (previousFtpSuccess) {
      debugPrint("FTP submission skipped: Already successful in previous attempt.");
      ftpResults = {'statuses': [{'status': 'Skipped', 'message': 'Already successful.', 'success': true}]};
      anyFtpSuccess = true;
    } else if (enabledFtpConfigs.isEmpty) {
      debugPrint("FTP submission skipped: No active FTP configurations found for $moduleName.");
      ftpResults = {'statuses': [{'status': 'Skipped', 'message': 'No active FTP servers.', 'success': true}]};
      anyFtpSuccess = true; // Treated as success to avoid indefinite L1 state
    } else {
      try {
        ftpResults = await _generateAndUploadFtpFiles(data, finalImageFiles, serverName, moduleName);
        anyFtpSuccess = !(ftpResults['statuses'] as List).any((status) => status['success'] == false && status['status'] != 'Not Configured');
      } catch (e) {
        debugPrint("FTP Error: $e");
        anyFtpSuccess = false;
      }
    }

    // 3. Determine Final Status
    final bool overallSuccess = anyApiSuccess || anyFtpSuccess;
    String finalStatus = (anyApiSuccess && anyFtpSuccess) ? 'S4' : (anyApiSuccess ? 'S3' : (anyFtpSuccess ? 'L4' : 'L1'));
    String finalMessage = overallSuccess ? 'Submission successful.' : 'Submission failed/queued.';

    await _logAndSave(
      data: data,
      status: finalStatus,
      message: finalMessage,
      apiResults: [apiDataResult, apiImageResult],
      ftpStatuses: ftpResults['statuses'],
      serverName: serverName,
      finalImageFiles: finalImageFiles,
      logDirectory: logDirectory,
    );

    if (overallSuccess) _handleNpeSuccessAlert(data, authProvider);

    return {'success': overallSuccess, 'message': finalMessage, 'reportId': data.reportId};
  }

  Future<Map<String, dynamic>> _performNpeOfflineQueuing({
    required MarineManualNpeReportData data,
    required String moduleName,
  }) async {
    final serverConfig = await _serverConfigService.getActiveApiConfig();
    final serverName = serverConfig?['config_name'] as String? ?? 'Default';

    data.submissionStatus = 'L1';
    data.submissionMessage = 'Queued (Offline)';

    final String? localLogPath = await _localStorageService.saveNpeReportData(data, serverName: serverName);

    if (localLogPath == null) return {'success': false, 'message': "Failed to save locally."};

    await _retryService.queueTask(
      type: 'npe_submission',
      payload: {'module': moduleName, 'localLogPath': localLogPath, 'serverConfig': serverConfig},
    );

    return {'success': true, 'message': "Saved locally and queued for upload."};
  }

  Future<Map<String, dynamic>> _generateAndUploadFtpFiles(MarineManualNpeReportData data, Map<String, File> imageFiles, String serverName, String moduleName) async {
    // --- FIX START: Logic to determine correct Station Code or Sanitized New Location ---
    String stationCode;

    if (data.selectedStation != null) {
      // If it's an existing station (Manual or Tarball)
      stationCode = data.selectedStation?['man_station_code'] ??
          data.selectedStation?['tbl_station_code'] ??
          'NA';
    } else {
      // If it's a New Location, use the description and replace spaces with underscores
      String rawDesc = data.locationDescription?.trim() ?? 'NEW_LOCATION';
      if (rawDesc.isEmpty) rawDesc = 'NEW_LOCATION';
      stationCode = rawDesc.replaceAll(' ', '_');
    }
    // --- FIX END ---

    final fileTimestamp = "${data.eventDate}_${data.eventTime}".replaceAll(':', '-').replaceAll(' ', '_');
    final baseFileName = '${stationCode}_${fileTimestamp}_NPE';

    final Directory? logDirectory = await _localStorageService.getLogDirectory(serverName: serverName, module: 'marine', subModule: 'marine_npe_report');
    final Directory? localSubmissionDir = logDirectory != null ? Directory(p.join(logDirectory.path, data.reportId ?? baseFileName)) : null;

    if (localSubmissionDir != null && !await localSubmissionDir.exists()) await localSubmissionDir.create(recursive: true);

    final dataZip = await _zippingService.createDataZip(
      jsonDataMap: {'db.json': jsonEncode(data.toDbJson())},
      baseFileName: baseFileName,
      destinationDir: localSubmissionDir,
    );

    Map<String, dynamic> ftpDataResult = {'success': true, 'statuses': []};
    if (dataZip != null) {
      ftpDataResult = await _submissionFtpService.submit(moduleName: moduleName, fileToUpload: dataZip, remotePath: '/${p.basename(dataZip.path)}');
    }

    final imageZip = await _zippingService.createImageZip(
      imageFiles: imageFiles.values.toList(),
      baseFileName: baseFileName,
      destinationDir: localSubmissionDir,
    );
    Map<String, dynamic> ftpImageResult = {'success': true, 'statuses': []};
    if (imageZip != null) {
      ftpImageResult = await _submissionFtpService.submit(moduleName: moduleName, fileToUpload: imageZip, remotePath: '/${p.basename(imageZip.path)}');
    }

    return {
      'statuses': <Map<String, dynamic>>[
        ...(ftpDataResult['statuses'] as List<dynamic>? ?? []),
        ...(ftpImageResult['statuses'] as List<dynamic>? ?? []),
      ],
    };
  }

  Future<void> _logAndSave({
    required MarineManualNpeReportData data,
    required String status,
    required String message,
    required List<Map<String, dynamic>> apiResults,
    required List<Map<String, dynamic>> ftpStatuses,
    required String serverName,
    required Map<String, File> finalImageFiles,
    String? logDirectory,
  }) async {
    data.submissionStatus = status;
    data.submissionMessage = message;
    final fileTimestamp = "${data.eventDate}_${data.eventTime}".replaceAll(':', '-').replaceAll(' ', '_');

    if (logDirectory != null) {
      final Map<String, dynamic> updatedLogData = data.toDbJson();
      updatedLogData['submissionStatus'] = status;
      updatedLogData['submissionMessage'] = message;
      updatedLogData['logDirectory'] = logDirectory;
      updatedLogData['serverConfigName'] = serverName;
      updatedLogData['api_status'] = jsonEncode(apiResults.where((r) => r.isNotEmpty).toList());
      updatedLogData['ftp_status'] = jsonEncode(ftpStatuses);

      final imageFilePaths = data.toApiImageFiles();
      imageFilePaths.forEach((key, file) {
        if (file != null) updatedLogData[key] = file.path;
      });

      await _localStorageService.updateNpeLog(updatedLogData);
    } else {
      await _localStorageService.saveNpeReportData(data, serverName: serverName);
    }

    final logData = {
      'submission_id': data.reportId ?? fileTimestamp,
      'module': 'marine',
      'type': 'NPE',
      'status': status,
      'message': message,
      'report_id': data.reportId,
      'created_at': DateTime.now().toIso8601String(),
      'form_data': jsonEncode(data.toDbJson()),
      'image_data': jsonEncode(finalImageFiles.values.map((f) => f.path).toList()),
      'server_name': serverName,
      'api_status': jsonEncode(apiResults),
      'ftp_status': jsonEncode(ftpStatuses),
    };
    await _dbHelper.saveSubmissionLog(logData);
  }

  Future<void> _handleNpeSuccessAlert(MarineManualNpeReportData data, AuthProvider authProvider) async {
    try {
      final message = data.generateTelegramAlertMessage();
      if (!await _telegramService.sendAlertImmediately('marine_npe_report', message, authProvider.appSettings)) {
        await _telegramService.queueMessage('marine_npe_report', message, authProvider.appSettings);
      }
    } catch (e) { debugPrint("Telegram Alert Error: $e"); }
  }
}