import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'dart:convert';

import '../../../config/translations/localization_service.dart';
import '../../../utils/crypto.dart';
import '../../../utils/log/logger.dart';
import '../../constants/keys.dart';
import '../../constants/sp_keys.dart';
import '../models/banner/banner_list.dart';
import '../models/launch/app_config.dart';
import '../models/launch/groups.dart';
import '../models/launch/launch.dart';
import '../models/launch/upgrade.dart';
import '../models/launch/user.dart';
import '../../modules/home/controllers/home_controller.dart';
import '../../modules/node/controllers/node_controller.dart';

class IXSP {
  // prevent making instance
  IXSP._();

  // get storage
  static late SharedPreferences _sharedPreferences;

  /// init get storage services
  static Future<void> init() async {
    _sharedPreferences = await SharedPreferences.getInstance();
  }

  static setStorage(SharedPreferences sharedPreferences) {
    _sharedPreferences = sharedPreferences;
  }

  /// set theme current type as light theme (legacy, for compatibility)
  static Future<void> setThemeIsLight(bool lightTheme) =>
      _sharedPreferences.setBool(SPKeys.lightTheme, lightTheme);

  /// get if the current theme type is light (legacy, for compatibility)
  static bool getThemeIsLight() =>
      _sharedPreferences.getBool(SPKeys.lightTheme) ??
      false; // todo set the default theme (true for light, false for dark)

  /// 主题模式: 'system', 'dark', 'light'
  static Future<void> setThemeMode(String mode) =>
      _sharedPreferences.setString(SPKeys.themeMode, mode);

  /// 获取主题模式，默认跟随系统
  static String getThemeMode() =>
      _sharedPreferences.getString(SPKeys.themeMode) ?? 'system';

  /// save current locale
  static Future<void> setCurrentLanguage(String languageCode) =>
      _sharedPreferences.setString(SPKeys.currentLocal, languageCode);

  /// get current locale
  static Locale getCurrentLocal() {
    String? langCode = _sharedPreferences.getString(SPKeys.currentLocal);
    // default language is english
    if (langCode == null) {
      return LocalizationService.defaultLanguage;
    }
    return LocalizationService.supportedLanguages[langCode]!;
  }

  /// save generated fcm token
  static Future<void> setFcmToken(String token) =>
      _sharedPreferences.setString(SPKeys.fcmToken, token);

  /// get authorization token
  static String getFcmToken() =>
      _sharedPreferences.getString(SPKeys.fcmToken) ?? '';

  /// set launch game
  static Future<void> setLaunchGame(bool isLaunch) =>
      _sharedPreferences.setBool(SPKeys.launchGame, isLaunch);

  /// get launch game
  static bool getLaunchGame() =>
      _sharedPreferences.getBool(SPKeys.launchGame) ?? false;

  /// clear all data from shared pref
  static Future<void> clear() async => await _sharedPreferences.clear();

  /// Save unique ID to shared preferences
  static Future<void> setDeviceId(String deviceId) =>
      _sharedPreferences.setString(SPKeys.deviceId, deviceId);

  /// Get unique ID from shared preferences
  static String? getDeviceId() => _sharedPreferences.getString(SPKeys.deviceId);

  /// Save ignore version to shared preferences
  static Future<void> setIgnoreVersion(int version) =>
      _sharedPreferences.setInt(SPKeys.ignoreVersion, version);

  /// Get ignore version from shared preferences
  static int getIgnoreVersion() =>
      _sharedPreferences.getInt(SPKeys.ignoreVersion) ?? 0;

  /// Save is new install to shared preferences
  static Future<void> setIsNewInstall(bool isNewInstall) =>
      _sharedPreferences.setBool(SPKeys.isNewInstall, isNewInstall);

  /// Get is new install from shared preferences
  static bool getIsNewInstall() =>
      _sharedPreferences.getBool(SPKeys.isNewInstall) ?? true;

  // 记录最后一次是否是用户禁用
  static Future<void> setLastIsUserDisabled(bool isUserDisabled) async {
    await _sharedPreferences.setBool(SPKeys.isUserDisabled, isUserDisabled);
  }

  // 获取最后一次是否是用户禁用
  static bool getLastIsUserDisabled() {
    return _sharedPreferences.getBool(SPKeys.isUserDisabled) ?? false;
  }

  // 记录最后一次是否是地区禁用
  static Future<void> setLastIsRegionDisabled(bool isRegionDisabled) async {
    await _sharedPreferences.setBool(SPKeys.isRegionDisabled, isRegionDisabled);
  }

  // 获取最后一次是否是地区禁用
  static bool getLastIsRegionDisabled() {
    return _sharedPreferences.getBool(SPKeys.isRegionDisabled) ?? false;
  }

