// lib/services/marine_manual_sonde_calibration_service.dart

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

import '../auth_provider.dart';
import '../models/marine_manual_sonde_calibration_data.dart';
import 'api_service.dart';
import 'package:environment_monitoring_app/services/database_helper.dart';
import 'package:environment_monitoring_app/services/local_storage_service.dart';
import 'package:environment_monitoring_app/services/server_config_service.dart';
import 'package:environment_monitoring_app/services/retry_service.dart';
import 'package:environment_monitoring_app/services/submission_api_service.dart';

import 'base_api_service.dart'; // Import for SessionExpiredException

class MarineManualSondeCalibrationService {
  // Use the new generic submission service
  final SubmissionApiService _submissionApiService = SubmissionApiService();
  final LocalStorageService _localStorageService = LocalStorageService();
  final ServerConfigService _serverConfigService = ServerConfigService();
  final DatabaseHelper _dbHelper = DatabaseHelper();
  final RetryService _retryService = RetryService();

  // The ApiService is kept only if other non-submission methods need it.
  // For this refactor, we'll remove it from the constructor.
  // final ApiService _apiService;
  // MarineManualSondeCalibrationService(this._apiService);
  MarineManualSondeCalibrationService(ApiService apiService); // Keep constructor signature for main.dart

  /// Main submission method with online/offline branching logic
  Future<Map<String, dynamic>> submitCalibration({
    required MarineManualSondeCalibrationData data,
    required AuthProvider authProvider,
    List<Map<String, dynamic>>? appSettings, // Added for consistency
    BuildContext? context, // Added for consistency
    String? logDirectory,
  }) async {
    const String moduleName = 'marine_sonde_calibration';

    // --- START: ADDED LINE ---
    // Populate the user name from the AuthProvider
    data.calibratedByUserName = authProvider.profileData?['first_name'] as String?;
    // --- END: ADDED LINE ---

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

    if (isOnline && isOfflineSession) {
      debugPrint(
          "$moduleName submission online during offline session. Attempting auto-relogin...");
      final bool transitionSuccess =
      await authProvider.checkAndTransitionToOnlineSession();
      if (transitionSuccess) {
        isOfflineSession = false;
      } else {
        isOnline = false;
      }
    }

    if (isOnline && !isOfflineSession) {
      debugPrint("Proceeding with direct ONLINE $moduleName submission...");
      return await _performOnlineSubmission(
        data: data,
        moduleName: moduleName,
        authProvider: authProvider,
        logDirectory: logDirectory,
      );
    } else {
      debugPrint("Proceeding with OFFLINE $moduleName queuing mechanism...");
      return await _performOfflineQueuing(
        data: data,
        moduleName: moduleName,
      );
    }
  }

  /// Handles the direct online submission.
  Future<Map<String, dynamic>> _performOnlineSubmission({
    required MarineManualSondeCalibrationData data,
    required String moduleName,
    required AuthProvider authProvider,
    String? logDirectory,
  }) async {
    final serverName =
        (await _serverConfigService.getActiveApiConfig())?['config_name']
        as String? ??
            'Default';
    Map<String, dynamic> apiResult;

    try {
      apiResult = await _submissionApiService.submitPost(
        moduleName: moduleName,
        endpoint: 'marine/calibration', // Endpoint from marine_api_service.dart
        body: data.toApiFormData(),
      );
    } on SessionExpiredException {
      final bool reloginSuccess = await authProvider.attemptSilentRelogin();
      if (reloginSuccess) {
        apiResult = await _submissionApiService.submitPost(
          moduleName: moduleName,
          endpoint: 'marine/calibration',
          body: data.toApiFormData(),
        );
      } else {
        apiResult = {
          'success': false,
          'message': 'Session expired. Please log in again.'
        };
      }
    } on SocketException catch (e) {
      apiResult = {
        'success': false,
        'message': "API submission failed with network error: $e"
      };
      // submission_api_service will queue this failure
    } on TimeoutException catch (e) {
      apiResult = {
        'success': false,
        'message': "API submission timed out: $e"
      };
      // submission_api_service will queue this failure
    } catch (e) {
      apiResult = {
        'success': false,
        'message': 'An unexpected error occurred: $e'
      };
    }

    // Log the final result
    final bool overallSuccess = apiResult['success'] == true;
    final String finalMessage =
        apiResult['message'] ?? (overallSuccess ? 'Submission successful.' : 'Submission failed.');
    final String finalStatus = overallSuccess ? 'S4' : 'L1'; // S4 = API Success

    if (overallSuccess) {
      // Assuming the API returns an ID. Adjust 'calibration_id' if needed.
      data.reportId = apiResult['data']?['calibration_id']?.toString();
    }

    await _logAndSave(
      data: data,
      status: finalStatus,
      message: finalMessage,
      apiResult: apiResult,
      serverName: serverName,
      logDirectory: logDirectory,
    );

    return apiResult;
  }

