// lib/models/river_inves_manual_sampling_data.dart

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

/// Data model for the multi-step River Investigative Manual Sampling form.
class RiverInvesManualSamplingData {
  // --- Step 1: Sampling & Station Info ---
  String? firstSamplerName;
  int? firstSamplerUserId;
  Map<String, dynamic>? secondSampler;
  String? samplingDate;
  String? samplingTime;
  String? samplingType = 'Investigative'; // Defaulted for this module
  String? sampleIdCode;

  // --- NEW: Station Type Selection ---
  String? stationTypeSelection; // 'Existing Manual Station', 'Existing Triennial Station', 'New Location'

  // --- Existing Station Fields ---
  String? selectedStateName; // Used by Manual/Triennial and as input for New
  String? selectedCategoryName; // Potentially relevant context? Keep for now.
  Map<String, dynamic>? selectedStation; // Holds selected MANUAL station
  Map<String, dynamic>? selectedTriennialStation; // Holds selected TRIENNIAL station

  // --- New Location Fields ---
  String? newStateName; // Specifically for New Location state input
  String? newBasinName;
  String? newRiverName;
  // *** ADDED: newStationName field ***
  String? newStationName; // User-defined name for the new location
  // *** END ADDED ***
  String? newStationCode; // Optional user-defined code for new location

  // --- Location Fields ---
  String? stationLatitude; // Derived from selected station OR user input for New
  String? stationLongitude; // Derived from selected station OR user input for New
  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; // Replaced tss
  double? batteryVoltage;

  // Flowrate properties (same as In-Situ)
  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; // Assuming the API returns an ID (e.g., r_inv_id)

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

  // Helper to get the determined station code regardless of type
  String? getDeterminedStationCode() {
    if (stationTypeSelection == 'Existing Manual Station') {
      return selectedStation?['sampling_station_code'];
    } else if (stationTypeSelection == 'Existing Triennial Station') {
      return selectedTriennialStation?['triennial_station_code'];
    } else if (stationTypeSelection == 'New Location') {
      return newStationCode; // Use user-provided code or null
    }
    return null;
  }

  // Helper to get determined State Name
  String? getDeterminedStateName() {
    if (stationTypeSelection == 'Existing Manual Station' || stationTypeSelection == 'Existing Triennial Station') {
      return selectedStateName;
    } else if (stationTypeSelection == 'New Location') {
      return newStateName;
    }
    return null;
  }

  // Helper to get determined River Name
  String? getDeterminedRiverName() {
    if (stationTypeSelection == 'Existing Manual Station') {
      return selectedStation?['sampling_river'];
    } else if (stationTypeSelection == 'Existing Triennial Station') {
      return selectedTriennialStation?['triennial_river'];
    } else if (stationTypeSelection == 'New Location') {
      return newRiverName;
    }
    return null;
  }

  // Helper to get determined Basin Name
  String? getDeterminedBasinName() {
    if (stationTypeSelection == 'Existing Manual Station') {
      return selectedStation?['sampling_basin'];
    } else if (stationTypeSelection == 'Existing Triennial Station') {
      return selectedTriennialStation?['triennial_basin'];
    } else if (stationTypeSelection == 'New Location') {
      return newBasinName;
    }
    return null;
  }

  // *** ADDED: getDeterminedStationName helper ***
  String? getDeterminedStationName() {
    // This combines River Name for existing stations or the New Station Name
    if (stationTypeSelection == 'Existing Manual Station') {
      return selectedStation?['sampling_river']; // Use river name as station name contextually
    } else if (stationTypeSelection == 'Existing Triennial Station') {
      return selectedTriennialStation?['triennial_river']; // Use river name as station name contextually
    } else if (stationTypeSelection == 'New Location') {
      return newStationName; // Use the specific name given for the new location
    }
    return null;
  }
  // *** END ADDED ***


