//
//  YHLivePlayerViewController.swift
//  galaxy
//
//  Created by alexzzw on 2024/11/25.
//  Copyright © 2024 https://www.galaxy-immi.com. All rights reserved.
//

import AgoraRtcKit
import HyphenateChat
import UIKit
import AGConnectAppLinking

class YHLivePlayerViewController: YHBasePlayerViewController {
    // MARK: - Properties

    private let liveId: Int
    private var roomId: String?
    private let messageQueue = DispatchQueue(label: "com.livePlayerRoom.messageQueue")
    let viewModel = YHLiveSalesViewModel()
    private var goodsListView: YHLiveShopView?
    private var isLiveStateOn: Bool = false

    private var listMaxWidth: CGFloat {
        return KScreenWidth * 248.0 / 375.0
    }
    
    private var isFirstAppear = true
    private var timer: DispatchSourceTimer?
    private var isDisappearFromZoom = false
    private let timeCount: Int = 120
    // 进聊天室尝试次数
    private let maxRetryCount = 3
    // 手势初始状态记录
    private var originalX: CGFloat = 0
    private var isMessageListHidden = false // 默认展示
    private lazy var bottomInputBar: YHInputBottomBar = {
        let view = YHInputBottomBar()
        view.textViewTappedEvent = { [weak self] in
            self?.present(self?.inputVC ?? UIViewController(), animated: false)
        }
        return view
    }()

    private lazy var inputVC: YHMessageInputViewController = {
        let ctl = YHMessageInputViewController()
        ctl.inputCallback = { [weak self] controller, text in
            self?.handleMessageInput(text: text, controller: controller)
        }
        return ctl
    }()

    private lazy var messageListView: YHLiveMessageListView = {
        let view = YHLiveMessageListView(frame: CGRect(x: 0, y: 0, width: listMaxWidth, height: listMaxWidth))
        return view
    }()

    private lazy var liveStateVC: YHLiveStateViewController = {
        let vc = YHLiveStateViewController()
        vc.shareEvent = { [weak self] in
            self?.shareLive()
        }

        vc.closeEvent = { [weak self] in
            // self?.leaveLiveRoom()
            self?.closeLive()
        }

        vc.backHomeEvent = { [weak self] in
            self?.closeLive()
            UIViewController.current?.navigationController?.popToRootViewController(animated: false)
            goTabBarBy(tabType: .home)
        }
        vc.backHomeLivePage = { [weak self] in
            self?.closeLive()
            UIViewController.current?.navigationController?.popToRootViewController(animated: false)
            goTabBarBy(tabType: .home)
            NotificationCenter.default.post(name: YhConstant.YhNotification.didJumpToHomePageLifeTabNotification, object: nil)
        }
        return vc
    }()
    
    private lazy var videoStatsLabel: UILabel = {
        let label = UILabel()
        label.textColor = .white
        label.font = .PFSC_R(ofSize: 13)
        label.numberOfLines = 0
        label.lineBreakMode = .byCharWrapping
        label.backgroundColor = .lightGray
        label.alpha = 0.7
        return label
    }()
    
    private lazy var bottomImageView: UIImageView = {
        let imageView = UIImageView(image: UIImage(named: "live_player_bg"))
        return imageView
    }()
    
