// ignore_for_file: non_constant_identifier_names

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/fis_lib_media_rt.dart';
import 'package:fis_ui/index.dart';
import 'package:flyinsono/architecture/define.dart';
import 'package:flyinsono/architecture/states/states.dart';
import 'package:flyinsono/global.dart';
import 'package:flyinsono/notifications/handlers/wechat/accept_meeting_handle.dart';
import 'package:flyinsono/notifications/handlers/wechat/meeting_hangup_handle.dart';
import 'package:flyinsono/notifications/handlers/wechat/reject_meeting_handle.dart';
import 'package:flyinsono/notifications/notifications.dart';
import 'package:flyinsono/rpc.dart';
import 'package:flyinsono/views/desktop/real_time_consultation/live_consultation/entitys/play_channel.dart';
import 'package:get/get.dart';
import 'index.dart';

class WxConsultationRoomController extends GetxController {
  final state = WxConsultationRoomState();
  IPublisher? _publisher;
  IPlayer? _player;
  bool _entered = false;
  bool _isExit = false;
  late final BaseRoom _room;

  // 会诊Id
  String consultationId = '';

  ///会诊房间信息
  StartConsultationResult _consultationRoomInfo = StartConsultationResult();

  LiveTerminalInfo2 _deviceInfo = LiveTerminalInfo2();
  LiveTerminalInfo2 get deviceInfo => _deviceInfo;

  /// 会诊频道集合
  final Map<String, PlayChannelInfo> _playChannels = {};

  WxConsultationRoomController();

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

  /// 根据 TRTC 中分配到的 Id 获取 Channel
  IChannel? getChannelById(String trtrId) {
    if (_playChannels.containsKey(trtrId) &&
        _playChannels[trtrId]!.channel != null &&
        _playChannels[trtrId]!.started) {
      return _playChannels[trtrId]!.channel!;
    }
    return null;
  }

  // 结束会诊
  void leaveConsultation() {
    Get.back();
  }

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

  /// 在 widget 内存中分配后立即调用。
  @override
  void onInit() {
    _initNotificationService();
    _updateNotificationService();
    _init();
    super.onInit();
  }

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

  void _enter() {
    var userCode = Store.user.code;
    _room.loadLocalMember(LocalMemberParams(
      userId: userCode,
      userSig: _consultationRoomInfo.meetingMemberInfos![0].userSign,
      extParams: {},
    ));
    _room.enter();
  }

  ///退出房间
  Future<void> _exit() async {
    if (_isExit) {
      return;
    }
    try {
      await _stopLocal();
      _room.exit();
      _isExit = true;
    } catch (e) {
      logger.e('MediaController exit ex:', e);
    }
  }

  Future<StartConsultationResult?> _getStartConsultationResult() async {
    final arg = Get.arguments;
    final String openId = Store.user.token;
    if (arg is String) {
      consultationId = arg;
      StartConsultationResult result =
          await rpc.appletAPI.startConsultationAsync(StartConsultationRequest(
        openId: openId,
        consultationId: consultationId,
      ));
      return result;
    } else {
      return null;
    }
  }

  /// 初始化房间
  void _init() async {
    /// 初始化房间参数
    StartConsultationResult? roomInfo = await _getStartConsultationResult();
    if (roomInfo == null) {
      print("初始化失败");
      return;
    } else {
      print("初始化成功");
      _consultationRoomInfo = roomInfo;
    }

    /// 初始化房间成员
    _initRoomMembers();

    ///初始化房间的一些事件监听
    _initRoom();

    ///进入房间
    _enter();
  }

  /// 初始化拉流监听（监听用户进入房间）
  void _initPlayer() {
    if (_player != null) return;
    _player = _room.createPlayer();
    _player!.channelAdded.addListener(_onChannelAdded);
    _player!.channelRemoved.addListener(_onChannelRemoved);
  }

  /// 初始化推流监听
  void _initPublisher() {
    if (_publisher != null) return;
    _publisher = _room.createPublisher();
    _playChannels[Store.user.code] =
        PlayChannelInfo(_publisher!.channels.first, started: false);
  }

