import 'dart:convert';

import 'package:fis_common/logger/logger.dart';
import 'package:fis_jsonrpc/services/index.dart';
import 'package:fis_measure/process/language/measure_language.dart';
import 'package:flyinsono/architecture/states/states.dart';
import 'package:flyinsono/architecture/storage/text_storage.dart';
import 'package:flyinsono/rpc.dart';
import 'package:get/get.dart';
import 'package:fis_i18n/i18n.dart';

///国际化语言翻译缓存
mixin _LanguageFinderMixin {
  /// 因为存储成文本之后 无法保存对应的类
  List<dynamic> _cache = [];

  /// 检查根据不同语言模块的父级Code获取集合
  ///
  /// [module] 当前模块
  /// [module] 翻译Code
  String findLanguageValueByCode(String module, String code) {
    try {
      String? examLanguage = _cache.firstWhere(
          (element) => element['LangugeModule'] == module)['Content'];

      if (examLanguage != null) {
        final String? children = jsonDecode(examLanguage)["Language"][code];
        return children ?? code;
      }
      return code;
    } catch (e) {
      return code;
    }
  }
}

///多语言服务
class LanguageService extends GetxService with _LanguageFinderMixin {
  static const _CHECK_FILENAME = "config_language.conf";
  static const _LOCAL_FILENAME = "configed_language_local.conf";
  TextStorage _languageStorage = TextStorage.createInstance(_CHECK_FILENAME);
  TextStorage _storedLanguageLocal =
      TextStorage.createInstance(_LOCAL_FILENAME);
  LanguageService() {
    MeasureLanguage.transFn = (application, key) {
      return findLanguageValueByCode(application, key);
    };
  }

  /// 是否已经初始化
  bool isHasBeenInitialized = false;

  /// 新增缓存版本号
  String _version = '';

  Future<void> init() async {
    logger.i('LanguageService init start');
    // 创建实例
    final list = await _languageStorage.fetch();
    final storedLocal = await _storedLanguageLocal.fetch();
    if (Store.user.token.isEmpty) {
      return;
    }
    final result = await _getLangugeData();
    if (result.isEmpty) {
      return;
    }
    print('init');
    final needUpdateLanguage = await _isVersionDifferent(result);
    if (isHasBeenInitialized &&
        list != null &&
        ifLocalIs(storedLocal) &&
        !needUpdateLanguage) return;

    if (ifLocalIs(storedLocal)) {
      if (list == null || needUpdateLanguage) {
        await _languageUpdate(result);
      } else {
        _cache = jsonDecode(list);
      }
    } else {
      await _languageUpdate(result);
    }
    isHasBeenInitialized = true;
    logger.i('LanguageService init end');
  }

  // 判断缓存的语言是否与当前语言一致
  bool ifLocalIs(String? curLocal) {
    return curLocal == (i18nBook.locale.toCodeString('-'));
  }

  ///重新加载语言
  Future<void> reload() async {
    final serverLanguage = await _getLangugeData();
    _languageUpdate(serverLanguage);
    await _languageStorage.fetch();
    await _storedLanguageLocal.fetch();
  }

  /// 存储语言库
  Future<bool> _saveData(String language) async {
    try {
      final saved = await _languageStorage.save(language);
      _storedLanguageLocal.save(i18nBook.locale.toCodeString('-'));
      return saved;
    } catch (e) {
      logger.e("ConfigService save data error.", e);
      return false;
    }
  }

  /// 更新语言库
  Future<bool> _languageUpdate(result) async {
    try {
      _cache = jsonDecode(jsonEncode(result));
      await _saveData(jsonEncode(_cache));
    } catch (e) {
      logger.e("LanguageService - call `_languageUpdate` error.", e);
    }
    return false;
  }

  /// 获取翻译包
  Future<List<LangugeDataResult>> _getLangugeData() async {
    try {
      final result = await rpc.organization.getLangugeDataListAsync(
        LangugeDataRequest(
          token: Store.user.token,
          langugeKey: i18nBook.locale.toCodeString('-'),
        ),
      );
      return result;
    } catch (e) {
      logger.e("LanguageService - call `_getLangugeData` error.", e);
    }
    return [];
  }

  /// 版本不同
  Future<bool> _isVersionDifferent(result) async {
    try {
      double settingVersion = 0.0;

      for (int i = 0; i < result.length; i++) {
        var version = result[i].version;
        if (version != null) {
          settingVersion += double.parse(version);
        }
      }
      if (settingVersion.toString() != _version) {
        _version = settingVersion.toString();
        return true;
      }
    } catch (e) {
      logger.e("LanguageService - call `_isVersionDifferent` error.", e);
    }
    return false;
  }
}