  // 记录最后一次是否是设备禁用
  static Future<void> setLastIsDeviceDisabled(bool isDeviceDisabled) async {
    await _sharedPreferences.setBool(SPKeys.isDeviceDisabled, isDeviceDisabled);
  }

  // 获取最后一次是否是设备禁用
  static bool getLastIsDeviceDisabled() {
    return _sharedPreferences.getBool(SPKeys.isDeviceDisabled) ?? false;
  }

  /// Save last metrics log
  static Future<void> setLastMetricsLog(String log) async {
    await _sharedPreferences.setString(SPKeys.lastMetricsLog, log);
  }

  /// Get last metrics log
  static String getLastMetricsLog() =>
      _sharedPreferences.getString(SPKeys.lastMetricsLog) ?? '';

  /// Save last es log
  static Future<void> setLastESLog(String log) async {
    await _sharedPreferences.setString(SPKeys.lastESLog, log);
  }

  /// Get last es log
  static String getLastESLog() =>
      _sharedPreferences.getString(SPKeys.lastESLog) ?? '';

  /// Save enable debug log
  static Future<void> setEnableDebugLog(bool enable) async {
    await _sharedPreferences.setBool(SPKeys.enableDebugLog, enable);
  }

  /// Get enable debug log
  static bool getEnableDebugLog() =>
      _sharedPreferences.getBool(SPKeys.enableDebugLog) ?? false;

  /// Save enable ping
  static Future<void> setEnablePingMode(int model) async {
    await _sharedPreferences.setInt(SPKeys.enablePingMode, model);
  }

  /// Get enable ping
  static int getEnablePingMode() =>
      _sharedPreferences.getInt(SPKeys.enablePingMode) ?? 0;

  /// 保存当前选中的节点
  static Future<void> saveSelectedLocation(
    Map<String, dynamic> location,
  ) async {
    try {
      await _sharedPreferences.setString(
        SPKeys.selectedLocation,
        jsonEncode(location),
      );
      log('IXSP', 'Selected location saved successfully');
    } catch (e) {
      log('IXSP', 'Error saving selected location: $e');
    }
  }

  /// 获取当前选中的节点
  static Map<String, dynamic>? getSelectedLocation() {
    try {
      final jsonData = _sharedPreferences.getString(SPKeys.selectedLocation);
      if (jsonData == null) {
        return null;
      }
      return jsonDecode(jsonData) as Map<String, dynamic>;
    } catch (e) {
      log('IXSP', 'Error getting selected location: $e');
      return null;
    }
  }

  /// 保存最近选择的节点列表
  static Future<void> saveRecentLocations(
    List<Map<String, dynamic>> locations,
  ) async {
    try {
      await _sharedPreferences.setString(
        SPKeys.recentLocations,
        jsonEncode(locations),
      );
      log('IXSP', 'Recent locations saved successfully');
    } catch (e) {
      log('IXSP', 'Error saving recent locations: $e');
    }
  }

  /// 获取最近选择的节点列表
  static List<Map<String, dynamic>> getRecentLocations() {
    try {
      final jsonData = _sharedPreferences.getString(SPKeys.recentLocations);
      if (jsonData == null || jsonData.isEmpty) {
        return [];
      }
      final List<dynamic> list = jsonDecode(jsonData);
      return list.map((e) => e as Map<String, dynamic>).toList();
    } catch (e) {
      log('IXSP', 'Error getting recent locations: $e');
      return [];
    }
  }

  /// 保存 Launch 数据
  static Future<bool> saveLaunch(Launch launch) async {
    try {
      // 获取旧的 Launch 数据，用于比较 groups
      final oldLaunch = getLaunch();
      final oldGroups = oldLaunch?.groups;
      final newGroups = launch.groups;

      final jsonData = jsonEncode(launch.toJson());

      // 保存数据
      await _sharedPreferences.setString(
        SPKeys.launchData,
        Crypto.encrypt(jsonData, Keys.aesKey, Keys.aesIv),
      );

      log('IXSP', 'Launch data saved successfully');

      // 检查 groups 是否有变化，如果有则通知更新
      if (_isGroupsChanged(oldGroups, newGroups)) {
        log('IXSP', 'Groups data changed, notifying controllers');
        _notifyControllersOnGroupsChanged();
      }

      return true;
    } catch (e) {
      log('IXSP', 'Error saving launch data: $e');
      return false;
    }
  }

