// lib/models/river_in_situ_sampling_data.dart

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

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

  String? selectedStateName;
  String? selectedCategoryName;
  Map<String, dynamic>? selectedStation;

  String? stationLatitude;
  String? stationLongitude;
  String? currentLatitude;
  String? currentLongitude;
  double? distanceDifferenceInKm;
  String? distanceDifferenceRemarks;

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

  File? backgroundStationImage;
  File? upstreamRiverImage;
  File? downstreamRiverImage;

  // --- Step 4: Additional Photos ---
  File? sampleTurbidityImage;

  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? ammonia; // MODIFIED: Replaced tss with ammonia
  double? batteryVoltage;

  // ADDED: New properties for Flowrate
  String? flowrateMethod; // 'Surface Drifter', 'Flowmeter', 'NA'
  double? flowrateSurfaceDrifterHeight;
  double? flowrateSurfaceDrifterDistance;
  String? flowrateSurfaceDrifterTimeFirst;
  String? flowrateSurfaceDrifterTimeLast;
  double? flowrateValue;


  // --- Post-Submission Status ---
  String? submissionStatus;
  String? submissionMessage;
  String? reportId;

  RiverInSituSamplingData({
    this.samplingDate,
    this.samplingTime,
  });

  factory RiverInSituSamplingData.fromJson(Map<String, dynamic> json) {
    File? fileFromJson(dynamic path) {
      return (path is String && path.isNotEmpty) ? File(path) : null;
    }

    double? doubleFromJson(dynamic value) {
      if (value is num) return value.toDouble();
      if (value is String) 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;
    }

    // --- START: MODIFIED FOR CONSISTENT SERIALIZATION ---
    return RiverInSituSamplingData()
      ..firstSamplerName = json['firstSamplerName'] ?? json['first_sampler_name']
      ..firstSamplerUserId = intFromJson(json['firstSamplerUserId'] ?? json['first_sampler_user_id'])
      ..secondSampler = json['secondSampler']
      ..samplingDate = json['samplingDate'] ?? json['r_man_date']
      ..samplingTime = json['samplingTime'] ?? json['r_man_time']
      ..samplingType = json['samplingType'] ?? json['r_man_type']
      ..sampleIdCode = json['sampleIdCode'] ?? json['r_man_sample_id_code']
      ..selectedStateName = json['selectedStateName']
      ..selectedCategoryName = json['selectedCategoryName']
      ..selectedStation = json['selectedStation']
      ..stationLatitude = json['stationLatitude']
      ..stationLongitude = json['stationLongitude']
      ..currentLatitude = (json['currentLatitude'] ?? json['r_man_current_latitude'])?.toString()
      ..currentLongitude = (json['currentLongitude'] ?? json['r_man_current_longitude'])?.toString()
      ..distanceDifferenceInKm = doubleFromJson(json['distanceDifferenceInKm'] ?? json['r_man_distance_difference'])
      ..distanceDifferenceRemarks = json['distanceDifferenceRemarks'] ?? json['r_man_distance_difference_remarks']
      ..weather = json['weather'] ?? json['r_man_weather']
      ..eventRemarks = json['eventRemarks'] ?? json['r_man_event_remark']
      ..labRemarks = json['labRemarks'] ?? json['r_man_lab_remark']
      ..sondeId = json['sondeId'] ?? json['r_man_sondeID']
      ..dataCaptureDate = json['dataCaptureDate'] ?? json['data_capture_date']
      ..dataCaptureTime = json['data_capture_time'] ?? json['data_capture_time']
      ..oxygenConcentration = doubleFromJson(json['oxygenConcentration'] ?? json['r_man_oxygen_conc'])
      ..oxygenSaturation = doubleFromJson(json['oxygenSaturation'] ?? json['r_man_oxygen_sat'])
      ..ph = doubleFromJson(json['ph'] ?? json['r_man_ph'])
      ..salinity = doubleFromJson(json['salinity'] ?? json['r_man_salinity'])
      ..electricalConductivity = doubleFromJson(json['electricalConductivity'] ?? json['r_man_conductivity'])
      ..temperature = doubleFromJson(json['temperature'] ?? json['r_man_temperature'])
      ..tds = doubleFromJson(json['tds'] ?? json['r_man_tds'])
      ..turbidity = doubleFromJson(json['turbidity'] ?? json['r_man_turbidity'])
      ..ammonia = doubleFromJson(json['ammonia'] ?? json['r_man_ammonia'])
      ..batteryVoltage = doubleFromJson(json['batteryVoltage'] ?? json['r_man_battery_volt'])
      ..optionalRemark1 = json['optionalRemark1'] ?? json['r_man_optional_photo_01_remarks']
      ..optionalRemark2 = json['optionalRemark2'] ?? json['r_man_optional_photo_02_remarks']
      ..optionalRemark3 = json['optionalRemark3'] ?? json['r_man_optional_photo_03_remarks']
      ..optionalRemark4 = json['optionalRemark4'] ?? json['r_man_optional_photo_04_remarks']
      ..backgroundStationImage = fileFromJson(json['backgroundStationImage'] ?? json['r_man_background_station'])
      ..upstreamRiverImage = fileFromJson(json['upstreamRiverImage'] ?? json['r_man_upstream_river'])
      ..downstreamRiverImage = fileFromJson(json['downstreamRiverImage'] ?? json['r_man_downstream_river'])
      ..sampleTurbidityImage = fileFromJson(json['sampleTurbidityImage'] ?? json['r_man_sample_turbidity'])
      ..optionalImage1 = fileFromJson(json['optionalImage1'] ?? json['r_man_optional_photo_01'])
      ..optionalImage2 = fileFromJson(json['optionalImage2'] ?? json['r_man_optional_photo_02'])
      ..optionalImage3 = fileFromJson(json['optionalImage3'] ?? json['r_man_optional_photo_03'])
      ..optionalImage4 = fileFromJson(json['optionalImage4'] ?? json['r_man_optional_photo_04'])
      ..flowrateMethod = json['flowrateMethod'] ?? json['r_man_flowrate_method']
      ..flowrateSurfaceDrifterHeight = doubleFromJson(json['flowrateSurfaceDrifterHeight'] ?? json['r_man_flowrate_sd_height'])
      ..flowrateSurfaceDrifterDistance = doubleFromJson(json['flowrateSurfaceDrifterDistance'] ?? json['r_man_flowrate_sd_distance'])
      ..flowrateSurfaceDrifterTimeFirst = json['flowrateSurfaceDrifterTimeFirst'] ?? json['r_man_flowrate_sd_time_first']
      ..flowrateSurfaceDrifterTimeLast = json['flowrateSurfaceDrifterTimeLast'] ?? json['r_man_flowrate_sd_time_last']
      ..flowrateValue = doubleFromJson(json['flowrateValue'] ?? json['r_man_flowrate_value'])
      ..submissionStatus = json['submissionStatus']
      ..submissionMessage = json['submissionMessage']
      ..reportId = json['reportId']?.toString();
  }


  /// Converts the data model into a Map<String, String> for the API form data.
  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;
        }
      }
    }

    // Step 1 Data
    add('first_sampler_user_id', firstSamplerUserId);
    add('r_man_second_sampler_id', secondSampler?['user_id']);
    add('r_man_date', samplingDate);
    add('r_man_time', samplingTime);
    add('r_man_type', samplingType);
    add('r_man_sample_id_code', sampleIdCode);
    add('station_id', selectedStation?['station_id']);
    add('r_man_current_latitude', currentLatitude);
    add('r_man_current_longitude', currentLongitude);
    add('r_man_distance_difference', distanceDifferenceInKm);
    add('r_man_distance_difference_remarks', distanceDifferenceRemarks);

    // Step 2 Data
    add('r_man_weather', weather);
    add('r_man_event_remark', eventRemarks);
    add('r_man_lab_remark', labRemarks);

    // Step 4 Data
    add('r_man_optional_photo_01_remarks', optionalRemark1);
    add('r_man_optional_photo_02_remarks', optionalRemark2);
    add('r_man_optional_photo_03_remarks', optionalRemark3);
    add('r_man_optional_photo_04_remarks', optionalRemark4);

    // Step 3 Data
    add('r_man_sondeID', sondeId);
    add('data_capture_date', dataCaptureDate);
    add('data_capture_time', dataCaptureTime);
    add('r_man_oxygen_conc', oxygenConcentration);
    add('r_man_oxygen_sat', oxygenSaturation);
    add('r_man_ph', ph);
    add('r_man_salinity', salinity);
    add('r_man_conductivity', electricalConductivity);
    add('r_man_temperature', temperature);
    add('r_man_tds', tds);
    add('r_man_turbidity', turbidity);
    add('r_man_ammonia', ammonia);
    add('r_man_battery_volt', batteryVoltage);

    // ADDED: Flowrate fields
    add('r_man_flowrate_method', flowrateMethod);
    add('r_man_flowrate_sd_height', flowrateSurfaceDrifterHeight);
    add('r_man_flowrate_sd_distance', flowrateSurfaceDrifterDistance);
    add('r_man_flowrate_sd_time_first', flowrateSurfaceDrifterTimeFirst);
    add('r_man_flowrate_sd_time_last', flowrateSurfaceDrifterTimeLast);
    add('r_man_flowrate_value', flowrateValue);

    // Additional data for display or logging
    add('first_sampler_name', firstSamplerName);
    add('r_man_station_code', selectedStation?['sampling_station_code']);
    add('r_man_station_name', selectedStation?['sampling_river']);

    return map;
  }

  /// Converts the image properties into a Map<String, File?> for the multipart API request.
  Map<String, File?> toApiImageFiles() {
    return {
      'r_man_background_station': backgroundStationImage,
      'r_man_upstream_river': upstreamRiverImage,
      'r_man_downstream_river': downstreamRiverImage,
      'r_man_sample_turbidity': sampleTurbidityImage,
      'r_man_optional_photo_01': optionalImage1,
      'r_man_optional_photo_02': optionalImage2,
      'r_man_optional_photo_03': optionalImage3,
      'r_man_optional_photo_04': optionalImage4,
    };
  }

  // ADDED: support for centralized submission logging
  Map<String, dynamic> toMap() {
    return {
      'firstSamplerName': firstSamplerName,
      'firstSamplerUserId': firstSamplerUserId,
      'secondSampler': secondSampler,
      'samplingDate': samplingDate,
      'samplingTime': samplingTime,
      'samplingType': samplingType,
      'sampleIdCode': sampleIdCode,
      'selectedStateName': selectedStateName,
      'selectedCategoryName': selectedCategoryName,
      'selectedStation': selectedStation,
      'stationLatitude': stationLatitude,
      'stationLongitude': stationLongitude,
      'currentLatitude': currentLatitude,
      'currentLongitude': currentLongitude,
      'distanceDifferenceInKm': distanceDifferenceInKm,
      'distanceDifferenceRemarks': distanceDifferenceRemarks,
      'weather': weather,
      'eventRemarks': eventRemarks,
      'labRemarks': labRemarks,
      'backgroundStationImage': backgroundStationImage?.path,
      'upstreamRiverImage': upstreamRiverImage?.path,
      'downstreamRiverImage': downstreamRiverImage?.path,
      'sampleTurbidityImage': sampleTurbidityImage?.path,
      'optionalImage1': optionalImage1?.path,
      'optionalRemark1': optionalRemark1,
      'optionalImage2': optionalImage2?.path,
      'optionalRemark2': optionalRemark2,
      'optionalImage3': optionalImage3?.path,
      'optionalRemark3': optionalRemark3,
      'optionalImage4': optionalImage4?.path,
      'optionalRemark4': optionalRemark4,
      'sondeId': sondeId,
      'dataCaptureDate': dataCaptureDate,
      'dataCaptureTime': dataCaptureTime,
      'oxygenConcentration': oxygenConcentration,
      'oxygenSaturation': oxygenSaturation,
      'ph': ph,
      'salinity': salinity,
      'electricalConductivity': electricalConductivity,
      'temperature': temperature,
      'tds': tds,
      'turbidity': turbidity,
      'ammonia': ammonia,
      'batteryVoltage': batteryVoltage,
      'flowrateMethod': flowrateMethod,
      'flowrateSurfaceDrifterHeight': flowrateSurfaceDrifterHeight,
      'flowrateSurfaceDrifterDistance': flowrateSurfaceDrifterDistance,
      'flowrateSurfaceDrifterTimeFirst': flowrateSurfaceDrifterTimeFirst,
      'flowrateSurfaceDrifterTimeLast': flowrateSurfaceDrifterTimeLast,
      'flowrateValue': flowrateValue,
      'submissionStatus': submissionStatus,
      'submissionMessage': submissionMessage,
      'reportId': reportId,
    };
  }

  /// Creates a single JSON object with all submission data, mimicking 'db.json'
  /// FORCING ALL VALUES TO STRING.
  String toDbJson() {
    final data = {
      'battery_cap': (batteryVoltage == null || batteryVoltage == -999.0) ? "NULL" : batteryVoltage.toString(),
      'device_name': (sondeId ?? "").toString(),
      'sampling_type': (samplingType ?? "").toString(),
      'report_id': (reportId ?? "").toString(),
      'sampler_2ndname': (secondSampler?['first_name'] ?? "").toString(),
      'sample_state': (selectedStateName ?? "").toString(),
      'station_id': (selectedStation?['sampling_station_code'] ?? "").toString(),
      'tech_id': (firstSamplerUserId ?? "NULL").toString(),
      'tech_phonenum': "",
      'tech_name': (firstSamplerName ?? "").toString(),
      'latitude': (stationLatitude ?? "").toString(),
      'longitude': (stationLongitude ?? "").toString(),
      'record_dt': (samplingDate != null && samplingTime != null)
          ? '$samplingDate $samplingTime'
          : "",
      'do_mgl': (oxygenConcentration == null || oxygenConcentration == -999.0) ? "NULL" : oxygenConcentration.toString(),
      'do_sat': (oxygenSaturation == null || oxygenSaturation == -999.0) ? "NULL" : oxygenSaturation.toString(),
      'ph': (ph == null || ph == -999.0) ? "NULL" : ph.toString(),
      'salinity': (salinity == null || salinity == -999.0) ? "NULL" : salinity.toString(),
      'temperature': (temperature == null || temperature == -999.0) ? "NULL" : temperature.toString(),
      'turbidity': (turbidity == null || turbidity == -999.0) ? "NULL" : turbidity.toString(),
      'tds': (tds == null || tds == -999.0) ? "NULL" : tds.toString(),
      'electric_conductivity': (electricalConductivity == null || electricalConductivity == -999.0) ? "NULL" : electricalConductivity.toString(),
      'flowrate': (flowrateValue == null || flowrateValue == -999.0) ? "NULL" : flowrateValue.toString(),
      'odour': "",
      'floatable': "",
      'sample_id': (sampleIdCode ?? "").toString(),
      'weather': (weather ?? "").toString(),
      'remarks_event': (eventRemarks ?? "").toString(),
      'remarks_lab': (labRemarks ?? "").toString(),
    };
    return jsonEncode(data);
  }

  /// Creates a JSON object for basic form info. FORCING ALL VALUES TO STRING.
  String toBasicFormJson() {
    final data = {
      'tech_name': (firstSamplerName ?? "").toString(),
      'sampler_2ndname': (secondSampler?['first_name'] ?? "").toString(),
      'sample_date': (samplingDate ?? "").toString(),
      'sample_time': (samplingTime ?? "").toString(),
      'sampling_type': (samplingType ?? "").toString(),
      'sample_state': (selectedStateName ?? "").toString(),
      'station_id': (selectedStation?['sampling_station_code'] ?? "").toString(),
      'station_latitude': (stationLatitude ?? "").toString(),
      'station_longitude': (stationLongitude ?? "").toString(),
      'latitude': (currentLatitude ?? "").toString(),
      'longitude': (currentLongitude ?? "").toString(),
      'sample_id': (sampleIdCode ?? "").toString(),
    };
    return jsonEncode(data);
  }

  /// Creates a JSON object for sensor readings. FORCING ALL VALUES TO STRING.
  String toReadingJson() {
    final data = {
      'do_mgl': (oxygenConcentration == null || oxygenConcentration == -999.0) ? "NULL" : oxygenConcentration.toString(),
      'do_sat': (oxygenSaturation == null || oxygenSaturation == -999.0) ? "NULL" : oxygenSaturation.toString(),
      'ph': (ph == null || ph == -999.0) ? "NULL" : ph.toString(),
      'salinity': (salinity == null || salinity == -999.0) ? "NULL" : salinity.toString(),
      'temperature': (temperature == null || temperature == -999.0) ? "NULL" : temperature.toString(),
      'turbidity': (turbidity == null || turbidity == -999.0) ? "NULL" : turbidity.toString(),
      'tds': (tds == null || tds == -999.0) ? "NULL" : tds.toString(),
      'electric_conductivity': (electricalConductivity == null || electricalConductivity == -999.0) ? "NULL" : electricalConductivity.toString(),
      'flowrate': (flowrateValue == null || flowrateValue == -999.0) ? "NULL" : flowrateValue.toString(),
      'date_sampling_reading': (dataCaptureDate ?? "").toString(),
      'time_sampling_reading': (dataCaptureTime ?? "").toString(),
    };
    return jsonEncode(data);
  }

  /// Creates a JSON object for manual info. FORCING ALL VALUES TO STRING.
  String toManualInfoJson() {
    final data = {
      'weather': (weather ?? "").toString(),
      'remarks_event': (eventRemarks ?? "").toString(),
      'remarks_lab': (labRemarks ?? "").toString(),
    };
    return jsonEncode(data);
  }
}