import 'dart:convert';
import 'package:crypto/crypto.dart';

import 'package:fis_common/helpers/encrypt.dart';
import 'package:fis_common/index.dart';
import 'package:fis_common/logger/logger.dart';
import 'package:flutter/foundation.dart';
import 'package:flyinsono/architecture/define.dart';
import 'package:flyinsono/architecture/storage/shared_storage.dart';
import 'package:flyinsono/architecture/storage/text_storage.dart';
import 'package:flyinsono/architecture/values/store_keys.dart';
import 'package:flyinsono/lab/env/env.dart';
import 'package:flyinsono/rpc.dart';
import 'package:get/get.dart';

import 'modules/app.dart';
import 'modules/user.dart';
import 'types.dart';

export 'modules/app.dart';
export 'modules/user.dart';

///持久化存储的存储器
class Store implements PersistentalbeState {
  /// 已注册模块名称
  static final Set<String> _registeredModuleNames = {};

  /// 文本存储文件名
  static const _PERSISTENCE_FILENAME = "states.dat";

  /// 文本存储文件名
  static const _PERSISTENCE_FILENAME_DEBUG = "states_debug.dat";

  /// 应用状态
  static AppState get app => _findModule();

  /// 全局单例
  static Store get ins => Get.find();

  /// 用户状态
  static UserState get user => _findModule();

  /// 文本存储
  late final TextStorage _persistenceStorage;

  /// 当前内容hash
  Digest _kStatesHash = Digest([0]);

  TextStorage get persistenceStorage => _persistenceStorage;

  Store._() {
    final fileName =
        kDebugMode ? _PERSISTENCE_FILENAME_DEBUG : _PERSISTENCE_FILENAME;
    _persistenceStorage = TextStorage.createInstance(fileName);
  }

  @override
  Future<void> acceptPersistenceJson(Map<String, dynamic> map) async {
    for (var key in map.keys) {
      var value = map[key];
      if (value != null) {
        logger.i('start acceptPersistenceJson by name:$key');
        final module = _findModuleByName(key);
        await module.acceptPersistenceJson(map[key]);
        logger.i('end acceptPersistenceJson by name:$key');
      }
    }
  }

  @override
  Map<String, dynamic> toPersistenceJson() {
    Map<String, dynamic> map = {};

    _registeredModuleNames.forEach((key) {
      final module = _findModuleByName(key);
      map[key] = module.toPersistenceJson();
    });

    return map;
  }

  Digest _getHash(String str) {
    return sha1.convert(utf8.encode(str));
  }

  Future<void> _loadPersistenceData() async {
    try {
      var text = await _persistenceStorage.fetch();
      if (text == null) {
        logger.e("States load persistence data: data is null.");
        return;
      }
      if (text.isEmpty) {
        logger.e("States load persistence data: data is empty.");
        return;
      }
      var needUseUnCryptedVersion =
          !kDebugMode && text.length > 2 && !text.startsWith('{');
      //科研版的壳子下面，不走flutter的加解密逻辑，由壳子自己控制
      if (kIsLab && FPlatform.isWindows) {
        needUseUnCryptedVersion = false;
      }
      if (needUseUnCryptedVersion) {
        try {
          text = FEncryptHelper.decrypAES(text);
        } catch (e) {
          return logger.e("States load persistence data: decrypt fail.", e);
        }
      }
      _kStatesHash = _getHash(text);
      final map = jsonDecode(text);
      await acceptPersistenceJson(map);
    } catch (e) {
      logger.e("States load persistence data error.", e);
    }
  }

  Future<bool> _persistent() async {
    try {
      final map = toPersistenceJson();
      String json = jsonEncode(map);
      String cryptoJson = "";
      if (!CartSystemPlatform.isCartSystemVersion) {
        if (_kStatesHash == _getHash(json)) {
          logger.i("same content, skip rewrite");
          return true;
        }
      }

      var needEncrypt = !kDebugMode;

      //科研版的壳子下面，不走flutter的加解密逻辑，由壳子自己控制
      if (kIsLab && FPlatform.isWindows) {
        needEncrypt = false;
      }
      if (needEncrypt) {
        // 非debug模式需要加密
        cryptoJson = FEncryptHelper.encrypAES(json);
      } else {
        cryptoJson = json;
      }
      final result = await _persistenceStorage.save(cryptoJson);

      if (kIsWeb) {
        // 用于原生web查询
        await SharedStorageService.ins.setList(
          StoreKeys.STORE_APP_LOCALE,
          [
            app.locale.languageCode,
            app.locale.countryCode ?? "",
          ],
        );
      }
      if (FPlatform.isMacOS || FPlatform.isWindows) {
        rpc.platform.reloadConfig();
      }
      _kStatesHash = _getHash(json);
      return result;
    } catch (e) {
      logger.e("States persistence error.", e);
    }
    return false;
  }

  /// 初始化单例
  static Future<Store> init() async {
    if (Get.isRegistered<Store>()) return ins;

    // 创建实例
    final instance = Store._();
    Get.put(instance);
    await Future.delayed(Duration(milliseconds: 500));
    // 注册状态模块
    _regModuleSync(AppState());
    _regModuleSync(UserState());

    // 加载持久化缓存
    try {
      await instance._loadPersistenceData();
    } catch (e) {
      logger.e("States load persistence data error.", e);
    } finally {
      logger.i('Store init end');
    }
    return instance;
  }

  /// 持久化
  static Future<bool> persistent() => ins._persistent();

  static T _findModule<T extends StateModuleBase>() {
    final name = _getName<T>();
    return _findModuleByName<T>(name);
  }

  static T _findModuleByName<T extends StateModuleBase>(String name) {
    final module = Get.find<StateModuleBase>(tag: name) as T;
    return module;
  }

  static String _getName<T extends StateModuleBase>() {
    final typeName = _classTagNameMap[T] ?? 'unknown';
    if (typeName == 'unknown') logger.e('_getName unknown module type:$T');
    // final name = typeName.replaceFirst("state", "");
    return typeName;
  }

  static void _regModuleSync<T extends StateModuleBase>(T module) {
    final name = _getName<T>();
    _registeredModuleNames.add(name);
    Get.put<StateModuleBase>(module, tag: name);
  }

  static Map<Type, String> _classTagNameMap = {
    AppState: "app",
    UserState: "user",
  };
}
