import 'package:fis_common/index.dart';
import 'package:fis_common/logger/logger.dart';
import 'package:fis_i18n/i18n.dart';
import 'package:fis_jsonrpc/rpc.dart';
import 'package:flutter/material.dart';
import 'package:flyinsono/architecture/app_parameters.dart';
import 'package:flyinsono/architecture/config/model.dart';
import 'package:flyinsono/architecture/define.dart';
import 'package:flyinsono/architecture/event_bus.dart';
import 'package:flyinsono/architecture/router/index.dart';
import 'package:flyinsono/architecture/services/entity/local_setting.dart';
import 'package:flyinsono/architecture/services/modules/config_language.dart';
import 'package:flyinsono/architecture/services/modules/local_setting_configurations.dart';
import 'package:flyinsono/architecture/states/states.dart';
import 'package:flyinsono/architecture/utils/common_util.dart';
import 'package:flyinsono/architecture/utils/prompt_box.dart';
import 'package:flyinsono/common_business.dart';
import 'package:flyinsono/global.dart';
import 'package:flyinsono/js_platform/listener.dart';
import 'package:flyinsono/managers/interfaces/language.dart';
import 'package:flyinsono/managers/interfaces/remote_controller.dart';
import 'package:flyinsono/managers/interfaces/user_info.dart';
import 'package:flyinsono/managers/interfaces/vboxcontrol.dart';
import 'package:flyinsono/managers/interfaces/window_state_manager.dart';
import 'package:flyinsono/pages/setting/server_setting/state.dart';
import 'package:flyinsono/pages/setting/server_setting/view.dart';
import 'package:flyinsono/rpc.dart';
import 'package:flyinsono/utils/export_status_type.dart';
import 'package:flyinsono/views/common/device_live/device_live_list/controller.dart';
import 'package:flyinsono/views/common/device_live/device_live_list/widgets/netWork_settings_dialog.dart';
import 'package:flyinsono/views/common/device_live/device_live_list/widgets/networkwifi_settings_dialog.dart';
import 'package:flyinsono/views/common/device_live/device_live_list/widgets/printer_settings_dialog.dart';
import 'package:flyinsono/views/desktop/device_live/device_live_list/controller.dart';
import 'package:flyinsono/views/desktop/real_time_consultation/widgets/simple_Info.dart';
import 'package:get/get.dart';
import 'package:fis_common/event/event_type.dart';
import 'index.dart';
import 'widgets/export_log.dart';

class UserSettingController extends FControllerBase {
  /// 中文
  static const Locale CHINESE_LOCALE = const Locale("zh", "CN");

  /// 英文
  static const Locale ENGLISH_LOCALE = const Locale("en", "US");

  final state = UserSettingState();
  final userInfoManager = Get.find<IUserInfoManager>();

  ///本地配置缓存服务
  final localSettingService = Get.find<LocalSettingService>();

  /// 本地缓存语言包
  final languageService = Get.find<LanguageService>();
  final windowStateManager = Get.find<IWindowStateManager>();

  final FEventHandler<String> onVBoxSettingPageUrlChange =
      FEventHandler<String>();

  JsListener businessParent = JsListener();

  UserSettingController();

  /// dispose 释放内存
  @override
  void dispose() {
    windowStateManager.onSecondWindowChange
        .removeListener(_onSecondWindowStateChange);
    super.dispose();
  }

  /// 导出日志
  Future<void> exportLog() async {
    await router.dialog(
      () => FExportLog(),
    );
  }

  ///获取我的专家助理和助理医师信息和我的用户角色
  Future<void> getMyAssistantAndAssistantPhysician() async {
    try {
      final result = await rpc.user.getUserInfoAsync(
        GetUserInfoRequest(
          token: Store.user.token,
        ),
      );
      state.bindingAssistant = result.bindAssistantUserCode ?? "";
      state.bindingAssistantPhysician =
          result.bindAssistantDoctorUserCode ?? "";
    } catch (e) {
      print(e);
    }
  }