  factory RiverInvesManualSamplingData.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;
    }

    // Adapted from RiverInSituSamplingData.fromJson
    return RiverInvesManualSamplingData()
    // Step 1
      ..firstSamplerName = json['firstSamplerName']
      ..firstSamplerUserId = intFromJson(json['firstSamplerUserId'])
      ..secondSampler = json['secondSampler']
      ..samplingDate = json['samplingDate']
      ..samplingTime = json['samplingTime']
      ..samplingType = json['samplingType'] ?? 'Investigative'
      ..sampleIdCode = json['sampleIdCode']
      ..stationTypeSelection = json['stationTypeSelection']
      ..selectedStateName = json['selectedStateName'] // State for existing stations
      ..selectedCategoryName = json['selectedCategoryName']
      ..selectedStation = json['selectedStation'] // Manual
      ..selectedTriennialStation = json['selectedTriennialStation'] // Triennial
      ..newStateName = json['newStateName'] // New Location state
      ..newBasinName = json['newBasinName']
      ..newRiverName = json['newRiverName']
      ..newStationName = json['newStationName'] // Load newStationName
      ..newStationCode = json['newStationCode']
      ..stationLatitude = json['stationLatitude']
      ..stationLongitude = json['stationLongitude']
      ..currentLatitude = json['currentLatitude']?.toString()
      ..currentLongitude = json['currentLongitude']?.toString()
      ..distanceDifferenceInKm = doubleFromJson(json['distanceDifferenceInKm'])
      ..distanceDifferenceRemarks = json['distanceDifferenceRemarks']
    // Step 2
      ..weather = json['weather']
      ..eventRemarks = json['eventRemarks']
      ..labRemarks = json['labRemarks']
      ..backgroundStationImage = fileFromJson(json['backgroundStationImage'])
      ..upstreamRiverImage = fileFromJson(json['upstreamRiverImage'])
      ..downstreamRiverImage = fileFromJson(json['downstreamRiverImage'])
    // Step 4
      ..sampleTurbidityImage = fileFromJson(json['sampleTurbidityImage'])
      ..optionalImage1 = fileFromJson(json['optionalImage1'])
      ..optionalRemark1 = json['optionalRemark1']
      ..optionalImage2 = fileFromJson(json['optionalImage2'])
      ..optionalRemark2 = json['optionalRemark2']
      ..optionalImage3 = fileFromJson(json['optionalImage3'])
      ..optionalRemark3 = json['optionalRemark3']
      ..optionalImage4 = fileFromJson(json['optionalImage4'])
      ..optionalRemark4 = json['optionalRemark4']
    // Step 3
      ..sondeId = json['sondeId']
      ..dataCaptureDate = json['dataCaptureDate']
      ..dataCaptureTime = json['dataCaptureTime']
      ..oxygenConcentration = doubleFromJson(json['oxygenConcentration'])
      ..oxygenSaturation = doubleFromJson(json['oxygenSaturation'])
      ..ph = doubleFromJson(json['ph'])
      ..salinity = doubleFromJson(json['salinity'])
      ..electricalConductivity = doubleFromJson(json['electricalConductivity'])
      ..temperature = doubleFromJson(json['temperature'])
      ..tds = doubleFromJson(json['tds'])
      ..turbidity = doubleFromJson(json['turbidity'])
      ..ammonia = doubleFromJson(json['ammonia'])
      ..batteryVoltage = doubleFromJson(json['batteryVoltage'])
      ..flowrateMethod = json['flowrateMethod']
      ..flowrateSurfaceDrifterHeight = doubleFromJson(json['flowrateSurfaceDrifterHeight'])
      ..flowrateSurfaceDrifterDistance = doubleFromJson(json['flowrateSurfaceDrifterDistance'])
      ..flowrateSurfaceDrifterTimeFirst = json['flowrateSurfaceDrifterTimeFirst']
      ..flowrateSurfaceDrifterTimeLast = json['flowrateSurfaceDrifterTimeLast']
      ..flowrateValue = doubleFromJson(json['flowrateValue'])
    // Status
      ..submissionStatus = json['submissionStatus']
      ..submissionMessage = json['submissionMessage']
      ..reportId = json['reportId']?.toString();
  }

  /// Converts the data model into a Map<String, dynamic> for saving/logging locally.
  Map<String, dynamic> toMap() {
    return {
      'firstSamplerName': firstSamplerName,
      'firstSamplerUserId': firstSamplerUserId,
      'secondSampler': secondSampler,
      'samplingDate': samplingDate,
      'samplingTime': samplingTime,
      'samplingType': samplingType,
      'sampleIdCode': sampleIdCode,
      'stationTypeSelection': stationTypeSelection,
      'selectedStateName': selectedStateName,
      'selectedCategoryName': selectedCategoryName,
      'selectedStation': selectedStation, // Manual
      'selectedTriennialStation': selectedTriennialStation, // Triennial
      'newStateName': newStateName, // New Loc
      'newBasinName': newBasinName,
      'newRiverName': newRiverName,
      'newStationName': newStationName, // Include newStationName
      'newStationCode': newStationCode,
      '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,
    };
  }


  /// Converts the data model into a Map<String, String> for the API form data.
  /// Keys should match the expected API endpoint fields for Investigative sampling.
  Map<String, String> toApiFormData() {
    final Map<String, String> map = {};

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

    // Sampler & Time Info (Assuming same API keys as manual)
    add('first_sampler_user_id', firstSamplerUserId);
    add('r_inves_second_sampler_id', secondSampler?['user_id']);
    add('r_inves_date', samplingDate);
    add('r_inves_time', samplingTime);
    add('r_inves_type', samplingType);
    add('r_inves_sample_id_code', sampleIdCode);

    // Station Info (Conditional)
    add('r_inves_station_type', stationTypeSelection);
    if (stationTypeSelection == 'Existing Manual Station') {
      add('station_id', selectedStation?['station_id']); // Assuming API wants the numeric ID
      add('r_inves_station_code', selectedStation?['sampling_station_code']); // Add code for display/logging if needed
    } else if (stationTypeSelection == 'Existing Triennial Station') {
      add('triennial_station_id', selectedTriennialStation?['station_id']); // Assuming a different key
      add('r_inves_station_code', selectedTriennialStation?['triennial_station_code']);
    } else if (stationTypeSelection == 'New Location') {
      add('r_inves_new_state_name', newStateName);
      add('r_inves_new_basin_name', newBasinName);
      add('r_inves_new_river_name', newRiverName);
      add('r_inves_new_station_name', newStationName); // Include newStationName
      add('r_inves_new_station_code', newStationCode); // Optional code
      add('r_inves_station_latitude', stationLatitude); // Use the captured/entered lat/lon
      add('r_inves_station_longitude', stationLongitude);
    }

    // Location Verification (Assuming same keys)
    add('r_inves_current_latitude', currentLatitude);
    add('r_inves_current_longitude', currentLongitude);
    add('r_inves_distance_difference', distanceDifferenceInKm);
    add('r_inves_distance_difference_remarks', distanceDifferenceRemarks);

    // Site Info (Assuming same keys)
    add('r_inves_weather', weather);
    add('r_inves_event_remark', eventRemarks);
    add('r_inves_lab_remark', labRemarks);

    // Optional Remarks (Assuming same keys)
    add('r_inves_optional_photo_01_remarks', optionalRemark1);
    add('r_inves_optional_photo_02_remarks', optionalRemark2);
    add('r_inves_optional_photo_03_remarks', optionalRemark3);
    add('r_inves_optional_photo_04_remarks', optionalRemark4);

    // Parameters (Assuming same keys)
    add('r_inves_sondeID', sondeId);
    // Note: data_capture_date/time might not be used by API if not in controller, but keeping generally safe
    add('data_capture_date', dataCaptureDate);
    add('data_capture_time', dataCaptureTime);
    add('r_inves_oxygen_conc', oxygenConcentration);
    add('r_inves_oxygen_sat', oxygenSaturation);
    add('r_inves_ph', ph);
    add('r_inves_salinity', salinity);
    add('r_inves_conductivity', electricalConductivity);
    add('r_inves_temperature', temperature);
    add('r_inves_tds', tds);
    add('r_inves_turbidity', turbidity);
    add('r_inves_ammonia', ammonia);
    add('r_inves_battery_volt', batteryVoltage);

    // Flowrate (Assuming same keys)
    add('r_inves_flowrate_method', flowrateMethod);
    add('r_inves_flowrate_sd_height', flowrateSurfaceDrifterHeight);
    add('r_inves_flowrate_sd_distance', flowrateSurfaceDrifterDistance);
    add('r_inves_flowrate_sd_time_first', flowrateSurfaceDrifterTimeFirst);
    add('r_inves_flowrate_sd_time_last', flowrateSurfaceDrifterTimeLast);
    add('r_inves_flowrate_value', flowrateValue);

    // Additional data that might be useful for display or if API needs it redundantly
    add('first_sampler_name', firstSamplerName);
    add('determined_state_name', getDeterminedStateName()); // Add determined values
    add('determined_basin_name', getDeterminedBasinName());
    add('determined_river_name', getDeterminedRiverName());
    add('determined_station_name', getDeterminedStationName()); // Add determined station name


    return map;
  }

  /// Converts the image properties into a Map<String, File?> for the multipart API request.
  /// Keys should match the expected API endpoint fields for Investigative images.
  Map<String, File?> toApiImageFiles() {
    return {
      'r_inves_background_station': backgroundStationImage,
      'r_inves_upstream_river': upstreamRiverImage,
      'r_inves_downstream_river': downstreamRiverImage,
      'r_inves_sample_turbidity': sampleTurbidityImage,
      'r_inves_optional_photo_01': optionalImage1,
      'r_inves_optional_photo_02': optionalImage2,
      'r_inves_optional_photo_03': optionalImage3,
      'r_inves_optional_photo_04': optionalImage4,
    };
  }

  /// Creates a single JSON object for FTP 'db.json', forcing every value to String.
  String toDbJson() {
    final data = {
      'battery_cap': (batteryVoltage == null || batteryVoltage == -999.0) ? "NULL" : batteryVoltage.toString(),
      'device_name': (sondeId ?? "").toString(),
      'sampling_type': (samplingType ?? "Investigative").toString(),
      'report_id': (reportId ?? "").toString(),
      'sampler_2ndname': (secondSampler?['first_name'] ?? "").toString(),
      'sample_state': (getDeterminedStateName() ?? "").toString(),
      'station_id': (getDeterminedStationCode() ?? "").toString(),
      'tech_id': (firstSamplerUserId ?? "NULL").toString(),
      'tech_phonenum': "NULL",
      'tech_name': (firstSamplerName ?? "").toString(),
      'latitude': (stationLatitude ?? "").toString(),
      'longitude': (stationLongitude ?? "").toString(),
      'record_dt': '$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(),
      'tss': (ammonia == null || ammonia == -999.0) ? "NULL" : ammonia.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(),
      'station_type': (stationTypeSelection ?? "").toString(),
      'new_basin': (newBasinName ?? "").toString(),
      'new_river': (newRiverName ?? "").toString(),
      'new_station_name': (newStationName ?? "").toString(),
      'tarball': "No",
      'tide_lvl': "",
      'sea_cond': "",
    };
    return jsonEncode(data);
  }

  /// Creates JSON for FTP 'river_inves_basic_form.json', forcing every value 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 ?? "Investigative").toString(),
      'sample_state': (getDeterminedStateName() ?? "").toString(),
      'station_id': (getDeterminedStationCode() ?? "").toString(),
      'station_latitude': (stationLatitude ?? "").toString(),
      'station_longitude': (stationLongitude ?? "").toString(),
      'latitude': (currentLatitude ?? "").toString(),
      'longitude': (currentLongitude ?? "").toString(),
      'sample_id': (sampleIdCode ?? "").toString(),
      'station_type': (stationTypeSelection ?? "").toString(),
      'new_basin': (newBasinName ?? "").toString(),
      'new_river': (newRiverName ?? "").toString(),
      'new_station_name': (newStationName ?? "").toString(),
    };
    return jsonEncode(data);
  }

  /// Creates JSON for FTP 'river_inves_reading.json', forcing every value 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(),
      'tss': (ammonia == null || ammonia == -999.0) ? "NULL" : ammonia.toString(),
      'flowrate': (flowrateValue == null || flowrateValue == -999.0) ? "NULL" : flowrateValue.toString(),
      'date_sampling_reading': (dataCaptureDate ?? "").toString(),
      'time_sampling_reading': (dataCaptureTime ?? "").toString(),
    };
    return jsonEncode(data);
  }

  /// Creates JSON for FTP 'river_inves_manual_info.json', forcing every value to String.
  String toManualInfoJson() {
    final data = {
      'weather': (weather ?? "").toString(),
      'remarks_event': (eventRemarks ?? "").toString(),
      'remarks_lab': (labRemarks ?? "").toString(),
    };
    return jsonEncode(data);
  }
}