// lib/screens/marine/manual/reports/npe_report_from_tarball.dart

import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:intl/intl.dart';
import 'package:provider/provider.dart';
import 'package:dropdown_search/dropdown_search.dart';

import '../../../../auth_provider.dart';
import '../../../../models/in_situ_sampling_data.dart';
import '../../../../models/marine_manual_npe_report_data.dart';
import '../../../../services/marine_in_situ_sampling_service.dart';
import '../../../../services/marine_npe_report_service.dart';
import '../../../../bluetooth/bluetooth_manager.dart';
import '../../../../serial/serial_manager.dart';
import '../../../../bluetooth/widgets/bluetooth_device_list_dialog.dart';
import '../../../../serial/widget/serial_port_list_dialog.dart';

class NPEReportFromTarball extends StatefulWidget {
  final MarineManualNpeReportData? initialData;
  const NPEReportFromTarball({super.key, this.initialData});

  @override
  State<NPEReportFromTarball> createState() => _NPEReportFromTarballState();
}

// Modified: Added WidgetsBindingObserver to handle app lifecycle changes (USB permission dialog)
class _NPEReportFromTarballState extends State<NPEReportFromTarball> with WidgetsBindingObserver {
  final _formKey = GlobalKey<FormState>();
  bool _isLoading = false;
  bool _isPickingImage = false;
  bool _areFieldsLocked = false;

  // Data
  final MarineManualNpeReportData _npeData = MarineManualNpeReportData();
  String? _selectedState;
  String? _selectedCategory;
  List<String> _categoriesForState = [];
  List<Map<String, dynamic>> _stationsForCategory = [];

  // Controllers
  final _stationIdController = TextEditingController();
  final _locationController = TextEditingController();
  final _eventDateTimeController = TextEditingController();
  final _latController = TextEditingController();
  final _longController = TextEditingController();
  final _possibleSourceController = TextEditingController();
  final _othersObservationController = TextEditingController();
  final _doPercentController = TextEditingController();
  final _doMgLController = TextEditingController();
  final _phController = TextEditingController();
  final _condController = TextEditingController();
  final _turbController = TextEditingController();
  final _tempController = TextEditingController();
  // ADDED: Remark controllers for images
  final _image1RemarkController = TextEditingController();
  final _image2RemarkController = TextEditingController();
  final _image3RemarkController = TextEditingController();
  final _image4RemarkController = TextEditingController();

  // In-Situ
  late final MarineInSituSamplingService _samplingService;
  StreamSubscription? _dataSubscription;
  bool _isAutoReading = false;
  Timer? _lockoutTimer;
  int _lockoutSecondsRemaining = 30;
  bool _isLockedOut = false;

  @override
  void initState() {
    super.initState();
    // Added: Register observer
    WidgetsBinding.instance.addObserver(this);
    _samplingService = Provider.of<MarineInSituSamplingService>(context, listen: false);

    WidgetsBinding.instance.addPostFrameCallback((_) {
      if (widget.initialData != null) {
        _populateFormFromTarballData(widget.initialData!);
      } else {
        _setDefaultDateTime();
      }
    });
  }

  @override
  void dispose() {
    // Added: Remove observer
    WidgetsBinding.instance.removeObserver(this);
    _stationIdController.dispose();
    _locationController.dispose();
    _eventDateTimeController.dispose();
    _latController.dispose();
    _longController.dispose();
    _possibleSourceController.dispose();
    _othersObservationController.dispose();
    _doPercentController.dispose();
    _doMgLController.dispose();
    _phController.dispose();
    _condController.dispose();
    _turbController.dispose();
    _tempController.dispose();
    // ADDED: Dispose remark controllers
    _image1RemarkController.dispose();
    _image2RemarkController.dispose();
    _image3RemarkController.dispose();
    _image4RemarkController.dispose();
    _dataSubscription?.cancel();
    _lockoutTimer?.cancel();
    super.dispose();
  }

