// lib/models/tarball_data.dart import 'dart:io'; import 'dart:convert'; import 'package:environment_monitoring_app/models/marine_manual_npe_report_data.dart'; /// This class holds all the data collected across the multi-step tarball sampling form. /// It acts as a temporary data container that is passed between screens. class TarballSamplingData { // --- Step 1 Data: Collected in TarballSamplingStep1 --- String? firstSampler; int? firstSamplerUserId; Map? secondSampler; // Holds the full user map for the 2nd sampler String? samplingDate; String? samplingTime; String? selectedStateName; String? selectedCategoryName; Map? selectedStation; // Holds the full station map String? stationLatitude; String? stationLongitude; String? currentLatitude; String? currentLongitude; double? distanceDifference; String? distanceDifferenceRemarks; // --- Step 2 Data: Collected in TarballSamplingStep2 --- int? classificationId; // NECESSARY CHANGE: Add property to hold the full classification object. Map? selectedClassification; File? leftCoastalViewImage; File? rightCoastalViewImage; File? verticalLinesImage; File? horizontalLineImage; File? optionalImage1; String? optionalRemark1; File? optionalImage2; String? optionalRemark2; File? optionalImage3; String? optionalRemark3; File? optionalImage4; String? optionalRemark4; // --- Step 3 Data: For handling the submission response --- String? reportId; String? submissionStatus; String? submissionMessage; /// Converts tarball data into a pre-filled NPE Report data object. MarineManualNpeReportData toNpeReportData() { final npeData = MarineManualNpeReportData(); npeData.firstSamplerName = firstSampler; npeData.firstSamplerUserId = firstSamplerUserId; npeData.eventDate = samplingDate; npeData.eventTime = samplingTime; npeData.selectedStation = selectedStation; // Pass the whole station map npeData.latitude = currentLatitude; npeData.longitude = currentLongitude; npeData.stateName = selectedStateName; // Pre-tick the relevant observation for a tarball event. npeData.fieldObservations['Observation of tar balls'] = true; // Transfer images final availableImages = [ leftCoastalViewImage, rightCoastalViewImage, verticalLinesImage, horizontalLineImage, optionalImage1, optionalImage2, optionalImage3, optionalImage4, ].where((img) => img != null).cast().toList(); if (availableImages.isNotEmpty) npeData.image1 = availableImages[0]; if (availableImages.length > 1) npeData.image2 = availableImages[1]; if (availableImages.length > 2) npeData.image3 = availableImages[2]; if (availableImages.length > 3) npeData.image4 = availableImages[3]; return npeData; } // --- REMOVED: generateTelegramAlertMessage method --- // Logic moved to MarineTarballSamplingService /// Converts the form's text and selection data into a Map suitable for JSON encoding. /// This map will be sent as the body of the first API request. Map toFormData() { final Map data = { // Required fields that were missing or not being sent correctly 'station_id': selectedStation?['station_id']?.toString() ?? '', 'sampling_date': samplingDate ?? '', 'sampling_time': samplingTime ?? '', 'classification_id': classificationId?.toString() ?? '', 'first_sampler_user_id': firstSamplerUserId?.toString() ?? '', // Optional fields 'second_sampler_user_id': secondSampler?['user_id']?.toString() ?? '', 'current_latitude': currentLatitude ?? '', 'current_longitude': currentLongitude ?? '', 'distance_difference': distanceDifference?.toString() ?? '', 'distance_remarks': distanceDifferenceRemarks ?? '', // Corrected key based on service 'optional_photo_remark_01': optionalRemark1 ?? '', 'optional_photo_remark_02': optionalRemark2 ?? '', 'optional_photo_remark_03': optionalRemark3 ?? '', 'optional_photo_remark_04': optionalRemark4 ?? '', // Human-readable names for the Telegram alert on the server-side 'tbl_station_name': selectedStation?['tbl_station_name']?.toString() ?? '', 'tbl_station_code': selectedStation?['tbl_station_code']?.toString() ?? '', 'first_sampler_name': firstSampler ?? '', 'classification_name': selectedClassification?['classification_name']?.toString() ?? '', }; // Remove keys with empty string values before sending data.removeWhere((key, value) => value.isEmpty); return data; } /// Gathers all non-null image files into a Map. /// This map is used to build the multipart request for the second API call (image upload). Map toImageFiles() { return { 'left_side_coastal_view': leftCoastalViewImage, 'right_side_coastal_view': rightCoastalViewImage, 'drawing_vertical_lines': verticalLinesImage, 'drawing_horizontal_line': horizontalLineImage, 'optional_photo_01': optionalImage1, 'optional_photo_02': optionalImage2, 'optional_photo_03': optionalImage3, 'optional_photo_04': optionalImage4, }; } /// Creates a single JSON object with all submission data for offline storage. Map toDbJson() { // Include image paths for local storage return { 'firstSampler': firstSampler, 'firstSamplerUserId': firstSamplerUserId, 'secondSampler': secondSampler, 'samplingDate': samplingDate, 'samplingTime': samplingTime, 'selectedStateName': selectedStateName, 'selectedCategoryName': selectedCategoryName, 'selectedStation': selectedStation, 'stationLatitude': stationLatitude, 'stationLongitude': stationLongitude, 'currentLatitude': currentLatitude, 'currentLongitude': currentLongitude, 'distanceDifference': distanceDifference, 'distanceDifferenceRemarks': distanceDifferenceRemarks, 'classificationId': classificationId, 'selectedClassification': selectedClassification, 'leftCoastalViewImage': leftCoastalViewImage?.path, 'rightCoastalViewImage': rightCoastalViewImage?.path, 'verticalLinesImage': verticalLinesImage?.path, 'horizontalLineImage': horizontalLineImage?.path, 'optionalImage1': optionalImage1?.path, 'optionalRemark1': optionalRemark1, 'optionalImage2': optionalImage2?.path, 'optionalRemark2': optionalRemark2, 'optionalImage3': optionalImage3?.path, 'optionalRemark3': optionalRemark3, 'optionalImage4': optionalImage4?.path, 'optionalRemark4': optionalRemark4, 'reportId': reportId, 'submissionStatus': submissionStatus, 'submissionMessage': submissionMessage, }; } /// Creates a JSON object for basic form info, mimicking 'basic_form.json'. Map toBasicFormJson() { final data = { 'tech_name': firstSampler, 'sampler_2ndname': secondSampler?['first_name'], // Assuming first_name is appropriate 'sample_date': samplingDate, 'sample_time': samplingTime, 'sample_state': selectedStateName, 'station_id': selectedStation?['tbl_station_code'], // Use station code 'station_latitude': stationLatitude, 'station_longitude': stationLongitude, 'latitude': currentLatitude, // Current location 'longitude': currentLongitude, // Current location 'sample_id': reportId, // Using reportId if available }; //data.removeWhere((key, value) => value == null); return data; } /// Creates a JSON object for sensor readings, mimicking 'reading.json'. Map toReadingJson() { final data = { 'classification': selectedClassification?['classification_name'], 'classification_id': classificationId, 'optional_remark_1': optionalRemark1, 'optional_remark_2': optionalRemark2, 'optional_remark_3': optionalRemark3, 'optional_remark_4': optionalRemark4, 'distance_difference': distanceDifference, 'distance_difference_remarks': distanceDifferenceRemarks, // Corrected key }; data.removeWhere((key, value) => value == null || (value is String && value.isEmpty)); return data; } /// Creates a JSON object for manual info, mimicking 'manual_info.json'. Map toManualInfoJson() { final data = { // Tarball forms don't have weather or general remarks separate from distance 'weather': null, // Explicitly null if not collected 'remarks_event': distanceDifferenceRemarks, // Use distance remarks if relevant 'remarks_lab': null, // Explicitly null if not collected }; data.removeWhere((key, value) => value == null || (value is String && value.isEmpty)); return data; } }