import 'dart:async';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/foundation.dart';
import 'package:firebase_database/firebase_database.dart';
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:seedina/services/auth_service.dart'; //

class HandlingProvider extends ChangeNotifier {
  // --- STATE AKTIF (Untuk Overview & Data Tersimpan) ---
  Map<String, dynamic> _activeParameters = {};
  String _activeSelectedPlant = '';

  // Nilai sensor aktual
  int humiLing = 0;
  int tdsAir = 0;
  double ecAir = 0.0;
  double tinggiAir = 0.0;
  double suhuAir = 0.0;
  double suhuLing = 0.0;

  // Nilai ideal yang diturunkan dari _activeParameters (untuk Overview)
  String namaTanaman = 'Pilih Tanaman';
  String namaLatin = '...';
  String gambar = 'assets/myicon/unknown.png';
  double idealWaktuSiram = 0.0;
  double idealJedaSiram = 0.0;
  double idealSuhu = 0.0;
  double idealNutrisi = 0.0;
  double idealEC = 0.0;

  // --- STATE DRAFT (Untuk Halaman EditPlants) ---
  Map<String, dynamic> _draftParametersForEditing = {};
  String _draftSelectedPlantForEditing = '';

  // --- State Lainnya ---
  String? _userSeedkey;
  bool _isInitialized = false;
  bool _isLoading = true;
  bool _isSeedKeyReady = false;

  double? onDemandPhValue;
  bool isPhMeasuring = false;
  String? phMeasurementError;

  StreamSubscription<DatabaseEvent>? _monitoringSubscription;
  StreamSubscription<DatabaseEvent>? _parameterSubscription;
  StreamSubscription<DatabaseEvent>? _onDemandPhSubscription;
  StreamSubscription<User?>? _authSubscription;

  final Map<String, Map<String, dynamic>> parameters = {
    'Selada Romaine': {
      'title': 'Selada Romaine',
      'latin': 'Lactuca sativa L. var. longifolia',
      'thumbnail': 'assets/plants/lettuce.png', //
      'jeda_siram': 25,
      'waktu_siram': 3,
      'min_suhuair': 18.0,
      'max_suhuair': 24.0,
      'min_suhuling': 15.0,
      'max_suhuling': 25.0,
      'min_tdsair': 560,
      'max_tdsair': 840,
      'min_humiling': 50,
      'max_humiling': 70,
    },
    'Bayam': {
      'title': 'Bayam',
      'latin': 'Amaranthus sp.',
      'thumbnail': 'assets/plants/spinach.png', //
      'jeda_siram': 30,
      'waktu_siram': 2,
      'min_suhuair': 18.0,
      'max_suhuair': 28.0,
      'min_suhuling': 18.0,
      'max_suhuling': 30.0,
      'min_tdsair': 1260,
      'max_tdsair': 1610,
      'min_humiling': 60,
      'max_humiling': 80,
    },
    'Kangkung': {
      'title': 'Kangkung',
      'latin': 'Ipomoea aquatica',
      'thumbnail': 'assets/plants/water-spinach.png', //
      'jeda_siram': 10,
      'waktu_siram': 1,
      'min_suhuair': 20.0,
      'max_suhuair': 30.0,
      'min_suhuling': 20.0,
      'max_suhuling': 30.0,
      'min_tdsair': 1050,
      'max_tdsair': 1400,
      'min_humiling': 70,
      'max_humiling': 90,
    },
    'Kustom': {
      'title': 'Tanaman Lain',
      'latin': 'Parameter Kustom',
      'thumbnail': 'assets/myicon/unknown.png', //
      'jeda_siram': 30, // Nilai default jika tidak ada dari RTDB
      'waktu_siram': 5, // Nilai default jika tidak ada dari RTDB
      'min_suhuair': 15.0,
      'max_suhuair': 35.0,
      'min_suhuling': 15.0,
      'max_suhuling': 35.0,
      'min_tdsair': 350,
      'max_tdsair': 2100,
      'min_humiling': 30,
      'max_humiling': 90,
    }
  };

  String get activeSelectedPlant => _activeSelectedPlant;
  Map<String, dynamic> get activeParametersReadonly => Map.unmodifiable(_activeParameters);

  String get draftSelectedPlantForEditing => _draftSelectedPlantForEditing;
  Map<String, dynamic> get draftParametersForEditingReadonly => Map.unmodifiable(_draftParametersForEditing);

