// global_data.dart
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:shared_preferences/shared_preferences.dart';

const String BASE_URL = 'http://192.168.100.9/kopikaocare_api';

List<Map<String, dynamic>> historyGlobal = [];

class HistoryManager {
  static const String _keyHistory = 'sensor_history';
  static const String _keyIntervalValue = 'interval_value';
  static const String _keyIntervalUnit = 'interval_unit';
  static const String _keyLastSync = 'last_sync_time';
  static const String _keyCurrentRange = 'current_range';

  static int intervalValue = 5;
  static String intervalUnit = 'detik';
  static DateTime? lastSyncTime;
  static String currentRange = 'semua';

  // Load history from LOCAL cache FIRST, then sync with server
  static Future<void> loadHistory(
      {String range = 'semua',
      int limit = 1000,
      bool forceRefresh = false}) async {
    currentRange = range;

    // First, load from local cache
    await _loadHistoryLocal();

    // Then, try to sync with server (if forceRefresh or cache is old)
    if (forceRefresh || _shouldSyncFromServer()) {
      await _syncFromServer(range, limit);
    }
  }

  // Check if should sync from server (every 5 minutes)
  static bool _shouldSyncFromServer() {
    if (lastSyncTime == null) return true;
    final difference = DateTime.now().difference(lastSyncTime!);
    return difference.inMinutes >= 5; // Sync every 5 minutes
  }

  // Load from local SharedPreferences cache
  static Future<void> _loadHistoryLocal() async {
    final prefs = await SharedPreferences.getInstance();

    // Load interval settings
    intervalValue = prefs.getInt(_keyIntervalValue) ?? 5;
    intervalUnit = prefs.getString(_keyIntervalUnit) ?? 'detik';

    // Load last sync time
    String? lastSyncStr = prefs.getString(_keyLastSync);
    if (lastSyncStr != null) {
      lastSyncTime = DateTime.tryParse(lastSyncStr);
    }

    // Load current range
    currentRange = prefs.getString(_keyCurrentRange) ?? 'semua';

    // Load history from local cache
    String? historyString = prefs.getString(_keyHistory);
    if (historyString != null && historyString.isNotEmpty) {
      try {
        List<dynamic> decoded = jsonDecode(historyString);
        historyGlobal = decoded.map((item) {
          Map<String, dynamic> map = Map<String, dynamic>.from(item);
          if (map['waktu'] is String) {
            map['waktu'] = DateTime.parse(map['waktu']);
          }
          return map;
        }).toList();
        print('Local cache loaded: ${historyGlobal.length} records');
      } catch (e) {
        print('Error loading local cache: $e');
        historyGlobal = [];
      }
    } else {
      historyGlobal = [];
      print('No local cache found');
    }
  }

  // Sync data from server with range filter
  static Future<void> _syncFromServer(String range, int limit) async {
    try {
      print('Syncing from server with range: $range');

      final response = await http.get(
        Uri.parse('$BASE_URL/get_history.php?range=$range&limit=$limit'),
      );

      if (response.statusCode == 200) {
        final data = jsonDecode(response.body);
        if (data['status'] == 'success') {
          final serverData =
              List<Map<String, dynamic>>.from(data['data']).map((item) {
            return {
              'suhu': double.parse(item['suhu'].toString()),
              'kelembapan': double.parse(item['kelembapan'].toString()),
              'berat': double.parse(item['berat'].toString()),
              'waktu': DateTime.parse(item['waktu']),
            };
          }).toList();

          // Replace with server data (server is source of truth for range)
          historyGlobal = serverData;
          await _saveHistoryLocal();

          // Save current range
          final prefs = await SharedPreferences.getInstance();
          await prefs.setString(_keyCurrentRange, range);

          lastSyncTime = DateTime.now();
          await _saveLastSyncTime();

          print(
              'Synced from server: ${historyGlobal.length} records (range: $range)');
        }
      }
    } catch (e) {
      print('Error syncing from server: $e, using cached data');
    }
  }