  ///获取当前账号的用户角色
  Future<void> getMyRoleType() async {
    try {
      final result = await rpc.user.getUserInfoAsync(
        GetUserInfoRequest(
          token: Store.user.token,
        ),
      );
      state.myRoleTypes = result.roleCodes ?? [];
    } catch (e) {
      print(e);
    }
  }

  ///查询机构对应的用户信息
  Future<List<SimpleInfoItem>> getUserInfosByOrganizationCode(
      String organizationCode, List<String> roleCodes) async {
    ///组织对应的用户信息
    List<SimpleInfoItem> organizationUserInfos = [];
    try {
      final result = await rpc.user.getUserListAsync(
        GetUserListRequest(
            token: Store.user.token,
            organizationCode: organizationCode,
            organizationQueryType: OrganizationQueryTypeEnum.All,
            language: i18nBook.locale.toCodeString('-'),
            roleCodes: roleCodes),
      );
      result.forEach(
        (element) async {
          final referUserName = element.displayName;
          if (element.roleName == null) {
            element.roleName = i18nBook.user.notAuthenticated.t;
          }
          organizationUserInfos.add(
            SimpleInfoItem(
              itemCode: element.userCode!,
              name: referUserName,
              role: element.roleName,
              des: element.fieldList,
              image: element.headImageUrl,
            ),
          );
        },
      );
    } catch (e) {
      print(e);
    }
    return organizationUserInfos;
  }

  /// 导出状态
  void handleProgressChanged(progress, exportState) {
    var exportStatInt = int.parse(exportState);
    state.exportState = ExportStatusType.values[exportStatInt];
  }

  void handleSecondWindowStatus(status) {
    // state.secondWindowOpening = false;
    // var exportStatInt = int.parse(status);
    // var exportState = SecondWindowStatus.values[exportStatInt];
    // var isSecondWindowOpended = exportState == SecondWindowStatus.Opened;
    // LocalSetting.ins.isUseSecondWindow = isSecondWindowOpended;
    // state.isUseSecondWindow = isSecondWindowOpended;
    // localSettingService.save();
  }

  /// 确认切换网络
  void makeSureChangedNetwork(String url) async {
    Global.config.data.server.current = url;

    Global.config.save();
    final fullAddress = url == DefaultServerName
        ? AppParameters.data.serverGateway
        : Global.config.data.server.current!;
    //Todo:finlay 通知盒子client更新服务地址
    // var uri = Uri.parse(fullAddress);
    // await CartSystemPlatform.synchServerAddressToSonopost(
    //     uri.host, uri.port.toString());
    // 通知rpc client更新服务地址
    bus.emit(bus.Keys.SERVER_ADDRESS_CHANGED, fullAddress);
    try {
      if (Global.config.data.server.current.isNullOrEmpty ||
          Global.config.data.server.current == DefaultServerName) {
        await Global.initServerSetting();
        logger.i('init flyinsono server end');
      }
    } catch (e) {
      logger.e('UserSettingController initServerSetting ex:', e);
    }
    await Store.user.handelLogOut();
    Store.app.cancelBusy();
    router.offAll(RouteNames.Auth.AuthBoard);
  }

  /// 报告标签自动弹出
  void onChangeAutoPopupReportTag(bool value) async {
    state.isAutoPopupReportTag = value;
    CommonUtil.debounce(
      () => setCommonSettingsAsync(
        CommonSettingsEnum.EnableReportLabel,
        value.toString(),
      ),
      durationTime: 1000,
    );
  }

  /// 开机自启动
  void onChangeAutoStartUp(bool value) async {
    state.isAutoStartUp = value;
    LocalSetting.ins.isAutoStartUp = value;
    localSettingService.save();
    if (FPlatform.isWindows || FPlatform.isMacOS) {
      await rpc.platform.setAutoStartAsync(value);
    }
  }