  Map<String, String> get draftPlantInfoForEditingPage {
    final paramsToUse = _draftParametersForEditing.isNotEmpty ? _draftParametersForEditing : parameters['Kustom']!;
    return {
      'title': paramsToUse['title'] as String? ?? _draftSelectedPlantForEditing,
      'latin': paramsToUse['latin'] as String? ?? '...',
      'thumbnail': paramsToUse['thumbnail'] as String? ?? 'assets/myicon/unknown.png',
    };
  }

  double get idealWaktuSiramForEditingPage => _parseToDouble(_draftParametersForEditing['waktu_siram']);
  double get idealJedaSiramForEditingPage => _parseToDouble(_draftParametersForEditing['jeda_siram']);
  double get idealSuhuForEditingPage {
    if (_draftParametersForEditing.isEmpty) return 0.0;
    return ((_parseToDouble(_draftParametersForEditing['min_suhuair']) + _parseToDouble(_draftParametersForEditing['max_suhuair'])) / 2);
  }
  double get idealNutrisiForEditingPage {
    if (_draftParametersForEditing.isEmpty) return 0.0;
    return ((_parseToDouble(_draftParametersForEditing['min_tdsair']) + _parseToDouble(_draftParametersForEditing['max_tdsair'])) / 2);
  }
  double get idealECForEditingPage {
    if (_draftParametersForEditing.isEmpty) return 0.0;
    double minECVal = (_parseToDouble(_draftParametersForEditing['min_tdsair']) / 700.0);
    double maxECVal = (_parseToDouble(_draftParametersForEditing['max_tdsair']) / 700.0);
    return (minECVal + maxECVal) / 2;
  }

  bool get isInitialized => _isInitialized;
  bool get isLoading => _isLoading;
  String? get currentUserSeedKey => _userSeedkey;
  bool get isSeedKeyReady => _isSeedKeyReady;

  DatabaseReference? get _baseRef {
    if (!_isSeedKeyReady || _userSeedkey == null || _userSeedkey!.isEmpty) return null;
    return FirebaseDatabase.instance.ref().child(_userSeedkey!);
  }
  DatabaseReference? get _monitoringDataRef => _baseRef?.child('monitoring');
  DatabaseReference? get _activeParameterDataRef => _baseRef?.child('parameter');
  DatabaseReference? get _phRequestRef => _baseRef?.child('commands/ph_request');
  DatabaseReference? get _phResultRef => _baseRef?.child('ph_ondemand');

  HandlingProvider() {
    _authSubscription = AuthService.authStateChanges.listen((user) { //
      final currentAuthUid = user?.uid;
      if (currentAuthUid == null) {
        _resetAllStates();
        if (hasListeners) notifyListeners();
      } else {
        AuthService.getUserDoc(currentAuthUid).then((userDoc) { //
          String? firestoreSeedKey;
          String? firestoreSelectedPlant;
          if (userDoc != null && userDoc.exists) {
            final data = userDoc.data() as Map<String, dynamic>?;
            firestoreSeedKey = data?['seedKey'];
            firestoreSelectedPlant = data?['selectedPlant'];
          }

          bool seedKeyChanged = _userSeedkey != firestoreSeedKey;
          _userSeedkey = firestoreSeedKey;
          _isSeedKeyReady = _userSeedkey != null && _userSeedkey!.isNotEmpty;

          if (!_isInitialized || seedKeyChanged || _activeSelectedPlant.isEmpty) {
             _initializeProviderStates(persistedSelectedPlant: firestoreSelectedPlant);
          } else if (_isLoading) {
            _isLoading = false;
            if (hasListeners) notifyListeners();
          }
        }).catchError((e) {
          if (kDebugMode) print("Error fetching user doc: $e");
          if (!_isInitialized || _userSeedkey == null) {
            _initializeProviderStates();
          }
        });
      }
    });
    if (AuthService.currentUser == null && !_isInitialized) { //
      _initializeProviderStates();
    }
  }

  void _resetAllStates() {
    _activeParameters = {};
    _activeSelectedPlant = '';
    _draftParametersForEditing = {};
    _draftSelectedPlantForEditing = '';

    humiLing = 0; tdsAir = 0; ecAir = 0.0; tinggiAir = 0.0; suhuAir = 0.0; suhuLing = 0.0;
    _updateDisplayParametersFromActiveData();

    // _userSeedkey & _isSeedKeyReady diurus oleh listener auth
    _isInitialized = true;
    _isLoading = false;

    onDemandPhValue = null; isPhMeasuring = false; phMeasurementError = null;

    _cancelSubscriptions();
    if (kDebugMode) print("[HandlingProvider] All states reset.");
  }