  void _initRoomMembers() {
    final roomInfo = _consultationRoomInfo;
    if (roomInfo.terminalInfos != null && roomInfo.terminalInfos!.length > 0) {
      _deviceInfo = roomInfo.terminalInfos![0];
      state.currDevice = ConsultationMemberModel(
        trtcId: _deviceInfo.id ?? '',
      );
    }
    if (roomInfo.meetingMemberInfos != null &&
        roomInfo.meetingMemberInfos!.length > 0) {
      List<ConsultationMemberModel> othersMemberList = [];
      for (var i = 0; i < roomInfo.meetingMemberInfos!.length; i++) {
        var memberInfo = roomInfo.meetingMemberInfos![i];
        if (memberInfo.id == Store.user.code) {
          state.currUser = ConsultationMemberModel(
            trtcId: Store.user.code,
          );
        } else {
          othersMemberList.add(ConsultationMemberModel(
            trtcId: memberInfo.id ?? '',
          ));
        }
      }
      state.othersMemberList = othersMemberList;
    }
  }

  void _initRoom() {
    final roomInfo = _consultationRoomInfo;
    FRTMediaConfig.trtc.appid = roomInfo.appId;
    _room = FRealTimeMedia.createRoom(
      roomInfo.integerRoomId.toString(),
      FRealTimeMediaServiceType.trtc,
    );
    _room.entered.addListener(_onEntered);
    _room.exited.addListener(_onExited);
  }

  void _onEntered(Object sender, void e) {
    _initPublisher();
    _initPlayer();
    if (!_entered) {
      _entered = true;
      _startLocal();
    }
  }

  /// 当新频道加入
  void _onChannelAdded(Object s, IPlayChannel channel) async {
    channel as BasePlayChannel;
    final trtcId = channel.member.userId ?? '';
    if (_playChannels.containsKey(trtcId)) {
      _playChannels.update(trtcId, (value) {
        value.channel = channel;
        return value;
      });
    } else {
      _playChannels[trtcId] = PlayChannelInfo(channel, started: true);
    }
    channel.readyStateChanged.addListener((sender, e) {
      if (e) {
        channel.play();
      }
    });
    _handleChannelAdded(trtcId);
  }

  /// 当频道移除
  void _onChannelRemoved(Object s, IPlayChannel channel) {
    channel as BasePlayChannel;
    final trtcId = channel.member.userId ?? '';
    if (_playChannels.containsKey(trtcId)) {
      _playChannels.update(trtcId, (value) {
        value.channel = null;
        value.started = false;
        return value;
      });
    } else {
      logger.i('channel remove userId:$trtcId');
    }
    _handleChannelRemoved(trtcId);
  }

  void _handleChannelAdded(String trtrId) {
    // 遍历所有的成员，如果存在将状态设置为 true
    state.othersMemberList.forEach((element) {
      if (element.trtcId == trtrId) {
        element.enter();
      }
    });
    // state.othersMemberList = state.othersMemberList;
    if (state.currUser.trtcId == trtrId) {
      state.currUser.enter();
    }
    if (state.currDevice.trtcId == trtrId) {
      state.currDevice.enter();
    }
    print("🚀🚀🚀🚀🚀🚀🚀🚀🚀 进入了 trtrId: $trtrId");
  }

  void _handleChannelRemoved(String trtrId) {
    // 遍历所有的成员，如果存在将状态设置为 false
    state.othersMemberList.forEach((element) {
      if (element.trtcId == trtrId) {
        element.exit();
      }
    });
    // state.othersMemberList = state.othersMemberList;
    if (state.currUser.trtcId == trtrId) {
      state.currUser.exit();
    }
    if (state.currDevice.trtcId == trtrId) {
      state.currDevice.exit();
    }
    print("🚀🚀🚀🚀🚀🚀🚀🚀🚀 离开了 trtrId: $trtrId");
  }

  void _onExited(Object sender, void e) {}

  /// 发起者收到对方接受通知
  void _onWSAcceptMeeting(AcceptMeetingNotification e) {
    print("收到接受通知");
    print("subscriberId ${e.subscriberId}");
    print("roomId ${e.roomId}");
    print("pushLiveState ${e.pushLiveState}");
  }

  /// 挂断通知
  void _onWSMeetingHangup(MeetingHangupNotification e) {
    print("收到挂断通知");
    print("挂断原因 ${e.hangupReason}");
    print("roomId ${e.roomId}");

    /// 弹窗通知会诊已结束
    FConfirmAlert.show(
      context: Get.context!,
      title: i18nBook.common.tip.t,
      subTitle: "对方已挂断，会诊已结束",
      businessParent: FVirtualPageWidget(""),
      confrimLabel: i18nBook.common.confirm.t,
      cancelLabel: i18nBook.common.cancel.t,
      onConfirm: () {
        Get.back();
      },
      onCancel: () {
        Get.back();
      },
    );
  }