  ///是否开启第二窗口
  void onChangeUseSecondWindow(bool value) {
    if (state.secondWindowOpening) {
      return;
    }
    if (FPlatform.isPureWeb) {
      _setSecondWindow(value);
      Store.app.enableNewTab = value;
      return;
    }

    if (FPlatform.isWindows || FPlatform.isMacOS) {
      rpc.platform.setSecondWindowStateInfoAsync(value);
      print('setSecondWindowStateInfoAsync value:$value');
      if (value) {
        state.secondWindowOpening = true;
        windowStateManager.onSecondWindowChange
            .addListener(_onSecondWindowStateChange);
      } else {
        _setSecondWindow(value);
      }
    }
  }

  void _setSecondWindow(value) {
    LocalSetting.ins.isUseSecondWindow = value;
    state.isUseSecondWindow = value;
    localSettingService.save();
  }

  /// 在 [onDelete] 方法之前调用。
  @override
  void onClose() {
    Store.persistent();
    super.onClose();
  }

  /// 在 widget 内存中分配后立即调用。
  @override
  Future<void> onInit() async {
    getMyRoleType();
    _initConfiguration();
    _initNetWorkSetting();
    _getAssistant();
    _getAssistantPhysician();
    super.onInit();
  }

  /// 网络设置
  Future<void> onNetworkSettingClick() async {
    await router.dialog(
      () => ServerSettingPage(
        isOpenInSettingPage: true,
        addServerListCallback: () {
          state.serverList = [];
          _initNetWorkSetting();
        },
      ),
    );
  }

  /// 在 onInit() 之后调用 1 帧。这是进入的理想场所
  @override
  void onReady() {
    super.onReady();
  }

  /// 取消服务器变更
  void onServerChangeCanceled() {
    state.currServer = Global.config.data.server.current!;
  }

  ///开启控制台
  void openConsole() {
    if (FPlatform.isWindows) {
      rpc.platform.openConsole();
    }
  }

  /// 设置 语言 或者报告标签是否弹出
  Future<void> setCommonSettingsAsync(
    CommonSettingsEnum currCommonSetting,
    String signatureValue,
  ) async {
    try {
      final result = await rpc.user.setCommonSettingsAsync(
        CommonSettingsRequest(
          token: Store.user.token,
          value: signatureValue,
          settingType: currCommonSetting,
        ),
      );
      if (result) {
        var manager = Get.find<IUserInfoManager>();
        await manager.getUserInfoAsync();
      }
    } catch (e) {
      printError(info: e.toString());
      logger.e("setCommonSettingsAsync ex:", e);
    }
  }

  ///设置选中的用户
  String? setSelectedUser(bool isAssistant, List<SimpleInfoItem> sourseList) {
    String? selectedUser;
    bool isSourseListHasBindingValue = false; //判断数据源里是否存在已绑定的助理医师或者认证专家
    if (isAssistant) {
      selectedUser =
          state.bindingAssistant.isEmpty ? null : state.bindingAssistant;
    } else {
      selectedUser = state.bindingAssistantPhysician.isEmpty
          ? null
          : state.bindingAssistantPhysician;
    }
    for (var item in sourseList) {
      if (item.itemCode == selectedUser) {
        isSourseListHasBindingValue = true;
        break;
      } else {
        continue;
      }
    }
    if (!isSourseListHasBindingValue) {
      selectedUser = null;
    }
    return selectedUser;
  }

  /// 切换语言
  Future<bool> swithLanguageConfirm(String languageCode) async {
    var result = await Get.find<ILanguageConfigManager>()
        .swithLanguageByCode(languageCode);
    if (result) {
      state.currLanguage = languageCode;
    }
    return result;
  }

  /// 更新语言方法
  Future<void> updateLanguage(Locale locale) async {
    Store.app.setBusy(i18nBook.auth.switching.t);
    try {
      if (FPlatform.isMacOS || FPlatform.isWindows) {
        rpc.platform.setLanguageCodeAsync(
          locale.toCodeString("-"),
        );
      }
      await appState.updateLocale(
        locale,
        updateApp: true,
        saveImmediately: true,
      );
    } catch (e) {
      logger.e('UserSettingController updateLanguage ex:', e);
      Store.app.cancelBusy();
    }
    Store.app.cancelBusy();
  }

