// lib/models/marine_inves_manual_sampling_data.dart

import 'dart:io';
import 'dart:convert'; // Added for jsonEncode

/// A data model class to hold all information for the multi-step
/// Marine Investigative Manual Sampling form.
class MarineInvesManualSamplingData {
  // --- Step 1: Sampling & Station Info ---
  String? firstSamplerName;
  int? firstSamplerUserId;
  Map<String, dynamic>? secondSampler;
  String? samplingDate;
  String? samplingTime;
  String? samplingType;
  String? sampleIdCode;

  // --- NEW: Step 1 Station Selection ---
  String? stationTypeSelection; // 'Existing Manual Station', 'Existing Tarball Station', 'New Location'

  // For 'Existing Manual Station'
  String? selectedManualStateName;
  String? selectedManualCategoryName;
  Map<String, dynamic>? selectedStation; // This is the MANUAL station

  // For 'Existing Tarball Station'
  String? selectedTarballStateName;
  Map<String, dynamic>? selectedTarballStation;

  // For 'New Location'
  String? newStationName;
  String? newStationCode;

  // --- Common Station/Location Fields ---
  String? stationLatitude;  // Populated from selected station OR manually entered
  String? stationLongitude; // Populated from selected station OR manually entered
  String? currentLatitude;
  String? currentLongitude;
  double? distanceDifferenceInKm;
  String? distanceDifferenceRemarks;

  // --- Step 2: Site Info & Photos ---
  String? weather;
  String? tideLevel;
  String? seaCondition;
  String? eventRemarks;
  String? labRemarks;

  File? leftLandViewImage;
  File? rightLandViewImage;
  File? waterFillingImage;
  File? seawaterColorImage;
  File? phPaperImage;

  File? optionalImage1;
  String? optionalRemark1;
  File? optionalImage2;
  String? optionalRemark2;
  File? optionalImage3;
  String? optionalRemark3;
  File? optionalImage4;
  String? optionalRemark4;

  // --- Step 3: Data Capture ---
  String? sondeId;
  String? dataCaptureDate;
  String? dataCaptureTime;
  double? oxygenConcentration;
  double? oxygenSaturation;
  double? ph;
  double? salinity;
  double? electricalConductivity;
  double? temperature;
  double? tds;
  double? turbidity;
  double? tss;
  double? batteryVoltage;

  // --- Post-Submission Status ---
  String? submissionStatus;
  String? submissionMessage;
  String? reportId; // This will be 'man_inves_id' from the DB OR Timestamp ID

  MarineInvesManualSamplingData({
    this.samplingDate,
    this.samplingTime,
    this.stationTypeSelection = 'Existing Manual Station', // Default value
  });

  /// Creates a single JSON object with all submission data for offline storage.
  /// Logic updated to replace -999.0 with "NULL" for external server compatibility.
  Map<String, dynamic> toDbJson() {
    return {
      // Step 1
      'first_sampler_name': firstSamplerName,
      'first_sampler_user_id': firstSamplerUserId,
      'secondSampler': secondSampler,
      'sampling_date': samplingDate,
      'sampling_time': samplingTime,
      'sampling_type': samplingType,
      'sample_id_code': sampleIdCode,
      'stationTypeSelection': stationTypeSelection,
      'selectedManualStateName': selectedManualStateName,
      'selectedManualCategoryName': selectedManualCategoryName,
      'selectedStation': selectedStation,
      'selectedTarballStateName': selectedTarballStateName,
      'selectedTarballStation': selectedTarballStation,
      'newStationName': newStationName,
      'newStationCode': newStationCode,
      'station_latitude': stationLatitude,
      'station_longitude': stationLongitude,
      'current_latitude': currentLatitude,
      'current_longitude': currentLongitude,
      'distance_difference_in_km': distanceDifferenceInKm,
      'distance_difference_remarks': distanceDifferenceRemarks,
      // Step 2
      'weather': weather,
      'tide_level': tideLevel,
      'sea_condition': seaCondition,
      'event_remarks': eventRemarks,
      'lab_remarks': labRemarks,
      'inves_optional_photo_01_remarks': optionalRemark1,
      'inves_optional_photo_02_remarks': optionalRemark2,
      'inves_optional_photo_03_remarks': optionalRemark3,
      'inves_optional_photo_04_remarks': optionalRemark4,
      // Step 3
      'sonde_id': sondeId,
      'data_capture_date': dataCaptureDate,
      'data_capture_time': dataCaptureTime,
      // Handle NULL values for JSON output
      'oxygen_concentration': (oxygenConcentration == null || oxygenConcentration == -999.0) ? "NULL" : oxygenConcentration,
      'oxygen_saturation': (oxygenSaturation == null || oxygenSaturation == -999.0) ? "NULL" : oxygenSaturation,
      'ph': (ph == null || ph == -999.0) ? "NULL" : ph,
      'salinity': (salinity == null || salinity == -999.0) ? "NULL" : salinity,
      'electrical_conductivity': (electricalConductivity == null || electricalConductivity == -999.0) ? "NULL" : electricalConductivity,
      'temperature': (temperature == null || temperature == -999.0) ? "NULL" : temperature,
      'tds': (tds == null || tds == -999.0) ? "NULL" : tds,
      'turbidity': (turbidity == null || turbidity == -999.0) ? "NULL" : turbidity,
      'tss': (tss == null || tss == -999.0) ? "NULL" : tss,
      'battery_voltage': (batteryVoltage == null || batteryVoltage == -999.0) ? "NULL" : batteryVoltage,
      // Status
      'submission_status': submissionStatus,
      'submission_message': submissionMessage,
      'report_id': reportId,

      // Image paths will be added by LocalStorageService during save
      'inves_left_side_land_view': leftLandViewImage?.path,
      'inves_right_side_land_view': rightLandViewImage?.path,
      'inves_filling_water_into_sample_bottle': waterFillingImage?.path,
      'inves_seawater_in_clear_glass_bottle': seawaterColorImage?.path,
      'inves_examine_preservative_ph_paper': phPaperImage?.path,
      'inves_optional_photo_01': optionalImage1?.path,
      'inves_optional_photo_02': optionalImage2?.path,
      'inves_optional_photo_03': optionalImage3?.path,
      'inves_optional_photo_04': optionalImage4?.path,
    };
  }

