import 'package:flutter/material.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 '../models/disconnect_domain.dart';
import '../models/launch/app_config.dart';
import '../models/launch/launch.dart';
import '../models/launch/upgrade.dart';
import '../models/launch/user.dart';

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

  // get storage
  static late SharedPreferences _sharedPreferences;

  // STORING KEYS
  /// Key for storing the device ID
  static const String _deviceIdKey = 'omon_device_id';
  static const String _fcmTokenKey = 'fcm_token';
  static const String _currentLocalKey = 'current_local';
  static const String _lightThemeKey = 'is_theme_light';
  static const String _launchGame = 'is_launch_game';
  static const String _ignoreVersionKey = 'ignore_version';
  static const String _isNewInstallKey = 'is_new_install';
  static const String _launchDataKey = 'launch_data';
  //记录网络报错的域名信息
  static const String _disconnectDomainsKey = 'disconnect_domains';
  //记录最后一次是否是地区禁用
  static const String _isRegionDisabledKey = 'is_region_disabled';
  //记录最后一次是否是用户禁用
  static const String _isUserDisabledKey = 'is_user_disabled';
  //记录最后一次是否是设备禁用
  static const String _isDeviceDisabledKey = 'is_device_disabled';
  //记录最后一次上传的性能日志boostSessionId
  static const String _lastMetricsLogKey = 'last_metrics_log';
  //记录最后一次上传的es日志boostSessionId
  static const String _lastESLogKey = 'last_es_log';
  //记录是否开启debug log
  static const String _enableDebugLogKey = 'enable_debug_log';
  //记录是否开启ping 0默认 1开启 2关闭
  static const String _enablePingModeKey = 'enable_ping_mode';

  /// 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
  static Future<void> setThemeIsLight(bool lightTheme) =>
      _sharedPreferences.setBool(_lightThemeKey, lightTheme);

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

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

  /// get current locale
  static Locale getCurrentLocal() {
    String? langCode = _sharedPreferences.getString(_currentLocalKey);
    // 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(_fcmTokenKey, token);

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

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

  /// get launch game
  static bool getLaunchGame() =>
      _sharedPreferences.getBool(_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(_deviceIdKey, deviceId);

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

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

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

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

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

  /// 保存 DisconnectDomain 列表，合并 domain+status 相同的数据
  static Future<void> addDisconnectDomain(DisconnectDomain newItem) async {
    try {
      final prefs = _sharedPreferences;
      // 读取已存在的数据
      final oldJson = prefs.getString(_disconnectDomainsKey);
      List<DisconnectDomain> allList = [];
      if (oldJson != null && oldJson.isNotEmpty) {
        final List<dynamic> oldList = jsonDecode(oldJson);
        allList = oldList.map((e) => DisconnectDomain.fromJson(e)).toList();
      }
      // 合并新旧数据
      allList.add(newItem);
      // 按 domain+status 分组合并
      final Map<String, DisconnectDomain> merged = {};
      for (var item in allList) {
        final key = '${item.domain}_${item.status}';
        if (!merged.containsKey(key)) {
          merged[key] = DisconnectDomain(
            domain: item.domain,
            status: item.status,
            msg: item.msg,
            startTime: item.startTime,
            endTime: item.endTime,
            count: item.count,
          );
        } else {
          final exist = merged[key]!;
          exist.startTime = exist.startTime < item.startTime
              ? exist.startTime
              : item.startTime;
          exist.endTime = exist.endTime > item.endTime
              ? exist.endTime
              : item.endTime;
          exist.count += item.count;
          // msg 以最新的为准
          exist.msg = item.msg;
        }
      }
      // 保存合并后的数据
      final mergedList = merged.values.toList();
      await prefs.setString(
        _disconnectDomainsKey,
        jsonEncode(mergedList.map((e) => e.toJson()).toList()),
      );
    } catch (e) {
      log('IVSP', 'addDisconnectDomain error: $e');
    }
  }

  /// 读取 DisconnectDomain 列表
  static List<DisconnectDomain> getDisconnectDomains() {
    final jsonStr = _sharedPreferences.getString(_disconnectDomainsKey);
    if (jsonStr == null || jsonStr.isEmpty) return [];
    final List<dynamic> list = jsonDecode(jsonStr);
    return list.map((e) => DisconnectDomain.fromJson(e)).toList();
  }

  /// 清空 DisconnectDomain 列表
  static Future<void> clearDisconnectDomains() async {
    await _sharedPreferences.remove(_disconnectDomainsKey);
  }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  /// 保存 Launch 数据
  static Future<bool> saveLaunch(Launch launch) async {
    try {
      final jsonData = jsonEncode(launch.toJson());

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

      // 保存保存时间
      log('IXSP', 'Launch data saved successfully');
      return true;
    } catch (e) {
      log('IXSP', 'Error saving launch data: $e');
      return false;
    }
  }

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

      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;
  }

  /// 获取升级信息
  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);
  }

  /// 清除 Launch 数据
  static Future<bool> clearLaunchData() async {
    try {
      await _sharedPreferences.remove(_launchDataKey);
      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;
    }
  }
}
