//
//  LiveRoomView.swift
//  SodaLive
//
//  Created by klaus on 2023/08/14.
//

import SwiftUI
import Kingfisher
import PopupView

struct LiveRoomView: View {
    @State private var isShowingNewChat = false
    @State private var isShowPhotoPicker = false
    
    let columns = [
        GridItem(.flexible()),
        GridItem(.flexible()),
        GridItem(.flexible()),
        GridItem(.flexible()),
        GridItem(.flexible())
    ]
    
    let chatColumns = [GridItem(.flexible())]
    
    @StateObject var keyboardHandler = KeyboardHandler()
    @StateObject var viewModel = LiveRoomViewModel()
    
    var body: some View {
        ZStack {
            Color.black.edgesIgnoringSafeArea(.all)
            
            VStack(spacing: 0) {
                VStack(alignment: .leading, spacing: 0) {
                    HStack(spacing: 6.7) {
                        Text(
                            UserDefaults.int(forKey: .userId) == viewModel.liveRoomInfo?.creatorId ?
                            "라이브 종료":
                                "나가기"
                        )
                        .font(.custom(Font.medium.rawValue, size: 10))
                        .foregroundColor(Color(hex: "ff5c49"))
                        .padding(.horizontal, 14.3)
                        .padding(.vertical, 8.3)
                        .overlay(
                            RoundedRectangle(cornerRadius: 13.3)
                                .stroke(Color(hex: "ff5c49"), lineWidth: 1)
                        )
                        .onTapGesture {
                            if let liveRoomInfo = viewModel.liveRoomInfo, liveRoomInfo.creatorId == UserDefaults.int(forKey: .userId) {
                                viewModel.isShowLiveEndPopup = true
                            } else {
                                viewModel.isShowQuitPopup = true
                            }
                        }
                        
                        Spacer()
                        
                        Text(viewModel.isBgOn ? "배경 ON" : "배경 OFF")
                            .font(.custom(Font.medium.rawValue, size: 10))
                            .foregroundColor(Color(hex: viewModel.isBgOn ? "9970ff" : "eeeeee"))
                            .padding(.horizontal, 14.3)
                            .padding(.vertical, 8.3)
                            .overlay(
                                RoundedRectangle(cornerRadius: 13.3)
                                    .stroke(Color(hex: viewModel.isBgOn ? "9970ff" : "bbbbbb"), lineWidth: 1)
                            )
                            .onTapGesture {
                                viewModel.isBgOn.toggle()
                            }
                        
                        HStack(spacing: 4.7) {
                            Image("ic_share")
                                .resizable()
                                .frame(width: 16, height: 16)
                        }
                        .padding(.horizontal, 14.3)
                        .padding(.vertical, 6)
                        .overlay(
                            RoundedRectangle(cornerRadius: 13.3)
                                .stroke(Color(hex: "bbbbbb"), lineWidth: 1)
                        )
                        .onTapGesture {
                            viewModel.shareRoom()
                        }
                        
                        if let liveRoomInfo = viewModel.liveRoomInfo,
                           liveRoomInfo.creatorId == UserDefaults.int(forKey: .userId) {
                            HStack(spacing: 4.7) {
                                Image("ic_edit")
                                    .resizable()
                                    .frame(width: 16, height: 16)
                            }
                            .padding(.horizontal, 14.3)
                            .padding(.vertical, 6)
                            .overlay(
                                RoundedRectangle(cornerRadius: 13.3)
                                    .stroke(Color(hex: "bbbbbb"), lineWidth: 1)
                            )
                            .onTapGesture {
                                viewModel.isShowEditRoomInfoDialog = true
                            }
                        }
                    }
                    .padding(.horizontal, 13.3)
                    
                    if let liveRoomInfo = viewModel.liveRoomInfo {
                        ZStack {
                            VStack(alignment: .leading, spacing: 0) {
                                HStack(spacing: 5.3) {
                                    if liveRoomInfo.isAdult {
                                        Text("19")
                                            .font(.custom(Font.bold.rawValue, size: 11.3))
                                            .foregroundColor(Color.white)
                                            .padding(4)
                                            .background(Color(hex: "e53621"))
                                            .clipShape(Circle())
                                    }
                                    
                                    Text(liveRoomInfo.title)
                                        .font(.custom(Font.bold.rawValue, size: 15.3))
                                        .foregroundColor(Color(hex: "eeeeee"))
                                        .lineLimit(1)
                                }
                                .padding(.top, 16.7)
                                .padding(.horizontal, 13.3)
                                
                                LiveRoomTopCreatorView(
                                    creatorId: liveRoomInfo.creatorId,
                                    nickname: liveRoomInfo.creatorNickname,
                                    profileImageUrl: liveRoomInfo.creatorProfileUrl,
                                    isFollowing: liveRoomInfo.isFollowing,
                                    onClickProfile: {
                                        if liveRoomInfo.creatorId != UserDefaults.int(forKey: .userId) {
                                            viewModel.getUserProfile(userId: liveRoomInfo.creatorId)
                                        }
                                    },
                                    onClickFollow: {
                                        if $0 {
                                            viewModel.creatorUnFollow()
                                        } else {
                                            viewModel.creatorFollow()
                                        }
                                    }
                                )
                                .padding(.top, 16.7)
                                .padding(.horizontal, 13.3)
                                
                                Rectangle()
                                    .frame(height: 1)
                                    .foregroundColor(Color(hex: "909090").opacity(0.3))
                                    .padding(.horizontal, 13.3)
                                    .padding(.top, 8)
                                
                                NotificationView(liveRoomInfo: liveRoomInfo)
                            }
                            
                            if viewModel.isMute {
                                Image("img_noti_mute")
                            }
                        }
                        
                        if viewModel.isShowNotice {
                            HStack(alignment: .top, spacing: 8) {
                                Text("[공지]")
                                    .font(.custom(Font.bold.rawValue, size: 11.3))
                                    .foregroundColor(.white)
                                
                                AttributedTextView(
                                    attributedString: makeAttributedString(liveRoomInfo.notice),
                                    lineLimit: viewModel.isExpandNotice ? Int.max : 1
                                ) {
                                    UIApplication.shared.open($0)
                                    
                                }
                                .fixedSize(horizontal: false, vertical: true)
                                .lineSpacing(6)
                            }
                            .padding(.horizontal, 26.7)
                            .padding(.vertical, 13.3)
                            .frame(width: screenSize().width, alignment: .leading)
                            .background(Color(hex: "3d2a6c"))
                            .padding(.top, 10)
                            .onTapGesture {
                                viewModel.isExpandNotice.toggle()
                            }
                        }
                        
                        if !viewModel.isSpeakerFold {
                            HStack(spacing: 0) {
                                Text("스피커")
                                    .font(.custom(Font.bold.rawValue, size: 12))
                                    .foregroundColor(Color(hex: "eeeeee"))
                                
                                Spacer()
                            }
                            .padding(.top, 20)
                            .padding(.horizontal, 23.3)
                            
                            LazyVGrid(columns: columns) {
                                ForEach(liveRoomInfo.speakerList, id: \.self) { speaker in
                                    VStack(spacing: 6.7) {
                                        ZStack {
                                            KFImage(URL(string: speaker.profileImage))
                                                .resizable()
                                                .scaledToFill()
                                                .frame(width: 46.7, height: 46.7, alignment: .top)
                                                .clipShape(Circle())
                                                .overlay(
                                                    Circle()
                                                        .stroke(
                                                            Color(hex: "9970ff"),
                                                            lineWidth: viewModel.activeSpeakers.contains(UInt(speaker.id)) ? 3 : 0
                                                        )
                                                )
                                            
                                            if viewModel.muteSpeakers.contains(UInt(speaker.id)) {
                                                Image("ic_mute")
                                                    .resizable()
                                                    .frame(width: 46.7, height: 46.7)
                                            }
                                            
                                            VStack(alignment: .leading, spacing: 0) {
                                                HStack(spacing: 0) {
                                                    Spacer()
                                                    
                                                    if liveRoomInfo.creatorId == speaker.id {
                                                        Image("ic_crown")
                                                            .resizable()
                                                            .frame(width: 16.7, height: 16.7)
                                                    }
                                                }
                                                
                                                Spacer()
                                            }
                                        }
                                        .frame(width: 46.7, height: 46.7)
                                        
                                        Text(speaker.nickname)
                                            .font(.custom(Font.light.rawValue, size: 12))
                                            .foregroundColor(Color(hex: "bbbbbb"))
                                            .lineLimit(1)
                                    }
                                    .onTapGesture {
                                        viewModel.selectedProfile = speaker
                                        viewModel.isShowProfilePopup = true
                                    }
                                }
                            }
                            .padding(.top, 16.7)
                            .padding(.horizontal, 23.3)
                        }
                    }
                }
                .padding(.vertical, 16.7)
                .frame(width: screenSize().width)
                .background(Color(hex: "222222"))
                .cornerRadius(16.7, corners: [.topLeft, .topRight])
                
                ZStack(alignment: .top) {
                    ScrollViewReader { proxy in
                        ZStack(alignment: .bottomTrailing) {
                            if let liveRoomInfo = viewModel.liveRoomInfo, viewModel.isBgOn {
                                GeometryReader { proxy in
                                    KFImage(URL(string: liveRoomInfo.coverImageUrl))
                                        .resizable()
                                        .scaledToFill()
                                        .frame(width: proxy.size.width, height: proxy.size.height, alignment: .center)
                                        .clipped()
                                    
                                    Color.black.opacity(0.4)
                                }
                            }
                            
                            VStack(alignment: .leading, spacing: 0) {
                                ScrollView(.vertical, showsIndicators: false) {
                                    scrollObservableView
                                    ChatView()
                                        .frame(width: screenSize().width)
                                }
                                .rotationEffect(Angle(degrees: 180))
                                .onTapGesture { hideKeyboard() }
                                .onPreferenceChange(ScrollOffsetKey.self) {
                                    viewModel.setOffset($0)
                                }
                                
                                InputChatView {
                                    isShowingNewChat = false
                                    proxy.scrollTo(viewModel.messages.count - 1, anchor: .center)
                                }.padding(.bottom, keyboardHandler.keyboardHeight > 0 ? 0 : 15)
                            }
                            
                            VStack(spacing: 13.3) {
                                if viewModel.role == .SPEAKER {
                                    Image(viewModel.isMute ? "ic_mic_off" : "ic_mic_on")
                                        .resizable()
                                        .frame(width: 26.7, height: 26.7)
                                        .padding(11)
                                        .background(Color(hex: "525252").opacity(0.6))
                                        .cornerRadius(10)
                                        .padding(.bottom, 13.3)
                                        .onTapGesture {
                                            viewModel.toggleMute()
                                        }
                                }
                                
                                Image(viewModel.isSpeakerMute ? "ic_speaker_off" : "ic_speaker_on")
                                    .resizable()
                                    .frame(width: 26.7, height: 26.7)
                                    .padding(11)
                                    .background(Color(hex: "525252").opacity(0.6))
                                    .cornerRadius(10)
                                    .padding(.bottom, 13.3)
                                    .onTapGesture {
                                        viewModel.toggleSpeakerMute()
                                    }
                                
                                if let liveRoomInfo = viewModel.liveRoomInfo, liveRoomInfo.creatorId == UserDefaults.int(forKey: .userId) && UserDefaults.string(forKey: .role) == MemberRole.CREATOR.rawValue {
                                    Image("ic_donation_message_list")
                                        .resizable()
                                        .frame(width: 26.7, height: 26.7)
                                        .padding(11)
                                        .background(Color(hex: "525252").opacity(0.6))
                                        .cornerRadius(10)
                                        .onTapGesture {
                                            viewModel.isShowDonationMessagePopup = true
                                        }
                                } else {
                                    Image("ic_donation")
                                        .resizable()
                                        .frame(width: 26.7, height: 26.7)
                                        .padding(11)
                                        .background(Color(hex: "525252").opacity(0.6))
                                        .cornerRadius(10)
                                        .onTapGesture {
                                            viewModel.isShowDonationPopup = true
                                        }
                                }
                            }
                            .padding(.trailing, 16.7)
                            .padding(.bottom, 85)
                            
                            if isShowingNewChat {
                                NewChatView{
                                    isShowingNewChat = false
                                    proxy.scrollTo(viewModel.messages.count - 1, anchor: .center)
                                }.padding(.bottom, 70)
                            }
                        }
                        .frame(width: screenSize().width)
                        .animation(nil)
                    }
                    
                    HStack(spacing: 0) {
                        Spacer()
                        
                        HStack(spacing: 6.7) {
                            Image(viewModel.isSpeakerFold ? "ic_live_detail_bottom" : "ic_live_detail_top")
                                .resizable()
                                .frame(width: 20, height: 20)
                            
                            Text(viewModel.isSpeakerFold ? "펼치기" : "접기")
                                .font(.custom(Font.medium.rawValue, size: 13.3))
                                .foregroundColor(Color(hex: "bbbbbb"))
                        }
                        .padding(.vertical, 6.7)
                        .padding(.horizontal, 13.3)
                        .background(Color(hex: "222222"))
                        .cornerRadius(10, corners: [.bottomLeft, .bottomRight])
                        .onTapGesture {
                            viewModel.isSpeakerFold.toggle()
                        }
                    }
                    .background(
                        LinearGradient(
                            gradient: Gradient(colors: [Color(hex: "222222").opacity(0.95), Color.black.opacity(0.005)]),
                            startPoint: .top,
                            endPoint: .bottom
                        ).ignoresSafeArea()
                    )
                }
            }
            .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(hex: "9970ff"))
                            .foregroundColor(Color.white)
                            .multilineTextAlignment(.center)
                            .cornerRadius(20)
                            .padding(.top, 66.7)
                        Spacer()
                    }
                    .onDisappear {
                        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()
                
                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 in
                        viewModel.donation(can: can, message: message)
                    }
                }
                
                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
                        }
                    )
                }
                
                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
                            }
                        }
                    }
                }
            }
            
            ZStack {
                if viewModel.isShowProfileList, let liveRoomInfo = viewModel.liveRoomInfo {
                    LiveRoomProfilesDialogView(
                        isShowing: $viewModel.isShowProfileList,
                        viewModel: viewModel,
                        roomInfo: liveRoomInfo,
                        isShowRequestSpeaker: viewModel.role != .SPEAKER,
                        onClickRequestSpeaker: {
                            viewModel.requestSpeaker()
                        },
                        registerNotification: { viewModel.creatorFollow() },
                        unRegisterNotification: { viewModel.creatorUnFollow() },
                        onClickProfile: {
                            if $0 != UserDefaults.int(forKey: .userId) {
                                viewModel.getUserProfile(userId: $0)
                            }
                        }
                    )
                }
                
                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
                        }
                    )
                    .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(hex: "9970ff"))
                                    .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(hex: "222222"))
                            .frame(width: screenSize().width, height: 15.3)
                    }
                    .ignoresSafeArea()
                }
                
                if viewModel.isShowUesrBlockConfirm {
                    UserBlockConfirmDialogView(
                        isShowing: $viewModel.isShowUesrBlockConfirm,
                        nickname: viewModel.reportUserNickname,
                        confirmAction: { viewModel.userBlock() }
                    )
                }
                
                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.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: $isShowPhotoPicker) {
            ImagePicker(
                isShowing: $isShowPhotoPicker,
                selectedImage: $viewModel.coverImage,
                sourceType: .photoLibrary
            )
        }
        .sheet(isPresented: $viewModel.isShowEditRoomInfoDialog) {
            if let liveRoomInfo = viewModel.liveRoomInfo {
                LiveRoomInfoEditDialog(
                    isShowing: $viewModel.isShowEditRoomInfoDialog,
                    isShowPhotoPicker: $isShowPhotoPicker,
                    viewModel: viewModel,
                    isLoading: viewModel.isLoading,
                    currentTitle: liveRoomInfo.title,
                    currentNotice: liveRoomInfo.notice,
                    coverImageUrl: liveRoomInfo.coverImageUrl,
                    coverImage: viewModel.coverImage
                ) { newTitle, newNotice in
                    self.viewModel.editLiveRoomInfo(
                        title: newTitle,
                        notice: newNotice
                    )
                }
            } else {
                EmptyView()
                    .onAppear {
                        viewModel.isShowEditRoomInfoDialog = false
                    }
            }
        }
        .sheet(isPresented: $viewModel.isShowDonationRankingPopup) {
            LiveRoomDonationRankingDialog(isShowing: $viewModel.isShowDonationRankingPopup)
        }
        .sheet(isPresented: $viewModel.isShowDonationMessagePopup) {
            LiveRoomDonationMessageDialog(isShowing: $viewModel.isShowDonationMessagePopup)
        }
    }
    
    func makeAttributedString(_ text: String) -> NSAttributedString {
        let attributedString = NSMutableAttributedString(string: text)
        
        let urlRegex = try! NSRegularExpression(pattern: "\\b(https?://\\S+\\b|www\\.\\S+\\b)")
        let matches = urlRegex.matches(in: text, options: [], range: NSRange(text.startIndex..., in: text))
        
        for match in matches {
            let url = (text as NSString).substring(with: match.range)
            if let detectedURL = URL(string: url) {
                attributedString.addAttribute(.link, value: detectedURL, range: match.range)
            }
        }
        
        return attributedString
    }
    
    
    private func inviteSpeaker(peerId: Int) {
        if viewModel.liveRoomInfo!.speakerList.count <= 9 {
            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()
        }
    }
    
    @ViewBuilder
    func NotificationView(liveRoomInfo: GetRoomInfoResponse) -> some View {
        HStack(spacing: 8) {
            Image(
                viewModel.isShowNotice ?
                "ic_notice_selected" :
                    "ic_notice_normal"
            )
            .onTapGesture {
                viewModel.isShowNotice.toggle()
            }
            .padding(.trailing, 10)
            
            Spacer()
            
            HStack(spacing: 4.7) {
                Image("ic_can")
                    .resizable()
                    .frame(width: 16, height: 16)
                
                Text("\(viewModel.totalDonationCan)")
                    .font(.custom(Font.medium.rawValue, size: 12))
                    .foregroundColor(Color(hex: "bbbbbb"))
            }
            .padding(.horizontal, 11.5)
            .padding(.vertical, 5.3)
            .overlay(
                RoundedRectangle(cornerRadius: 12.8)
                    .strokeBorder(lineWidth: 1)
                    .foregroundColor(Color(hex: "eeeeee"))
            )
            .onTapGesture {
                viewModel.isShowDonationRankingPopup = true
            }
            
            HStack(spacing: 0) {
                Text("참여자")
                    .font(.custom(Font.medium.rawValue, size: 12))
                    .foregroundColor(Color(hex: "bbbbbb"))
                
                Text("\(liveRoomInfo.participantsCount)")
                    .font(.custom(Font.medium.rawValue, size: 12))
                    .foregroundColor(Color(hex: "9970ff"))
                    .padding(.leading, 6.7)
            }
            .padding(.horizontal, 11.5)
            .padding(.vertical, 7.3)
            .overlay(
                RoundedRectangle(cornerRadius: 12.8)
                    .strokeBorder(lineWidth: 1)
                    .foregroundColor(Color(hex: "eeeeee"))
            )
            .onTapGesture {
                viewModel.isShowProfileList = true
            }
        }
        .padding(.top, 13.3)
        .padding(.horizontal, 13.3)
    }
    
    @ViewBuilder
    func NewChatView(scrollToBottom: @escaping () -> Void) -> some View {
        HStack(spacing: 0) {
            Spacer()
            
            HStack(spacing: 6.7) {
                Image("ic_bottom_white")
                Text("새로운 채팅")
                    .font(.custom(Font.medium.rawValue, size: 13.3))
                    .foregroundColor(Color(hex: "eeeeee"))
            }
            .padding(.vertical, 8)
            .padding(.horizontal, 13.3)
            .background(Color(hex: "555555").opacity(0.8))
            .cornerRadius(16.7)
            .padding(.bottom, 13.3)
            .onTapGesture { scrollToBottom() }
            
            Spacer()
        }
    }
    
    @ViewBuilder
    func InputChatView(scrollToBottom: @escaping () -> Void) -> some View {
        HStack(spacing: 0) {
            TextField("채팅을 입력하세요", text: $viewModel.chatMessage)
                .autocapitalization(.none)
                .disableAutocorrection(true)
                .font(.custom(Font.medium.rawValue, size: 13.3))
                .foregroundColor(Color(hex: "eeeeee"))
                .accentColor(Color(hex: "9970ff"))
                .keyboardType(.default)
                .padding(.horizontal, 13.3)
            
            Spacer()
            
            Image("btn_message_send")
                .resizable()
                .frame(width: 35, height: 35)
                .padding(6.7)
                .onTapGesture {
                    viewModel.sendMessage()
                    scrollToBottom()
                }
        }
        .background(Color(hex: "232323"))
        .cornerRadius(10)
        .overlay(
            RoundedRectangle(cornerRadius: 10)
                .strokeBorder(lineWidth: 1)
                .foregroundColor(Color(hex: "eeeeee"))
        )
        .padding(13.3)
    }
    
    @ViewBuilder
    func ChatView() -> some View {
        LazyVGrid(columns: chatColumns, alignment: .leading, spacing: 20) {
            ForEach(0..<viewModel.messages.count, id: \.self) { index in
                switch (viewModel.messages[index].type) {
                case LiveRoomChatType.DONATION:
                    let chatMessage = viewModel.messages[index] as! LiveRoomDonationChat
                    LiveRoomDonationChatItemView(chatMessage: chatMessage)
                    
                case LiveRoomChatType.JOIN:
                    let chatMessage = viewModel.messages[index] as! LiveRoomJoinChat
                    LiveRoomJoinChatItemView(chatMessage: chatMessage)
                    
                default:
                    let chatMessage = viewModel.messages[index] as! LiveRoomNormalChat
                    LiveRoomChatItemView(
                        chatMessage: chatMessage,
                        onClickProfile: {
                            if chatMessage.userId != UserDefaults.int(forKey: .userId) {
                                viewModel.getUserProfile(userId: chatMessage.userId)
                            }
                        }
                    )
                }
            }
        }
        .rotationEffect(Angle(degrees: 180))
        .valueChanged(value: viewModel.messageChangeFlag) { _ in
            if viewModel.offset - viewModel.originOffset > (56.7 * 2) {
                isShowingNewChat = true
            }
        }
    }
}