  /// Creates an InSituSamplingData object from a JSON map (for offline logs).
  factory MarineInvesManualSamplingData.fromJson(Map<String, dynamic> json) {
    double? doubleFromJson(dynamic value) {
      if (value is num) return value.toDouble();
      if (value is String) {
        if (value == "NULL") return -999.0;
        return double.tryParse(value);
      }
      return null;
    }

    int? intFromJson(dynamic value) {
      if (value is int) return value;
      if (value is String) return int.tryParse(value);
      return null;
    }

    File? fileFromPath(dynamic path) {
      return (path is String && path.isNotEmpty) ? File(path) : null;
    }

    final data = MarineInvesManualSamplingData();

    // Step 1
    data.firstSamplerName = json['first_sampler_name'];
    data.firstSamplerUserId = intFromJson(json['first_sampler_user_id']);
    data.secondSampler = json['secondSampler'];
    data.samplingDate = json['sampling_date'];
    data.samplingTime = json['sampling_time'];
    data.samplingType = json['sampling_type'];
    data.sampleIdCode = json['sample_id_code'];
    data.stationTypeSelection = json['stationTypeSelection'];
    data.selectedManualStateName = json['selectedManualStateName'];
    data.selectedManualCategoryName = json['selectedManualCategoryName'];
    data.selectedStation = json['selectedStation'];
    data.selectedTarballStateName = json['selectedTarballStateName'];
    data.selectedTarballStation = json['selectedTarballStation'];
    data.newStationName = json['newStationName'];
    data.newStationCode = json['newStationCode'];
    data.stationLatitude = json['station_latitude']?.toString();
    data.stationLongitude = json['station_longitude']?.toString();
    data.currentLatitude = json['current_latitude']?.toString();
    data.currentLongitude = json['current_longitude']?.toString();
    data.distanceDifferenceInKm = doubleFromJson(json['distance_difference_in_km']);
    data.distanceDifferenceRemarks = json['distance_difference_remarks'];

    // Step 2
    data.weather = json['weather'];
    data.tideLevel = json['tide_level'];
    data.seaCondition = json['sea_condition'];
    data.eventRemarks = json['event_remarks'];
    data.labRemarks = json['lab_remarks'];
    data.optionalRemark1 = json['inves_optional_photo_01_remarks'];
    data.optionalRemark2 = json['inves_optional_photo_02_remarks'];
    data.optionalRemark3 = json['inves_optional_photo_03_remarks'];
    data.optionalRemark4 = json['inves_optional_photo_04_remarks'];

    // Step 2 Images
    data.leftLandViewImage = fileFromPath(json['inves_left_side_land_view']);
    data.rightLandViewImage = fileFromPath(json['inves_right_side_land_view']);
    data.waterFillingImage = fileFromPath(json['inves_filling_water_into_sample_bottle']);
    data.seawaterColorImage = fileFromPath(json['inves_seawater_in_clear_glass_bottle']);
    data.phPaperImage = fileFromPath(json['inves_examine_preservative_ph_paper']);
    data.optionalImage1 = fileFromPath(json['inves_optional_photo_01']);
    data.optionalImage2 = fileFromPath(json['inves_optional_photo_02']);
    data.optionalImage3 = fileFromPath(json['inves_optional_photo_03']);
    data.optionalImage4 = fileFromPath(json['inves_optional_photo_04']);

    // Step 3
    data.sondeId = json['sonde_id'];
    data.dataCaptureDate = json['data_capture_date'];
    data.dataCaptureTime = json['data_capture_time'];
    data.oxygenConcentration = doubleFromJson(json['oxygen_concentration']);
    data.oxygenSaturation = doubleFromJson(json['oxygen_saturation']);
    data.ph = doubleFromJson(json['ph']);
    data.salinity = doubleFromJson(json['salinity']);
    data.electricalConductivity = doubleFromJson(json['electrical_conductivity']);
    data.temperature = doubleFromJson(json['temperature']);
    data.tds = doubleFromJson(json['tds']);
    data.turbidity = doubleFromJson(json['turbidity']);
    data.tss = doubleFromJson(json['tss']);
    data.batteryVoltage = doubleFromJson(json['battery_voltage']);

    // Status
    data.submissionStatus = json['submission_status'];
    data.submissionMessage = json['submission_message'];
    data.reportId = json['report_id']?.toString();

    return data;
  }