  /// 拒绝通知
  void _onWSRejectMeeting(RejectMeetingNotification e) {
    print("收到拒绝通知");
    print("userId ${e.userId}");
    print("roomId ${e.roomId}");

    /// 弹窗通知会诊已结束
    FConfirmAlert.show(
      context: Get.context!,
      title: i18nBook.common.tip.t,
      subTitle: "对方拒绝了您的会诊请求，会诊已结束",
      businessParent: FVirtualPageWidget(""),
      confrimLabel: i18nBook.common.confirm.t,
      cancelLabel: i18nBook.common.cancel.t,
      onConfirm: () {
        Get.back();
      },
      onCancel: () {
        Get.back();
      },
    );
  }

  /// 开启本地预览推流
  void _startLocal() async {
    _playChannels.update(Store.user.code, (value) {
      value.started = true;
      return value;
    });
    _publisher!.setProfile(PublisherProfile(
        resolutionMode: ResolutionMode.landscape,
        resolution: Resolutions.sd_480p,
        frameRate: 10,
        idealCameraName: "",
        idealMicrophoneName: ""));
    _publisher!.channels.first.readyStateChanged.addListener((sender, e) async {
      if (e) {
        await _publisher!.startLocal();
      }
    });
  }

  /// 停止本地预览推流
  Future<void> _stopLocal() async {
    await _publisher?.stopLocal();
    // if (_playChannels.containsKey(Store.user.code)) {
    //   _playChannels.update(Store.user.code, (value) {
    //     value.started = false;
    //     return value;
    //   });
    // }
  }

  /// WebSocket 相关
  void _initNotificationService() {
    if (notificationCenter.isRunning == false) {
      Global.unlistenWsConnection();
      final host = StringFormatter.format(
          'ws://192.168.6.74:7308?token={0}&type={1}', [Store.user.token, 4]);
      notificationCenter.setHost(host);
      notificationCenter.start();
      Global.listenWsConnection();
    }
  }

  /// 更新通知订阅
  void _updateNotificationService() {
    final MeetingHangupNotificationHandler MHNHandler =
        Get.find<MeetingHangupNotificationHandler>();
    MHNHandler.subscribe(_onWSMeetingHangup);
    final RejectMeetingNotificationHandler RMNHandler =
        Get.find<RejectMeetingNotificationHandler>();
    RMNHandler.subscribe(_onWSRejectMeeting);
    final AcceptMeetingNotificationHandler AMNHandler =
        Get.find<AcceptMeetingNotificationHandler>();
    AMNHandler.subscribe(_onWSAcceptMeeting);
  }

  /// 取消订阅
  void _cancelNotificationService() {
    final MeetingHangupNotificationHandler MHNHandler =
        Get.find<MeetingHangupNotificationHandler>();
    MHNHandler.unsubscribe(_onWSMeetingHangup);
    final RejectMeetingNotificationHandler RMNHandler =
        Get.find<RejectMeetingNotificationHandler>();
    RMNHandler.unsubscribe(_onWSRejectMeeting);
    final AcceptMeetingNotificationHandler AMNHandler =
        Get.find<AcceptMeetingNotificationHandler>();
    AMNHandler.unsubscribe(_onWSAcceptMeeting);
  }
}

class ConsultationMemberModel extends GetxController {
  /// 用于TRTC的唯一标识
  final String trtcId;

  RxBool _isEntered = false.obs;

  /// 当前状态
  ConsultationMemberState state = ConsultationMemberState.notEntered;

  ConsultationMemberModel({required this.trtcId});

  // 空构造
  ConsultationMemberModel.empty() : trtcId = '';

  bool get isEntered => _isEntered.value;

  void enter() {
    state = ConsultationMemberState.entered;
    _isEntered.value = true;
  }

  void exit() {
    state = ConsultationMemberState.exited;
    _isEntered.value = false;
  }
}

enum ConsultationMemberState {
  /// 未进入
  notEntered,

  /// 已进入
  entered,

  /// 已退出
  exited,
}