  /// Handles saving the submission to local storage and queuing for retry.
  Future<Map<String, dynamic>> _performOfflineQueuing({
    required MarineManualSondeCalibrationData data,
    required String moduleName,
  }) async {
    final serverConfig = await _serverConfigService.getActiveApiConfig();
    final serverName =
        serverConfig?['config_name'] as String? ?? 'Default';

    data.submissionStatus = 'L1';
    data.submissionMessage = 'Sonde Calibration queued due to being offline.';

    // This method is added to LocalStorageService
    final String? localLogPath =
    await _localStorageService.saveSondeCalibrationData(data, serverName: serverName);

    if (localLogPath == null) {
      const message =
          "Failed to save Sonde Calibration to local device storage.";
      await _logAndSave(
          data: data,
          status: 'Error',
          message: message,
          apiResult: {},
          serverName: serverName);
      return {'success': false, 'message': message};
    }

    await _retryService.queueTask(
      type: 'sonde_calibration_submission', // New task type
      payload: {
        'module': moduleName,
        'localLogPath': localLogPath,
        'serverConfig': serverConfig,
      },
    );

    const successMessage =
        "No internet connection. Sonde Calibration has been saved and queued for upload.";
    return {'success': true, 'message': successMessage};
  }

  /// Logs the submission to the local file system and the central SQL database.
  Future<void> _logAndSave({
    required MarineManualSondeCalibrationData data,
    required String status,
    required String message,
    required Map<String, dynamic> apiResult,
    required String serverName,
    String? logDirectory,
  }) async {
    data.submissionStatus = status;
    data.submissionMessage = message;

    final fileTimestamp = data.startDateTime?.replaceAll(':', '-').replaceAll(' ', '_') ?? DateTime.now().toIso8601String();

    // --- START: MODIFIED BLOCK ---
    // Use the new toDbJson() method to get ALL data for logging
    final Map<String, dynamic> logDataMap = data.toDbJson();
    // Add submission-specific metadata
    logDataMap['api_status'] = jsonEncode(apiResult);
    logDataMap['serverConfigName'] = serverName;
    // --- END: MODIFIED BLOCK ---


    if (logDirectory != null) {
      // This is an update to an existing log file
      logDataMap['logDirectory'] = logDirectory; // Ensure logDirectory is in the map
      await _localStorageService.updateSondeCalibrationLog(logDataMap);
    } else {
      // This is a new log
      // Pass the complete data object, which now includes the user name
      await _localStorageService.saveSondeCalibrationData(data, serverName: serverName);
    }

    final logData = {
      'submission_id': data.reportId ?? fileTimestamp,
      'module': 'marine',
      'type': 'Sonde Calibration',
      'status': data.submissionStatus,
      'message': data.submissionMessage,
      'report_id': data.reportId,
      'created_at': DateTime.now().toIso8601String(),
      'form_data': jsonEncode(data.toDbJson()), // <-- Use toDbJson here
      'image_data': null, // No images
      'server_name': serverName,
      'api_status': jsonEncode(apiResult),
      'ftp_status': null, // No FTP
    };
    await _dbHelper.saveSubmissionLog(logData);
  }
}