  void _cancelSubscriptions() {
    _monitoringSubscription?.cancel(); _monitoringSubscription = null;
    _parameterSubscription?.cancel(); _parameterSubscription = null;
    _onDemandPhSubscription?.cancel(); _onDemandPhSubscription = null;
  }

  Future<void> _initializeProviderStates({String? persistedSelectedPlant}) async {
    if (!_isLoading) {
      _isLoading = true;
      if (hasListeners) notifyListeners();
    }
    _isInitialized = false;
    _cancelSubscriptions();

    final currentUser = AuthService.currentUser; //
    if (currentUser == null || !_isSeedKeyReady || _activeParameterDataRef == null) {
      _activeSelectedPlant = persistedSelectedPlant ?? await _getPlantFromPrefsOrFallback();
      _activeParameters = Map.from(parameters[_activeSelectedPlant] ?? parameters["Kustom"]!);
      _updateDisplayParametersFromActiveData();
      _initializeDraftParametersFromActive(forceOverwrite: true);
      _isLoading = false;
      _isInitialized = true;
      if (kDebugMode) print("[HandlingProvider] Initialized (no user/seedkey/ref): ActivePlant='$_activeSelectedPlant'");
      if (hasListeners) notifyListeners();
      return;
    }
    
    // Prioritas selectedPlant: Firestore (dari auth listener) > SharedPreferences > Default
    _activeSelectedPlant = persistedSelectedPlant ?? await _getPlantFromPrefsOrFallback();
    if (kDebugMode) print("[HandlingProvider] Initializing with plant: $_activeSelectedPlant (from persisted/prefs)");

    await _loadAndSetupFirebaseData();
    _isInitialized = true; // isLoading dihandle di _loadAndSetupFirebaseData
  }

