import 'package:fis_jsonrpc/encrpyt.dart';
import 'package:fis_jsonrpc/rpc.dart';
import 'package:get/get.dart';
import 'package:vitalapp/architecture/types/index.dart';
import 'package:vitalapp/managers/interfaces/account.dart';
import 'package:vitalapp/managers/interfaces/organization.dart';
import 'package:vitalapp/managers/interfaces/system_setting.dart';
import 'package:vitalapp/managers/interfaces/template.dart';
import 'package:vitalapp/rpc.dart';
import 'package:fis_common/logger/logger.dart';

import '../defines.dart';
import '../store.dart';

class UserState extends StateModuleBase {
  String? _token;
  String? _account;
  String? _password;

  /// 是否自动登录
  bool _isAutoLogin = false;
  final RxList<UserFeatureDTO> _menuPermissionList = RxList<UserFeatureDTO>();
  final RxList<UserFeatureDTO> _operationPermissionList =
      RxList<UserFeatureDTO>();

  final RxString _displayName = ''.obs;
  final RxList<String> _features = RxList<String>();
  final Rx<String> _headImageToken = Rx('');
  final Rx<PatientDTO?> _currentSelectPatientInfo = Rx(null);

  /// 登录令牌
  String? get token => _token;

  /// 是否登录中
  bool get isLogOn => token != null && token!.isNotEmpty;

  /// 是否自动登录
  bool get isAutoLogin => _isAutoLogin;

  /// 登录账号
  String? get account => _account;

  /// 用户Code
  String? get userCode => _userInfo?.code;

  /// 登录密码
  String? get password => _password;

  /// 外显名称
  String get displayName => _displayName.value;
  set displayName(String val) => _displayName.value = val;

  /// 团队名称
  String get teamName => _userInfo?.teamName ?? "";

  /// 负责医生
  String get principalName => _userInfo?.principalName ?? "";

  /// 医生电话
  String get principalPhone => _userInfo?.principalPhone ?? "";

  /// 机构code
  String get organizationCode => _userInfo?.organizationCode ?? "";

  /// 机构名称
  String get organizationName => _userInfo?.organizationName ?? "";

  /// 机构电话
  String get organizationPhone => _userInfo?.organizationPhone ?? "";

  /// 医生签名
  String get signature => _userInfo?.signature ?? "";

  ///头像
  String get headImageToken => _headImageToken.value;
  set headImageToken(String val) => _headImageToken.value = val;

  /// 当前选中的病人详情
  PatientDTO? get currentSelectPatientInfo => _currentSelectPatientInfo.value;
  set currentSelectPatientInfo(PatientDTO? val) {
    _currentSelectPatientInfo.value = val;
    logger.i("UserState currentSelectPatientInfo name:${val?.patientName}.");
  }

  /// 当前用户的菜单权限
  List<UserFeatureDTO>? get menuPermissionList => _menuPermissionList;

  List<UserFeatureDTO>? get operationPermissionList => _operationPermissionList;

  /// 权限集合
  List<String> get features => _features;

  /// 是否有指定权限
  ///
  /// [key] 权限Key
  bool hasFeature(String key) => features.contains(key);

  /// 负责区域(村)集合
  List<StringKVModel> get residence =>
      _userInfo?.residence
          ?.map((e) => StringKVModel(e.code!, e.name!))
          .toList() ??
      [];

  /// 用户信息
  UserDTO? _userInfo;

  /// 处理登录
  Future<void> handleLogin(
    String account,
    String token,
    String password,
    bool isAutoLogin,
  ) async {
    _token = token;
    _account = account;
    _password = password;
    _isAutoLogin = isAutoLogin;
    _updateRpcResEncryptKey(token);
    final templateController = Get.find<ITemplateManager>();
    await templateController.saveTemplate();
    await _fetchFeatures();
    await Store.persistent();
  }

  /// 处理登出
  Future<void> handleLogOut() async {
    _token = null;
    _currentSelectPatientInfo.value = null;
    _updateRpcResEncryptKey("");

    await Store.persistent();
  }

