import 'dart:async';
import 'package:fis_common/event/event_type.dart';
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:fis_lib_media_rt/interface/index.dart';
import 'package:fis_ui/index.dart';
import 'package:fis_lib_media_rt/config.dart';
import 'package:flutter/services.dart';
import 'package:flyinsono/architecture/define.dart';
import 'package:flyinsono/architecture/router/index.dart';
import 'package:flyinsono/architecture/services/entity/local_setting.dart';
import 'package:flyinsono/architecture/states/states.dart';
import 'package:flyinsono/architecture/utils/prompt_box.dart';
import 'package:flyinsono/architecture/utils/web_parameter_helpler.dart';
import 'package:flyinsono/global.dart';
import 'package:flyinsono/managers/interfaces/device.dart';
import 'package:flyinsono/managers/interfaces/entities/consultation_member.dart';
import 'package:flyinsono/managers/interfaces/entities/live_consultation.dart';
import 'package:flyinsono/managers/interfaces/live_consultation.dart';
import 'package:flyinsono/managers/interfaces/user_info.dart';
import 'package:flyinsono/notifications/notifications.dart';
import 'package:flyinsono/rpc.dart';
import 'package:flyinsono/views/desktop/real_time_consultation/controller/real_time_consultation_controller.dart';
import 'package:flyinsono/views/desktop/real_time_consultation/live_consultation/controllers/recording_controller.dart';
import 'package:flyinsono/views/desktop/real_time_consultation/live_consultation/state.dart';
import 'package:get/get.dart';
import 'package:get/get_rx/src/rx_workers/utils/debouncer.dart';
import 'package:universal_html/html.dart' as html;
import 'controllers/loading_controller.dart';
import 'controllers/media_controller.dart';
import 'controllers/member_status_listeners.dart';
import 'controllers/members_controller.dart';
import 'controllers/whiteboard_controller.dart';

class LiveConsultationController extends FControllerBase {
  static const String pageName = 'liveConsultation';

  final state = LiveConsulationState();
  final liveConsultationManager = Get.find<ILiveConsultationManager>();
  final _debouncer = Debouncer(delay: Duration(milliseconds: 200));

  ///设备频道加入房间事件
  final FEventHandler<IPlayChannel> onDeviceChannelAdd =
      FEventHandler<IPlayChannel>();

  RealTimeConsultationController? realTimeConsultationController;

  /// 获取到清除事件通知
  FEventHandler<String> onClearCanavsHandler = FEventHandler<String>();
  late RecordingController recordingController;
  late MediaController mediaController;
  late WhiteboardController whiteboardController;
  late MemberListeners memberListeners;
  late LoadingController loadingController;
  late MembersController membersController;

  bool _isJoin = false;
  FEventHandler<bool> onSwitchPosition = FEventHandler<bool>();
  LiveConsultationController() {
    mediaController = MediaController(this);
    recordingController = RecordingController(this);
    whiteboardController = WhiteboardController(this);
    memberListeners = MemberListeners(this);
    loadingController = LoadingController(this);
    membersController = MembersController(this);
  }

  ///添加会诊成员
  Future<void> addConsultationMember([List<String>? mobileUserCodes]) async {
    return await membersController.addConsultationMember(mobileUserCodes);
  }

  Future<void> addMember() async {
    return await membersController.addMember();
  }

  ///再次呼叫
  Future<void> callAgain(String targetId) async {
    return await membersController.callAgain(targetId);
  }

  ///取消呼叫
  Future<void> cancelCall(String targetId) async {
    return await membersController.cancelCall(targetId);
  }

  /// 截取一帧 vid
  void captureOneFrame() async {
    return recordingController.captureOneFrame();
  }

  void closeVolumeSetting() {
    state.isShowVolumeSetting4Mobile = false;
  }

  /// 连接超声机进行远程调参: 发起连接
  Future<void> controlParameterAsync() async {
    ConsultationMember device = state.memberStatus.values
        .firstWhere((element) => element.memberType == LiveMemberEnum.Device);
    if (device.videoDeviceInfos == null) {
      PromptBox.toast(i18nBook.remoteControl.probeInfoEmpty.t);
      return;
    }
    final deviceManager = Get.find<IDeviceManager>();
    var deviceInfo = await deviceManager.getDeviceInfo(device.id!);
    if (deviceInfo?.isCanRemoteMaintenance == false) {
      PromptBox.toast(i18nBook.remedical.remoteParameterNotSupported.t);
      return;
    }

    var result = await liveConsultationManager.controlParameterAsync(
      state.liveConsultation.consultationCode ?? '',
      [],
      ControlDeviceParameterEnum.Start,
    );
    if (result == true) {
      await deviceManager.openRemoteControllerPage(
        device.id!,
        isLiveConsultationController: true,
        consultationCode: state.consultationDetail.consultationCode!,
      );

      state.isLoading = false;
    } else {
      PromptBox.toast(i18nBook.remoteControl.connectionFailed.t);
    }
  }

