//
//  LiveRoomViewV2.swift
//  SodaLive
//
//  Created by klaus on 2024/01/17.
//

import SwiftUI
import Kingfisher
import SDWebImageSwiftUI

struct LiveRoomViewV2: View {
    
    @StateObject var keyboardHandler = KeyboardHandler()
    @StateObject var viewModel = LiveRoomViewModel()
    
    @State private var textHeight: CGFloat = .zero
    @State private var menuTextHeight: CGFloat = .zero
    
    var body: some View {
        ZStack {
            Color.black.edgesIgnoringSafeArea(.all)
            
            VStack(spacing: 0) {
                if let liveRoomInfo = viewModel.liveRoomInfo {
                    if liveRoomInfo.creatorId == UserDefaults.int(forKey: .userId) {
                        LiveRoomInfoHostView(
                            title: liveRoomInfo.title,
                            totalHeart: viewModel.totalHeartCount,
                            totalDonationCan: viewModel.totalDonationCan,
                            participantsCount: liveRoomInfo.participantsCount,
                            isOnBg: viewModel.isBgOn,
                            isOnNotice: viewModel.isShowNotice,
                            isOnMenuPan: viewModel.isShowMenuPan,
                            isOnSignature: viewModel.isSignatureOn,
                            isShowMenuPanButton: !liveRoomInfo.menuPan.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty,
                            creatorId: liveRoomInfo.creatorId,
                            creatorNickname: liveRoomInfo.creatorNickname,
                            creatorProfileUrl: liveRoomInfo.creatorProfileUrl,
                            speakerList: liveRoomInfo.speakerList,
                            muteSpeakerList: viewModel.muteSpeakers,
                            activeSpeakerList: viewModel.activeSpeakers,
                            isAdult: liveRoomInfo.isAdult,
                            onClickQuit: {
                                viewModel.isShowLiveEndPopup = true
                            },
                            onClickToggleBg: {
                                viewModel.isBgOn.toggle()
                            },
                            onClickShare: {
                                viewModel.shareRoom()
                            },
                            onClickEdit: {
                                viewModel.isShowEditRoomInfoDialog = true
                            },
                            onClickProfile: {
                                if $0 != UserDefaults.int(forKey: .userId) {
                                    viewModel.getUserProfile(userId: $0)
                                }
                            },
                            onClickNotice: {
                                viewModel.isShowNotice.toggle()
                            },
                            onClickMenuPan: {
                                viewModel.isShowMenuPan.toggle()
                            },
                            onClickTotalHeart: {
                                viewModel.isShowHeartRankingPopup = true
                            },
                            onClickTotalDonation: {
                                viewModel.isShowDonationRankingPopup = true
                            },
                            onClickParticipants: {
                                viewModel.isShowProfileList = true
                            },
                            onClickToggleSignature: {
                                viewModel.isSignatureOn.toggle()
                            }
                        )
                    } else {
                        LiveRoomInfoGuestView(
                            title: liveRoomInfo.title,
                            totalHeart: viewModel.totalHeartCount,
                            totalDonationCan: viewModel.totalDonationCan,
                            isOnBg: viewModel.isBgOn,
                            isOnNotice: viewModel.isShowNotice,
                            isOnMenuPan: viewModel.isShowMenuPan,
                            isOnSignature: viewModel.isSignatureOn,
                            isShowMenuPanButton: !liveRoomInfo.menuPan.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty,
                            creatorId: liveRoomInfo.creatorId,
                            creatorNickname: liveRoomInfo.creatorNickname,
                            creatorProfileUrl: liveRoomInfo.creatorProfileUrl,
                            speakerList: liveRoomInfo.speakerList,
                            muteSpeakerList: viewModel.muteSpeakers,
                            activeSpeakerList: viewModel.activeSpeakers,
                            isFollowing: liveRoomInfo.isFollowing,
                            isAdult: liveRoomInfo.isAdult,
                            onClickQuit: {
                                viewModel.isShowQuitPopup = true
                            },
                            onClickToggleBg: {
                                viewModel.isBgOn.toggle()
                            },
                            onClickShare: {
                                viewModel.shareRoom()
                            },
                            onClickFollow: {
                                if $0 {
                                    viewModel.creatorUnFollow()
                                } else {
                                    viewModel.creatorFollow()
                                }
                            },
                            onClickProfile: {
                                if $0 != UserDefaults.int(forKey: .userId) {
                                    viewModel.getUserProfile(userId: $0)
                                }
                            },
                            onClickNotice: {
                                viewModel.isShowNotice.toggle()
                            },
                            onClickMenuPan: {
                                viewModel.isShowMenuPan.toggle()
                            },
                            onClickTotalHeart: {
                                viewModel.isShowHeartRankingPopup = true
                            },
                            onClickTotalDonation: {
                                viewModel.isShowDonationRankingPopup = true
                            },
                            onClickChangeListener: {
                                viewModel.setListener()
                            },
                            onClickToggleSignature: {
                                viewModel.isSignatureOn.toggle()
                            }
                        )
                    }
                    
                    ZStack(alignment: .topLeading) {
                        Rectangle()
                            .foregroundColor(.gray22)
                            .frame(height: 16)
                            .frame(maxWidth: .infinity)
                        
                        ScrollViewReader { proxy in
                            ZStack(alignment: .bottom) {
                                ZStack {
                                    if viewModel.isBgOn {
                                        KFImage(URL(string: liveRoomInfo.coverImageUrl))
                                            .resizable()
                                            .scaledToFit()
                                            .frame(maxWidth: .infinity, maxHeight: .infinity)
                                    }
                                    
                                    Rectangle()
                                        .foregroundColor(.black.opacity(0.25))
                                        .frame(maxWidth: .infinity)
                                    
                                    ScrollView(.vertical, showsIndicators: false) {
                                        scrollObservableView
                                        
                                        if !viewModel.changeIsAdult || UserDefaults.bool(forKey: .auth) {
                                            LiveRoomChatView(messages: viewModel.messages) {
                                                if $0 != UserDefaults.int(forKey: .userId) {
                                                    viewModel.getUserProfile(userId: $0)
                                                }
                                            }
                                            .frame(width: screenSize().width)
                                            .rotationEffect(Angle(degrees: 180))
                                            .valueChanged(value: viewModel.messageChangeFlag) { _ in
                                                if viewModel.offset - viewModel.originOffset > (56.7 * 2) {
                                                    viewModel.isShowingNewChat = true
                                                }
                                            }
                                        }
                                    }
                                    .rotationEffect(Angle(degrees: 180))
                                    .onTapGesture { hideKeyboard() }
                                    .onPreferenceChange(ScrollOffsetKey.self) {
                                        viewModel.setOffset($0)
                                    }
                                    .padding(.bottom, 70)
                                }
                                .padding(.top, 16)
                                
                                VStack(alignment: .trailing, spacing: 0) {
                                    Spacer()
                                    
                                    LiveRoomRightBottomButton(
                                        imageName: viewModel.isSpeakerMute ? "ic_speaker_off" : "ic_speaker_on",
                                        onClick: { viewModel.toggleSpeakerMute() }
                                    )
                                    .padding(.bottom, 40)
                                    .padding(.trailing, 13.3)
                                    
                                    ZStack(alignment: .bottom) {
                                        VStack(spacing: 13.3) {
                                            if viewModel.role == .SPEAKER {
                                                LiveRoomRightBottomButton(
                                                    imageName: viewModel.isMute ? "ic_mic_off" : "ic_mic_on",
                                                    onClick: { viewModel.toggleMute() }
                                                )
                                            }
                                            
                                            LiveRoomRightBottomButton(
                                                imageName: "ic_donation_message_list",
                                                onClick: {
                                                    DispatchQueue.main.async {
                                                        hideKeyboard()
                                                        viewModel.isShowDonationMessagePopup = true
                                                    }
                                                }
                                            )
                                            
                                            if liveRoomInfo.creatorId == UserDefaults.int(forKey: .userId) {
                                                LiveRoomRightBottomButton(
                                                    imageName: "ic_roulette_settings",
                                                    onClick: {
                                                        DispatchQueue.main.async {
                                                            hideKeyboard()
                                                            viewModel.isShowRouletteSettings = true
                                                        }
                                                    }
                                                )
                                            } else {
                                                if viewModel.isActiveRoulette {
                                                    LiveRoomRightBottomButton(
                                                        imageName: "ic_roulette",
                                                        onClick: {
                                                            DispatchQueue.main.async {
                                                                hideKeyboard()
                                                                viewModel.showRoulette()
                                                            }
                                                        }
                                                    )
                                                }
                                            }
                                            
                                            if liveRoomInfo.creatorId != UserDefaults.int(forKey: .userId) {
                                                LiveRoomRightBottomButton(
                                                    imageName: "ic_donation",
                                                    onClick: {
                                                        DispatchQueue.main.async {
                                                            hideKeyboard()
                                                            viewModel.isShowDonationPopup = true
                                                        }
                                                    }
                                                )
                                            }
                                            
                                            if liveRoomInfo.creatorId != UserDefaults.int(forKey: .userId) {
                                                LiveRoomRightBottomButton(
                                                    imageName: "ic_heart_pink",
                                                    onClick: { viewModel.likeHeart() }
                                                )
                                            }
                                        }
                                        
                                        ZStack {
                                            ForEach(viewModel.hearts) { heart in
                                                LiveRoomHeartView(heart: heart)
                                                    .offset(x: heart.offsetX, y: heart.offsetY)
                                                    .opacity(heart.opacity)
                                            }
                                        }.padding(.bottom, 40)
                                    }
                                    .padding(.trailing, 13.3)
                                    
                                    LiveRoomInputChatView {
                                        viewModel.sendMessage(chatMessage: $0) {
                                            viewModel.isShowingNewChat = false
                                            proxy.scrollTo(viewModel.messages.count - 1, anchor: .center)
                                        }
                                        
                                        return true
                                    }
                                    .padding(.bottom, 10)
                                }
                                
                                if viewModel.isShowingNewChat {
                                    LiveRoomNewChatView{
                                        viewModel.isShowingNewChat = false
                                        proxy.scrollTo(viewModel.messages.count - 1, anchor: .center)
                                    }.padding(.bottom, 70)
                                }
                                
                                if viewModel.isSignatureOn && viewModel.signatureImageUrl.trimmingCharacters(in: .whitespacesAndNewlines).count > 0 {
                                    VStack {
                                        Spacer()
                                        
                                        AnimatedImage(url: URL(string: viewModel.signatureImageUrl))
                                            .resizable()
                                            .aspectRatio(contentMode: .fit)
                                            .frame(width: screenSize().width - 64)
                                        
                                        Spacer()
                                        Spacer()
                                        Spacer()
                                    }
                                }
                                
                                if let signature = viewModel.signature, viewModel.isSignatureOn {
                                    VStack {
                                        Spacer()
                                        
                                        AnimatedImage(url: URL(string: signature.imageUrl))
                                            .resizable()
                                            .aspectRatio(contentMode: .fit)
                                            .frame(width: screenSize().width - 64)
                                        
                                        Spacer()
                                        Spacer()
                                        Spacer()
                                    }
                                }
                            }
                        }
                        
                        if let heartNickname = viewModel.heartNickname {
                            LiveRoomHeartDonationChatItemView(nickname: heartNickname)
                                .padding(.top, 16)
                        }
                        
                        if viewModel.isShowNotice {
                            VStack(alignment: .leading, spacing: 0) {
                                Image("ic_notice_triangle")
                                    .padding(.leading, 13.3)
                                
                                VStack(alignment: .leading, spacing: 8) {
                                    Text("[방송공지]")
                                        .font(.custom(Font.bold.rawValue, size: 11.3))
                                        .foregroundColor(.white)
                                    
                                    DetectableTextView(text: liveRoomInfo.notice)
                                        .frame(
                                            width: 280,
                                            height: textHeight > 450 ? 450 : textHeight
                                        )
                                        .onAppear {
                                            self.textHeight = self.estimatedHeight(
                                                for: liveRoomInfo.notice,
                                                width: 280
                                            )
                                        }
                                        .onChange(of: liveRoomInfo.notice) { newText in
                                            self.textHeight = self.estimatedHeight(
                                                for: newText,
                                                width: 280
                                            )
                                        }
                                }
                                .padding(8)
                                .background(Color.gray33)
                                .padding(.horizontal, 13.3)
                                .padding(.bottom, 120)
                            }
                        }
                        
                        if viewModel.isShowMenuPan {
                            VStack(alignment: .leading, spacing: 0) {
                                Image("ic_notice_triangle")

                                ScrollView(.vertical) {
                                    VStack(alignment: .leading, spacing: 8) {
                                        Text("[메뉴판]")
                                            .font(.custom(Font.bold.rawValue, size: 11.3))
                                            .foregroundColor(.white)
                                        
                                        Text(liveRoomInfo.menuPan)
                                            .font(.custom(Font.light.rawValue, size: 11.3))
                                            .foregroundColor(.white)
                                            .lineSpacing(4)
                                    }
                                    .background(GeometryReader { geometry in
                                        Color.clear.preference(key: TextViewHeightKey.self, value: geometry.size.height)
                                    })
                                    .padding(8)
                                }
                                .background(Color.gray33)
                                .frame(height: menuTextHeight > 500 ? 500 : menuTextHeight)
                                .onPreferenceChange(TextViewHeightKey.self) { value in
                                    menuTextHeight = value + 15
                                }
                            }
                            .frame(maxWidth: 350, alignment: .leading)
                            .padding(.leading, 60)
                        }
                    }
                }
            }
            .popup(isPresented: $viewModel.isShowErrorPopup, type: .toast, position: .top, autohideIn: 1.3) {
                GeometryReader { geo in
                    HStack {
                        Spacer()
                        Text(viewModel.errorMessage)
                            .padding(.vertical, 13.3)
                            .frame(width: geo.size.width - 66.7, alignment: .center)
                            .font(.custom(Font.medium.rawValue, size: 12))
                            .background(Color.button)
                            .foregroundColor(Color.white)
                            .multilineTextAlignment(.center)
                            .cornerRadius(20)
                            .padding(.top, 66.7)
                        Spacer()
                    }
                    .onDisappear {
                        if viewModel.liveRoomInfo == nil {
                            viewModel.quitRoom()
                        }
                    }
                }
            }
            .cornerRadius(16.7, corners: [.topLeft, .topRight])
            .offset(y: -(keyboardHandler.keyboardHeight > 0 ? keyboardHandler.keyboardHeight : 0))
            .onAppear {
                UIApplication.shared.isIdleTimerDisabled = true
                UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
                
                viewModel.getMemberCan()
                viewModel.initAgoraEngine()
                viewModel.getRoomInfo()
                viewModel.getBlockedMemberIdList()
                
                NotificationCenter.default.addObserver(
                    forName: UIApplication.willTerminateNotification,
                    object: nil,
                    queue: .main) { _ in
                        viewModel.quitRoom()
                        sleep(3)
                    }
            }
            .onDisappear {
                UIApplication.shared.isIdleTimerDisabled = false
                NotificationCenter.default.removeObserver(self)
            }
            
            ZStack {
                if viewModel.isShowProfilePopup, let liveRoomInfo = viewModel.liveRoomInfo, let selectedProfile = viewModel.selectedProfile {
                    LiveRoomProfileDialog(
                        isShowing: $viewModel.isShowProfilePopup,
                        profileInfo: selectedProfile,
                        creatorId: liveRoomInfo.creatorId,
                        isSpeaker: viewModel.role == .SPEAKER,
                        onClickInviteSpeaker: { inviteSpeaker(peerId: $0) },
                        onClickChangeListener: {
                            if $0 == UserDefaults.int(forKey: .userId) {
                                viewModel.setListener()
                                return
                            }
                            
                            viewModel.changeListener(peerId: $0)
                        }
                    )
                }
                
                if viewModel.isShowDonationPopup {
                    LiveRoomDonationDialogView(isShowing: $viewModel.isShowDonationPopup, isAudioContentDonation: false) { can, message, isSecret in
                        viewModel.donation(can: can, message: message, isSecret: isSecret)
                    }
                }
                
                if viewModel.changeIsAdult && !UserDefaults.bool(forKey: .auth) {
                    SodaDialog(
                        title: "알림",
                        desc: "지금 참여하던 라이브는 '19세 이상' 연령제한이 설정되어 정보통신망 이용촉진 및 정보 보호 등에 관한 법률 및 청소년 보호법의 규정에 의해 만 19세 미만의 청소년은 이용할 수 없습니다.\n마이페이지에서 본인인증 후 다시 이용하시기 바랍니다.",
                        confirmButtonTitle: "확인",
                        confirmButtonAction: {
                            viewModel.quitRoom()
                        }
                    )
                }
                
                if viewModel.isShowNoticeLikeHeart {
                    SodaDialog(
                        title: "안내",
                        desc: "'좋아해요'는 유료 후원입니다.\n" +
                        "클릭시 1캔이 소진됩니다.",
                        confirmButtonTitle: "확인"
                    ) {
                        viewModel.isShowNoticeLikeHeart = false
                    }
                }
                
                if viewModel.isShowQuitPopup {
                    SodaDialog(
                        title: "라이브 나가기",
                        desc: "라이브에서 나가시겠습니까?",
                        confirmButtonTitle: "예",
                        confirmButtonAction: {
                            viewModel.isShowQuitPopup = false
                            viewModel.quitRoom()
                        },
                        cancelButtonTitle: "아니오",
                        cancelButtonAction: {
                            viewModel.isShowQuitPopup = false
                        }
                    )
                }
                
                if viewModel.isShowLiveEndPopup {
                    SodaDialog(
                        title: "라이브 종료",
                        desc: "라이브를 종료하시겠습니까?\n" +
                        "라이브를 종료하면 대화내용은\n" +
                        "저장되지 않고 사라집니다.\n" +
                        "참여자들 또한 라이브가 종료되어\n" +
                        "강제퇴장 됩니다.",
                        confirmButtonTitle: "예",
                        confirmButtonAction: {
                            viewModel.isShowLiveEndPopup = false
                            viewModel.quitRoom()
                        },
                        cancelButtonTitle: "아니오",
                        cancelButtonAction: {
                            viewModel.isShowLiveEndPopup = false
                        }
                    )
                }
            }
            
            ZStack {
                if viewModel.isShowProfileList, let liveRoomInfo = viewModel.liveRoomInfo {
                    LiveRoomProfilesDialogView(
                        isShowing: $viewModel.isShowProfileList,
                        viewModel: viewModel,
                        roomInfo: liveRoomInfo,
                        registerNotification: { viewModel.creatorFollow() },
                        unRegisterNotification: { viewModel.creatorUnFollow() },
                        onClickProfile: {
                            if $0 != UserDefaults.int(forKey: .userId) {
                                viewModel.getUserProfile(userId: $0)
                            }
                        },
                        onClickNoChatting: { userId, nickname, profileUrl in
                            viewModel.noChattingUserId = userId
                            viewModel.noChattingUserNickname = nickname
                            viewModel.noChattingUserProfileUrl = profileUrl
                            viewModel.isShowNoChattingConfirm = true
                        }
                    )
                }
                
                if viewModel.isShowUserProfilePopup, let userProfile = viewModel.userProfile {
                    Color.black.opacity(0.7)
                        .edgesIgnoringSafeArea(.all)
                    
                    LiveRoomUserProfileDialogView(
                        isShowing: $viewModel.isShowUserProfilePopup,
                        viewModel: viewModel,
                        userProfile: userProfile,
                        onClickSetManager: {
                            viewModel.setManagerMessageToPeer(userId: $0)
                            viewModel.setManager(userId: $0)
                        },
                        onClickReleaseManager: { viewModel.changeListener(peerId: $0, isFromManager: true) },
                        onClickFollow: { viewModel.creatorFollow(creatorId: $0, isGetUserProfile: true) },
                        onClickUnFollow: { viewModel.creatorUnFollow(creatorId: $0, isGetUserProfile: true) },
                        onClickInviteSpeaker: { inviteSpeaker(peerId: $0) },
                        onClickChangeListener: {
                            viewModel.changeListener(peerId: $0)
                        },
                        onClickMenu: { userId, userNickname, isBlocked in
                            viewModel.reportUserId = userId
                            viewModel.reportUserNickname = userNickname
                            viewModel.reportUserIsBlocked = isBlocked
                            viewModel.isShowReportMenu = true
                        },
                        onClickNoChatting: { userId, nickname, profileUrl in
                            viewModel.noChattingUserId = userId
                            viewModel.noChattingUserNickname = nickname
                            viewModel.noChattingUserProfileUrl = profileUrl
                            viewModel.isShowNoChattingConfirm = true
                        }
                    )
                    .padding(20)
                    .popup(isPresented: $viewModel.isShowReportPopup, type: .toast, position: .top, autohideIn: 1.3) {
                        GeometryReader { geo in
                            HStack {
                                Spacer()
                                Text(viewModel.reportMessage)
                                    .padding(.vertical, 13.3)
                                    .frame(width: geo.size.width - 66.7, alignment: .center)
                                    .font(.custom(Font.medium.rawValue, size: 12))
                                    .background(Color.button)
                                    .foregroundColor(Color.white)
                                    .multilineTextAlignment(.center)
                                    .cornerRadius(20)
                                    .padding(.top, 66.7)
                                Spacer()
                            }
                        }
                    }
                }
                
                if viewModel.isShowReportMenu {
                    VStack(spacing: 0) {
                        ProfileReportMenuView(
                            isShowing: $viewModel.isShowReportMenu,
                            isBlockedUser: viewModel.reportUserIsBlocked,
                            userBlockAction: { viewModel.isShowUesrBlockConfirm = true },
                            userUnBlockAction: { viewModel.userUnBlock() },
                            userReportAction: { viewModel.isShowUesrReportView = true },
                            profileReportAction: { viewModel.isShowProfileReportConfirm = true }
                        )
                        
                        Rectangle()
                            .foregroundColor(Color.gray22)
                            .frame(width: screenSize().width, height: 15.3)
                    }
                    .ignoresSafeArea()
                }
                
                if viewModel.isShowUesrBlockConfirm {
                    UserBlockConfirmDialogView(
                        isShowing: $viewModel.isShowUesrBlockConfirm,
                        nickname: viewModel.reportUserNickname,
                        confirmAction: {
                            viewModel.userBlock { userId in
                                viewModel.kickOutId = userId
                                viewModel.kickOut()
                            }
                        }
                    )
                }
                
                if viewModel.isShowUesrReportView {
                    UserReportDialogView(
                        isShowing: $viewModel.isShowUesrReportView,
                        confirmAction: { reason in
                            viewModel.report(type: .USER, reason: reason)
                        }
                    )
                }
                
                if viewModel.isShowProfileReportConfirm {
                    ProfileReportDialogView(
                        isShowing: $viewModel.isShowProfileReportConfirm,
                        confirmAction: {
                            viewModel.report(type: .PROFILE)
                        }
                    )
                }
                
                if viewModel.isShowNoChattingConfirm && viewModel.noChattingUserId > 0 {
                    LiveRoomNoChattingDialogView(
                        nickname: viewModel.noChattingUserNickname,
                        profileUrl: viewModel.noChattingUserProfileUrl,
                        confirmAction: {
                            viewModel.isShowNoChattingConfirm = false
                            viewModel.setNoChatting()
                        },
                        cancelAction: {
                            viewModel.noChattingUserId = 0
                            viewModel.noChattingUserNickname = ""
                            viewModel.noChattingUserProfileUrl = ""
                            viewModel.isShowNoChattingConfirm = false
                        }
                    )
                }
                
                if viewModel.isShowPopup {
                    LiveRoomDialogView(
                        content: viewModel.popupContent,
                        cancelTitle: viewModel.popupCancelTitle,
                        cancelAction: viewModel.popupCancelAction,
                        confirmTitle: viewModel.popupConfirmTitle,
                        confirmAction: viewModel.popupConfirmAction
                    ).onAppear {
                        if viewModel.popupConfirmTitle == nil && viewModel.popupConfirmAction == nil {
                            DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
                                viewModel.isShowPopup = false
                                viewModel.popupCancelTitle = nil
                                viewModel.popupCancelAction = nil
                                viewModel.popupConfirmTitle = nil
                                viewModel.popupConfirmAction = nil
                            }
                        }
                    }
                }
            }
            
            if viewModel.isShowRouletteSettings {
                RouletteSettingsView(isShowing: $viewModel.isShowRouletteSettings, availableActive: true) { isActiveRoulette, message in
                    self.viewModel.setActiveRoulette(
                        isActiveRoulette: isActiveRoulette,
                        message: message
                    )
                }
            }
            
            if !viewModel.roulettePreviewList.isEmpty && viewModel.isShowRoulettePreview {
                RoulettePreviewDialog(
                    isShowing: $viewModel.isShowRoulettePreview,
                    title: nil,
                    onClickSpin: { viewModel.spinRoulette(rouletteId: $0) },
                    previewList: viewModel.roulettePreviewList
                )
            }
            
            if viewModel.isShowRoulette {
                RouletteViewDialog(isShowing: $viewModel.isShowRoulette, options: viewModel.rouletteItems, selectedOption: viewModel.rouletteSelectedItem) {
                    viewModel.sendRouletteDonation()
                }
            }
            
            if viewModel.isLoading && viewModel.liveRoomInfo == nil {
                LoadingView()
            }
        }
        .ignoresSafeArea(.keyboard)
        .edgesIgnoringSafeArea(keyboardHandler.keyboardHeight > 0 ? .bottom : .init())
        .sheet(
            isPresented: $viewModel.isShowShareView,
            onDismiss: { viewModel.shareMessage = "" },
            content: {
                ActivityViewController(activityItems: [viewModel.shareMessage])
            }
        )
        .sheet(isPresented: $viewModel.isShowPhotoPicker) {
            ImagePicker(
                isShowing: $viewModel.isShowPhotoPicker,
                selectedImage: $viewModel.coverImage,
                sourceType: .photoLibrary
            )
        }
        .sheet(isPresented: $viewModel.isShowEditRoomInfoDialog) {
            if let liveRoomInfo = viewModel.liveRoomInfo {
                LiveRoomInfoEditDialog(
                    isShowing: $viewModel.isShowEditRoomInfoDialog,
                    isShowPhotoPicker: $viewModel.isShowPhotoPicker,
                    viewModel: viewModel,
                    isAdult: liveRoomInfo.isAdult,
                    isLoading: viewModel.isLoading,
                    currentTitle: liveRoomInfo.title,
                    currentNotice: liveRoomInfo.notice,
                    coverImageUrl: liveRoomInfo.coverImageUrl,
                    coverImage: viewModel.coverImage
                ) { newTitle, newNotice, isAdult in
                    self.viewModel.editLiveRoomInfo(
                        title: newTitle,
                        notice: newNotice,
                        isAdult: isAdult
                    )
                }
            } else {
                EmptyView()
                    .onAppear {
                        viewModel.isShowEditRoomInfoDialog = false
                    }
            }
        }
        .sheet(isPresented: $viewModel.isShowDonationRankingPopup) {
            LiveRoomDonationRankingDialog(isShowing: $viewModel.isShowDonationRankingPopup)
        }
        .sheet(isPresented: $viewModel.isShowHeartRankingPopup) {
            LiveRoomHeartRankingDialog(
                isShowing: $viewModel.isShowHeartRankingPopup,
                isShowPopup: $viewModel.isShowPopup,
                errorMessage: viewModel.errorMessage,
                isLoading: viewModel.isLoading,
                heartStatus: viewModel.heartStatus
            ) {
                viewModel.getHeartStatus()
            }
        }
        .sheet(isPresented: $viewModel.isShowDonationMessagePopup) {
            LiveRoomDonationMessageDialog(viewModel: viewModel, isShowing: $viewModel.isShowDonationMessagePopup)
        }
    }
    
    private func estimatedHeight(for text: String, width: CGFloat) -> CGFloat {
        let textView = UITextView(frame: CGRect(x: 0, y: 0, width: width, height: .greatestFiniteMagnitude))
        textView.font = UIFont.systemFont(ofSize: 11.3)
        textView.text = text
        return textView.sizeThatFits(CGSize(width: width, height: .greatestFiniteMagnitude)).height
    }
    
    private func inviteSpeaker(peerId: Int) {
        if viewModel.liveRoomInfo!.speakerList.count <= 5 {
            viewModel.inviteSpeaker(peerId: peerId)
            self.viewModel.popupContent = "스피커 요청을 보냈습니다.\n잠시만 기다려 주세요."
            self.viewModel.isShowPopup = true
        } else {
            viewModel.popupContent = "스피커 정원을 초과했습니다."
            viewModel.isShowPopup = true
        }
    }
    
    private var scrollObservableView: some View {
        GeometryReader { proxy in
            let offsetY = proxy.frame(in: .global).origin.y
            Color.clear
                .preference(
                    key: ScrollOffsetKey.self,
                    value: offsetY
                )
                .onAppear {
                    viewModel.setOriginOffset(offsetY)
                }
        }
        .frame(height: 0)
    }
    
    struct ScrollOffsetKey: PreferenceKey {
        static var defaultValue: CGFloat = .zero
        static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) {
            value += nextValue()
        }
    }
    
    struct TextViewHeightKey: PreferenceKey {
        static var defaultValue: CGFloat = .zero
        static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) {
            value = nextValue()
        }
    }
}

struct LiveRoomViewV2_Previews: PreviewProvider {
    static var previews: some View {
        LiveRoomViewV2()
    }
}