  /// Maps data to keys for the API submission. Preserved exactly as originally provided.
  Map<String, String> toApiFormData() {
    final Map<String, String> map = {};

    void add(String key, dynamic value) {
      if (value != null) {
        String stringValue;
        if (value is double) {
          if (value == -999.0) {
            stringValue = '-999';
          } else {
            stringValue = value.toStringAsFixed(5);
          }
        } else {
          stringValue = value.toString();
        }

        if (stringValue.isNotEmpty) {
          map[key] = stringValue;
        }
      }
    }

    add('inves_date', samplingDate);
    add('inves_time', samplingTime);
    add('first_sampler_user_id', firstSamplerUserId);
    add('inves_second_sampler_id', secondSampler?['user_id']);
    add('inves_type', samplingType);
    add('inves_sample_id_code', sampleIdCode);
    add('inves_current_latitude', currentLatitude);
    add('inves_current_longitude', currentLongitude);
    add('inves_distance_difference', distanceDifferenceInKm);
    add('inves_distance_difference_remarks', distanceDifferenceRemarks);

    add('inves_station_type', stationTypeSelection);
    if (stationTypeSelection == 'Existing Manual Station') {
      // FIX: Ensure 'station_id' is added correctly for limit validation
      add('station_id', selectedStation?['station_id'] ?? selectedStation?['man_station_id']);
      add('inves_station_code', selectedStation?['man_station_code']);
      add('inves_station_name', selectedStation?['man_station_name']);
    } else if (stationTypeSelection == 'Existing Tarball Station') {
      add('tbl_station_id', selectedTarballStation?['station_id'] ?? selectedTarballStation?['tbl_station_id']);
      add('inves_station_code', selectedTarballStation?['tbl_station_code']);
      add('inves_station_name', selectedTarballStation?['tbl_station_name']);
    } else if (stationTypeSelection == 'New Location') {
      add('inves_new_station_name', newStationName);
      add('inves_new_station_code', newStationCode);
      add('inves_station_latitude', stationLatitude);
      add('inves_station_longitude', stationLongitude);
    }

    add('inves_weather', weather);
    add('inves_tide_level', tideLevel);
    add('inves_sea_condition', seaCondition);
    add('inves_event_remark', eventRemarks);
    add('inves_lab_remark', labRemarks);
    add('inves_optional_photo_01_remarks', optionalRemark1);
    add('inves_optional_photo_02_remarks', optionalRemark2);
    add('inves_optional_photo_03_remarks', optionalRemark3);
    add('inves_optional_photo_04_remarks', optionalRemark4);
    add('inves_sondeID', sondeId);
    add('data_capture_date', dataCaptureDate);
    add('data_capture_time', dataCaptureTime);
    add('inves_oxygen_conc', oxygenConcentration);
    add('inves_oxygen_sat', oxygenSaturation);
    add('inves_ph', ph);
    add('inves_salinity', salinity);
    add('inves_conductivity', electricalConductivity);
    add('inves_temperature', temperature);
    add('inves_tds', tds);
    add('inves_turbidity', turbidity);
    add('inves_tss', tss);
    add('inves_battery_volt', batteryVoltage);

    add('first_sampler_name', firstSamplerName);

    return map;
  }

  /// Maps image files to keys for the API submission.
  Map<String, File?> toApiImageFiles() {
    return {
      'inves_left_side_land_view': leftLandViewImage,
      'inves_right_side_land_view': rightLandViewImage,
      'inves_filling_water_into_sample_bottle': waterFillingImage,
      'inves_seawater_in_clear_glass_bottle': seawaterColorImage,
      'inves_examine_preservative_ph_paper': phPaperImage,
      'inves_optional_photo_01': optionalImage1,
      'inves_optional_photo_02': optionalImage2,
      'inves_optional_photo_03': optionalImage3,
      'inves_optional_photo_04': optionalImage4,
    };
  }
}