  /// 当前颜色
  Color currectColor() {
    return whiteboardController.currectColor();
  }

  @override
  void dispose() {
    _destroyMemory();
    super.dispose();
  }

  ///结束录制
  void endRecording() async {
    return recordingController.endRecording();
  }

  ///获取成员播放频道
  IChannel? getMemberPreviewChannel(ConsultationMember member) {
    return mediaController.getMemberPreviewChannel(member);
  }

  /// 初始化截图列表
  void initCaptureImageList() {
    recordingController.initCaptureImageList();
  }

  Future<void> retryLoadDevice() async {
    if (FRTMediaConfig.serviceType == FRealTimeMediaServiceType.trtc) {
      await trtcRetryLoadDevice();
    } else {
      await rtmpRetryLoadDevice();
    }
  }

  /// 会诊设备重试进入房间 [TRTC]
  Future<void> trtcRetryLoadDevice() async {
    try {
      await liveConsultationManager
          .trtcRetryLoadDevice(state.consultationDetail.consultationCode!);
    } catch (e) {
      logger.e('LiveConsultationController retryLoadDevice ex:', e);
    }
    loadingController.startLoading();
  }

  /// 会诊设备重试进入房间 [RTMP]
  Future<void> rtmpRetryLoadDevice() async {
    try {
      // rebuild 会诊设备，获取新的设备信息，通过 RTMP 桥接器触发虚拟的成员加入事件
      await liveConsultationManager
          .rtmpRetryLoadDevice(state.consultationDetail.consultationCode!);
    } catch (e) {
      logger.e('LiveConsultationController retryLoadDevice ex:', e);
    }
  }

  ///离开房间
  Future<void> leaveConsultation() async {
    _debouncer.call(() async {
      try {
        liveConsultationManager.onExitConsultation.emit(this, true);
        stopFullRecording();
        mediaController.exit();
        liveConsultationManager
            .leaveLiveConsultationAsync(
                state.liveConsultation.consultationCode ?? '')
            .then((result) {
          var consultationCode = result.consultationCode ?? '';
          if (consultationCode.isNotEmpty) {
            logger.i('$consultationCode endConsultation success');
          } else {
            logger.i('$consultationCode endConsultation failed');
          }
        });
      } catch (e) {
        logger.e('LiveConsultationController leaveConsultation ex:', e);
      }
      rpc.user.removeUserSingleTokenAsync(RemoveUserSingleTokenRequest(
        token: Store.user.token,
        wSToken: Store.user.token + "_1",
      ));
      exitCurrentPage();
    });
  }

  @override
  void onClose() {
    recordingController.dispose();
    _destroyMemory();
    super.onClose();
  }

  @override
  void onReady() {
    super.onReady();
    _setMobilePreferredOrientations();
    _initData();
  }

  ///开启全程录制
  void onRecordingOperation() async {
    recordingController.fullRecordingOperation();
  }

  ///更换病人
  Future<void> onSelectedPatientChange(String consultationId) async {
    await sendInteractiveBoardData('', true);
    for (ConsultationMember m in state.liveConsultation.memberLiveDatas ?? []) {
      if (m.memberType == LiveMemberEnum.User) {
        onClearCanavsHandler.emit('', m.id ?? '');
      }
    }
    final originalCode = state.selectedConsultationCode;
    state.selectedConsultationCode = consultationId;
    print('consultation $originalCode change to $consultationId');
    var result = await rpc.liveConsultation.changeConsultationAsync(
      ChangeConsultationRequest(
        token: Store.user.token,
        originalCode: originalCode,
        currentCode: consultationId,
      ),
    );
    var liveConsultation = LiveConsultation(
      consultationCode: result.consultationCode,
      roomNo: result.roomNo,
      initiatorCode: result.initiatorCode,
    );
    state.captureImageList = [];
    liveConsultation.consultationMemberConvert(result.memberLiveDatas ?? []);
    state.liveConsultation = liveConsultation;
    await _initConsultationInfo(isReload: true);
    membersController.initWaitInLineForConsultationOatients();
  }

