import 'dart:convert';

import 'package:flutter/foundation.dart';
import 'package:shared_preferences/shared_preferences.dart';

import '../../shared/utils/lru_eviction.dart';

mixin SettingsPersistence {
  SharedPreferences? _prefs;

  Future<SharedPreferences> getPrefs() async {
    return _prefs ??= await SharedPreferences.getInstance();
  }

  Future<bool> persistField(String key, dynamic value) async {
    try {
      final p = await getPrefs();
      if (value == null) return p.remove(key);
      if (value is bool) return p.setBool(key, value);
      if (value is int) return p.setInt(key, value);
      if (value is double) return p.setDouble(key, value);
      if (value is String) return p.setString(key, value);
      if (value is List<String>) return p.setStringList(key, value);
      return false;
    } catch (e) {
      debugPrint('[SettingsPersistence] Failed to persist $key: $e');
      return false;
    }
  }

  Future<bool> persistFields(Map<String, dynamic> fields) async {
    try {
      final p = await getPrefs();
      final futures = <Future<bool>>[];
      for (final entry in fields.entries) {
        final key = entry.key;
        final value = entry.value;
        if (value == null) {
          futures.add(p.remove(key));
        } else if (value is bool) {
          futures.add(p.setBool(key, value));
        } else if (value is int) {
          futures.add(p.setInt(key, value));
        } else if (value is double) {
          futures.add(p.setDouble(key, value));
        } else if (value is String) {
          futures.add(p.setString(key, value));
        } else if (value is List<String>) {
          futures.add(p.setStringList(key, value));
        }
      }
      await Future.wait(futures);
      return true;
    } catch (e) {
      debugPrint('[SettingsPersistence] Failed to persist fields: $e');
      return false;
    }
  }


  Future<void> putRemembered(
    String prefsKey,
    String entryKey,
    Map<String, dynamic> entryJson,
    int maxEntries,
  ) async {
    final p = await getPrefs();
    final raw = p.getString(prefsKey);
    final map = raw != null
        ? (jsonDecode(raw) as Map<String, dynamic>)
        : <String, dynamic>{};
    map[entryKey] = entryJson;
    evictOldestEntries(map, maxEntries);
    await p.setString(prefsKey, jsonEncode(map));
  }


  Future<Map<String, dynamic>?> readRemembered(
    String prefsKey,
    String entryKey,
  ) async {
    final raw = (await getPrefs()).getString(prefsKey);
    if (raw == null) return null;
    final entry = (jsonDecode(raw) as Map<String, dynamic>)[entryKey];
    return entry is Map<String, dynamic> ? entry : null;
  }
}