  /// 更新用户信息
  Future<void> updateUserInfo(UserDTO dto) async {
    _userInfo = dto;
    _headImageToken.value = dto.headImageToken ?? '';
    _displayName.value = _userInfo?.realName ?? _userInfo?.userName ?? "";
    await Store.persistent();
  }

  /// 更新用户签名
  Future<void> updateSignature(String value) async {
    if (_userInfo != null) {
      _userInfo!.signature = value;
      await Store.persistent();
    }
  }

  @override
  Future<void> acceptPersistenceJson(Map<String, dynamic> map) async {
    // key对应值不为空时，给相应字段赋值
    map.pickPersistentProp('token', (x) => _token = x);
    map.pickPersistentProp('isAutoLogin', (x) => _isAutoLogin = x);
    map.pickPersistentProp(
      'features',
      (x) => _updateFeatures((x as List).cast<String>()),
    );
    map.pickPersistentProps({
      'account': (x) => _account = x,
      'password': (x) => _password = x,
      'displayName': (x) => _displayName.value = x,
    });
    map.pickPersistentProp(
      'userInfo',
      (x) {
        if (x != null) {
          _userInfo = UserDTO.fromJson(x);
          _headImageToken.value = _userInfo?.headImageToken ?? '';
          _displayName.value = _userInfo?.realName ?? _userInfo?.userName ?? "";
        }
      },
    );
    map.pickPersistentProp('selectPatientInfo', (x) {
      if (x != null) {
        _updateSelectPatientInfo(PatientDTO.fromJson(x));
      }
    });
    map.pickPersistentProp('menuPermissionList', (x) {
      if (x != null) {
        _updateMenuPermissionList((x as List).cast<UserFeatureDTO>());
      }
    });
    map.pickPersistentProp('operationPermissionList', (x) {
      if (x != null) {
        _updateOperationPermissionList((x as List).cast<UserFeatureDTO>());
      }
    });
  }

  @override
  Map<String, dynamic> toPersistenceJson() {
    return {
      "token": token,
      "isAutoLogin": isAutoLogin,
      "account": account,
      "password": password,
      "displayName": displayName,
      "userInfo": _userInfo,
      "features": _features,
      "selectPatientInfo": _currentSelectPatientInfo,
      "menuPermissionList": _menuPermissionList,
      "operationPermissionList": _operationPermissionList,
    };
  }

  void _updateFeatures(Iterable<String> features) {
    _features.value = List.unmodifiable(features);
  }

  void _updateMenuPermissionList(Iterable<UserFeatureDTO> permissionList) {
    _menuPermissionList.value = List.unmodifiable(permissionList);
  }

  void _updateOperationPermissionList(Iterable<UserFeatureDTO> permissionList) {
    _operationPermissionList.value = List.unmodifiable(permissionList);
  }

  void _updateSelectPatientInfo(PatientDTO patient) {
    _currentSelectPatientInfo.value = patient;
  }

  void _clearFeatures() => _features.value = [];

  // 更新RPC响应秘钥
  void _updateRpcResEncryptKey(String key) {
    final originResEncryptCfg = rpc.responseEncryptConfig;
    rpc.responseEncryptConfig = JsonRpcEncryptConfig(
      enable: originResEncryptCfg.enable,
      encryptMode: originResEncryptCfg.encryptMode,
      encryptKey: key,
    );
  }

  Future<void> _fetchFeatures() async {
    final accountController = Get.find<IAccountManager>();

    _clearFeatures();
    try {
      final items = await accountController.getOperationPermission();
      final menuPermission = await accountController.getMenuPermission();
      _menuPermissionList.value = menuPermission ?? [];
      _operationPermissionList.value = items ?? [];
      final featureKeys = items!.map((e) => e.code!);
      _updateFeatures(featureKeys);
      _updateMenuPermissionList(_menuPermissionList);
      _updateOperationPermissionList(_operationPermissionList);
    } catch (e) {
      logger.e("UserState fetch features error.", e);
    }
  }
}
