// ignore_for_file: constant_identifier_names

import 'dart:convert';

import 'package:fis_common/helpers/encrypt.dart';
import 'package:fis_common/logger/logger.dart';
import 'package:flutter/foundation.dart';
import 'package:get/get.dart';
import 'package:vnoteapp/store/modules/user.dart';

import '../architecture/storage/text_storage.dart';
import 'defines.dart';
import 'modules/app.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<AppState>();

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

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

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

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

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

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

    // 加载持久化缓存
    await instance._loadPersistenceData();

    print('Store init end');
    return instance;
  }

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

  @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 = {};

    for (final name in _registeredModuleNames) {
      final module = _findModuleByName(name);
      map[name] = module.toPersistenceJson();
    }

    return map;
  }

  Future<void> _loadPersistenceData() async {
    try {
      var text = await _persistenceStorage.read();
      if (text == null || text.isEmpty) return;

      if (!kDebugMode && text.length > 2 && !text.startsWith('{')) {
        try {
          text = FEncryptHelper.decrypAES(text);
        } catch (e) {
          return logger.e("States load persistence data: decrypt fail.", e);
        }
      }
      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();
      var json = jsonEncode(map);
      if (!kDebugMode) {
        // 非debug模式需要加密
        json = FEncryptHelper.encrypAES(json);
      }

      final result = await _persistenceStorage.save(json);
      return result;
    } catch (e) {
      logger.e("States persistence error.", e);
    }
    return false;
  }

  static T _findModule<T extends StateModuleBase>() {
    final tag = T.hashCode.toString();
    return _findModuleByName<T>(tag);
  }

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

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