  Future<String> _getPlantFromPrefsOrFallback() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    String? prefPlant = prefs.getString('selectedPlant');
    if (prefPlant != null && prefPlant.isNotEmpty && parameters.containsKey(prefPlant)) {
      return prefPlant;
    }
    return parameters.keys.firstWhere((k) => k != "Kustom", orElse: () => "Kustom");
  }

  Future<void> _loadAndSetupFirebaseData() async {
    bool initialMonitoringLoaded = false;
    bool initialParameterLoaded = false;

    void checkInitialLoadComplete() {
      if (initialMonitoringLoaded && initialParameterLoaded) {
        _initializeDraftParametersFromActive(forceOverwrite: true);
        if (_isLoading) {
          _isLoading = false;
          if (hasListeners) notifyListeners();
           if (kDebugMode) print("[HandlingProvider] Firebase initial load complete. ActivePlant='$_activeSelectedPlant'");
        }
      }
    }

    try {
      DatabaseEvent initialParameterEvent = await _activeParameterDataRef!.once().timeout(const Duration(seconds: 7));
      _handleActiveParameterData(initialParameterEvent.snapshot, isInitialLoad: true);
    } catch (e) {
      if (kDebugMode) print("[HandlingProvider] Error loading initial active parameters from RTDB: $e. Using local for '$_activeSelectedPlant'.");
      _activeParameters = Map.from(parameters[_activeSelectedPlant] ?? parameters["Kustom"]!);
      _updateDisplayParametersFromActiveData();
    } finally {
      initialParameterLoaded = true;
      checkInitialLoadComplete();
    }

    try {
      DatabaseEvent initialMonitoringEvent = await _monitoringDataRef!.once().timeout(const Duration(seconds: 7));
      _handleMonitoringData(initialMonitoringEvent);
    } catch (e) {
      _resetSensorValues();
      if (kDebugMode) print("[HandlingProvider] Error loading initial monitoring data: $e.");
    } finally {
      initialMonitoringLoaded = true;
      checkInitialLoadComplete();
    }

    _parameterSubscription = _activeParameterDataRef!.onValue.listen(
        (event) => _handleActiveParameterData(event.snapshot),
        onError: (e) => _handleListenerError("ActiveParameter", e));
    _monitoringSubscription = _monitoringDataRef!.onValue.listen(_handleMonitoringData, onError: (e) => _handleListenerError("Monitoring", e));
    if (_phResultRef != null) {
      _onDemandPhSubscription = _phResultRef!.onValue.listen(_handlePhResult, onError: (e) => _handleListenerError("OnDemandPHResult", e));
    }
  }

  void _resetSensorValues() {
    humiLing = 0; tdsAir = 0; ecAir = 0.0; tinggiAir = 0.0; suhuAir = 0.0; suhuLing = 0.0;
  }
  
  void _handleActiveParameterData(DataSnapshot snapshot, {bool isInitialLoad = false}) {
    final dynamic data = snapshot.value;
    Map<String, dynamic> paramsFromRTDB;
    String determinedPlantType = _activeSelectedPlant; // Mulai dengan apa yang sudah ada (dari Prefs/Firestore)

    if (data != null && data is Map && data.isNotEmpty) {
      paramsFromRTDB = Map<String, dynamic>.from(data);
      final String? rtdbTitle = paramsFromRTDB['title'] as String?;

      if (rtdbTitle != null && rtdbTitle.isNotEmpty) {
        if (parameters.containsKey(rtdbTitle)) { // Judul adalah nama preset
          determinedPlantType = rtdbTitle;
          // Lengkapi paramsFromRTDB dengan default preset jika ada field yang hilang
          Map<String, dynamic> presetDefaults = Map.from(parameters[determinedPlantType]!);
          presetDefaults.addAll(paramsFromRTDB); // Timpa default dengan yang dari RTDB
          paramsFromRTDB = presetDefaults;
        } else { // Judul bukan preset, ini pasti Kustom
          determinedPlantType = "Kustom";
          // Pastikan field Kustom default ada jika tidak ada di RTDB, tapi prioritaskan dari RTDB
          Map<String, dynamic> kustomDefaults = Map.from(parameters["Kustom"]!);
          kustomDefaults.addAll(paramsFromRTDB); // Timpa default dengan yang dari RTDB
          paramsFromRTDB = kustomDefaults;
          // Jika title dari RTDB tidak "Tanaman Lain", pertahankan title dari RTDB
          if (paramsFromRTDB['title'] != parameters['Kustom']!['title']) {
             // Biarkan title dari RTDB
          } else {
            paramsFromRTDB['title'] = parameters['Kustom']!['title']; // Pastikan title default jika RTDB juga default
          }
        }
      } else { // Tidak ada title di RTDB
         if (determinedPlantType == "Kustom" || (paramsFromRTDB.containsKey('jeda_siram') && paramsFromRTDB.containsKey('waktu_siram'))) {
            determinedPlantType = "Kustom";
            Map<String, dynamic> kustomDefaults = Map.from(parameters["Kustom"]!);
            kustomDefaults.addAll(paramsFromRTDB);
            paramsFromRTDB = kustomDefaults;
         } else if (parameters.containsKey(determinedPlantType)) { // Misal _activeSelectedPlant dari prefs adalah "Selada Romaine"
            Map<String, dynamic> presetDefaults = Map.from(parameters[determinedPlantType]!);
            presetDefaults.addAll(paramsFromRTDB);
            paramsFromRTDB = presetDefaults;
         } else { // Fallback akhir jika determinedPlantType tidak dikenali
            determinedPlantType = "Kustom";
            paramsFromRTDB = Map.from(parameters["Kustom"]!);
         }
      }
      
      if (!mapEquals(_activeParameters, paramsFromRTDB) || _activeSelectedPlant != determinedPlantType) {
        _activeParameters = paramsFromRTDB;
        _activeSelectedPlant = determinedPlantType;
        _updateDisplayParametersFromActiveData();
        SharedPreferences.getInstance().then((prefs) => prefs.setString('selectedPlant', _activeSelectedPlant));
        if (!isInitialLoad) _initializeDraftParametersFromActive(forceOverwrite: false); // Hanya update draft jika bukan load awal & draft tidak diubah user
        if (kDebugMode) print("[HandlingProvider] Active params updated from RTDB. Plant: $_activeSelectedPlant, Title: ${_activeParameters['title']}");
      }
    } else { // Data RTDB kosong atau tidak valid
      if (kDebugMode) print("[HandlingProvider] Active parameter data from RTDB is null/empty. Using local for '$_activeSelectedPlant'.");
      Map<String,dynamic> fallbackParams = Map.from(parameters[_activeSelectedPlant] ?? parameters["Kustom"]!);
      if (!mapEquals(_activeParameters, fallbackParams) || _activeParameters.isEmpty){
        _activeParameters = fallbackParams;
        _updateDisplayParametersFromActiveData();
        if (!isInitialLoad) _initializeDraftParametersFromActive(forceOverwrite: false);
      }
    }
  }

  void _updateDisplayParametersFromActiveData() {
    if (_activeParameters.isEmpty && _activeSelectedPlant.isNotEmpty && parameters.containsKey(_activeSelectedPlant)) {
       _activeParameters = Map.from(parameters[_activeSelectedPlant]!);
    } else if (_activeParameters.isEmpty) {
      _activeParameters = Map.from(parameters["Kustom"]!);
      _activeSelectedPlant = "Kustom";
    }

    namaTanaman = (_activeParameters['title'] as String?) ?? (_activeSelectedPlant.isNotEmpty ? _activeSelectedPlant : 'Tanaman');
    namaLatin = (_activeParameters['latin'] as String?) ?? '...';
    gambar = (_activeParameters['thumbnail'] as String?) ?? 'assets/myicon/unknown.png';

    idealWaktuSiram = _parseToDouble(_activeParameters['waktu_siram']);
    idealJedaSiram = _parseToDouble(_activeParameters['jeda_siram']);
    idealSuhu = ((_parseToDouble(_activeParameters['min_suhuair']) + _parseToDouble(_activeParameters['max_suhuair'])) / 2);
    idealNutrisi = ((_parseToDouble(_activeParameters['min_tdsair']) + _parseToDouble(_activeParameters['max_tdsair'])) / 2);
    double minECVal = (_parseToDouble(_activeParameters['min_tdsair']) / 700.0);
    double maxECVal = (_parseToDouble(_activeParameters['max_tdsair']) / 700.0);
    idealEC = (minECVal + maxECVal) / 2;

    if (hasListeners) notifyListeners();
  }
  
  void _initializeDraftParametersFromActive({bool forceOverwrite = false}) {
    // forceOverwrite = true akan menimpa draft.
    // forceOverwrite = false hanya akan menginisialisasi jika draft kosong atau sama dengan active.
    bool shouldUpdateDraft = forceOverwrite || 
                             _draftParametersForEditing.isEmpty || 
                             mapEquals(_draftParametersForEditing, _activeParameters);

    if (shouldUpdateDraft) {
      if (_activeSelectedPlant.isNotEmpty) {
        _draftSelectedPlantForEditing = _activeSelectedPlant;
        _draftParametersForEditing = Map.from(_activeParameters.isNotEmpty ? _activeParameters : parameters[_activeSelectedPlant] ?? parameters["Kustom"]!);
        
        // Jika yang aktif adalah Kustom, pastikan title, latin, thumb di draft sesuai standar Kustom untuk form
        if (_draftSelectedPlantForEditing == "Kustom") {
            _draftParametersForEditing['title'] = parameters['Kustom']!['title'];
            _draftParametersForEditing['latin'] = parameters['Kustom']!['latin'];
            _draftParametersForEditing['thumbnail'] = parameters['Kustom']!['thumbnail'];
        }

      } else if (parameters.isNotEmpty) {
        _draftSelectedPlantForEditing = parameters.keys.firstWhere((k) => k != "Kustom", orElse: () => "Kustom");
        _draftParametersForEditing = Map.from(parameters[_draftSelectedPlantForEditing]!);
      } else { 
        _draftSelectedPlantForEditing = "Kustom";
        _draftParametersForEditing = Map.from(parameters["Kustom"]!);
      }
      if (kDebugMode) print("[HandlingProvider] Draft parameters ${_draftParametersForEditing.isEmpty ? 'emptied' : 'initialized/updated'} from active: $_draftSelectedPlantForEditing. Force Overwrite: $forceOverwrite");
      if (hasListeners) notifyListeners();
    } else {
        if (kDebugMode) print("[HandlingProvider] Draft parameters NOT updated from active because draft is dirty or already different.");
    }
  }

  void selectPlantForEditingPage(String plantNameFromDropdown) {
    if (kDebugMode) print("[HandlingProvider] User selected '$plantNameFromDropdown' from dropdown for editing.");
    _draftSelectedPlantForEditing = plantNameFromDropdown;

    if (plantNameFromDropdown == "Kustom") {
      // Jika memilih Kustom dari dropdown:
      // Ambil basis parameter dari _activeParameters JIKA _activeSelectedPlant saat ini juga Kustom.
      // Jika tidak (misal _activeSelectedPlant "Selada", lalu pilih "Kustom" di dropdown),
      // maka basisnya adalah default Kustom.
      Map<String, dynamic> baseParamsForCustomDraft;
      if (_activeSelectedPlant == "Kustom" && _activeParameters.isNotEmpty) {
        baseParamsForCustomDraft = Map.from(_activeParameters);
         if (kDebugMode) print("   -> Kustom selected. Base from ACTIVE Kustom params.");
      } else {
        baseParamsForCustomDraft = Map.from(parameters["Kustom"]!);
         if (kDebugMode) print("   -> Kustom selected. Base from DEFAULT Kustom params.");
      }
      _draftParametersForEditing = baseParamsForCustomDraft;
      // Selalu set title, latin, thumbnail ke default Kustom untuk form
      _draftParametersForEditing['title'] = parameters['Kustom']!['title'];
      _draftParametersForEditing['latin'] = parameters['Kustom']!['latin'];
      _draftParametersForEditing['thumbnail'] = parameters['Kustom']!['thumbnail'];
      
    } else if (parameters.containsKey(plantNameFromDropdown)) {
      _draftParametersForEditing = Map.from(parameters[plantNameFromDropdown]!);
      if (kDebugMode) print("   -> Preset '$plantNameFromDropdown' selected. Draft loaded from local preset map.");
    } else {
      // Fallback, seharusnya tidak terjadi jika dropdown diisi dengan benar
      _draftSelectedPlantForEditing = parameters.keys.firstWhere((k) => k != "Kustom", orElse: () => "Kustom");
      _draftParametersForEditing = Map.from(parameters[_draftSelectedPlantForEditing]!);
      if (kDebugMode) print("   -> Fallback. Draft set to '$_draftSelectedPlantForEditing'.");
    }
    if (kDebugMode) print("   -> Final draft title for form: ${_draftParametersForEditing['title']}");
    notifyListeners();
  }

  Future<bool> applyDraftPresetToActive(BuildContext context) async {
    if (_draftSelectedPlantForEditing == "Kustom" || !parameters.containsKey(_draftSelectedPlantForEditing)) {
      if (context.mounted) ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text("Pilih preset yang valid untuk diterapkan.")));
      return false;
    }

    _activeParameters = Map.from(_draftParametersForEditing);
    _activeSelectedPlant = _draftSelectedPlantForEditing;

    bool firestoreSuccess = await _saveActiveSelectedPlantToFirestore(context);
    bool rtdbSuccess = false;
    if (firestoreSuccess) {
      rtdbSuccess = await _saveActiveParametersToRTDB(context: context, paramsToSave: _activeParameters);
    } else {
        if (context.mounted) ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text("Gagal menyimpan pilihan tanaman ke server.")));
    }

    if (rtdbSuccess) {
      _updateDisplayParametersFromActiveData();
      _initializeDraftParametersFromActive(forceOverwrite: true); // Sinkronkan draft setelah berhasil
      if (kDebugMode) print("[HandlingProvider] Applied preset '$_activeSelectedPlant' to active and RTDB.");
      if (context.mounted) {
        ScaffoldMessenger.of(context).showSnackBar(SnackBar(
          content: Text("Parameter untuk '$_activeSelectedPlant' berhasil diupdate ke sistem."),
          backgroundColor: Colors.green,
        ));
      }
    }
    return rtdbSuccess && firestoreSuccess;
  }

  Future<bool> applyCustomDraftToActive(BuildContext context, Map<String, dynamic> customParamsFromForm) async {
    // Update _draftParametersForEditing dengan data dari form, pastikan field meta Kustom ada
    Map<String, dynamic> newCustomParams = Map.from(parameters['Kustom']!); // Mulai dengan template Kustom (untuk thumbnail dll)
    newCustomParams.addAll(customParamsFromForm); // Timpa dengan nilai dari form
    
    _draftParametersForEditing = newCustomParams;
    _draftSelectedPlantForEditing = "Kustom"; // Ini sudah pasti Kustom

    _activeParameters = Map.from(_draftParametersForEditing);
    _activeSelectedPlant = "Kustom";

    bool firestoreSuccess = await _saveActiveSelectedPlantToFirestore(context);
    bool rtdbSuccess = false;
    if (firestoreSuccess) {
        rtdbSuccess = await _saveActiveParametersToRTDB(context: context, paramsToSave: _activeParameters);
    } else {
         if (context.mounted) ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text("Gagal menyimpan pilihan 'Kustom' ke server.")));
    }

    if (rtdbSuccess) {
      _updateDisplayParametersFromActiveData();
      _initializeDraftParametersFromActive(forceOverwrite: true); // Sinkronkan draft setelah berhasil
      if (kDebugMode) print("[HandlingProvider] Applied custom parameters (title: '${_activeParameters['title']}') to active and RTDB.");
       if (context.mounted) {
        ScaffoldMessenger.of(context).showSnackBar(SnackBar(
          content: Text("Parameter kustom '${_activeParameters['title']}' berhasil diupdate ke sistem."),
          backgroundColor: Colors.green,
        ));
      }
    }
    return rtdbSuccess && firestoreSuccess;
  }

  Future<bool> _saveActiveSelectedPlantToFirestore(BuildContext context) async {
    final uid = AuthService.currentUser?.uid; //
    if (uid == null) return false;
    if (_activeSelectedPlant.isEmpty) return false;

    bool success = await AuthService.updateUserDocument(uid, {'selectedPlant': _activeSelectedPlant}, context); //
    if (success) {
      SharedPreferences prefs = await SharedPreferences.getInstance();
      await prefs.setString('selectedPlant', _activeSelectedPlant);
      if (kDebugMode) print("[HandlingProvider] Saved _activeSelectedPlant ('$_activeSelectedPlant') to Firestore & SharedPreferences.");
    }
    return success;
  }

  Future<bool> _saveActiveParametersToRTDB({BuildContext? context, required Map<String, dynamic> paramsToSave}) async {
    if (!_isSeedKeyReady || _userSeedkey == null || _userSeedkey!.isEmpty || _activeParameterDataRef == null) {
      if (context?.mounted ?? false) ScaffoldMessenger.of(context!).showSnackBar(const SnackBar(content: Text("SeedKey/Referensi DB belum siap.")));
      return false;
    }

    if (paramsToSave.isEmpty) {
      if (context?.mounted ?? false) ScaffoldMessenger.of(context!).showSnackBar(const SnackBar(content: Text("Tidak ada parameter untuk disimpan.")));
      return false;
    }
    
    // Pastikan field meta (title, latin, thumbnail) ADA dan BENAR sebelum menyimpan ke RTDB
    // Untuk Kustom, title bisa diedit pengguna, jadi ambil dari paramsToSave['title']
    // Untuk Preset, title diambil dari nama preset itu sendiri.
    Map<String, dynamic> finalParamsToSave = Map.from(paramsToSave);

    if (_activeSelectedPlant == "Kustom") {
      finalParamsToSave['title'] = paramsToSave['title'] ?? parameters['Kustom']!['title'];
      finalParamsToSave['latin'] = paramsToSave['latin'] ?? parameters['Kustom']!['latin'];
      finalParamsToSave['thumbnail'] = parameters['Kustom']!['thumbnail']; // Kustom selalu thumbnail default
    } else if (parameters.containsKey(_activeSelectedPlant)) {
      // Untuk preset, pastikan title, latin, thumbnail konsisten dengan definisi preset
      finalParamsToSave['title'] = parameters[_activeSelectedPlant]!['title'];
      finalParamsToSave['latin'] = parameters[_activeSelectedPlant]!['latin'];
      finalParamsToSave['thumbnail'] = parameters[_activeSelectedPlant]!['thumbnail'];
    } else {
      // Fallback jika _activeSelectedPlant tidak dikenali (seharusnya tidak terjadi)
      finalParamsToSave.putIfAbsent('title', () => parameters['Kustom']!['title']);
      finalParamsToSave.putIfAbsent('latin', () => parameters['Kustom']!['latin']);
      finalParamsToSave.putIfAbsent('thumbnail', () => parameters['Kustom']!['thumbnail']);
    }


    try {
      await _activeParameterDataRef!.set(finalParamsToSave);
      if (kDebugMode) print("[HandlingProvider] Parameters for '${finalParamsToSave['title']}' saved to RTDB.");
      return true;
    } catch (e) {
      if (kDebugMode) print("[HandlingProvider] Failed to save parameters to RTDB: $e");
      if (context?.mounted ?? false) {
        ScaffoldMessenger.of(context!).showSnackBar(SnackBar(content: Text("Gagal update parameter ke RTDB: ${e.toString()}")));
      }
      return false;
    }
  }
  
  void _handleListenerError(String listenerName, Object error) {
    if (kDebugMode) print("[$runtimeType] Firebase Listener Error ($listenerName): $error");
    if (listenerName == "OnDemandPHResult") {
      phMeasurementError = "Gagal membaca hasil pH. Coba lagi.";
      isPhMeasuring = false;
    }
    if (listenerName == "ActiveParameter" && (_activeParameters.isEmpty || _activeSelectedPlant.isEmpty)) {
        String plantToUse = _activeSelectedPlant.isNotEmpty && parameters.containsKey(_activeSelectedPlant) 
                            ? _activeSelectedPlant 
                            : parameters.keys.firstWhere((k) => k != "Kustom", orElse: () => "Kustom");
        _activeSelectedPlant = plantToUse;
        _activeParameters = Map.from(parameters[plantToUse]!);
        _updateDisplayParametersFromActiveData();
        _initializeDraftParametersFromActive(forceOverwrite: true); // Re-init draft jika active gagal load
        if (kDebugMode) print("[HandlingProvider] ActiveParameter listener error, fallback to local: $plantToUse");
    }
    if(hasListeners) notifyListeners();
  }

  double _parseToDouble(dynamic value) {
    if (value is int) return value.toDouble();
    if (value is double) return value;
    if (value is String) return double.tryParse(value) ?? 0.0;
    return 0.0;
  }
  int _parseToInt(dynamic value) {
    if (value is int) return value;
    if (value is double) return value.round();
    if (value is String) return int.tryParse(value) ?? 0;
    return 0;
  }

  void _handleMonitoringData(DatabaseEvent event) {
    final dynamic data = event.snapshot.value;
    if (data == null || data is! Map) {
      _resetSensorValues();
    } else {
      ecAir = _parseToDouble(data['ec_air']);
      tdsAir = _parseToInt(data['tds_air']);
      tinggiAir = _parseToDouble(data['tinggi_air']);
      suhuAir = _parseToDouble(data['suhu_air']);
      suhuLing = _parseToDouble(data['suhu_ling']);
      humiLing = _parseToInt(data['humi_ling']);
    }
    if (hasListeners) notifyListeners();
  }
  
  void _handlePhResult(DatabaseEvent event) {
    final dynamic data = event.snapshot.value;
    if (data !=null && data is Map) {
      final resultData = Map<String, dynamic>.from(data);
      onDemandPhValue = _parseToDouble(resultData['ph_val']);
      phMeasurementError = null;
    } else if (data == null) {
      // Keep current onDemandPhValue
    } else {
        phMeasurementError = "Format hasil pH tidak valid.";
    }
    isPhMeasuring = false;
    if(hasListeners) notifyListeners();
  }

  Future<void> requestPhMeasurement(BuildContext context) async {
    if (!_isSeedKeyReady || _phRequestRef == null) {
      if(context.mounted) {
        ScaffoldMessenger.of(context).showSnackBar(
          const SnackBar(content: Text("Sistem belum siap untuk pengukuran pH."),
          backgroundColor: Colors.orange),
        );
      }
      return;
    }
    if (isPhMeasuring) {
        if(context.mounted) {
          ScaffoldMessenger.of(context).showSnackBar(
            const SnackBar(content: Text("Pengukuran pH sedang berlangsung..."), backgroundColor: Colors.blueAccent),
          );
        }
        return;
    }

    try {
      isPhMeasuring = true;
      onDemandPhValue = null;
      phMeasurementError = null;
      if(hasListeners) notifyListeners();

      await _phRequestRef!.set(true);
       if(context.mounted) {
          ScaffoldMessenger.of(context).showSnackBar(
            const SnackBar(content: Text("Permintaan pengukuran pH terkirim. Mohon tunggu..."), backgroundColor: Colors.green),
          );
       }
    } catch (e) {
      phMeasurementError = "Gagal mengirim permintaan pH: ${e.toString()}";
      isPhMeasuring = false;
      if(hasListeners) notifyListeners();
      if(context.mounted) {
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(content: Text(phMeasurementError!), backgroundColor: Colors.redAccent),
        );
      }
    }
  }
  
   Future<void> updateUserSeedKey(String seedKey) async {
    final newSeedKeyValue = seedKey.isNotEmpty ? seedKey : null;
    
    if (_userSeedkey == newSeedKeyValue) return;
   
    _cancelSubscriptions();

    _userSeedkey = newSeedKeyValue;
    _isSeedKeyReady = newSeedKeyValue != null && newSeedKeyValue.isNotEmpty;
    
    _isLoading = true;
    _isInitialized = false; 
    if(hasListeners) notifyListeners();

    // Tidak perlu pass persistedSelectedPlant karena akan diambil dari Firestore/Prefs lagi
    await _initializeProviderStates();
  }

  @override
  void dispose() {
    _authSubscription?.cancel();
    _cancelSubscriptions();
    super.dispose();
  }
}