  ///更新设置自己的专家助理和助理医师
  Future<bool> updateMyOrganizationAssistant(
      String assistantUserCode, String assistantDoctorUserCode) async {
    try {
      return await rpc.liveConsultation.updateMyOrganizationAssistantAsync(
        UpdateMyOrganizationAssistantRequest(
            token: Store.user.token,
            assistantUserCode: assistantUserCode,
            assistantDoctorUserCode: assistantDoctorUserCode),
      );
    } catch (e) {
      print(e);
      return false;
    }
  }

  ///获取专家助理
  Future<void> _getAssistant() async {
    state.assistantList = await userInfoManager.getUserPages(
      organizationCode: Store.user.rootOrganizationCode ?? "",
      roleCodes: [RoleType.expertAssistant],
    );
  }

  ///获取认证医师
  Future<void> _getAssistantPhysician() async {
    state.certifiedPhysicianList = await userInfoManager.getUserPages(
      organizationCode: Store.user.rootOrganizationCode ?? "",
      roleCodes: [RoleType.certifiedPhysician],
    );
  }

  ///初始本地缓存中的配置
  void _initConfiguration() {
    LocalSetting localSetting = LocalSetting.ins;
    state.isUseSecondWindow = localSetting.isUseSecondWindow ?? false;
    state.isAutoStartUp = localSetting.isAutoStartUp ?? false;
    state.isAutoPopupReportTag = Store.user.enableReportLabel;
    state.currLanguage = Store.app.locale.languageCode;
  }

  /// 初始化本地网络配置
  void _initNetWorkSetting() {
    var current = Global.config.data.server.current;
    if (Global.config.data.server.current.isNullOrEmpty) {
      Global.config.data.server.current = DefaultServerName;
    }
    final serverList = _loadCachedOptions();
    var uri = Uri.parse(AppParameters.data.serverGateway);
    // 在最前端插入默认选项
    serverList.insert(
      0,
      ServerOptionModel(
        name: i18nBook.common.appName.t,
        host: uri.host,
        port: uri.port.toString(),
        protocol: uri.scheme,
        isDefault: true,
      ),
    );
    state.serverList.addAll(serverList);
    if (current == DefaultServerName) {
      state.currServer = serverList.first.disPlayName;
    } else {
      var currentServerName = serverList
          .firstWhereOrNull((element) => element.fullAddress == current)
          ?.disPlayName;
      if (currentServerName != null) {
        state.currServer = currentServerName;
      } else {
        state.currServer = serverList.first.disPlayName;
      }
    }
  }

  /// 处理地址选项删除
  Future<void> onAddressOptionDeleted(ServerOptionModel value) async {
    setBusy(i18nBook.user.deleting.t);
    if (Global.config.data.server.current != DefaultServerName) {
      final currentUri = Global.config.data.server.currentUri!;

      // 不可删除当前正在使用的网络地址
      bool isCurrectNetWork = currentUri.host == value.host &&
          currentUri.port.toString() == value.port;
      // 数据更新
      if (isCurrectNetWork) {
        PromptBox.toast(i18nBook.setting.currentServerAddressInUse.t);
        return;
      }
    }
    state.serverList.remove(value);
    Global.config.data.server.optionSource = state.serverList
        .where((e) => !e.isDefault)
        .map((e) => e.fullAddress)
        .toList();
    await Global.config.save();
    busy = false;
    PromptBox.toast(i18nBook.user.deleteSuccess.t);
    if (FPlatform.isMacOS || FPlatform.isWindows) {
      rpc.platform.reloadConfig();
    }
  }

