// lib/models/in_situ_sampling_data.dart

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

import 'package:environment_monitoring_app/models/marine_manual_npe_report_data.dart';

/// A data model class to hold all information for the multi-step
/// In-Situ Sampling form.
class InSituSamplingData {
  // --- 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? 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;

  // --- START: NPE Report Compatibility Fields ---
  Map<String, bool> npeFieldObservations = {
    'Oil slick on the water surface/ Oil spill': false,
    'Discoloration of the sea water': false,
    'Formation of foam on the surface': false,
    'Coral bleaching or dead corals': false,
    'Observation of tar balls': false,
    'Excessive debris': false,
    'Red tides or algae blooms': false,
    'Silt plume': false,
    'Foul smell': false,
    'Others': false,
  };
  String? npeOthersObservationRemark;
  String? npePossibleSource;

  File? npeImage1;
  File? npeImage2;
  File? npeImage3;
  File? npeImage4;
  // --- END: NPE Report Compatibility Fields ---


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

  /// Creates a pre-populated NPE Report object from the current In-Situ data.
  MarineManualNpeReportData toNpeReportData() {
    final npeData = MarineManualNpeReportData();
    npeData.firstSamplerName = firstSamplerName;
    npeData.firstSamplerUserId = firstSamplerUserId;
    npeData.eventDate = samplingDate;
    npeData.eventTime = samplingTime;
    npeData.selectedStation = selectedStation;
    npeData.latitude = currentLatitude;
    npeData.longitude = currentLongitude;
    npeData.oxygenSaturation = oxygenSaturation;
    npeData.electricalConductivity = electricalConductivity;
    npeData.oxygenConcentration = oxygenConcentration;
    npeData.turbidity = turbidity;
    npeData.ph = ph;
    npeData.temperature = temperature;
    npeData.possibleSource = eventRemarks;

    if ((turbidity ?? 0) > 50) npeData.fieldObservations['Silt plume'] = true;
    if ((oxygenConcentration ?? 999) < 4) npeData.fieldObservations['Foul smell'] = true;

    final availableImages = [
      leftLandViewImage, rightLandViewImage, waterFillingImage,
      seawaterColorImage, phPaperImage, optionalImage1,
      optionalImage2, optionalImage3, optionalImage4,
    ].where((img) => img != null).cast<File>().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;
  }

  factory InSituSamplingData.fromJson(Map<String, dynamic> json) {
    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;
    }
    File? fileFromPath(dynamic path) => (path is String && path.isNotEmpty) ? File(path) : null;

    final data = InSituSamplingData();
    data.firstSamplerName = json['first_sampler_name'];
    data.firstSamplerUserId = intFromJson(json['first_sampler_user_id']);
    data.secondSampler = json['secondSampler'] ?? json['second_sampler'];
    data.samplingDate = json['sampling_date'] ?? json['man_date'];
    data.samplingTime = json['sampling_time'] ?? json['man_time'];
    data.samplingType = json['sampling_type'];
    data.sampleIdCode = json['sample_id_code'];
    data.selectedStateName = json['selected_state_name'];
    data.selectedCategoryName = json['selected_category_name'];
    data.selectedStation = json['selectedStation'];
    data.stationLatitude = json['station_latitude'];
    data.stationLongitude = json['station_longitude'];
    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'];
    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['man_optional_photo_01_remarks'];
    data.optionalRemark2 = json['man_optional_photo_02_remarks'];
    data.optionalRemark3 = json['man_optional_photo_03_remarks'];
    data.optionalRemark4 = json['man_optional_photo_04_remarks'];
    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']);
    data.submissionStatus = json['submission_status'];
    data.submissionMessage = json['submission_message'];
    data.reportId = json['report_id']?.toString();

    data.leftLandViewImage = fileFromPath(json['man_left_side_land_view']);
    data.rightLandViewImage = fileFromPath(json['man_right_side_land_view']);
    data.waterFillingImage = fileFromPath(json['man_filling_water_into_sample_bottle']);
    data.seawaterColorImage = fileFromPath(json['man_seawater_in_clear_glass_bottle']);
    data.phPaperImage = fileFromPath(json['man_examine_preservative_ph_paper']);
    data.optionalImage1 = fileFromPath(json['man_optional_photo_01']);
    data.optionalImage2 = fileFromPath(json['man_optional_photo_02']);
    data.optionalImage3 = fileFromPath(json['man_optional_photo_03']);
    data.optionalImage4 = fileFromPath(json['man_optional_photo_04']);

    if (json['npe_field_observations'] is Map) {
      data.npeFieldObservations = Map<String, bool>.from(json['npe_field_observations']);
    }
    data.npeOthersObservationRemark = json['npe_others_observation_remark'];
    data.npePossibleSource = json['npe_possible_source'];
    data.npeImage1 = fileFromPath(json['npe_image_1']);
    data.npeImage2 = fileFromPath(json['npe_image_2']);
    data.npeImage3 = fileFromPath(json['npe_image_3']);
    data.npeImage4 = fileFromPath(json['npe_image_4']);