  // Added: Handle App Lifecycle changes (specifically for USB permission dialog return)
  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    if (state == AppLifecycleState.resumed) {
      if (mounted) {
        final btConnecting = _samplingService.bluetoothConnectionState.value == BluetoothConnectionState.connecting;
        final serialConnecting = _samplingService.serialConnectionState.value == SerialConnectionState.connecting;

        // If the UI is still loading or the service thinks it's still connecting (stuck after permission dialog),
        // force a disconnect/reset so the user can try again.
        if (_isLoading || btConnecting || serialConnecting) {
          _disconnectFromAll();
        }
      }
    }
  }

  void _setDefaultDateTime() {
    final now = DateTime.now();
    _eventDateTimeController.text = DateFormat('yyyy-MM-dd HH:mm').format(now);
  }

  void _populateFormFromTarballData(MarineManualNpeReportData data) {
    final auth = Provider.of<AuthProvider>(context, listen: false);
    final allTarballStations = auth.tarballStations ?? [];
    final station = data.selectedStation;

    if (station == null) return;

    setState(() {
      _areFieldsLocked = true;
      _selectedState = station['state_name'];
      _selectedCategory = station['category_name'];
      _npeData.selectedStation = station;

      _categoriesForState = allTarballStations
          .where((s) => s['state_name'] == _selectedState)
          .map((s) => s['category_name'] as String)
          .toSet()
          .toList();

      _stationsForCategory = allTarballStations
          .where((s) => s['state_name'] == _selectedState && s['category_name'] == _selectedCategory)
          .toList();

      _stationIdController.text = station['tbl_station_code'] ?? '';
      _locationController.text = station['tbl_station_name'] ?? '';
      _latController.text = data.latitude ?? station['tbl_latitude']?.toString() ?? '';
      _longController.text = data.longitude ?? station['tbl_longitude']?.toString() ?? '';

      if (data.eventDate != null && data.eventTime != null) {
        _eventDateTimeController.text = '${data.eventDate} ${data.eventTime}';
      } else {
        _setDefaultDateTime();
      }

      _npeData.fieldObservations.clear();
      _npeData.fieldObservations.addAll(data.fieldObservations);

      // ADDED: Populate image remarks if they exist
      _image1RemarkController.text = data.image1Remark ?? '';
      _image2RemarkController.text = data.image2Remark ?? '';
      _image3RemarkController.text = data.image3Remark ?? '';
      _image4RemarkController.text = data.image4Remark ?? '';
    });
  }

  Future<void> _submitNpeReport() async {
    // --- START: VALIDATION CHECKS ---
    // 1. Check for at least one field observation
    final bool atLeastOneObservation = _npeData.fieldObservations.values.any((isChecked) => isChecked == true);
    if (!atLeastOneObservation) {
      _showSnackBar('Please select at least one field observation.', isError: true);
      return;
    }

    // 2. Check for all 4 required photos
    if (_npeData.image1 == null || _npeData.image2 == null || _npeData.image3 == null || _npeData.image4 == null) {
      _showSnackBar('Please attach all 4 figures.', isError: true);
      return;
    }

    // 3. Validate form fields (including "Others" remark)
    if (!_formKey.currentState!.validate()) {
      _showSnackBar('Please fill in all required fields.', isError: true);
      return;
    }
    // --- END: VALIDATION CHECKS ---

    setState(() => _isLoading = true);
    final auth = Provider.of<AuthProvider>(context, listen: false);
    final service = Provider.of<MarineNpeReportService>(context, listen: false);

    _npeData.firstSamplerName = auth.profileData?['first_name'];
    _npeData.firstSamplerUserId = auth.profileData?['user_id'];
    _npeData.eventDate = _eventDateTimeController.text.split(' ')[0];
    _npeData.eventTime = _eventDateTimeController.text.split(' ').length > 1 ? _eventDateTimeController.text.split(' ')[1] : '';
    _npeData.stateName = _selectedState;
    _npeData.latitude = _latController.text;
    _npeData.longitude = _longController.text;
    _npeData.possibleSource = _possibleSourceController.text;
    _npeData.othersObservationRemark = _othersObservationController.text;
    _npeData.oxygenSaturation = double.tryParse(_doPercentController.text);
    _npeData.electricalConductivity = double.tryParse(_condController.text);
    _npeData.oxygenConcentration = double.tryParse(_doMgLController.text);
    _npeData.turbidity = double.tryParse(_turbController.text);
    _npeData.ph = double.tryParse(_phController.text);
    _npeData.temperature = double.tryParse(_tempController.text);

    // ADDED: Save image remarks
    _npeData.image1Remark = _image1RemarkController.text;
    _npeData.image2Remark = _image2RemarkController.text;
    _npeData.image3Remark = _image3RemarkController.text;
    _npeData.image4Remark = _image4RemarkController.text;

    final result = await service.submitNpeReport(data: _npeData, authProvider: auth);
    setState(() => _isLoading = false);
    if (mounted) {
      _showSnackBar(result['message'], isError: result['success'] != true);
      if (result['success'] == true) {
        Navigator.of(context).popUntil((route) => route.isFirst);
      }
    }
  }

  void _showSnackBar(String message, {bool isError = false}) {
    if (mounted) {
      ScaffoldMessenger.of(context).showSnackBar(SnackBar(
        content: Text(message),
        backgroundColor: isError ? Colors.red : null,
      ));
    }
  }

  Future<void> _processAndSetImage(ImageSource source, int imageNumber) async {
    if (_isPickingImage) return;
    setState(() => _isPickingImage = true);

    // --- FIX START: Extract correct code and name for proper filename generation ---
    String stationName = _locationController.text;
    String stationCode = 'NA';

    // Check _npeData first as it is the source of truth for the selected station
    if (_npeData.selectedStation != null) {
      stationCode = _npeData.selectedStation!['man_station_code'] ??
          _npeData.selectedStation!['tbl_station_code'] ??
          'NA';
    }
    // --- FIX END ---

    final watermarkData = InSituSamplingData()
      ..samplingDate = _eventDateTimeController.text.split(' ')[0]
      ..samplingTime = _eventDateTimeController.text.split(' ').length > 1 ? _eventDateTimeController.text.split(' ')[1] : ''
      ..currentLatitude = _latController.text
      ..currentLongitude = _longController.text
    // --- FIX: Pass BOTH code and name to the image service ---
      ..selectedStation = {
        'man_station_name': stationName,
        'man_station_code': stationCode,
        'tbl_station_code': stationCode, // Fallback depending on processor logic
      };

    final file = await _samplingService.pickAndProcessImage(
      source,
      data: watermarkData,
      imageInfo: 'NPE ATTACHMENT $imageNumber',
      isRequired: true, // MODIFIED: Watermark is now compulsory
    );

    if (file != null) {
      setState(() {
        switch (imageNumber) {
          case 1: _npeData.image1 = file; break;
          case 2: _npeData.image2 = file; break;
          case 3: _npeData.image3 = file; break;
          case 4: _npeData.image4 = file; break;
        }
      });
    }
    if (mounted) setState(() => _isPickingImage = false);
  }

  void _updateTextFields(Map<String, double> readings) {
    const defaultValue = -999.0;
    setState(() {
      _doMgLController.text = (readings['Optical Dissolved Oxygen: Compensated mg/L'] ?? defaultValue).toStringAsFixed(5);
      _doPercentController.text = (readings['Optical Dissolved Oxygen: Compensated % Saturation'] ?? defaultValue).toStringAsFixed(5);
      _phController.text = (readings['PH: PH units'] ?? defaultValue).toStringAsFixed(5);
      _tempController.text = (readings['External Temp: Degrees Celcius'] ?? defaultValue).toStringAsFixed(5);
      _condController.text = (readings['Conductivity: us/cm'] ?? defaultValue).toStringAsFixed(5);
      _turbController.text = (readings['Turbidity: FNU'] ?? defaultValue).toStringAsFixed(5);
    });
  }

  Map<String, dynamic>? _getActiveConnectionDetails() {
    if (_samplingService.bluetoothConnectionState.value != BluetoothConnectionState.disconnected) {
      return {'type': 'bluetooth', 'state': _samplingService.bluetoothConnectionState.value, 'name': _samplingService.connectedBluetoothDeviceName};
    }
    if (_samplingService.serialConnectionState.value != SerialConnectionState.disconnected) {
      return {'type': 'serial', 'state': _samplingService.serialConnectionState.value, 'name': _samplingService.connectedSerialDeviceName};
    }
    return null;
  }

  Future<void> _handleConnectionAttempt(String type) async {
    final hasPermissions = await _samplingService.requestDevicePermissions();
    if (!hasPermissions && mounted) {
      _showSnackBar("Bluetooth & Location permissions are required.", isError: true);
      return;
    }
    _disconnectFromAll();
    await Future.delayed(const Duration(milliseconds: 250));
    final bool connectionSuccess = await _connectToDevice(type);
    if (connectionSuccess && mounted) {
      _dataSubscription?.cancel();
      final stream = type == 'bluetooth' ? _samplingService.bluetoothDataStream : _samplingService.serialDataStream;
      _dataSubscription = stream.listen((readings) {
        if (mounted) _updateTextFields(readings);
      });
    }
  }

  Future<bool> _connectToDevice(String type) async {
    setState(() => _isLoading = true);
    bool success = false;
    try {
      if (type == 'bluetooth') {
        final devices = await _samplingService.getPairedBluetoothDevices();
        if (devices.isEmpty && mounted) {
          _showSnackBar('No paired Bluetooth devices found.', isError: true);
          return false;
        }
        final selectedDevice = await showBluetoothDeviceListDialog(context: context, devices: devices);
        if (selectedDevice != null) {
          await _samplingService.connectToBluetoothDevice(selectedDevice);
          success = true;
        }
      } else if (type == 'serial') {
        final devices = await _samplingService.getAvailableSerialDevices();
        if (devices.isEmpty && mounted) {
          _showSnackBar('No USB Serial devices found.', isError: true);
          return false;
        }
        final selectedDevice = await showSerialPortListDialog(context: context, devices: devices);
        if (selectedDevice != null) {
          await _samplingService.connectToSerialDevice(selectedDevice);
          success = true;
        }
      }
    } catch (e) {
      debugPrint("Connection failed: $e");
      if (mounted) _showConnectionFailedDialog();
    } finally {
      if (mounted) setState(() => _isLoading = false);
    }
    return success;
  }

  void _disconnectFromAll() {
    if (_samplingService.bluetoothConnectionState.value != BluetoothConnectionState.disconnected) _disconnect('bluetooth');
    if (_samplingService.serialConnectionState.value != SerialConnectionState.disconnected) _disconnect('serial');
  }

  Future<void> _showConnectionFailedDialog() async {
    if (!mounted) return;
    return showDialog<void>(
      context: context,
      barrierDismissible: false,
      builder: (BuildContext context) {
        return AlertDialog(
          title: const Text('Connection Failed'),
          content: const SingleChildScrollView(
            child: Text('Could not connect to the device. Please check that the device is turned on, within range, and not connected to another application.'),
          ),
          actions: <Widget>[
            TextButton(
              child: const Text('OK'),
              onPressed: () {
                Navigator.of(context).pop();
              },
            ),
          ],
        );
      },
    );
  }

  void _startLockoutTimer() {
    _lockoutTimer?.cancel();
    setState(() {
      _isLockedOut = true;
      _lockoutSecondsRemaining = 30;
    });

    _lockoutTimer = Timer.periodic(const Duration(seconds: 1), (timer) {
      if (_lockoutSecondsRemaining > 0) {
        if (mounted) setState(() => _lockoutSecondsRemaining--);
      } else {
        timer.cancel();
        if (mounted) setState(() => _isLockedOut = false);
      }
    });
  }

  void _toggleAutoReading(String activeType) {
    setState(() {
      _isAutoReading = !_isAutoReading;
      if (_isAutoReading) {
        if (activeType == 'bluetooth') {
          _samplingService.startBluetoothAutoReading();
        } else {
          _samplingService.startSerialAutoReading();
        }
        _startLockoutTimer();
      } else {
        if (activeType == 'bluetooth') {
          _samplingService.stopBluetoothAutoReading();
        } else {
          _samplingService.stopSerialAutoReading();
        }
      }
    });
  }

  void _disconnect(String type) {
    if (type == 'bluetooth') {
      _samplingService.disconnectFromBluetooth();
    } else {
      _samplingService.disconnectFromSerial();
    }
    _dataSubscription?.cancel();
    _dataSubscription = null;
    _lockoutTimer?.cancel();
    if (mounted) {
      setState(() {
        _isAutoReading = false;
        _isLockedOut = false;
        _isLoading = false; // Added: Reset isLoading to unlock buttons
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    final auth = Provider.of<AuthProvider>(context, listen: false);
    final allTarballStations = auth.tarballStations ?? [];

    return Scaffold(
      appBar: AppBar(title: const Text("NPE from Tarball Station")),
      body: Form(
        key: _formKey,
        child: ListView(
          padding: const EdgeInsets.all(20.0),
          children: [
            _buildSectionTitle("1. Select Tarball Station"),
            DropdownSearch<String>(
              items: allTarballStations.map((s) => s['state_name'] as String).toSet().toList()..sort(),
              selectedItem: _selectedState,
              enabled: !_areFieldsLocked,
              popupProps: const PopupProps.menu(showSearchBox: true, searchFieldProps: TextFieldProps(decoration: InputDecoration(hintText: "Search State..."))),
              dropdownDecoratorProps: const DropDownDecoratorProps(dropdownSearchDecoration: InputDecoration(labelText: "Select State *")),
              onChanged: (state) {
                setState(() {
                  _selectedState = state;
                  _selectedCategory = null;
                  _npeData.selectedStation = null;
                  _stationIdController.clear();
                  _locationController.clear();
                  _latController.clear();
                  _longController.clear();
                  _categoriesForState = state != null ? allTarballStations.where((s) => s['state_name'] == state).map((s) => s['category_name'] as String).toSet().toList() : [];
                  _stationsForCategory = [];
                });
              },
              validator: (val) => val == null ? "State is required" : null,
            ),
            const SizedBox(height: 12),
            DropdownSearch<String>(
              items: _categoriesForState,
              selectedItem: _selectedCategory,
              enabled: !_areFieldsLocked && _categoriesForState.isNotEmpty,
              popupProps: const PopupProps.menu(showSearchBox: true, searchFieldProps: TextFieldProps(decoration: InputDecoration(hintText: "Search Category..."))),
              dropdownDecoratorProps: const DropDownDecoratorProps(dropdownSearchDecoration: InputDecoration(labelText: "Select Category *")),
              onChanged: (category) {
                setState(() {
                  _selectedCategory = category;
                  _npeData.selectedStation = null;
                  _stationIdController.clear();
                  _locationController.clear();
                  _latController.clear();
                  _longController.clear();
                  _stationsForCategory = category != null ? allTarballStations.where((s) => s['state_name'] == _selectedState && s['category_name'] == category).toList() : [];
                });
              },
              validator: (val) => val == null && _categoriesForState.isNotEmpty ? "Category is required" : null,
            ),
            const SizedBox(height: 12),
            DropdownSearch<Map<String, dynamic>>(
              items: _stationsForCategory,
              selectedItem: _npeData.selectedStation,
              enabled: !_areFieldsLocked && _stationsForCategory.isNotEmpty,
              itemAsString: (s) => "${s['tbl_station_code']} - ${s['tbl_station_name']}",
              popupProps: const PopupProps.menu(showSearchBox: true, searchFieldProps: TextFieldProps(decoration: InputDecoration(hintText: "Search Station..."))),
              dropdownDecoratorProps: const DropDownDecoratorProps(dropdownSearchDecoration: InputDecoration(labelText: "Select Station *")),
              onChanged: (station) {
                setState(() {
                  _npeData.selectedStation = station;
                  _stationIdController.text = station?['tbl_station_code'] ?? '';
                  _locationController.text = station?['tbl_station_name'] ?? '';
                  _latController.text = station?['tbl_latitude']?.toString() ?? '';
                  _longController.text = station?['tbl_longitude']?.toString() ?? '';
                });
              },
              validator: (val) => val == null && _stationsForCategory.isNotEmpty ? "Station is required" : null,
            ),
            const SizedBox(height: 12),
            _buildTextFormField(controller: _eventDateTimeController, label: "Event Date/Time", readOnly: true),
            const SizedBox(height: 24),

            _buildSectionTitle("2. In-situ Measurements"),
            _buildInSituSection(),
            const SizedBox(height: 24),

            _buildSectionTitle("3. Field Observations *"),
            ..._buildObservationsCheckboxes(),
            const SizedBox(height: 24),

            _buildSectionTitle("4. Possible Source"),
            _buildTextFormField(controller: _possibleSourceController, label: "Possible Source", maxLines: 3),
            const SizedBox(height: 24),

            _buildSectionTitle("5. Attachments (Figures) *"),
            _buildImageAttachmentSection(),
            const SizedBox(height: 32),

            Center(
              child: ElevatedButton(
                style: ElevatedButton.styleFrom(padding: const EdgeInsets.symmetric(horizontal: 40, vertical: 15)),
                onPressed: _isLoading ? null : _submitNpeReport,
                child: _isLoading ? const CircularProgressIndicator(color: Colors.white) : const Text("Submit Report"),
              ),
            ),
          ],
        ),
      ),
    );
  }

  Widget _buildSectionTitle(String title) {
    return Padding(
      padding: const EdgeInsets.only(bottom: 12.0),
      child: Text(title, style: Theme.of(context).textTheme.titleLarge?.copyWith(fontWeight: FontWeight.bold)),
    );
  }

  List<Widget> _buildObservationsCheckboxes() {
    return [
      for (final key in _npeData.fieldObservations.keys)
        CheckboxListTile(
          title: Text(key),
          value: _npeData.fieldObservations[key],
          onChanged: (newValue) => setState(() => _npeData.fieldObservations[key] = newValue!),
          controlAffinity: ListTileControlAffinity.leading,
          contentPadding: EdgeInsets.zero,
        ),
      if (_npeData.fieldObservations['Others'] ?? false)
        Padding(
          padding: const EdgeInsets.symmetric(horizontal: 16.0),
          child: _buildTextFormField(
            controller: _othersObservationController,
            label: "Please specify *", // MODIFIED: Added * to make it required
          ),
        ),
    ];
  }

  Widget _buildImageAttachmentSection() {
    return Column(
      children: [
        _buildNPEImagePicker(
          title: 'Figure 1 *',
          imageFile: _npeData.image1,
          onClear: () => setState(() => _npeData.image1 = null),
          imageNumber: 1,
          remarkController: _image1RemarkController,
        ),
        _buildNPEImagePicker(
          title: 'Figure 2 *',
          imageFile: _npeData.image2,
          onClear: () => setState(() => _npeData.image2 = null),
          imageNumber: 2,
          remarkController: _image2RemarkController,
        ),
        _buildNPEImagePicker(
          title: 'Figure 3 *',
          imageFile: _npeData.image3,
          onClear: () => setState(() => _npeData.image3 = null),
          imageNumber: 3,
          remarkController: _image3RemarkController,
        ),
        _buildNPEImagePicker(
          title: 'Figure 4 *',
          imageFile: _npeData.image4,
          onClear: () => setState(() => _npeData.image4 = null),
          imageNumber: 4,
          remarkController: _image4RemarkController,
        ),
      ],
    );
  }

  Widget _buildNPEImagePicker({
    required String title,
    File? imageFile,
    required VoidCallback onClear,
    required int imageNumber,
    required TextEditingController remarkController, // ADDED
  }) {
    return Padding(
      padding: const EdgeInsets.symmetric(vertical: 8.0),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Text(title, style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w500)),
          const SizedBox(height: 8),
          imageFile != null
              ? Stack(
            alignment: Alignment.topRight,
            children: [
              ClipRRect(borderRadius: BorderRadius.circular(8.0), child: Image.file(imageFile, key: UniqueKey(), height: 150, width: double.infinity, fit: BoxFit.cover)),
              Container(
                margin: const EdgeInsets.all(4),
                decoration: BoxDecoration(color: Colors.black.withOpacity(0.6), shape: BoxShape.circle),
                child: IconButton(
                  visualDensity: VisualDensity.compact,
                  icon: const Icon(Icons.close, color: Colors.white, size: 20),
                  onPressed: () { // MODIFIED: Clear remarks controller
                    onClear();
                    remarkController.clear();
                  },
                ),
              ),
            ],
          )
              : Row(
            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
            children: [
              ElevatedButton.icon(onPressed: _isPickingImage ? null : () => _processAndSetImage(ImageSource.camera, imageNumber), icon: const Icon(Icons.camera_alt), label: const Text("Camera")),
              ElevatedButton.icon(onPressed: _isPickingImage ? null : () => _processAndSetImage(ImageSource.gallery, imageNumber), icon: const Icon(Icons.photo_library), label: const Text("Gallery")),
            ],
          ),
          // --- ADDED: Conditional remarks field ---
          if (imageFile != null) ...[
            const SizedBox(height: 8),
            TextFormField(
              controller: remarkController,
              decoration: const InputDecoration(
                labelText: 'Remarks (Optional)',
                border: OutlineInputBorder(),
              ),
              maxLines: 1,
            ),
          ],
          // --- END: Added section ---
        ],
      ),
    );
  }

  TextFormField _buildTextFormField({
    required TextEditingController controller,
    required String label,
    int? maxLines = 1,
    bool readOnly = false
  }) {
    return TextFormField(
      controller: controller,
      decoration: InputDecoration(
        labelText: label,
        border: const OutlineInputBorder(),
      ),
      maxLines: maxLines,
      readOnly: readOnly,
      validator: (value) {
        if (!label.contains('*')) return null; // Unchanged: handles optional fields
        // MODIFIED: Validator for required fields (label contains '*')
        if (!readOnly && (value == null || value.trim().isEmpty)) {
          // Custom message for "Others"
          if (label.contains("Please specify")) {
            return 'This field cannot be empty when "Others" is selected';
          }
          return 'This field cannot be empty';
        }
        return null;
      },
    );
  }

  Widget _buildInSituSection() {
    final activeConnection = _getActiveConnectionDetails();
    final String? activeType = activeConnection?['type'] as String?;

    return Column(
      children: [
        Row(
          children: [
            Expanded(
              child: activeType == 'bluetooth'
                  ? FilledButton.icon(icon: const Icon(Icons.bluetooth_connected), label: const Text("Bluetooth"), onPressed: _isLoading ? null : () => _handleConnectionAttempt('bluetooth'))
                  : OutlinedButton.icon(icon: const Icon(Icons.bluetooth), label: const Text("Bluetooth"), onPressed: _isLoading ? null : () => _handleConnectionAttempt('bluetooth')),
            ),
            const SizedBox(width: 16),
            Expanded(
              child: activeType == 'serial'
                  ? FilledButton.icon(icon: const Icon(Icons.usb), label: const Text("USB Serial"), onPressed: _isLoading ? null : () => _handleConnectionAttempt('serial'))
                  : OutlinedButton.icon(icon: const Icon(Icons.usb), label: const Text("USB Serial"), onPressed: _isLoading ? null : () => _handleConnectionAttempt('serial')),
            ),
          ],
        ),
        const SizedBox(height: 16),
        if (activeConnection != null)
          _buildConnectionCard(type: activeConnection['type'], connectionState: activeConnection['state'], deviceName: activeConnection['name']),
        const SizedBox(height: 16),
        _buildParameterListItem(icon: Icons.air, label: "DO", unit: "mg/L", controller: _doMgLController),
        _buildParameterListItem(icon: Icons.percent, label: "DO", unit: "%", controller: _doPercentController),
        _buildParameterListItem(icon: Icons.science_outlined, label: "PH", unit: "", controller: _phController),
        _buildParameterListItem(icon: Icons.flash_on, label: "Cond", unit: "µS/cm", controller: _condController),
        _buildParameterListItem(icon: Icons.thermostat, label: "Temp", unit: "°C", controller: _tempController),
        _buildParameterListItem(icon: Icons.opacity, label: "Turb", unit: "NTU", controller: _turbController),
      ],
    );
  }

  Widget _buildConnectionCard({required String type, required dynamic connectionState, String? deviceName}) {
    final isConnected = connectionState == BluetoothConnectionState.connected || connectionState == SerialConnectionState.connected;
    final isConnecting = connectionState == BluetoothConnectionState.connecting || connectionState == SerialConnectionState.connecting;
    Color statusColor = isConnected ? Colors.green : Colors.red;
    String statusText = isConnected ? 'Connected to ${deviceName ?? 'device'}' : 'Disconnected';
    if (isConnecting) {
      statusColor = Colors.orange;
      statusText = 'Connecting...';
    }
    return Card(
      elevation: 2,
      child: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          children: [
            Text(statusText, style: TextStyle(color: statusColor, fontWeight: FontWeight.bold, fontSize: 16)),
            const SizedBox(height: 16),
            if (isConnecting || _isLoading)
              const CircularProgressIndicator()
            else if (isConnected)
              Row(
                mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                children: [
                  Flexible(
                    child: ElevatedButton.icon(
                      icon: Icon(_isAutoReading ? Icons.stop_circle_outlined : Icons.play_circle_outlined),
                      label: Text(_isAutoReading
                          ? (_isLockedOut ? 'Stop Reading (${_lockoutSecondsRemaining}s)' : 'Stop Reading')
                          : 'Start Reading'),
                      onPressed: (_isAutoReading && _isLockedOut) ? null : () => _toggleAutoReading(type),
                      style: ElevatedButton.styleFrom(
                        backgroundColor: _isAutoReading
                            ? (_isLockedOut ? Colors.grey.shade600 : Colors.orange)
                            : Colors.green,
                        foregroundColor: Colors.white,
                      ),
                    ),
                  ),
                  TextButton.icon(
                    icon: const Icon(Icons.link_off),
                    label: const Text('Disconnect'),
                    onPressed: () => _disconnect(type),
                    style: TextButton.styleFrom(foregroundColor: Colors.red),
                  )
                ],
              )
          ],
        ),
      ),
    );
  }

  Widget _buildParameterListItem({required IconData icon, required String label, required String unit, required TextEditingController controller}) {
    final bool isMissing = controller.text.isEmpty || controller.text.contains('-999');
    final String displayValue = isMissing ? '-.--' : controller.text;
    final String displayLabel = unit.isEmpty ? label : '$label ($unit)';

    return Card(
      margin: const EdgeInsets.symmetric(vertical: 4.0),
      child: ListTile(
        leading: Icon(icon, color: Theme.of(context).primaryColor, size: 32),
        title: Text(displayLabel),
        trailing: Text(
          displayValue,
          style: Theme.of(context).textTheme.titleMedium?.copyWith(
              fontWeight: FontWeight.bold,
              color: isMissing ? Colors.grey : Theme.of(context).colorScheme.primary),
        ),
      ),
    );
  }
}