  // Save to local SharedPreferences cache (PRIVATE)
  static Future<void> _saveHistoryLocal() async {
    final prefs = await SharedPreferences.getInstance();

    List<Map<String, dynamic>> toSave = historyGlobal.map((item) {
      Map<String, dynamic> copy = Map.from(item);
      if (copy['waktu'] is DateTime) {
        copy['waktu'] = (copy['waktu'] as DateTime).toIso8601String();
      }
      return copy;
    }).toList();

    String historyString = jsonEncode(toSave);
    await prefs.setString(_keyHistory, historyString);
    print('Local cache saved: ${historyGlobal.length} records');
  }

  // PUBLIC: Save to local SharedPreferences cache (for external use)
  static Future<void> saveHistoryLocal() async {
    await _saveHistoryLocal();
  }

  // Save last sync time
  static Future<void> _saveLastSyncTime() async {
    final prefs = await SharedPreferences.getInstance();
    if (lastSyncTime != null) {
      await prefs.setString(_keyLastSync, lastSyncTime!.toIso8601String());
    }
  }

  // Save single data to MySQL and local cache
  static Future<void> addData(Map<String, dynamic> newData) async {
    try {
      final response = await http.post(
        Uri.parse('$BASE_URL/save_history.php'),
        headers: {'Content-Type': 'application/json'},
        body: jsonEncode({
          'suhu': newData['suhu'],
          'kelembapan': newData['kelembapan'],
          'berat': newData['berat'],
        }),
      );

      if (response.statusCode == 200) {
        final result = jsonDecode(response.body);
        if (result['status'] == 'success') {
          // Add to local cache
          Map<String, dynamic> dataWithTime = {
            ...newData,
            'waktu': DateTime.now(),
          };
          historyGlobal.insert(0, dataWithTime);

          // Limit to 1000 data
          if (historyGlobal.length > 1000) {
            historyGlobal.removeLast();
          }

          await _saveHistoryLocal();
          print('Data saved to MySQL and local cache');
        }
      }
    } catch (e) {
      print('Error saving to MySQL: $e');
    }
  }

  // Delete selected data by index from display list
  static Future<void> deleteSelectedData(List<int> indices) async {
    if (indices.isEmpty) return;

    // Get display data (reversed from historyGlobal)
    List<Map<String, dynamic>> displayData = List.from(historyGlobal.reversed);

    List<Map<String, dynamic>> toDelete = [];
    for (var index in indices) {
      if (index < displayData.length) {
        toDelete.add(displayData[index]);
      }
    }

    if (toDelete.isEmpty) return;

    // Remove from historyGlobal
    historyGlobal.removeWhere((item) {
      return toDelete.any((deleteItem) =>
          deleteItem['waktu'].toString() == item['waktu'].toString());
    });

    // Save to local cache
    await _saveHistoryLocal();

    // Also sync deletion to server (optional - you may need to implement server-side deletion)
    // For now, we'll just update local and server will sync on next refresh

    print('${toDelete.length} data deleted locally');
  }

  // Delete single data by its id or index
  static Future<void> deleteSingleData(
      Map<String, dynamic> dataToDelete) async {
    historyGlobal.removeWhere((item) {
      return item['waktu'].toString() == dataToDelete['waktu'].toString();
    });
    await _saveHistoryLocal();
    print('Single data deleted');
  }

  // Clear all history from MySQL and local cache
  static Future<void> clearHistory() async {
    try {
      final response = await http.post(
        Uri.parse('$BASE_URL/clear_history.php'),
      );
      if (response.statusCode == 200) {
        historyGlobal.clear();
        await _saveHistoryLocal();
        print('History cleared from MySQL and local cache');
      }
    } catch (e) {
      print('Error clearing history: $e');
    }
  }

  // Update interval settings
  static Future<void> updateInterval(int value, String unit) async {
    intervalValue = value;
    intervalUnit = unit;

    final prefs = await SharedPreferences.getInstance();
    await prefs.setInt(_keyIntervalValue, value);
    await prefs.setString(_keyIntervalUnit, unit);

    print('Interval updated: every $value $unit');
  }

  // Force refresh from server
  static Future<void> forceRefresh(
      {String range = 'semua', int limit = 1000}) async {
    await _syncFromServer(range, limit);
  }
}