struct LiveRoomView_Previews: PreviewProvider {
    static var previews: some View {
        LiveRoomView()
    }
}

struct AttributedTextView: UIViewRepresentable {
    let attributedString: NSAttributedString
    let lineLimit: Int
    let onURLTapped: (URL) -> Void
    
    
    func makeUIView(context: Context) -> UITextView {
        let textView = UITextView()
        textView.isEditable = false
        textView.isSelectable = false
        textView.isScrollEnabled = false
        textView.backgroundColor = .clear
        textView.font = UIFont(name: Font.light.rawValue, size: 11.3)
        textView.textColor = .white
        textView.textContainer.lineFragmentPadding = 0
        textView.textContainerInset = .zero
        textView.textContainer.maximumNumberOfLines = lineLimit
        textView.textContainer.lineBreakMode = lineLimit == 1 ? .byTruncatingTail : .byWordWrapping
        textView.delegate = context.coordinator
        
        textView.isUserInteractionEnabled = true
        
        // Add tap gesture recognizer to handle URL tap events
        let tapGestureRecognizer = UITapGestureRecognizer(target: context.coordinator, action: #selector(Coordinator.handleTapGesture(_:)))
        textView.addGestureRecognizer(tapGestureRecognizer)

        
        return textView
    }
    
    func updateUIView(_ uiView: UITextView, context: Context) {
        uiView.attributedText = attributedString
        uiView.textColor = UIColor.white
        uiView.textContainer.maximumNumberOfLines = lineLimit
        uiView.textContainer.lineBreakMode = lineLimit == 1 ? .byTruncatingTail : .byWordWrapping
    }
    
    func makeCoordinator() -> Coordinator {
        Coordinator(onURLTapped: onURLTapped)
    }
    
    class Coordinator: NSObject, UITextViewDelegate {
        let onURLTapped: (URL) -> Void
        let linkAttributeName = NSAttributedString.Key.link.rawValue
        
        init(onURLTapped: @escaping (URL) -> Void) {
            self.onURLTapped = onURLTapped
        }
        
        @objc func handleTapGesture(_ gesture: UITapGestureRecognizer) {
            let textView = gesture.view as? UITextView
            let location = gesture.location(in: textView)
            
            let layoutManager = textView?.layoutManager
            let characterIndex = layoutManager?.characterIndex(for: location, in: textView!.textContainer, fractionOfDistanceBetweenInsertionPoints: nil)
            
            if characterIndex != NSNotFound {
                let attributedString = textView?.attributedText
                
                attributedString?.enumerateAttribute(NSAttributedString.Key(rawValue: linkAttributeName), in: NSRange(location: 0, length: attributedString!.length), options: []) { value, range, _ in
                    if let url = value as? URL, NSLocationInRange(characterIndex!, range) {
                        onURLTapped(url)
                    }
                }
            }
        }
    }
}