// lib/screens/river/manual/triennial/widgets/river_manual_triennial_step_3_data_capture.dart

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:flutter_bluetooth_serial/flutter_bluetooth_serial.dart';
import 'package:usb_serial/usb_serial.dart';
import 'package:intl/intl.dart';

import '../../../../../auth_provider.dart';
import '../../../../../models/river_manual_triennial_sampling_data.dart';
//import '../../../../../services/api_service.dart'; // Import to access DatabaseHelper
import 'package:environment_monitoring_app/services/database_helper.dart';
import '../../../../../services/river_in_situ_sampling_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 RiverManualTriennialStep3DataCapture extends StatefulWidget {
  final RiverManualTriennialSamplingData data;
  final VoidCallback onNext;

  const RiverManualTriennialStep3DataCapture({
    super.key,
    required this.data,
    required this.onNext,
  });

  @override
  State<RiverManualTriennialStep3DataCapture> createState() => _RiverManualTriennialStep3DataCaptureState();
}

class _RiverManualTriennialStep3DataCaptureState extends State<RiverManualTriennialStep3DataCapture> with WidgetsBindingObserver {
  final _formKey = GlobalKey<FormState>();
  bool _isLoading = false;
  bool _isAutoReading = false;
  StreamSubscription? _dataSubscription;

  // --- START: Added for lockout timer ---
  Timer? _lockoutTimer;
  int _lockoutSecondsRemaining = 30;
  bool _isLockedOut = false;
  // --- END: Added for lockout timer ---

  late final RiverInSituSamplingService _samplingService;

  // --- START: Added for direct database access ---
  final DatabaseHelper _dbHelper = DatabaseHelper();
  // --- END: Added for direct database access ---

  Map<String, double>? _previousReadingsForComparison;
  Set<String> _outOfBoundsKeys = {};

  final Map<String, String> _parameterKeyToLimitName = const {
    'oxygenConcentration': 'Oxygen Conc',
    'oxygenSaturation': 'Oxygen Sat',
    'ph': 'pH',
    'salinity': 'Salinity',
    'electricalConductivity': 'Conductivity',
    'temperature': 'Temperature',
    'tds': 'TDS',
    'turbidity': 'Turbidity',
    'ammonia': 'Ammonia',
    'batteryVoltage': 'Battery',
  };

  final List<Map<String, dynamic>> _parameters = [];

  // Sonde parameter controllers
  final _sondeIdController = TextEditingController();
  final _dateController = TextEditingController();
  final _timeController = TextEditingController();
  final _oxyConcController = TextEditingController();
  final _oxySatController = TextEditingController();
  final _phController = TextEditingController();
  final _salinityController = TextEditingController();
  final _ecController = TextEditingController();
  final _tempController = TextEditingController();
  final _tdsController = TextEditingController();
  final _turbidityController = TextEditingController();
  final _ammoniaController = TextEditingController();
  final _batteryController = TextEditingController();

  // Flowrate controllers and state
  String? _selectedFlowrateMethod;
  final _flowrateValueController = TextEditingController();
  final _sdHeightController = TextEditingController();
  final _sdDistanceController = TextEditingController();

  // --- MODIFICATION: Duration controllers instead of TimeFirst/Last ---
  final _sdDurationHourController = TextEditingController();
  final _sdDurationMinuteController = TextEditingController();
  final _sdDurationSecondController = TextEditingController();
  // --- END MODIFICATION ---

  @override
  void initState() {
    super.initState();
    _samplingService = Provider.of<RiverInSituSamplingService>(context, listen: false);
    _initializeControllers();
    _initializeFlowrateControllers();
    WidgetsBinding.instance.addObserver(this);
  }