  ///重新加载病人信息，房间不变
  Future<void> reload(LiveConsultation consulation) async {
    await sendInteractiveBoardData('', true);
    //图像列表置空
    state.captureImageList = [];
    for (ConsultationMember m in state.liveConsultation.memberLiveDatas ?? []) {
      if (m.memberType == LiveMemberEnum.User) {
        onClearCanavsHandler.emit('', m.id ?? '');
      }
    }
    state.selectedConsultationCode = consulation.consultationCode ?? '';
    state.liveConsultation = consulation;
    _initConsultationInfo(isReload: true);
  }

  /// 发送白板数据
  Future<void> sendInteractiveBoardData(String boardData,
      [bool isClear = false]) async {
    whiteboardController.sendInteractiveBoardData(boardData, isClear);
  }

  /// 开启音量设置面板
  void openVolumeSetting() {
    state.isShowVolumeSetting4Mobile = true;
  }

  ///设置静音
  void setAudioMute(bool isMute, String userCode) {
    mediaController.setAudioMute(isMute, userCode);
  }

  ///设置麦克风静音
  Future<bool> setMicrophone(bool isMute) async {
    if (state.memberStatus.containsKey(Store.user.code)) {
      state.memberStatus.update(Store.user.code, (value) {
        value.mute = isMute;
        return value;
      });
    }
    mediaController.setAudioMute(isMute, Store.user.code);
    var result = await liveConsultationManager.muteLiveConsultationAsync(
        state.liveConsultation.consultationCode ?? '', isMute);
    final consultationCode = result.consultationCode ?? '';
    return consultationCode.isNotEmpty;
  }

  ///设置是否启用摄像头
  Future<bool> setVideoOpend(bool isOperate) async {
    mediaController.switchVideoOpen(isOperate);
    if (FRTMediaConfig.serviceType == FRealTimeMediaServiceType.ntRtmp) {
      if (!isOperate) {
        mediaController.stopLocal();
      } else {
        mediaController.startLocal();
      }
    }
    var result = await liveConsultationManager.switchLiveConsultationVideoAsync(
        state.liveConsultation.consultationCode ?? '', isOperate);
    final consultationCode = result.consultationCode ?? '';
    return consultationCode.isNotEmpty;
  }

  /// 切换音量设置面板
  void switchVolumeSetting() {
    state.isShowVolumeSetting4Mobile = !state.isShowVolumeSetting4Mobile;
  }

  ///开启录制
  void startRecording() async {
    return recordingController.startRecording();
  }

  ///结束全程录制
  void stopFullRecording() async {
    return recordingController.stopFullRecording();
  }

  Future<void> _destroyMemory() async {
    _unsetMobilePreferredOrientations();
    membersController.destroyMemory();
    memberListeners.dispose();
    await mediaController.exit();
    onSwitchPosition.dispose();
  }