  List<ServerOptionModel> _loadCachedOptions() {
    final sercerCfg = Global.config.data.server;
    // 读取选项列表
    final List<ServerOptionModel> options = sercerCfg.optionSource.map((e) {
      String url = e;
      if (e.startsWith("http") == false) {
        url = "http://$e";
      }
      final uri = Uri.parse(url);
      final portStr = uri.hasPort ? ":${uri.port}" : "";
      return ServerOptionModel(
        name: "${uri.host}$portStr",
        host: uri.host,
        port: uri.port.toString(),
        protocol: uri.scheme,
      );
    }).toList();

    return options;
  }

  ///打印驱动设置
  Future<void> onPrinterSettingsClick() async {
    //TODO(Loki):打印驱动设置页面
    CartSystemPlatform.specialOnceOperationFlag = true;
    var controller = Get.put(DeviceLiveListDesktopController());
    Get.put<DeviceLiveListController>(controller);
    router.dialog(
      () => PrinterSettingsDialog(deviceCode: '', localSetting: true),
      dismissible: false,
    );
    await Future.delayed(Duration(milliseconds: 10));
    final remoteControllerManager = Get.find<IRemoteControllerManager>();
    var installerPrinters = await rpc.platform.getAllInstalledPrinterInfos();
    //["WPS PDF", "OneNote for Windows 10"];
    remoteControllerManager.onDevicePrinterResult.emit(
      this,
      DevicePrinterResultNotification(
        setPrinterEnum: DevicePrinterEnum.GetInstalledPrinters,
        devicePrinterList: installerPrinters
            .map((e) => DevicePrinterParameterDTO(name: e))
            .toList(),
      ),
    );
  }

  ///SP60有线网络连接设置
  Future<void> onNetworkSettingsClick() async {
    var controller = Get.put(DeviceLiveListDesktopController());
    Get.put<DeviceLiveListController>(controller);
    var vBoxControl = Get.find<IVBoxControlManager>();
    var networkResult = await vBoxControl.getNetworkCardsInfo();
    router.dialog(
      () => NetworkSettingsDialog(
        networkResult: networkResult,
      ),
      dismissible: false,
    );
    await Future.delayed(Duration(milliseconds: 10));
  }

  Future<void> onNetworkWifiSetting() async {
    var controller = Get.put(DeviceLiveListDesktopController());
    Get.put<DeviceLiveListController>(controller);
    var vBoxControl = Get.find<IVBoxControlManager>();
    var networkWifiResult = await vBoxControl.getWirelessCardInfo();
    if (networkWifiResult.isSuccess) {
      router.dialog(
        () => NetworkWifiSettingDialog(
          networkWifiResult: networkWifiResult,
        ),
        dismissible: false,
      );
    } else {
      PromptBox.toast(i18nBook.setting.wirelessNetworkCardNotFound.t);
    }

    await Future.delayed(Duration(milliseconds: 10));
  }

  Future<void> flushDNS() async {
    var controller = Get.put(DeviceLiveListDesktopController());
    Get.put<DeviceLiveListController>(controller);
    var vBoxControl = Get.find<IVBoxControlManager>();
    var isSuccess = await vBoxControl.flushDNS();
    if (!isSuccess) {
      PromptBox.toast(i18nBook.setting.refreshDNSFailed.t);
    }
  }

  /// 【切换语言】下拉列表选中语言 (String?, int?)
  void onLanguageSelected(String? value, int? index) async {
    var targetValue = value ?? '';
    if (state.currLanguage != targetValue) {
      await swithLanguageConfirm(targetValue);
      state.currLanguage = targetValue;
      update();
    }
  }

  void _onSecondWindowStateChange(Object sender, bool e) {
    print('_onSecondWindowStateChange $e');
    PromptBox.toast(i18nBook.setting.switchingSecondWindowSuccess.t);
    _setSecondWindow(e);
    state.secondWindowOpening = false;
  }
}

enum SecondWindowStatus {
  ///开启中
  Opening,

  ///已开启
  Opened,

  ///关闭中
  Closing,

  ///已关闭
  Closed,
}