  @override
  void dispose() {
    // --- MODIFICATION: Robust cleanup on dispose ---
    _disconnectFromAll();
    // --- END MODIFICATION ---

    _disposeControllers();
    _disposeFlowrateControllers();
    WidgetsBinding.instance.removeObserver(this);
    super.dispose();
  }

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    if (state == AppLifecycleState.resumed) {
      if (mounted) {
        // --- START MODIFICATION ---
        final service = _samplingService;
        final btConnecting = service.bluetoothConnectionState.value == BluetoothConnectionState.connecting;
        final serialConnecting = service.serialConnectionState.value == SerialConnectionState.connecting;

        // If the widget's local state is loading OR the service's state is stuck connecting
        if (_isLoading || btConnecting || serialConnecting) {
          // Force-call disconnect to reset both the service's state
          // and the local _isLoading flag (inside _disconnect).
          _disconnectFromAll();
        } else {
          // If not stuck, just a normal refresh
          setState(() {});
        }
        // --- END MODIFICATION ---
      }
    }
  }

  // --- MODIFICATION: Added helper to clear data fields ---
  void _clearDataFields() {
    const defaultValue = '-999.0';
    _oxyConcController.text = defaultValue;
    _oxySatController.text = defaultValue;
    _phController.text = defaultValue;
    _salinityController.text = defaultValue;
    _ecController.text = defaultValue;
    _tempController.text = defaultValue;
    _tdsController.text = defaultValue;
    _turbidityController.text = defaultValue;
    _ammoniaController.text = defaultValue;
    _batteryController.text = defaultValue;

    // Also clear Sonde ID
    _sondeIdController.clear();
  }
  // --- END MODIFICATION ---

  void _initializeControllers() {
    widget.data.dataCaptureDate = widget.data.samplingDate;
    widget.data.dataCaptureTime = widget.data.samplingTime;

    _sondeIdController.text = widget.data.sondeId ?? '';
    _dateController.text = widget.data.dataCaptureDate ?? '';
    _timeController.text = widget.data.dataCaptureTime ?? '';

    _oxyConcController.text = widget.data.oxygenConcentration?.toString() ?? '-999.0';
    _oxySatController.text = widget.data.oxygenSaturation?.toString() ?? '-999.0';
    _phController.text = widget.data.ph?.toString() ?? '-999.0';
    _salinityController.text = widget.data.salinity?.toString() ?? '-999.0';
    _ecController.text = widget.data.electricalConductivity?.toString() ?? '-999.0';
    _tempController.text = widget.data.temperature?.toString() ?? '-999.0';
    _tdsController.text = widget.data.tds?.toString() ?? '-999.0';
    _turbidityController.text = widget.data.turbidity?.toString() ?? '-999.0';
    _ammoniaController.text = widget.data.ammonia?.toString() ?? '-999.0';
    _batteryController.text = widget.data.batteryVoltage?.toString() ?? '-999.0';

    if (_parameters.isEmpty) {
      _parameters.addAll([
        {'key': 'oxygenConcentration', 'icon': Icons.air, 'label': 'Oxygen Conc.', 'unit': 'mg/L', 'controller': _oxyConcController},
        {'key': 'oxygenSaturation', 'icon': Icons.percent, 'label': 'Oxygen Sat.', 'unit': '%', 'controller': _oxySatController},
        {'key': 'ph', 'icon': Icons.science_outlined, 'label': 'pH', 'unit': '', 'controller': _phController},
        {'key': 'salinity', 'icon': Icons.waves, 'label': 'Salinity', 'unit': 'ppt', 'controller': _salinityController},
        {'key': 'electricalConductivity', 'icon': Icons.flash_on, 'label': 'Conductivity', 'unit': 'µS/cm', 'controller': _ecController},
        {'key': 'temperature', 'icon': Icons.thermostat, 'label': 'Temperature', 'unit': '°C', 'controller': _tempController},
        {'key': 'tds', 'icon': Icons.grain, 'label': 'TDS', 'unit': 'mg/L', 'controller': _tdsController},
        {'key': 'turbidity', 'icon': Icons.opacity, 'label': 'Turbidity', 'unit': 'NTU', 'controller': _turbidityController},
        {'key': 'ammonia', 'icon': Icons.science, 'label': 'Ammonia', 'unit': 'mg/L', 'controller': _ammoniaController},
        {'key': 'batteryVoltage', 'icon': Icons.battery_charging_full, 'label': 'Battery', 'unit': 'V', 'controller': _batteryController},
      ]);
    }
  }

  void _disposeControllers() {
    _sondeIdController.dispose();
    _dateController.dispose();
    _timeController.dispose();
    _oxyConcController.dispose();
    _oxySatController.dispose();
    _phController.dispose();
    _salinityController.dispose();
    _ecController.dispose();
    _tempController.dispose();
    _tdsController.dispose();
    _turbidityController.dispose();
    _ammoniaController.dispose();
    _batteryController.dispose();
  }

  void _initializeFlowrateControllers() {
    _selectedFlowrateMethod = widget.data.flowrateMethod;
    _flowrateValueController.text = widget.data.flowrateValue?.toString() ?? '';
    _sdHeightController.text = widget.data.flowrateSurfaceDrifterHeight?.toString() ?? '';
    _sdDistanceController.text = widget.data.flowrateSurfaceDrifterDistance?.toString() ?? '';

    // --- MODIFICATION: Parse existing duration if available ---
    if (widget.data.flowrateSurfaceDrifterTimeLast != null &&
        widget.data.flowrateSurfaceDrifterTimeLast!.contains(':')) {
      final parts = widget.data.flowrateSurfaceDrifterTimeLast!.split(':');
      if (parts.length == 3) {
        _sdDurationHourController.text = parts[0];
        _sdDurationMinuteController.text = parts[1];
        _sdDurationSecondController.text = parts[2];
      }
    }
    // --- END MODIFICATION ---
  }

  void _disposeFlowrateControllers() {
    _flowrateValueController.dispose();
    _sdHeightController.dispose();
    _sdDistanceController.dispose();
    // --- MODIFICATION: Dispose duration controllers ---
    _sdDurationHourController.dispose();
    _sdDurationMinuteController.dispose();
    _sdDurationSecondController.dispose();
    // --- END MODIFICATION ---
  }

  void _onFlowrateMethodChanged(String? value) {
    setState(() {
      _selectedFlowrateMethod = value;
      widget.data.flowrateMethod = value; // Update model immediately
      if (value == 'NA') {
        _flowrateValueController.text = 'NA';
      } else if (value == 'Flowmeter') {
        _flowrateValueController.clear();
        _sdHeightController.clear();
        _sdDistanceController.clear();
        // --- MODIFICATION: Clear duration fields ---
        _sdDurationHourController.clear();
        _sdDurationMinuteController.clear();
        _sdDurationSecondController.clear();
        // --- END MODIFICATION ---

      } else { // Surface Drifter
        _flowrateValueController.clear(); // Will be calculated
      }
    });
  }

  void _calculateFlowrate() {
    final distance = double.tryParse(_sdDistanceController.text);
    // --- MODIFICATION: Calculate using duration ---
    final hours = int.tryParse(_sdDurationHourController.text) ?? 0;
    final minutes = int.tryParse(_sdDurationMinuteController.text) ?? 0;
    final seconds = int.tryParse(_sdDurationSecondController.text) ?? 0;

    if (distance == null) {
      _showSnackBar("Please enter the Distance.", isError: true);
      return;
    }

    final totalSeconds = (hours * 3600) + (minutes * 60) + seconds;

    if (totalSeconds <= 0) {
      _showSnackBar("Total duration must be greater than zero.", isError: true);
      return;
    }

    try {
      final flowrate = distance / totalSeconds;
      setState(() {
        _flowrateValueController.text = flowrate.toStringAsFixed(4);
      });
    } catch (e) {
      _showSnackBar("Error calculating flowrate.", isError: true);
    }
    // --- END MODIFICATION ---
  }

  Future<void> _selectTime(BuildContext context, TextEditingController controller) async {
    final TimeOfDay? picked = await showTimePicker(
      context: context,
      initialTime: TimeOfDay.now(),
    );
    if (picked != null) {
      final now = DateTime.now();
      final dt = DateTime(now.year, now.month, now.day, picked.hour, picked.minute);
      setState(() {
        controller.text = DateFormat('HH:mm:ss').format(dt);
      });
    }
  }

  Future<void> _handleConnectionAttempt(String type) async {
    final service = context.read<RiverInSituSamplingService>();
    final bool hasPermissions = await service.requestDevicePermissions();
    if (!hasPermissions && mounted) {
      _showSnackBar("Bluetooth & Location permissions are required to connect.", isError: true);
      return;
    }

    // --- MODIFICATION: Aggressive disconnect sequence ---
    _disconnectFromAll(); // 1. Stop streams and disconnect services
    _clearDataFields();   // 2. Clear all UI fields to remove old data

    // 3. Wait to ensure streams are fully closed
    await Future.delayed(const Duration(milliseconds: 500));
    // --- END MODIFICATION ---

    final bool connectionSuccess = await _connectToDevice(type);
    if (connectionSuccess && mounted) {
      _dataSubscription?.cancel();
      final stream = type == 'bluetooth' ? service.bluetoothDataStream : service.serialDataStream;
      _dataSubscription = stream.listen((readings) {
        if (mounted) {
          _updateTextFields(readings);
        }
      }, onError: (error) {
        debugPrint("Error on data stream: $error");
        if (mounted) _showSnackBar("Data stream error: $error", isError: true);
        _disconnect(type); // Disconnect on stream error
      }, onDone: () {
        debugPrint("Data stream done.");
        if (mounted) _disconnect(type); // Disconnect when stream closes
      });
    }
  }

  Future<bool> _connectToDevice(String type) async {
    setState(() => _isLoading = true);
    final service = context.read<RiverInSituSamplingService>();
    bool success = false;
    try {
      if (type == 'bluetooth') {
        final devices = await service.getPairedBluetoothDevices();
        if (!mounted) return false; // Check mounted after async gap
        if (devices.isEmpty) {
          _showSnackBar('No paired Bluetooth devices found.', isError: true);
          return false;
        }
        final selectedDevice = await showBluetoothDeviceListDialog(context: context, devices: devices);
        if (selectedDevice != null) {
          await service.connectToBluetoothDevice(selectedDevice);
          success = true;
        }
      } else if (type == 'serial') {
        final devices = await service.getAvailableSerialDevices();
        if (!mounted) return false;
        if (devices.isEmpty) {
          _showSnackBar('No USB Serial devices found. Ensure device is plugged in.', isError: true);
          return false;
        }
        final selectedDevice = await showSerialPortListDialog(context: context, devices: devices);
        if (selectedDevice != null) {
          await service.connectToSerialDevice(selectedDevice);
          success = true;
        }
      }
    } catch (e) {
      if (mounted) _showSnackBar('Connection failed: $e', isError: true);
      success = false;
    } finally {
      if (mounted) setState(() => _isLoading = false);
    }
    return success;
  }

  // --- START: MODIFIED VALIDATION FLOW ---
  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) {
    final service = context.read<RiverInSituSamplingService>();
    setState(() {
      _isAutoReading = !_isAutoReading;
      if (_isAutoReading) {
        if (activeType == 'bluetooth') service.startBluetoothAutoReading(); else service.startSerialAutoReading();
        _startLockoutTimer(); // --- MODIFICATION: Start countdown
      } else {
        if (activeType == 'bluetooth') service.stopBluetoothAutoReading(); else service.stopSerialAutoReading();
        // NOTE: _lockoutTimer is intentionally NOT cancelled here so the lockout persists for the remaining duration
      }
    });
  }

  void _disconnect(String type) {
    // --- START MODIFICATION ---
    final service = _samplingService; // NEW: Use the member variable
    // --- END MODIFICATION ---
    if (type == 'bluetooth') {
      service.disconnectFromBluetooth();
    } else {
      service.disconnectFromSerial();
    }

    // --- MODIFICATION: Unconditional cleanup ---
    _dataSubscription?.cancel();
    _dataSubscription = null;
    _lockoutTimer?.cancel();
    _clearDataFields(); // Clear UI
    // --- END MODIFICATION ---

    if (mounted) {
      setState(() {
        _isAutoReading = false;
        _isLockedOut = false; // --- MODIFICATION: Reset lockout state ---
        _isLoading = false;   // --- NEW: Also reset the loading flag ---
      });
    }
  }

  void _disconnectFromAll() {
    // --- MODIFICATION: Unconditional cleanup ---
    // 1. Cancel local listeners first
    _dataSubscription?.cancel();
    _dataSubscription = null;
    _lockoutTimer?.cancel();

    // 2. Disconnect services if active
    final service = _samplingService;
    if (service.bluetoothConnectionState.value != BluetoothConnectionState.disconnected) {
      service.disconnectFromBluetooth();
    }
    if (service.serialConnectionState.value != SerialConnectionState.disconnected) {
      service.disconnectFromSerial();
    }

    // 3. Reset local state
    if (mounted) {
      setState(() {
        _isAutoReading = false;
        _isLockedOut = false;
        _isLoading = false;
      });
    }
    // --- END MODIFICATION ---
  }

  void _updateTextFields(Map<String, double> readings) {
    const defaultValue = -999.0;
    setState(() {
      _oxyConcController.text = (readings['Optical Dissolved Oxygen: Compensated mg/L'] ?? defaultValue).toStringAsFixed(5);
      _oxySatController.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);
      _ecController.text = (readings['Conductivity: us/cm'] ?? defaultValue).toStringAsFixed(5);
      _salinityController.text = (readings['Conductivity: Salinity'] ?? defaultValue).toStringAsFixed(5);
      _tdsController.text = (readings['Conductivity:TDS mg/L'] ?? defaultValue).toStringAsFixed(5);
      _turbidityController.text = (readings['Turbidity: FNU'] ?? defaultValue).toStringAsFixed(5);
      _batteryController.text = (readings['Sonde: Battery Voltage'] ?? defaultValue).toStringAsFixed(5);
      _ammoniaController.text = (readings['Ammonium (NH4+) mg/L'] ?? defaultValue).toStringAsFixed(5);
    });
  }

  void _validateAndProceed() async {
    // --- START MODIFICATION: Add lockout check ---
    if (_isLockedOut) {
      _showSnackBar("Please wait for the initial reading period to complete.", isError: true);
      return;
    }
    // --- END MODIFICATION ---

    // --- START MODIFICATION: Disable Next if Connected and Auto Reading is active ---
    if (_isAutoReading) {
      _showStopReadingDialog();
      return;
    }

    if (!_formKey.currentState!.validate()) {
      return;
    }
    _formKey.currentState!.save();

    final currentReadings = _captureReadingsToMap();

    // Directly load river-specific limits from the new table via DatabaseHelper.
    final List<Map<String, dynamic>> riverLimits = await _dbHelper.loadRiverParameterLimits() ?? [];

    final outOfBoundsParams = _validateParameters(currentReadings, riverLimits);

    setState(() {
      _outOfBoundsKeys = outOfBoundsParams.map((p) => _parameters.firstWhere((param) => param['label'] == p['label'])['key'] as String).toSet();
    });

    if (outOfBoundsParams.isNotEmpty) {
      _showParameterLimitDialog(outOfBoundsParams, currentReadings);
    } else {
      _saveDataAndMoveOn(currentReadings);
    }
  }

  Map<String, double> _captureReadingsToMap() {
    final Map<String, double> readings = {};
    for (var param in _parameters) {
      final key = param['key'] as String;
      final controller = param['controller'] as TextEditingController;
      readings[key] = double.tryParse(controller.text) ?? -999.0;
    }
    return readings;
  }

  List<Map<String, dynamic>> _validateParameters(Map<String, double> readings, List<Map<String, dynamic>> limits) {
    final List<Map<String, dynamic>> invalidParams = [];

    double? _parseLimitValue(dynamic value) {
      if (value == null) return null;
      if (value is num) return value.toDouble();
      if (value is String) return double.tryParse(value);
      return null;
    }

    readings.forEach((key, value) {
      if (value == -999.0) return;

      final limitName = _parameterKeyToLimitName[key];
      if (limitName == null) return;

      final limitData = limits.firstWhere(
            (l) => l['param_parameter_list'] == limitName,
        orElse: () => {},
      );

      if (limitData.isNotEmpty) {
        final lowerLimit = _parseLimitValue(limitData['param_lower_limit']);
        final upperLimit = _parseLimitValue(limitData['param_upper_limit']);

        if ((lowerLimit != null && value < lowerLimit) || (upperLimit != null && value > upperLimit)) {
          final paramInfo = _parameters.firstWhere((p) => p['key'] == key, orElse: () => {});
          invalidParams.add({
            'label': paramInfo['label'] ?? key,
            'value': value,
            'lower_limit': lowerLimit,
            'upper_limit': upperLimit,
          });
        }
      }
    });
    return invalidParams;
  }

  void _saveDataAndMoveOn(Map<String, double> readings) {
    try {
      const defaultValue = -999.0;
      widget.data.sondeId = _sondeIdController.text; // Ensure ID is saved
      widget.data.temperature = readings['temperature'] ?? defaultValue;
      widget.data.ph = readings['ph'] ?? defaultValue;
      widget.data.salinity = readings['salinity'] ?? defaultValue;
      widget.data.electricalConductivity = readings['electricalConductivity'] ?? defaultValue;
      widget.data.oxygenConcentration = readings['oxygenConcentration'] ?? defaultValue;
      widget.data.oxygenSaturation = readings['oxygenSaturation'] ?? defaultValue;
      widget.data.tds = readings['tds'] ?? defaultValue;
      widget.data.turbidity = readings['turbidity'] ?? defaultValue;
      widget.data.ammonia = readings['ammonia'] ?? defaultValue;
      widget.data.batteryVoltage = readings['batteryVoltage'] ?? defaultValue;

      widget.data.flowrateMethod = _selectedFlowrateMethod;
      if (_selectedFlowrateMethod == 'Surface Drifter') {
        widget.data.flowrateSurfaceDrifterHeight = double.tryParse(_sdHeightController.text);
        widget.data.flowrateSurfaceDrifterDistance = double.tryParse(_sdDistanceController.text);

        // --- MODIFICATION: Save formatted duration ---
        String twoDigits(int n) => n.toString().padLeft(2, "0");
        String formattedDuration =
            "${twoDigits(int.tryParse(_sdDurationHourController.text) ?? 0)}:"
            "${twoDigits(int.tryParse(_sdDurationMinuteController.text) ?? 0)}:"
            "${twoDigits(int.tryParse(_sdDurationSecondController.text) ?? 0)}";

        widget.data.flowrateSurfaceDrifterTimeFirst = "00:00:00";
        widget.data.flowrateSurfaceDrifterTimeLast = formattedDuration;
        // --- END MODIFICATION ---

        widget.data.flowrateValue = double.tryParse(_flowrateValueController.text);
      } else if (_selectedFlowrateMethod == 'Flowmeter') {
        widget.data.flowrateSurfaceDrifterHeight = null;
        widget.data.flowrateSurfaceDrifterDistance = null;
        widget.data.flowrateSurfaceDrifterTimeFirst = null;
        widget.data.flowrateSurfaceDrifterTimeLast = null;
        widget.data.flowrateValue = double.tryParse(_flowrateValueController.text);
      } else { // NA
        widget.data.flowrateSurfaceDrifterHeight = null;
        widget.data.flowrateSurfaceDrifterDistance = null;
        widget.data.flowrateSurfaceDrifterTimeFirst = null;
        widget.data.flowrateSurfaceDrifterTimeLast = null;
        widget.data.flowrateValue = null;
      }

    } catch (e) {
      _showSnackBar("Could not save parameters due to a data format error.", isError: true);
      return;
    }

    setState(() {
      _outOfBoundsKeys.clear();
      if (_previousReadingsForComparison != null) {
        _previousReadingsForComparison = null;
      }
    });

    widget.onNext();
  }

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

  void _showStopReadingDialog() {
    showDialog(
        context: context,
        builder: (BuildContext context) {
          return AlertDialog(
              title: const Text('Data Collection Active'),
              content: const Text('Please stop the live data collection before proceeding.'),
              actions: <Widget>[
                TextButton(child: const Text('OK'), onPressed: () => Navigator.of(context).pop())
              ]
          );
        }
    );
  }

  Map<String, dynamic>? _getActiveConnectionDetails() {
    // --- START FIX: Use read() instead of watch() ---
    final service = context.read<RiverInSituSamplingService>();
    // --- END FIX ---

    if (service.bluetoothConnectionState.value != BluetoothConnectionState.disconnected) {
      return {'type': 'bluetooth', 'state': service.bluetoothConnectionState.value, 'name': service.connectedBluetoothDeviceName};
    }
    if (service.serialConnectionState.value != SerialConnectionState.disconnected) {
      return {'type': 'serial', 'state': service.serialConnectionState.value, 'name': service.connectedSerialDeviceName};
    }
    return null;
  }

  @override
  Widget build(BuildContext context) {
    final service = context.watch<RiverInSituSamplingService>();
    final activeConnection = _getActiveConnectionDetails();
    final String? activeType = activeConnection?['type'] as String?;

    // Check if ANY device is currently connected
    final bool isDeviceConnected = activeConnection != null;

    // --- START MODIFICATION: Logic for disabling inputs ---
    // Disable interaction if auto-reading is active OR if locked out.
    // If reading is stopped (even if connected), we allow interaction.
    final bool shouldDisableInput = _isAutoReading || _isLockedOut;
    // --- END MODIFICATION ---

    // --- START MODIFICATION: Add WillPopScope to block back navigation ---
    return WillPopScope(
      onWillPop: () async {
        if (_isLockedOut) {
          _showSnackBar("Please wait for the initial reading period to complete.", isError: true);
          return false; // Prevent back navigation
        }
        _disconnectFromAll();
        return true; // Allow back navigation
      },
      child: Form(
        key: _formKey,
        child: ListView(
          padding: const EdgeInsets.all(24.0),
          children: [
            Text("Data Capture", style: Theme.of(context).textTheme.headlineSmall),
            const SizedBox(height: 16),
            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: 24),
            ValueListenableBuilder<String?>(
              valueListenable: service.sondeId,
              builder: (context, sondeId, child) {
                // --- START FIX: Only update if non-null to prevent clearing on disconnect ---
                if (sondeId != null && sondeId.isNotEmpty) {
                  final newSondeId = sondeId;
                  WidgetsBinding.instance.addPostFrameCallback((_) {
                    if (mounted && _sondeIdController.text != newSondeId) {
                      _sondeIdController.text = newSondeId;
                      widget.data.sondeId = newSondeId;
                    }
                  });
                }
                // --- END FIX ---
                return TextFormField(
                  controller: _sondeIdController,
                  decoration: const InputDecoration(labelText: 'Sonde ID *', hintText: 'Connect device or enter manually'),
                  validator: (v) => v == null || v.isEmpty ? 'Sonde ID is required' : null,
                  onChanged: (value) { widget.data.sondeId = value; },
                  onSaved: (v) => widget.data.sondeId = v,
                );
              },
            ),
            const SizedBox(height: 16),
            Row(
              children: [
                Expanded(child: TextFormField(controller: _dateController, readOnly: true, decoration: const InputDecoration(labelText: 'Date'))),
                const SizedBox(width: 16),
                Expanded(child: TextFormField(controller: _timeController, readOnly: true, decoration: const InputDecoration(labelText: 'Time'))),
              ],
            ),

            if (_previousReadingsForComparison != null)
              _buildComparisonView(),

            const Divider(height: 32),
            Column(
              children: _parameters.map((param) {
                return _buildParameterListItem(
                  icon: param['icon'] as IconData,
                  label: param['label'] as String,
                  unit: param['unit'] as String,
                  controller: param['controller'] as TextEditingController,
                  isOutOfBounds: _outOfBoundsKeys.contains(param['key']),
                );
              }).toList(),
            ),
            const Divider(height: 32),

            // --- MODIFIED: Use 'shouldDisableInput' instead of 'isDeviceConnected' ---
            _buildFlowrateSection(isInputDisabled: shouldDisableInput),
            const SizedBox(height: 32),

            // --- MODIFIED: Enable Next button if reading stopped (even if connected) ---
            ElevatedButton(
              // Disable if locked out OR reading is active
              onPressed: (_isLockedOut || _isAutoReading) ? null : _validateAndProceed,
              style: ElevatedButton.styleFrom(padding: const EdgeInsets.symmetric(vertical: 16)),
              child: Text(
                  _isLockedOut
                      ? 'Next ($_lockoutSecondsRemaining\s)'
                      : (_isAutoReading ? 'Stop Reading to Proceed' : 'Next')
              ),
            ),
            // --- END MODIFICATION ---
          ],
        ),
      ),
    );
    // --- END MODIFICATION ---
  }

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

    final Color valueColor = isOutOfBounds
        ? Colors.red
        : (isMissing ? Colors.grey : Theme.of(context).colorScheme.primary);

    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: valueColor),
        ),
      ),
    );
  }

  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)
            // --- START FIX: Replaced Row with Wrap to fix horizontal overflow with countdown timer ---
              Wrap(
                alignment: WrapAlignment.spaceEvenly,
                crossAxisAlignment: WrapCrossAlignment.center,
                spacing: 8.0, // Horizontal space between buttons
                runSpacing: 4.0, // Vertical space if it wraps
                children: [
                  // --- START MODIFICATION: Add countdown to Stop Reading button ---
                  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,
                    ),
                  ),
                  // --- END MODIFICATION ---
                  TextButton.icon(
                    icon: const Icon(Icons.link_off),
                    label: const Text('Disconnect'),
                    // --- MODIFICATION: Disabled during lockout ---
                    onPressed: _isLockedOut ? null : () => _disconnect(type),
                    // --- END MODIFICATION ---
                    style: TextButton.styleFrom(foregroundColor: Colors.red),
                  )
                ],
              )
            // --- END FIX ---
          ],
        ),
      ),
    );
  }

  Widget _buildComparisonView() {
    final previousReadings = _previousReadingsForComparison!;
    final isDarkTheme = Theme.of(context).brightness == Brightness.dark;

    return Card(
      margin: const EdgeInsets.only(top: 24.0),
      color: Theme.of(context).cardColor,
      child: Padding(
        padding: const EdgeInsets.all(16.0),
        child: DefaultTextStyle(
          style: TextStyle(color: Theme.of(context).textTheme.bodyLarge?.color),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Text(
                "Resample Comparison",
                style: Theme.of(context).textTheme.titleLarge?.copyWith(color: Theme.of(context).primaryColor),
              ),
              const SizedBox(height: 8),
              Table(
                columnWidths: const {
                  0: FlexColumnWidth(2),
                  1: FlexColumnWidth(1.5),
                  2: FlexColumnWidth(1.5),
                },
                border: TableBorder(
                  horizontalInside: BorderSide(width: 1, color: Colors.grey.shade700, style: BorderStyle.solid),
                  verticalInside: BorderSide(width: 1, color: Colors.grey.shade700, style: BorderStyle.solid),
                  top: BorderSide(width: 1.5, color: Colors.grey.shade500),
                  bottom: BorderSide(width: 1.5, color: Colors.grey.shade500),
                ),
                children: [
                  TableRow(
                    decoration: BoxDecoration(color: isDarkTheme ? Colors.grey.shade800 : Colors.grey.shade200),
                    children: [
                      Padding(padding: const EdgeInsets.all(8.0), child: Text('Parameter', style: TextStyle(fontWeight: FontWeight.bold, color: Theme.of(context).textTheme.titleMedium?.color))),
                      Padding(padding: const EdgeInsets.all(8.0), child: Text('Previous', style: TextStyle(fontWeight: FontWeight.bold, color: Theme.of(context).textTheme.titleMedium?.color))),
                      Padding(padding: const EdgeInsets.all(8.0), child: Text('Current', style: TextStyle(fontWeight: FontWeight.bold, color: Theme.of(context).textTheme.titleMedium?.color))),
                    ],
                  ),
                  ..._parameters.map((param) {
                    final key = param['key'] as String;
                    final label = param['label'] as String;
                    final controller = param['controller'] as TextEditingController;
                    final previousValue = previousReadings[key];
                    final bool isCurrentValueOutOfBounds = _outOfBoundsKeys.contains(key);
                    final currentValue = double.tryParse(controller.text) ?? -999.0;

                    return TableRow(
                      children: [
                        Padding(padding: const EdgeInsets.all(8.0), child: Text(label)),
                        Padding(
                          padding: const EdgeInsets.all(8.0),
                          child: Text(
                            previousValue == -999.0 ? '-.--' : previousValue!.toStringAsFixed(5),
                            style: TextStyle(color: isDarkTheme ? Colors.orange.shade200 : Colors.orange.shade700),
                          ),
                        ),
                        Padding(
                          padding: const EdgeInsets.all(8.0),
                          child: Text(
                            currentValue == -999.0 ? '-.--' : currentValue.toStringAsFixed(5),
                            style: TextStyle(
                                color: isCurrentValueOutOfBounds
                                    ? Colors.red
                                    : (isDarkTheme ? Colors.green.shade200 : Colors.green.shade700),
                                fontWeight: FontWeight.bold
                            ),
                          ),
                        ),
                      ],
                    );
                  }).toList(),
                ],
              ),
            ],
          ),
        ),
      ),
    );
  }

  Future<void> _showParameterLimitDialog(List<Map<String, dynamic>> invalidParams, Map<String, double> readings) async {
    return showDialog(
      context: context,
      barrierDismissible: false,
      builder: (BuildContext context) {
        final isDarkTheme = Theme.of(context).brightness == Brightness.dark;
        return AlertDialog(
          title: const Text('Parameter Limit Warning'),
          content: SingleChildScrollView(
            child: DefaultTextStyle(
              style: TextStyle(color: Theme.of(context).textTheme.bodyMedium?.color),
              child: Column(
                mainAxisSize: MainAxisSize.min,
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  const Text('The following parameters are outside the standard limits:'),
                  const SizedBox(height: 16),
                  Table(
                    columnWidths: const {
                      0: FlexColumnWidth(2),
                      1: FlexColumnWidth(2.5),
                      2: FlexColumnWidth(1.5),
                    },
                    border: TableBorder(
                      horizontalInside: BorderSide(width: 0.5, color: isDarkTheme ? Colors.grey.shade700 : Colors.grey.shade300),
                      verticalInside: BorderSide(width: 0.5, color: isDarkTheme ? Colors.grey.shade700 : Colors.grey.shade300),
                      top: BorderSide(width: 1, color: isDarkTheme ? Colors.grey.shade600 : Colors.grey.shade400),
                      bottom: BorderSide(width: 1, color: isDarkTheme ? Colors.grey.shade600 : Colors.grey.shade400),
                    ),
                    children: [
                      TableRow(
                        decoration: BoxDecoration(color: isDarkTheme ? Colors.grey.shade800 : Colors.grey.shade200),
                        children: [
                          Padding(padding: const EdgeInsets.all(6.0), child: Text('Parameter', style: TextStyle(fontWeight: FontWeight.bold, color: Theme.of(context).textTheme.titleSmall?.color))),
                          Padding(padding: const EdgeInsets.all(6.0), child: Text('Limit Range', style: TextStyle(fontWeight: FontWeight.bold, color: Theme.of(context).textTheme.titleSmall?.color))),
                          Padding(padding: const EdgeInsets.all(6.0), child: Text('Current', style: TextStyle(fontWeight: FontWeight.bold, color: Theme.of(context).textTheme.titleSmall?.color))),
                        ],
                      ),
                      ...invalidParams.map((p) => TableRow(
                        children: [
                          Padding(padding: const EdgeInsets.all(6.0), child: Text(p['label'])),
                          Padding(padding: const EdgeInsets.all(6.0), child: Text('${p['lower_limit']?.toStringAsFixed(5) ?? 'N/A'} - ${p['upper_limit']?.toStringAsFixed(5) ?? 'N/A'}')),
                          Padding(
                            padding: const EdgeInsets.all(6.0),
                            child: Text(
                              p['value'].toStringAsFixed(5),
                              style: const TextStyle(color: Colors.redAccent, fontWeight: FontWeight.bold),
                            ),
                          ),
                        ],
                      )).toList(),
                    ],
                  ),
                  const SizedBox(height: 16),
                  const Text('Do you want to resample or proceed with the current values? Please verify with standard solution.'),
                ],
              ),
            ),
          ),
          actions: <Widget>[
            TextButton(
              child: const Text('Resample'),
              onPressed: () {
                setState(() {
                  _previousReadingsForComparison = readings;
                });
                Navigator.of(context).pop();
              },
            ),
            FilledButton(
              child: const Text('Proceed Anyway'),
              onPressed: () {
                Navigator.of(context).pop();
                _saveDataAndMoveOn(readings);
              },
            ),
          ],
        );
      },
    );
  }

  Widget _buildFlowrateSection({bool isInputDisabled = false}) {
    return Card(
      margin: const EdgeInsets.symmetric(vertical: 4.0),
      child: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Text("Flowrate", style: Theme.of(context).textTheme.titleLarge),
            if (isInputDisabled)
              Padding(
                padding: const EdgeInsets.only(top: 8.0, bottom: 8.0),
                child: Row(
                  children: [
                    Icon(Icons.info_outline, color: Colors.orange, size: 20),
                    const SizedBox(width: 8),
                    Expanded(
                      child: Text(
                        "Please stop reading to enter flowrate.",
                        style: TextStyle(color: Colors.orange[800], fontSize: 12),
                      ),
                    ),
                  ],
                ),
              ),
            const SizedBox(height: 8),
            AbsorbPointer(
              absorbing: isInputDisabled,
              child: Opacity(
                opacity: isInputDisabled ? 0.5 : 1.0,
                child: Column(
                  children: [
                    Wrap(
                      alignment: WrapAlignment.spaceAround,
                      spacing: 8.0,
                      runSpacing: 4.0,
                      children: [
                        _buildFlowrateRadioButton("Surface Drifter"),
                        _buildFlowrateRadioButton("Flowmeter"),
                        _buildFlowrateRadioButton("NA"),
                      ],
                    ),
                    if (_selectedFlowrateMethod == 'Surface Drifter')
                      _buildSurfaceDrifterFields(),
                    if (_selectedFlowrateMethod == 'Flowmeter')
                      _buildFlowmeterField(),
                    if (_selectedFlowrateMethod == 'NA')
                      _buildNAField(),
                  ],
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }

  Widget _buildFlowrateRadioButton(String title) {
    return Column(
      children: [
        Radio<String>(
          value: title,
          groupValue: _selectedFlowrateMethod,
          onChanged: _onFlowrateMethodChanged,
        ),
        Text(
          title,
          textAlign: TextAlign.center,
          overflow: TextOverflow.ellipsis,
        ),
      ],
    );
  }

  Widget _buildSurfaceDrifterFields() {
    return Padding(
      padding: const EdgeInsets.only(top: 16.0),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          TextFormField(
            controller: _sdHeightController,
            decoration: const InputDecoration(labelText: 'Height (m)'),
            keyboardType: const TextInputType.numberWithOptions(decimal: true),
          ),
          const SizedBox(height: 16),
          TextFormField(
            controller: _sdDistanceController,
            decoration: const InputDecoration(labelText: 'Distance (m) *'),
            keyboardType: const TextInputType.numberWithOptions(decimal: true),
            validator: (v) => v == null || v.isEmpty ? 'Distance is required' : null,
          ),
          const SizedBox(height: 16),

          // --- MODIFICATION: Duration Input Fields ---
          const Text("Duration of Travel", style: TextStyle(fontWeight: FontWeight.bold, fontSize: 14)),
          const SizedBox(height: 8),
          Row(
            children: [
              Expanded(
                child: TextFormField(
                  controller: _sdDurationHourController,
                  decoration: const InputDecoration(
                    labelText: 'Hours',
                    counterText: "",
                  ),
                  keyboardType: TextInputType.number,
                  maxLength: 2,
                ),
              ),
              const SizedBox(width: 8),
              Expanded(
                child: TextFormField(
                  controller: _sdDurationMinuteController,
                  decoration: const InputDecoration(
                    labelText: 'Minutes',
                    counterText: "",
                  ),
                  keyboardType: TextInputType.number,
                  maxLength: 2,
                ),
              ),
              const SizedBox(width: 8),
              Expanded(
                child: TextFormField(
                  controller: _sdDurationSecondController,
                  decoration: const InputDecoration(
                    labelText: 'Seconds',
                    counterText: "",
                  ),
                  keyboardType: TextInputType.number,
                  maxLength: 2,
                ),
              ),
            ],
          ),
          // --- END MODIFICATION ---

          const SizedBox(height: 16),
          ElevatedButton(
            onPressed: _calculateFlowrate,
            child: const Text('Calculate Flowrate'),
          ),
          const SizedBox(height: 16),
          TextFormField(
            controller: _flowrateValueController,
            decoration: const InputDecoration(labelText: 'Calculated Flowrate (m/s)'),
            readOnly: true,
          ),
        ],
      ),
    );
  }

  Widget _buildFlowmeterField() {
    return Padding(
      padding: const EdgeInsets.only(top: 16.0),
      child: TextFormField(
        controller: _flowrateValueController,
        decoration: const InputDecoration(labelText: 'Flowrate (m/s) *'),
        keyboardType: const TextInputType.numberWithOptions(decimal: true),
        validator: (v) => v == null || v.isEmpty ? 'Flowrate value is required' : null,
      ),
    );
  }

  Widget _buildNAField() {
    if (_flowrateValueController.text != 'NA') {
      _flowrateValueController.text = 'NA';
    }

    return Padding(
      padding: const EdgeInsets.only(top: 16.0),
      child: TextFormField(
        controller: _flowrateValueController,
        decoration: const InputDecoration(labelText: 'Flowrate (m/s)'),
        readOnly: true,
      ),
    );
  }
}