  /// 检查 Groups 数据是否有变化
  static bool _isGroupsChanged(Groups? oldGroups, Groups? newGroups) {
    // 如果两者都为 null，没有变化
    if (oldGroups == null && newGroups == null) return false;
    // 如果一个为 null 一个不为 null，有变化
    if (oldGroups == null || newGroups == null) return true;

    // 比较 JSON 序列化后的字符串
    try {
      final oldJson = jsonEncode(oldGroups.toJson());
      final newJson = jsonEncode(newGroups.toJson());
      return oldJson != newJson;
    } catch (e) {
      log('IXSP', 'Error comparing groups: $e');
      return true; // 出错时默认认为有变化
    }
  }

  /// 通知控制器 Groups 数据变化
  static void _notifyControllersOnGroupsChanged() {
    try {
      // 通知 HomeController
      if (Get.isRegistered<HomeController>()) {
        Get.find<HomeController>().refreshOnLaunchChanged();
      }

      // 通知 NodeController
      if (Get.isRegistered<NodeController>()) {
        Get.find<NodeController>().refreshOnLaunchChanged();
      }
    } catch (e) {
      log('IXSP', 'Error notifying controllers: $e');
    }
  }

  /// 获取 Launch 数据
  static Launch? getLaunch() {
    try {
      final jsonData = _sharedPreferences.getString(SPKeys.launchData);

      if (jsonData == null) {
        return null;
      }

      final Map<String, dynamic> map = jsonDecode(
        Crypto.decrypt(jsonData, Keys.aesKey, Keys.aesIv),
      );
      return Launch.fromJson(map);
    } catch (e) {
      log('IXSP', 'Error getting launch data: $e');
      return null;
    }
  }

  /// 获取用户信息
  static User? getUser() {
    final launch = getLaunch();
    return launch?.userConfig;
  }

  /// 获取app配置
  static AppConfig? getAppConfig() {
    final launch = getLaunch();
    return launch?.appConfig;
  }

  /// 获取升级信息
  static Upgrade? getUpgrade() {
    final launch = getLaunch();
    return launch?.upgradeConfig;
  }

  /// 保存用户信息
  static Future<void> saveUser(User user) async {
    final launch = getLaunch();
    final newLaunch = launch!.copyWith(userConfig: user);
    await saveLaunch(newLaunch);
  }

  /// 保存app配置
  static Future<void> saveAppConfig(AppConfig appConfig) async {
    final launch = getLaunch();
    final newLaunch = launch!.copyWith(appConfig: appConfig);
    await saveLaunch(newLaunch);
  }

  /// 保存 Groups 数据
  static Future<void> saveGroups(Groups groups) async {
    final launch = getLaunch();
    final newLaunch = launch!.copyWith(groups: groups);
    await saveLaunch(newLaunch);
  }

  /// 清除 Launch 数据
  static Future<bool> clearLaunchData() async {
    try {
      await _sharedPreferences.remove(SPKeys.launchData);
      log('IXSP', 'Launch data cleared');
      return true;
    } catch (e) {
      log('IXSP', 'Error clearing launch data: $e');
      return false;
    }
  }

  /// 通用获取字符串方法
  static String? getString(String key) {
    return _sharedPreferences.getString(key);
  }

  /// 通用设置字符串方法
  static Future<bool> setString(String key, String value) async {
    try {
      return await _sharedPreferences.setString(key, value);
    } catch (e) {
      log('IXSP', 'Error setting string for key $key: $e');
      return false;
    }
  }

  /// 保存 Banner 缓存
  /// [position] banner 位置类型，如 "boost"、"home" 等
  static Future<bool> saveBanner(String position, BannerList bannerList) async {
    try {
      final key = SPKeys.bannerCacheKey(position);
      final jsonData = jsonEncode(bannerList.toJson());
      await _sharedPreferences.setString(key, jsonData);
      log('IXSP', 'Banner cache saved for position: $position');
      return true;
    } catch (e) {
      log('IXSP', 'Error saving banner cache for position $position: $e');
      return false;
    }
  }

  /// 获取 Banner 缓存
  /// [position] banner 位置类型，如 "boost"、"home" 等
  static BannerList? getBanner(String position) {
    try {
      final key = SPKeys.bannerCacheKey(position);
      final jsonData = _sharedPreferences.getString(key);
      if (jsonData == null) {
        return null;
      }
      final Map<String, dynamic> map = jsonDecode(jsonData);
      return BannerList.fromJson(map);
    } catch (e) {
      log('IXSP', 'Error getting banner cache for position $position: $e');
      return null;
    }
  }

  /// 清除指定位置的 Banner 缓存
  static Future<bool> clearBanner(String position) async {
    try {
      final key = SPKeys.bannerCacheKey(position);
      await _sharedPreferences.remove(key);
      log('IXSP', 'Banner cache cleared for position: $position');
      return true;
    } catch (e) {
      log('IXSP', 'Error clearing banner cache for position $position: $e');
      return false;
    }
  }
}