  ///初始化会诊信息
  Future<void> _initConsultationInfo({bool isReload = false}) async {
    try {
      logger.i(
          'findConsultationDetailAsync by id:${state.selectedConsultationCode}');
      var consulationInfo = await liveConsultationManager
          .findConsultationDetailAsync(state.selectedConsultationCode);
      if (consulationInfo == null) {
        return;
      }
      state.consultationDetail = consulationInfo;
      var expertUserCode = consulationInfo.expertUserCode ?? '';
      var memberLiveDatas = state.liveConsultation.memberLiveDatas ?? [];
      if (!isReload) {
        logger.i(
            'initiateLiveConsultationAsync by id:${state.selectedConsultationCode},isJoin:$_isJoin');
        if (_isJoin) {
          state.liveConsultation = await liveConsultationManager
              .joinInLiveConsultationAsync(state.selectedConsultationCode);
        } else if (consulationInfo.isEmergency &&
            consulationInfo.applyUserCode != Store.user.code) {
          state.liveConsultation =
              await liveConsultationManager.acceptLiveConsultationAsync(
            state.selectedConsultationCode,
          );
        } else if (expertUserCode == Store.user.code ||
            (consulationInfo.isEmergency &&
                consulationInfo.applyUserCode == Store.user.code)) {
          state.liveConsultation = await liveConsultationManager
              .initiateLiveConsultationAsync(state.selectedConsultationCode);
        } else {
          state.liveConsultation = await liveConsultationManager
              .acceptLiveConsultationAsync(state.selectedConsultationCode);
        }
        logger.i(
            'initiateLiveConsultationAsync by id:${state.selectedConsultationCode},end');
        if (consulationInfo.isEmergency) {
          var retryConsultationDetail = await liveConsultationManager
              .findConsultationDetailAsync(state.selectedConsultationCode);
          if (retryConsultationDetail != null) {
            state.consultationDetail = retryConsultationDetail;
          }
        }
        memberLiveDatas = state.liveConsultation.memberLiveDatas ?? [];
        var interactiveBoardDatas =
            state.liveConsultation.interactiveBoardDatas ?? [];
        List<String> initBoardDatas = [];
        for (var interactiveBoardData in interactiveBoardDatas) {
          initBoardDatas.add(interactiveBoardData.boardData ?? '');
        }
        state.initBoardDatas = initBoardDatas;
        Map<String, ConsultationMember> statuses = {};
        for (var member in memberLiveDatas) {
          var memberId = member.id ?? '';
          statuses[memberId] = member;
          if (!member.isOnline) {
            statuses[memberId]!.status = MemberStatus.Offline;
            if (member.memberType == LiveMemberEnum.Device) {
              state.isLoading = false;
              state.showRetryButton = true;
            }
          } else if (member.isBusy) {
            statuses[memberId]!.status = MemberStatus.Busyline;
          } else if (member.memberType == LiveMemberEnum.User &&
              member.status == MemberStatus.Default) {
            statuses[memberId]!.status = MemberStatus.Calling;
          }
        }
        state.memberStatus = statuses;
      } else {
        state.initBoardDatas = [];

        state.memberStatus.clear();
        Map<String, ConsultationMember> memberStatus = {};
        for (var member in memberLiveDatas) {
          var userId = member.id ?? '';
          memberStatus[userId] = member;

          if (!member.isOnline) {
            memberStatus[userId]!.status = MemberStatus.Offline;
            if (member.memberType == LiveMemberEnum.Device) {
              state.isLoading = false;
              state.showRetryButton = true;
            }
          } else if (member.isBusy) {
            memberStatus[userId]!.status = MemberStatus.Busyline;
          } else if (member.memberType == LiveMemberEnum.User &&
              member.status == MemberStatus.Default) {
            memberStatus[userId]!.status = MemberStatus.Calling;
          } else {
            member.videoOpend = true;
          }
        }
        state.memberStatus = memberStatus;
        List<String> playChannelKeys = [];
        playChannelKeys.addAll(state.playChannels.keys);
        for (var playChannelKey in playChannelKeys) {
          if (!memberStatus.containsKey(playChannelKey)) {
            state.playChannels.remove(playChannelKey);
          }

          ///会诊助理3秒后再加载视频流，为了解决视频成员位置变化时无法拉流的问题
          if (memberStatus[playChannelKey]?.sortLevel == 3) {
            state.playChannels.update(playChannelKey, (value) {
              value.started = false;
              return value;
            });
            Future.delayed(Duration(seconds: 3), () {
              state.playChannels.update(playChannelKey, (value) {
                value.started = true;
                return value;
              });
            });
          }
        }
      }
    } on JsonRpcException {
      if (FPlatform.isMacOS || FPlatform.isWindows) {
        await Future.delayed(Duration(milliseconds: 1000), () {
          rpc.platform.closeLiveConsultation();
        });
      } else if (FPlatform.isPureWeb) {
        await Future.delayed(Duration(milliseconds: 1000), () {
          html.window.close();
        });
      } else {
        router.back(id: kIsMobile ? null : NavIds.HOME);
      }
    } catch (e) {
      logger.e('LiveConsultationController _initConsultationInfo ex:', e);
    }
  }