    private lazy var messageListStateButton: UIButton = {
        let button = UIButton(type: .custom)
        button.setImage(UIImage(named: "live_message_show"), for: .selected)
        button.setImage(UIImage(named: "live_message_hide"), for: .normal)
        button.addTarget(self, action: #selector(messageListStateButtonClicked(_:)), for: .touchUpInside)
        return button
    }()
    
    private lazy var closeButton: UIButton = {
        let button = UIButton(type: .custom)
        button.isHidden = true
        button.setImage(UIImage(named: "live_room_close"), for: .normal)
        button.addTarget(self, action: #selector(closeButtonClicked), for: .touchUpInside)
        button.contentEdgeInsets = UIEdgeInsets(top: 4, left: 4, bottom: 4, right: 4)
        return button
    }()

    private lazy var playButton: UIButton = {
        let button = UIButton(type: .custom)
        button.setImage(UIImage(named: "live_play_interface_orientatio"), for: .normal)
        button.addTarget(self, action: #selector(playeButtonClicked), for: .touchUpInside)
        return button
    }()
    
    // MARK: - Initialization
    init(id: Int, url: String? = nil, title: String? = nil, roomId: String? = nil) {
        liveId = id
        self.roomId = roomId
        super.init(nibName: nil, bundle: nil)
        // 隐藏播控UI
        // controlView.isHidden = true
        player?.delegate = self // 设置播放器代理
        if let roomId = roomId {
            setupChatRoom(roomId: roomId)
        }
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    // MARK: - Lifecycle

    override func viewDidLoad() {
        super.viewDidLoad()
        modalPresentationStyle = .fullScreen
        setupLiveUI()
        setupLiveNotifications()
        setupData()
        if YHLoginManager.shared.isLogin() {
            joinLiveRoom(id: liveId, callback: { _, _ in })
        }
        setupTimer()
        setupLifeCycleNotifications()
        NotificationCenter.default.addObserver(self, selector: #selector(orientationDidChange), name: UIDevice.orientationDidChangeNotification, object: nil)
    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        if !isFirstAppear {
            if let liveDetail = viewModel.liveDetailModel, !liveDetail.rtmp_channel.isEmpty, !liveDetail.token.isEmpty, let uid = playbackInfo?.uid, let player = player {
                YHPlayerManager.shared.joinChannel(for: player, token: liveDetail.token, channelId: liveDetail.rtmp_channel, uid: uid, view: playerView, defaultMuted: false)
            }
        }
    }
    
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        if !isDisappearFromZoom {
            if let player = player {
                changePortrait()
                YHPlayerManager.shared.leaveChannel(for: player)
            }
        }
    }
    
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        if isFirstAppear {
            isFirstAppear = false
        }
    }

    deinit {
        NotificationCenter.default.removeObserver(self)
        quitChatRoom()
        cancelTimer()
    }

    // MARK: - Setup

    private func setupLiveUI() {
        playerView.addSubview(bottomImageView)
        // playerView.addSubview(blurredView)
        containerView.addSubview(bottomInputBar)
        containerView.addSubview(messageListView)
        containerView.addSubview(messageListStateButton)
        containerView.addSubview(closeButton)
        containerView.addSubview(playButton)
        bottomImageView.snp.makeConstraints { make in
            make.edges.equalToSuperview()
        }
        bottomInputBar.snp.makeConstraints { make in
            make.left.right.bottom.equalToSuperview()
            make.top.equalTo(view.safeAreaLayoutGuide.snp.bottom)
                .offset(-YHInputBottomBar.inputActionHeight)
        }

        messageListView.snp.makeConstraints { make in
            make.left.equalToSuperview().offset(16)
            make.bottom.equalTo(bottomInputBar.snp.top).offset(-14)
            make.height.width.equalTo(listMaxWidth)
        }
        
        messageListStateButton.snp.makeConstraints { make in
            make.right.equalToSuperview().offset(-16)
            make.bottom.equalTo(bottomInputBar.snp.top).offset(-10)
            make.height.width.equalTo(44)
        }
        
        closeButton.snp.makeConstraints { make in
            make.centerY.equalTo(topBarView.headPortrait)
            make.right.equalToSuperview().offset(-12)
            make.width.height.equalTo(32)
        }
        
        playButton.snp.makeConstraints { make in
            make.centerY.equalToSuperview()
            make.right.equalToSuperview().offset(-16)
            make.width.height.equalTo(44)
        }
        
        topBarView.closeButtonClickEvent = { [weak self] in
            self?.closeLive()
        }

        topBarView.zoomButtonClickEvent = { [weak self] in
            YHAnalytics.track("APP_LivePage_ClickWindowPlay")
            if let playbackInfo = self?.playbackInfo, playbackInfo.isFromSaleDetail {
                self?.clearInfo()
                if let nav = self?.navigationController, nav.viewControllers.count > 1 {
                    nav.popViewController(animated: true)
                } else {
                    self?.dismiss(animated: true)
                }
            } else {
                self?.isDisappearFromZoom = true
                self?.quitChatRoom()
                self?.leaveLiveRoom()
//                self?.clearInfo()
                self?.enterFloating()
            }
        }

        topBarView.shareButtonClickEvent = { [weak self] in
            YHAnalytics.track("APP_LivePage_ClickShare")
            self?.shareLive()
        }

        bottomInputBar.giftButtonClickEvent = { [weak self] in
            self?.showGoods()
            YHAnalytics.track("APP_LivePage_ClickProductWindow")
        }
#if DEBUG || TESTENV
        playerView.addSubview(videoStatsLabel)
        videoStatsLabel.snp.makeConstraints { make in
            make.left.equalToSuperview().offset(16)
            make.top.equalToSuperview().offset(100)
            make.width.equalTo(300)
        }
#endif
        
        // 保存初始位置
        originalX = messageListView.frame.origin.x
        // 添加拖拽手势
        let panGesture = UIPanGestureRecognizer(target: self, action: #selector(handlePanGesture(_:)))
        view.addGestureRecognizer(panGesture)
    }

    private func setupStateViewController() {
        isLiveStateOn = true
        // 1. 添加子控制器
        addChild(liveStateVC)
        liveStateVC.view.frame = self.view.bounds
        view.addSubview(liveStateVC.view)
        view.bringSubviewToFront(liveStateVC.view)
        // 2. 使用SnapKit设置约束
        liveStateVC.view.snp.makeConstraints { make in
            make.edges.equalToSuperview()
        }
        // 3. 通知子控制器已被添加到父控制器
//        liveStateVC.didMove(toParent: self)
    }

    // 移除子控制器
    private func removeStateViewController() {
        isLiveStateOn = false
//        liveStateVC.willMove(toParent: nil)
        liveStateVC.view.removeFromSuperview()
//        liveStateVC.removeFromParent()
    }

    private func setupData() {
        viewModel.getLiveDetail(id: liveId) { [weak self] liveDetail, error in
            guard let self = self else { return }

            if let liveDetail = liveDetail {
                self.handleLiveDetailSuccess(liveDetail)
            } else {
                printLog("YHLivePlayerViewController: 请求失败")
                if let errorMsg = error?.errorMsg, !errorMsg.isEmpty {
                    YHHUD.flash(message: errorMsg)
                }
                return
            }
        }
    }

    private func handleLiveDetailSuccess(_ liveDetail: YHLiveDetailModel, needJoinIMRoom: Bool = true, needJoinLiveChannel: Bool = true) {
        // 更新顶部栏信息
        topBarView.setupTopBarView(
            headUrl: liveDetail.avatar,
            nickname: liveDetail.account,
            count: liveDetail.access_num
        )
        
//        blurredView.setImageUrl(liveDetail.avatar) { [weak self] flag in
//            self?.bottomImageView.isHidden = flag
//            self?.blurredView.isHidden = !flag
//        }
        
        playbackInfo?.channelId = liveDetail.rtmp_channel
        playbackInfo?.token = liveDetail.token
        playbackInfo?.title = liveDetail.live_title
        playbackInfo?.uid = UInt(liveDetail.user_id)
        messageListView.anchorName = liveDetail.hxNickname
        let isOnLive = liveDetail.getLiveState() == .onLive || liveDetail.getLiveState() == .stop
        if needJoinLiveChannel {
            if !liveDetail.rtmp_channel.isEmpty, !liveDetail.token.isEmpty, let uid = playbackInfo?.uid, let player = player, isOnLive {
                YHPlayerManager.shared.joinChannel(for: player, token: liveDetail.token, channelId: liveDetail.rtmp_channel, uid: uid, view: playerView, defaultMuted: false)
            } else if !isOnLive {
                if let player = player {
                    changePortrait()
                    YHPlayerManager.shared.leaveChannel(for: player)
                }
            }
        }
        // 如果没有预设roomId，使用接口返回的roomId
        if roomId == nil, needJoinIMRoom {
            roomId = liveDetail.roomId
            setupChatRoom(roomId: liveDetail.roomId)
        }
        bottomInputBar.updateGiftCount(liveDetail.goods.count)
        if liveDetail.getLiveState() != .onLive {
            if !isLiveStateOn {
                setupStateViewController()
            }
            changePortrait()
            liveStateVC.setupData(liveDetail: liveDetail)
        } else {
            removeStateViewController()
        }
    }

    private func setupChatRoom(roomId: String) {
        // 初始化聊天室
        joinChatRoom(roomId: roomId)
    }

    private func setupLiveNotifications() {
        NotificationCenter.default.addObserver(
            self,
            selector: #selector(didUserEnterRoomMessages(_:)),
            name: YHIMHelper.didUserEnterRoomMessages,
            object: nil
        )
        
        NotificationCenter.default.addObserver(
            self,
            selector: #selector(didChatManagerReceiveMessages(_:)),
            name: YHIMHelper.didChatManagerReceiveMessages,
            object: nil
        )

        NotificationCenter.default.addObserver(
            self,
            selector: #selector(didLoginEaseIMSuccess),
            name: YHIMHelper.didLoginEaseIMSuccess,
            object: nil
        )

        NotificationCenter.default.addObserver(
            self,
            selector: #selector(didLogOutEaseIM),
            name: YHIMHelper.didLogOutEaseIM,
            object: nil
        )

        NotificationCenter.default.addObserver(self, selector: #selector(didLoginYH), name: YhConstant.YhNotification.didLoginSuccessNotifiction, object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(didLogOutYH), name: YhConstant.YhNotification.didLogoutSuccessNotifiction, object: nil)
    }

    // MARK: - Public Methods

//    func play(url: String, title: String? = nil) {
//        currentPlayingURL = url
//        currentVideoTitle = title
//        YHPlayerManager.shared.play(url: url, inView: playerView, title: title)
//    }
    
    // 是否可旋转
    func canDoRotateFunc() -> Bool {
        return true // 直播暂停时有其他问题 先放开
        if let model = viewModel.liveDetailModel {
            if model.status == 1 {
                if model.stream_status == 1 || model.stream_status == 2 {
                    return true
                }
            }
        }
        return false
    }

    func enterFloating() {
        guard let playbackInfo = playbackInfo else {
            return
        }
        YHPlayerManager.shared.enterFloating(from: self, playbackInfo: playbackInfo)
    }

    // MARK: - Chat Room Methods

    private func joinChatRoom(roomId: String) {
        func joinRoom(retryCount: Int) {
            YHIMHelper.shared.joinChatRoom(roomID: roomId, leaveOtherRooms: true) { [weak self] error in
                guard let self = self else { return }
                if let error = error, retryCount <= self.maxRetryCount {
                    printLog("joinChatRoom: \(error)")
                    self.logJoinChatRoomError(roomId: roomId, errorMsg: error.errorDescription ?? "")
                    DispatchQueue.main.asyncAfter(deadline: .now() + TimeInterval(5 * retryCount)) {
                        YHIMHelper.shared.newRegisterAndLoginCurrentUser { _ in
                            joinRoom(retryCount: retryCount + 1)
                        }
                    }
                } else {
                    self.loadHistoryMessages(roomId: roomId)
                }
            }
        }
        
        if !YHIMHelper.shared.isCurrentUserLogin {
            YHIMHelper.shared.newRegisterAndLoginCurrentUser { _ in
                joinRoom(retryCount: 0)
            }
        } else {
            joinRoom(retryCount: 0)
        }
    }
    
    private func logJoinChatRoomError(roomId: String, errorMsg: String) {
        let dic: [AnyHashable: Any] = [
            "type": "joinChatroomError",
            "chatroomId": roomId,
            "channelId": playbackInfo?.channelId ?? "",
            "uid": playbackInfo?.uid ?? 0,
            "errorMsg": errorMsg
        ]
        YHAliYunLogManager.shared.addModuleName(.logTypeError, remark: dic)
    }

    private func loadHistoryMessages(roomId: String) {
        YHIMHelper.shared.fetchHistoryMessage(roomID: roomId) { [weak self] list, _ in
            guard let self = self, let messages = list else { return }
            self.messageListView.clearMessages()
            if let tips = self.viewModel.liveDetailModel?.tips, tips.count > 0 {
                self.appendTipsMessage(tips)
            }
            self.appendHistoryMessages(messages)
        }
    }

    private func leaveLiveRoom() {
        guard YHLoginManager.shared.isLogin() else {
            return
        }
        leaveLiveRoom(id: liveId) { _, error in
            if let error = error {
                printLog("leaveLiveRoom: \(error)")
            } else {
                printLog("leaveLiveRoom: success")
            }
        }
    }

    private func quitChatRoom() {
        guard let roomId = roomId else { return }

        YHIMHelper.shared.quitChatRoom(roomID: roomId) { error in
            if let error = error {
                printLog("quitChatRoom: \(error)")
            } else {
                printLog("quitChatRoom: success")
            }
        }
    }
    
    private func clearInfo() {
        quitChatRoom()
        leaveLiveRoom()
        // YHPlayerManager.shared.stop(type: .main)
        if let player = player {
            changePortrait()
            YHPlayerManager.shared.leaveChannel(for: player)
        }
    }

    private func closeLive() {
        clearInfo()
        if let nav = navigationController, nav.viewControllers.count > 1 {
            nav.popViewController(animated: true)
        } else {
            dismiss(animated: true)
        }
    }

    private func shareLive() {
        guard let liveModel = viewModel.liveDetailModel else {
            return
        }
        
        DispatchQueue.global().async {
            var param: [String: String] = ["LiveID": String(self.liveId)]
            if let userId = YHLoginManager.shared.userModel?.id, userId.count > 0 {
                param["fromUserId"] = userId
                param["sourceType"] = "1"
            }
            YHShareManager.shared.createMutilShareShortUrl(type: 1, param: param) { shortUrl, _ in
                if let url = shortUrl {
                    let tmpT = url.base64Encoded ?? ""// 对deepLink使用 base64编码
                    var oldUrl = liveModel.live_h5_url
                    if oldUrl.contains("?") {
                        oldUrl += "&appDeepLink=\(tmpT)"
                    } else {
                        oldUrl += "?appDeepLink=\(tmpT)"
                    }
                    
                    YHShareAlertView.show(image: liveModel.live_image, title: "@" + liveModel.account, subMessage: liveModel.live_title, linkUrl: oldUrl, isLive: true, fromAiSale: true)
                    return
                }
                YHShareAlertView.show(image: liveModel.live_image, title: "@" + liveModel.account, subMessage: liveModel.live_title, linkUrl: liveModel.live_h5_url, isLive: true, fromAiSale: true)
            }
        }
    }

    private func showGoods() {
        let list = viewModel.liveDetailModel?.goods ?? []
        let view = YHLiveShopView.show { [weak self] index in
            guard list.count > index else {
                return
            }
            let model = list[index]
            self?.gotoH5GoodsDetail(id: model.id)
        }
        view.fromPage = .live
        view.dataSource = list
        view.closeEvent = { [weak self] in
            self?.goodsListView = nil
        }
        view.buyData = { [weak self] index in
            guard list.count > index else {
                return
            }
            let model = list[index]
            self?.createOrder(id: model.id)
        }
        goodsListView = view
    }

    private func createOrder(id: Int) {
        YHHUD.show(.progress(message: "加载中..."))
        viewModel.createOrder(source: 1, sourceId: liveId, productId: id) { [weak self] orderModel, error in
            YHHUD.hide()
            guard let self = self else {
                return
            }
            guard let orderModel = orderModel else {
                if let errorMsg = error?.errorMsg, errorMsg.count > 0 {
                    YHHUD.flash(message: errorMsg)
                }
                return
            }
            var url = YHBaseUrlManager.shared.curH5URL() + "superAppBridge.html#/order/order-confirm" + "?id=\(orderModel.id)"
            if YHLoginManager.shared.isLogin() {
                let token = YHLoginManager.shared.h5Token
                let urlHasParam = String.hasQueryParameters(urlString: url)
                if urlHasParam {
                    url = url + "&param=" + token
                } else {
                    url = url + "?param=" + token
                }
            }
            var tUrl = url
            if !url.contains("navigationH=") {
                tUrl = url + "?navigationH=\(k_Height_NavigationtBarAndStatuBar)"
                if url.contains("?") {
                    tUrl = url + "&navigationH=\(k_Height_NavigationtBarAndStatuBar)"
                }
            }
            let vc = YHH5WebViewVC()
            vc.url = tUrl
            vc.isHideNavigationBar = false
            vc.isFullScreenFlag = false
            goodsListView?.dismiss()
            navigationController?.pushViewController(vc)
        }
    }

    private func gotoH5GoodsDetail(id: Int) {
        var url = YHBaseUrlManager.shared.curH5URL() + "superAppBridge.html#/goods/sales-detail" + "?id=\(id)"
        if YHLoginManager.shared.isLogin() {
            let token = YHLoginManager.shared.h5Token
            let urlHasParam = String.hasQueryParameters(urlString: url)
            if urlHasParam {
                url = url + "&param=" + token
            } else {
                url = url + "?param=" + token
            }
        }
        var tUrl = url
        if !url.contains("navigationH=") {
            tUrl = url + "?navigationH=\(k_Height_NavigationtBarAndStatuBar)"
            if url.contains("?") {
                tUrl = url + "&navigationH=\(k_Height_NavigationtBarAndStatuBar)"
            }
        }
        let vc = YHH5WebViewVC()
        vc.url = tUrl
        vc.isHideNavigationBar = false
        goodsListView?.dismiss()
        navigationController?.pushViewController(vc)
    }

    // MARK: - Message Handling

    private func handleMessageInput(text: String, controller: YHMessageInputViewController) {
        guard checkLogin(),
              let roomId = roomId else { return }

        YHIMHelper.shared.sendMessage(roomID: roomId, sendText: text) { [weak self] message, error in
            guard let self = self else { return }

            if let message = message {
                controller.updateText("")
                controller.closeKeyboard(nil)
                self.appendHistoryMessages([message])
            } else if let error = error {
                switch error.code {
                case .moderationFailed:
                    YHHUD.flash(message: "发送了敏感信息")
                case .userPermissionDenied:
                    YHHUD.flash(message: "您已被拉黑")
                default:
//                    for test hjl
                    YHHUD.flash(message: "发送失败")
                }
            }
        }
    }

    private func appendHistoryMessages(_ newMessages: [EMChatMessage]) {
        messageQueue.async {
            let filterMessages = newMessages.filter { message in
                if let body = message.body as? EMTextMessageBody, body.type == .text {
                    return true
                }
                return false
            }
            DispatchQueue.main.async {
                self.messageListView.addMessages(filterMessages)
            }
        }
    }

    private func appendTipsMessage(_ tips: String) {
        messageQueue.async {
            let body = EMCustomMessageBody(event: YHChatRoomCustomLocal.tipsEvent, customExt: [YHChatRoomCustomLocal.tipsKey: tips])
            let message = EMChatMessage(conversationID: self.roomId ?? "", body: body, ext: nil)
            message.chatType = .chatRoom
            DispatchQueue.main.async {
                self.messageListView.addMessages([message])
            }
        }
    }
    
    private func checkLogin() -> Bool {
        if !YHLoginManager.shared.isLogin() {
            YHOneKeyLoginManager.shared.oneKeyLogin()
            return false
        }
        return true
    }

    // MARK: - Notification Handlers
    @objc private func didChatManagerReceiveMessages(_ note: Notification) {
        guard let messages = note.object as? [EMChatMessage],
              let message = messages.first,
              message.conversationId == roomId else {
            return
        }
        appendHistoryMessages(messages)
        messages.forEach { message in
            if let body = message.body as? EMCustomMessageBody, let event = body.event, let roomCustomEvent = YHChatRoomCustomEvent(rawValue: event) {
                DispatchQueue.main.async {
                    self.updateLiveDetailWith(event: roomCustomEvent)
                }
            }
        }
    }
    
    // 用户进入直播间通知
    @objc private func didUserEnterRoomMessages(_ note: Notification) {
        guard let messages = note.object as? String else {
            return
        }
        appendUserEnterRoomMessage(messages)
    }
    
    private func appendUserEnterRoomMessage(_ userName: String) {
        messageQueue.async {
            let body = EMCustomMessageBody(event: YHChatRoomCustomLocal.userEnterRoomEvent, customExt: [YHChatRoomCustomLocal.userEnterRoomEvent: userName])
            let message = EMChatMessage(conversationID: self.roomId ?? "", body: body, ext: nil)
            message.chatType = .chatRoom
            DispatchQueue.main.async {
                self.messageListView.addMessages([message])
            }
        }
    }

    private func updateLiveDetailWith(event: YHChatRoomCustomEvent) {
        viewModel.getLiveDetail(id: liveId) { [weak self] liveDetail, _ in
            guard let self = self else { return }
            if let liveDetail = liveDetail {
                switch event {
                case .liveStart:
                    self.handleLiveDetailSuccess(liveDetail, needJoinIMRoom: false, needJoinLiveChannel: true)
                case .liveEnd:
                    self.handleLiveDetailSuccess(liveDetail, needJoinIMRoom: false, needJoinLiveChannel: true)
                case .livePause:
                    self.handleLiveDetailSuccess(liveDetail, needJoinIMRoom: false, needJoinLiveChannel: false)
                case .liveResume:
                    self.handleLiveDetailSuccess(liveDetail, needJoinIMRoom: false, needJoinLiveChannel: true)
                case .liveGoodsRefresh:
                    self.handleLiveDetailSuccess(liveDetail, needJoinIMRoom: false, needJoinLiveChannel: false)
                    self.goodsListView?.dataSource = liveDetail.goods
                }
            } else {
                printLog("YHLivePlayerViewController: 请求失败")
//                if let errorMsg = error?.errorMsg, !errorMsg.isEmpty {
//                    YHHUD.flash(message: errorMsg)
//                }
            }
        }
    }

    @objc private func didLoginYH() {
        if YHLoginManager.shared.isLogin() {
            joinLiveRoom(id: liveId, callback: { _, _ in })
        }
    }

    @objc private func didLogOutYH() {
        //
    }

    @objc private func didLoginEaseIMSuccess() {
        if let roomId = roomId {
            joinChatRoom(roomId: roomId)
        }
    }

    @objc private func didLogOutEaseIM() {
        quitChatRoom()
    }
    
    @objc private func messageListStateButtonClicked(_ button: UIButton) {
        if isMessageListHidden {
            showWithAnimation()
        } else {
            hideWithAnimation()
        }
    }
    
    /// 设置定时器
    private func setupTimer() {
        timer = DispatchSource.makeTimerSource(queue: .main)
        timer?.schedule(deadline: .now(), repeating: .seconds(timeCount))
        timer?.setEventHandler(handler: { [weak self] in
            guard let self = self else {
                return
            }
            viewModel.getLivePeople(id: liveId) { [weak self] livePeople, _ in
                guard let self = self else {
                    return
                }
                DispatchQueue.main.async {
                    if let num = livePeople?.num, num.count > 0 {
                        self.topBarView.updateCountLabel(num)
                    }
                }
            }
        })
        timer?.resume()
    }
    
    /// 取消定时器
    private func cancelTimer() {
        if timer != nil {
            timer?.cancel()
            timer = nil
        }
    }
}

// MARK: - YHPlayerDelegate

extension YHLivePlayerViewController: YHPlayerDelegate {
    func player(_ player: YHPlayer, didChangedTo positionMs: Int, atTimestamp timestampMs: TimeInterval) {
        DispatchQueue.main.async {
            //
        }
    }

    func player(_ player: YHPlayer, didChangedToState state: AgoraMediaPlayerState, reason: AgoraMediaPlayerReason) {
        DispatchQueue.main.async {
            // 更新通用UI状态
            switch state {
            case .playing:
                // 直播开始时的特殊处理
                break
            case .paused, .stopped:
                // 直播开始时的特殊处理
                break
            case .failed:
                break
                // self.showAlert(message: "播放失败，错误原因：\(reason.rawValue)")
            default:
                break
            }
        }
    }

    func player(_ player: YHPlayer, didChangedToPosition position: Int) {
    }

    func player(_ player: YHPlayer, didReceiveVideoSize size: CGSize) {
        // 处理视频尺寸变化，如果需要的话
    }
    
    func player(_ player: YHPlayer, remoteVideoStats stats: AgoraRtcRemoteVideoStats) {
#if DEBUG || TESTENV
        DispatchQueue.main.async {
            self.videoStatsLabel.text = "width:\(stats.width),height:\(stats.height)\nreceivedBitrate:\(stats.receivedBitrate)\nreceivedFrameRate:\(stats.receivedFrameRate)\ndecoderOutputFrameRate:\(stats.decoderOutputFrameRate)\nrendererOutputFrameRate:\(stats.rendererOutputFrameRate)\nframeLossRate:\(stats.frameLossRate)"
        }
#endif
    }
}

// MARK: - Notifications
extension YHLivePlayerViewController {
    private func setupLifeCycleNotifications() {
        NotificationCenter.default.addObserver(
            self,
            selector: #selector(handleAppDidEnterBackground),
            name: UIApplication.didEnterBackgroundNotification,
            object: nil
        )
        
        NotificationCenter.default.addObserver(
            self,
            selector: #selector(handleAppWillEnterForeground),
            name: UIApplication.willEnterForegroundNotification,
            object: nil
        )
        /*
        NotificationCenter.default.addObserver(
            self,
            selector: #selector(handleAudioSessionInterruption),
            name: AVAudioSession.interruptionNotification,
            object: nil
        )
         */
    }
    
    @objc private func handleAppDidEnterBackground() {
        leaveLiveRoom()
    }
    
    @objc private func handleAppWillEnterForeground() {
        if YHLoginManager.shared.isLogin() {
            joinLiveRoom(id: liveId, callback: { _, _ in })
            if let roomId = roomId {
                setupChatRoom(roomId: roomId)
            }
        }
    }
    /*
    @objc private func handleAudioSessionInterruption(_ notification: Notification) {
        guard let userInfo = notification.userInfo,
              let typeValue = userInfo[AVAudioSessionInterruptionTypeKey] as? UInt,
              let type = AVAudioSession.InterruptionType(rawValue: typeValue) else {
            return
        }
        
        switch type {
        case .began:
            if let player = player {
                YHPlayerManager.shared.leaveChannel(for: player)
            }
        case .ended:
            if let optionsValue = userInfo[AVAudioSessionInterruptionOptionKey] as? UInt {
                let options = AVAudioSession.InterruptionOptions(rawValue: optionsValue)
                if options.contains(.shouldResume) {
                    if let liveDetail = viewModel.liveDetailModel, !liveDetail.rtmp_channel.isEmpty, !liveDetail.token.isEmpty, let uid = playbackInfo?.uid, let player = player {
                        YHPlayerManager.shared.joinChannel(for: player, token: liveDetail.token, channelId: liveDetail.rtmp_channel, uid: uid, view: playerView, defaultMuted: false)
                    }
                }
            }
        @unknown default:
            break
        }
    }
    */
}

extension YHLivePlayerViewController {
    // MARK: - Gesture Handling
    
    @objc private func closeButtonClicked() {
        closeLive()
    }

    // 切换横屏
    @objc private func playeButtonClicked() {
        guard let windowScene = view.window?.windowScene else { return }

        // 判断当前方向并确定新的方向
        let newOrientation: UIInterfaceOrientation
        if windowScene.interfaceOrientation.isLandscape {
            newOrientation = .portrait
        } else {
            newOrientation = .landscapeRight
        }

        // 请求几何更新
        let orientationMask: UIInterfaceOrientationMask = newOrientation == .portrait ? .portrait : .landscape
        
        if newOrientation == .portrait {
            bottomInputBar.isHidden = false
            messageListView.isHidden = false
            messageListStateButton.isHidden = false
            closeButton.isHidden = false
            topBarView.isHidden = false
            self.playButton.setImage(UIImage(named: "live_play_interface_orientatio"), for: .normal)
        } else {
            bottomInputBar.isHidden = true
            messageListView.isHidden = true
            messageListStateButton.isHidden = true
            closeButton.isHidden = true
            topBarView.isHidden = true
            self.playButton.setImage(UIImage(named: "live_play_interface_orientatio_up"), for: .normal)
        }
        
        if #available(iOS 16.0, *) {
            windowScene.requestGeometryUpdate(.iOS(interfaceOrientations: orientationMask))
        } else {
            let orientation: UIInterfaceOrientation = orientationMask == .portrait ? .portrait : .landscapeRight
            UIDevice.current.setValue(orientation.rawValue, forKey: "orientation")
            UIViewController.attemptRotationToDeviceOrientation()
        }
    }
    
    // 切换成竖屏
    func changePortrait() {
        guard let windowScene = view.window?.windowScene else { return }
        let orientationMask: UIInterfaceOrientationMask = .portrait
        if #available(iOS 16.0, *) {
            windowScene.requestGeometryUpdate(.iOS(interfaceOrientations: orientationMask))
        } else {
            let orientation: UIInterfaceOrientation = .portrait
            UIDevice.current.setValue(orientation.rawValue, forKey: "orientation")
            UIViewController.attemptRotationToDeviceOrientation()
        }
        bottomInputBar.isHidden = false
        messageListView.isHidden = false
        messageListStateButton.isHidden = false
        closeButton.isHidden = false
        topBarView.isHidden = false
        self.playButton.setImage(UIImage(named: "live_play_interface_orientatio"), for: .normal)
    }
    
    func changeLandscape() {
        guard let windowScene = view.window?.windowScene else { return }
        let orientationMask: UIInterfaceOrientationMask = .landscape
        if #available(iOS 16.0, *) {
            windowScene.requestGeometryUpdate(.iOS(interfaceOrientations: orientationMask))
        } else {
            let orientation: UIInterfaceOrientation = .landscapeRight
            UIDevice.current.setValue(orientation.rawValue, forKey: "orientation")
            UIViewController.attemptRotationToDeviceOrientation()
        }
        bottomInputBar.isHidden = true
        messageListView.isHidden = true
        messageListStateButton.isHidden = true
        closeButton.isHidden = true
        topBarView.isHidden = true
        self.playButton.setImage(UIImage(named: "live_play_interface_orientatio_up"), for: .normal)
    }
    
    @objc func orientationDidChange() {
        let orientation = UIDevice.current.orientation
        switch orientation {
        case .portrait:
            changePortrait()
        default:
            if isLiveStateOn {
                changePortrait()
            } else {
                changeLandscape()
            }
        }
    }
    
    @objc private func handlePanGesture(_ gesture: UIPanGestureRecognizer) {
        let translation = gesture.translation(in: view)
        
        switch gesture.state {
        case .began:
            break
            
        case .changed:
            if isMessageListHidden {
                // 隐藏状态下，只允许向左拖拽显示
                if translation.x <= 0 {
                    // 计算新位置（从隐藏位置向左拖）
                    let newX = (originalX + view.frame.width) + translation.x
                    // 限制不能拖过原始位置
                    messageListView.frame.origin.x = max(originalX, newX)
                    topBarView.frame.origin.x = max(originalX, newX)
                    bottomInputBar.frame.origin.x = max(originalX, newX)
                }
            } else {
                // 显示状态下，只允许向右拖拽隐藏
                if translation.x >= 0 {
                    // 计算新位置（从原始位置向右拖）
                    let newX = originalX + translation.x
                    // 限制最大拖拽距离
                    messageListView.frame.origin.x = min(originalX + view.frame.width, newX)
                    
                    topBarView.frame.origin.x = min(originalX + view.frame.width, newX)
                    bottomInputBar.frame.origin.x = min(originalX + view.frame.width, newX)
                }
            }
            
        case .ended, .cancelled:
//            let velocity = gesture.velocity(in: view)
            let translation = gesture.translation(in: view)
            
            if isMessageListHidden {
                // 当前是隐藏状态，判断是否需要显示
                if translation.x < -view.frame.width / 3 {
                    // 向左速度够快或拖动距离够大，显示
                    showWithAnimation()
                } else {
                    // 保持隐藏
                    hideWithAnimation()
                }
            } else {
                // 当前是显示状态，判断是否需要隐藏
                if translation.x > view.frame.width / 3 {
                    // 向右速度够快或拖动距离够大，隐藏
                    hideWithAnimation()
                } else {
                    // 保持显示
                    showWithAnimation()
                }
            }
            
        default:
            break
        }
    }

    private func hideWithAnimation() {
        isMessageListHidden = true
        messageListStateButton.isSelected = true
        UIView.animate(withDuration: 0.3,
                      delay: 0,
                      options: .curveEaseOut) {
            self.messageListView.frame.origin.x = self.view.frame.width
            self.topBarView.frame.origin.x =  self.view.frame.width
            self.bottomInputBar.frame.origin.x = self.view.frame.width
            self.closeButton.isHidden = false
            guard let windowScene = self.view.window?.windowScene else { return }
            if windowScene.interfaceOrientation.isLandscape {
                self.closeButton.isHidden = true
            }
            
        }
    }

    private func showWithAnimation() {
        isMessageListHidden = false
        messageListStateButton.isSelected = false
        UIView.animate(withDuration: 0.3,
                      delay: 0,
                      options: .curveEaseIn) {
            self.messageListView.frame.origin.x = 16
            self.topBarView.frame.origin.x = 0
            self.bottomInputBar.frame.origin.x = 0
            self.closeButton.isHidden = false
            guard let windowScene = self.view.window?.windowScene else { return }
            if windowScene.interfaceOrientation.isLandscape {
                self.closeButton.isHidden = true
            }
        }
    }
}