    return data;
  }

  Map<String, dynamic> toMap() {
    return {
      'first_sampler_name': firstSamplerName,
      'first_sampler_user_id': firstSamplerUserId,
      'secondSampler': secondSampler,
      'sampling_date': samplingDate,
      'sampling_time': samplingTime,
      'sampling_type': samplingType,
      'sample_id_code': sampleIdCode,
      'selected_state_name': selectedStateName,
      'selected_category_name': selectedCategoryName,
      'selectedStation': selectedStation,
      'station_latitude': stationLatitude,
      'station_longitude': stationLongitude,
      'current_latitude': currentLatitude,
      'current_longitude': currentLongitude,
      'distance_difference_in_km': distanceDifferenceInKm,
      'distance_difference_remarks': distanceDifferenceRemarks,
      'weather': weather,
      'tide_level': tideLevel,
      'sea_condition': seaCondition,
      'event_remarks': eventRemarks,
      'lab_remarks': labRemarks,
      'man_optional_photo_01_remarks': optionalRemark1,
      'man_optional_photo_02_remarks': optionalRemark2,
      'man_optional_photo_03_remarks': optionalRemark3,
      'man_optional_photo_04_remarks': optionalRemark4,
      'sonde_id': sondeId,
      'data_capture_date': dataCaptureDate,
      'data_capture_time': dataCaptureTime,
      'oxygen_concentration': oxygenConcentration,
      'oxygen_saturation': oxygenSaturation,
      'ph': ph,
      'salinity': salinity,
      'electrical_conductivity': electricalConductivity,
      'temperature': temperature,
      'tds': tds,
      'turbidity': turbidity,
      'tss': tss,
      'battery_voltage': batteryVoltage,
      'submission_status': submissionStatus,
      'submission_message': submissionMessage,
      'report_id': reportId,
      'npe_field_observations': npeFieldObservations,
      'npe_others_observation_remark': npeOthersObservationRemark,
      'npe_possible_source': npePossibleSource,
    };
  }

  /// Creates a single JSON object for '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?['man_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(),
      'tss': (tss == null || tss == -999.0) ? "NULL" : tss.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(),
      'sample_id': (sampleIdCode ?? "").toString(),
      'tarball': "No",
      'weather': (weather ?? "").toString(),
      'tide_lvl': (tideLevel ?? "").toString(),
      'sea_cond': (seaCondition ?? "").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(),
      'sample_category': (selectedCategoryName ?? "").toString(),
      'station_id': (selectedStation?['man_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(),
      'tds': (tds == null || tds == -999.0) ? "NULL" : tds.toString(),
      'tss': (tss == null || tss == -999.0) ? "NULL" : tss.toString(),
      'temperature': (temperature == null || temperature == -999.0) ? "NULL" : temperature.toString(),
      'turbidity': (turbidity == null || turbidity == -999.0) ? "NULL" : turbidity.toString(),
      'electric_conductivity': (electricalConductivity == null || electricalConductivity == -999.0) ? "NULL" : electricalConductivity.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 = {
      'tarball': "",
      'weather': (weather ?? "").toString(),
      'tide_lvl': (tideLevel ?? "").toString(),
      'sea_cond': (seaCondition ?? "").toString(),
      'remarks_event': (eventRemarks ?? "").toString(),
      'remarks_lab': (labRemarks ?? "").toString(),
    };
    return jsonEncode(data);
  }

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

    add('station_id', selectedStation?['station_id']);
    add('man_date', samplingDate);
    add('man_time', samplingTime);
    add('first_sampler_user_id', firstSamplerUserId);
    add('man_second_sampler_id', secondSampler?['user_id']);
    add('man_type', samplingType);
    add('man_sample_id_code', sampleIdCode);
    add('man_current_latitude', currentLatitude);
    add('man_current_longitude', currentLongitude);
    add('man_distance_difference', distanceDifferenceInKm);
    add('man_distance_difference_remarks', distanceDifferenceRemarks);
    add('man_weather', weather);
    add('man_tide_level', tideLevel);
    add('man_sea_condition', seaCondition);
    add('man_event_remark', eventRemarks);
    add('man_lab_remark', labRemarks);
    add('man_optional_photo_01_remarks', optionalRemark1);
    add('man_optional_photo_02_remarks', optionalRemark2);
    add('man_optional_photo_03_remarks', optionalRemark3);
    add('man_optional_photo_04_remarks', optionalRemark4);
    add('man_sondeID', sondeId);
    add('data_capture_date', dataCaptureDate);
    add('data_capture_time', dataCaptureTime);
    add('man_oxygen_conc', oxygenConcentration);
    add('man_oxygen_sat', oxygenSaturation);
    add('man_ph', ph);
    add('man_salinity', salinity);
    add('man_conductivity', electricalConductivity);
    add('man_temperature', temperature);
    add('man_tds', tds);
    add('man_turbidity', turbidity);
    add('man_tss', tss);
    add('man_battery_volt', batteryVoltage);
    add('first_sampler_name', firstSamplerName);
    add('man_station_code', selectedStation?['man_station_code']);
    add('man_station_name', selectedStation?['man_station_name']);
    return map;
  }

  Map<String, File?> toApiImageFiles() {
    return {
      'man_left_side_land_view': leftLandViewImage,
      'man_right_side_land_view': rightLandViewImage,
      'man_filling_water_into_sample_bottle': waterFillingImage,
      'man_seawater_in_clear_glass_bottle': seawaterColorImage,
      'man_examine_preservative_ph_paper': phPaperImage,
      'man_optional_photo_01': optionalImage1,
      'man_optional_photo_02': optionalImage2,
      'man_optional_photo_03': optionalImage3,
      'man_optional_photo_04': optionalImage4,
    };
  }
}