  ///初始化数据
  void _initData() async {
    var parameters = router.getParams() ?? {};
    if (parameters.isEmpty) {
      parameters = router.getParams(NavIds.HOME) ?? {};
      if (parameters.isEmpty) {
        parameters = ParameterHelper.parasmeters;
        Future.delayed(Duration(milliseconds: 1000), () {
          ParameterHelper.setWindowState();
        });
      }
    }
    if (parameters.isNotEmpty) {
      if (parameters.containsKey('token')) {
        var token = parameters['token'] ?? '';
        Store.user.setToken(token);
        await Get.find<IUserInfoManager>().getUserInfoAsync();
      }
      state.selectedConsultationCode = parameters["consultationCode"] ?? '';
      var isJoinStr = parameters["isJoin"] ?? '';
      _isJoin = (isJoinStr == 'true' || isJoinStr == 'True');
      if (state.selectedConsultationCode.isEmpty) {
        print("consultationCode isempty");
        return;
      }

      await _initConsultationInfo();
      if (state.selectedConsultationCode.isNotEmpty) {
        membersController.startHeartbeat();
        var deviceMember = state.memberStatus.values.toList().firstWhereOrNull(
            (element) => element.memberType == LiveMemberEnum.Device);
        if (deviceMember != null && deviceMember.isOnline) {
          loadingController.startLoading();
        } else if (deviceMember?.isOnline == false) {
          Future.delayed(Duration(milliseconds: 500), () {
            PromptBox.toast(i18nBook.errorCodes.errorCode806.t);
          });
        }
      }
      var deviceMember = state.memberStatus.values.toList().firstWhereOrNull(
          (element) => element.memberType == LiveMemberEnum.Device);
      if (deviceMember != null) {
        var deviceCode = deviceMember.id ?? '';
        final deviceManager = Get.find<IDeviceManager>();
        var deviceInfo = await deviceManager.getDeviceInfo(deviceCode);
        if (deviceInfo != null && deviceInfo.deviceType != 'US') {
          state.isUSDevice = false;
        }
      }
      memberListeners.addListeners();
    }
    membersController.initWaitInLineForConsultationOatients();
    mediaController.init();
    //TODO(Loki):realTimeConsultationController应该脱离依赖（添加会诊成员页面需要单独的Controller）
    realTimeConsultationController = Get.put(RealTimeConsultationController());
    realTimeConsultationController!.state.currentConsultationCode =
        state.selectedConsultationCode;
    await realTimeConsultationController!.initReferOrganization();
    await realTimeConsultationController!.findConsultationDetailAsync();
  }

  void _setMobilePreferredOrientations() {
    // 手机强制横屏
    if (FPlatform.isAndroid) {
      SystemChrome.setPreferredOrientations([DeviceOrientation.landscapeLeft]);
      SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersive);
      SystemChrome.setSystemUIChangeCallback((systemOverlaysAreVisible) async {
        await Future.delayed(const Duration(seconds: 1));
        SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersive);
      });
    } else if (FPlatform.isIOS) {
      SystemChrome.setPreferredOrientations([DeviceOrientation.landscapeRight]);
      SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersive);
      SystemChrome.setSystemUIChangeCallback((systemOverlaysAreVisible) async {
        await Future.delayed(const Duration(seconds: 1));
        SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersive);
      });
    }
  }

  void _unsetMobilePreferredOrientations() async {
    if (FPlatform.isAndroid || FPlatform.isIOS) {
      // 恢复竖屏
      await SystemChrome.setPreferredOrientations(
        [
          DeviceOrientation.portraitUp, // 竖屏 Portrait 模式
          DeviceOrientation.portraitDown,
        ],
      );
      SystemChrome.setPreferredOrientations([
        DeviceOrientation.portraitUp,
      ]);
      SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual,
          overlays: SystemUiOverlay.values);
      SystemChrome.setSystemUIChangeCallback((systemOverlaysAreVisible) async {
        // do nothing
      });
    }
  }

  Future<void> exitCurrentPage() async {
    if (FPlatform.isMacOS || FPlatform.isWindows) {
      try {
        if (LocalSetting.ins.isUseSecondWindow!) {
          Global.unlistenWsConnection();
          notificationCenter.stop();
          final wsConnection = notificationCenter.connection;
          if (wsConnection != null && wsConnection.isConnected) {
            await Future.delayed(Duration(milliseconds: 10));
            wsConnection.close();
            logger.i('ws status:${wsConnection.status}');
          }
          await Future.delayed(Duration(microseconds: 10));
          logger.i('ws status:${wsConnection?.status}');
        }
        await _destroyMemory();
      } catch (e) {
        logger.e('leaveConsultation stop notificationCenter ex:', e);
      }
      if (CartSystemPlatform.isCartSystemVersion ||
          LocalSetting.ins.isUseSecondWindow != true) {
        router.back();
      } else {
        await rpc.platform.closeLiveConsultation();
      }
    } else if (FPlatform.isPureWeb &&
        LocalSetting.ins.isUseSecondWindow == true) {
      html.window.close();
    } else {
      _unsetMobilePreferredOrientations();
      router.back(
          id: (kIsMobile || LocalSetting.ins.isUseSecondWindow != true)
              ? null
              : NavIds.HOME);
    }
  }
}
