<template>
    <div class="video-group-container">
        <video autoplay class="select-video" ref="selectStream"></video>
        <div class="video-list">
            <div v-for="video in videos" :key="video.userId" class="video-card">
                <!-- 遍历渲染多人音视频控件 -->
                <div :class="['group-video-container', playerUserId === video.userId ? 'playerVideo' : 'defaultVideo']" @click="selectVideoPlay(video)">
                    <video autoplay class="group-video" :srcObject="video.stream"></video>
                    <span class="video-username">{{video.userName}}</span>
                </div>
            </div>
        </div>
        <!-- 挂断通话 -->
        <svg class="leave-btn icon" @click="leave()" style="margin-left: -120px;" t="1739368256646" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3572" width="40" height="40"><path d="M0 512a512 512 0 1 0 1024 0A512 512 0 1 0 0 512z" fill="#F75855" p-id="3573"></path><path d="M502.24 414.2c78.71 2.19 155.93 11.61 225.57 52.4 46.19 27.06 59.2 52.68 52.6 96.3-4.54 30-21.84 44.86-51.68 46.7-58.81 3.61-84.16-15.87-90.44-72.24-2.11-18.94-14-26.82-29.03-30.22-63.34-14.31-127.14-13.52-190.84-2.28-20.32 3.59-29.81 17.2-28.68 37.58 2.13 38.35-20.49 54.18-54.04 60.39-41.35 7.65-70-3.01-84.89-31.53-15.68-30.04-10.26-65.69 14.51-90.09 28.34-27.91 64.05-42.34 101.72-51.48 44.29-10.76 89.33-17.04 135.2-15.53z" fill="#FEFEFE" p-id="3574"></path></svg>
    </div>

</template>

<script>
  import axios from 'axios';
  import { defineEmits, inject, defineComponent, ref, onMounted, onUnmounted, watch, onBeforeUnmount } from 'vue';
  export default defineComponent({
    props: {
        openVideo: Boolean,
        selectChatUserRef: Object
    },
    setup(props, { emit }) {
        
        const socket = ref(null);
        const messageQueue = ref([]); // 存储未发送的消息队列
        const isConnected = ref(false);
        const reconnectInterval = ref(5000); // 重连间隔时间，单位：毫秒
        const heartbeatInterval = ref(30000); // 心跳间隔时间，单位：毫秒
    
        const loginUser = ref(inject('loginUser'));
        // 反转下角色，由接听人来发offer信息
        const offerUser = ref(props.openVideo);
        const selectChatUser = ref(props.selectChatUserRef);
        // 本地音视频流
        const localStream = ref(null)
        const playerUserId = ref(loginUser.value.userId)
        const selectStream = ref(null)
        // 标记当前在线所有用户
        const onlineUserIds = ref([])
        const onlineUsernames = ref({})
        const exchangeUserId = ref("")
        const videos = ref([])
        // 当前已经完成peeConnection连接管理中的用户id
        const connectedUserIds = ref([])
        // 维护当前客户端与其他音视频在线用户的peerConnection对象
        const peerConnnections = ref({})

        // 配置ICE Server（用于网络穿透）
        const iceServerConfiguration = {
            "iceServers": [
                {
                    "urls": "stun:stun.l.google.com:19302"
                }
            ]
        }

        // 每个用户进度，先获取本地媒体流
        // 修改点 1：使用标准的 RTCPeerConnection
        const PeerConnection = window.RTCPeerConnection || window.mozRTCPeerConnection || window.webkitRTCPeerConnection;
        // 获取当前客户端与指定客户端uid端到端之间的音视频连接对象
        // 如果连接存在，不重复创建，直接服用，反之则创建新链接对象
        const getPeerConnetion = (uid) => {
            let peerConntion = null;
            let peerConnKey = getPeerConnId(uid);
            if(peerConnnections.value[peerConnKey]) {
                peerConntion = peerConnnections.value[peerConnKey];
                return peerConntion;
            }
            peerConntion = new PeerConnection(iceServerConfiguration);
            peerConnnections.value[peerConnKey] = peerConntion;
            return peerConntion;
        }

        // 两两端之间音视频连接唯一标识获取
        const getPeerConnId = (uid) => {
            let peerConnKeyArr = [loginUser.value.userId, uid];
            return peerConnKeyArr.sort().join('-');
        }

        // 修改点 2：重构初始化本地流的逻辑
        const initLocalStream = async () => {
            try {
                // 获取本地媒体流
                localStream.value = await navigator.mediaDevices.getUserMedia({
                    video: true,
                    audio: true
                });
                selectStream.value.srcObject = localStream.value;
                videos.value.push({
                    userId: loginUser.value.userId,
                    userName: "我",
                    stream: localStream.value
                }) 
                initSignalServerConnection();
            } catch (error) {
                console.error('初始化本地流失败:', error);
            }
        };
        initLocalStream();

        // 初始化信令服务器连接（ws）
        const initSignalServerConnection = () => {
            socket.value = new WebSocket(`/connect-service/ws/group/video/PC_WEB_CHAT/` + selectChatUser.value.userId + `/` + loginUser.value.userId);
            socket.value.onopen = () => {
                console.log('WebSocket 已连接');
                isConnected.value = true;
                // 发送队列中的消息
                messageQueue.value.forEach(message => socket.value.send(message));
                messageQueue.value = [];
                startHeartbeat();
            };

            socket.value.onmessage = (event) => {
                const messageData = JSON.parse(event.data);
                console.log('收到WS消息 messageData.type:' + messageData.type);
                switch(messageData.type) {
                    case "online": 
                        handleUserOnline(messageData);
                        break;
                    case "offline": 
                        handleUserOffline(messageData);
                        break;
                    case "offer": 
                        handleOffer(messageData.userId, messageData.offer);
                        break;
                    case "answer": 
                        handleAnswer(messageData.userId, messageData.answer);
                        break;
                    case "candidate" :
                        handleCandidate(messageData.userId, messageData.candidate);
                        break;
                    case "leave" :

                    break;
                }
            };
            const startHeartbeat = () => {
                const heartbeat = () => {
                    if (isConnected.value) {
                    socket.value.send('ping'); // 发送心跳包
                    }
                };
                setInterval(heartbeat, heartbeatInterval.value);
            };
        
            socket.value.onerror = (error) => {
                console.error('WebSocket 错误:', error);
                isConnected.value = false;
                // 关闭当前连接
                socket.value.close();
                // 尝试重连
                setTimeout(initSignalServerConnection, reconnectInterval.value);
            };

            socket.value.onclose = () => {
                console.log('WebSocket 已关闭');
                isConnected.value = false;
                // 尝试重连
                setTimeout(initSignalServerConnection, reconnectInterval.value);
            };
        }
         // 初始化ws连接
        //  initSignalServerConnection();

         const sendObjMessage = (obj) => {
            sendMessage(JSON.stringify(obj))
         }
        const sendMessage = (message) => {
            if (isConnected.value) {
                socket.value.send(message);
            } else {
                messageQueue.value.push(message);
            }
        };
        // 处理用户上线
        const handleUserOnline = (message) => {
            exchangeUserId.value = message.userId;
            onlineUserIds.value = message.onlineUserIds;
            onlineUsernames.value = message.onlineUsernames;
            // 处理call类型消息
            if(message.onlineUserIds.length === 1) {
                // 认为当前客户端为第一个加入音视频房间的用户，由当前客户端发起call消息（呼叫所有群成员）
                // 作为呼叫方呼叫
                sendObjMessage({
                    type: "call",
                    userId: loginUser.value.userId,
                    groupId: selectChatUser.value.userId
                });
            }
            // 基于Mesh模式，实现两两端到端音视频通信连接
            handlePeerConnByOnlineUsersMessage();
        }

        // 用户上线，基于Mesh模式实现多人音视频链接管理
        const handlePeerConnByOnlineUsersMessage = async () => {
            for(var i = 0; i < onlineUserIds.value.length; i ++) {
                // 遍历当前所有音视频在线用户
                let uid = onlineUserIds.value[i];
                if (connectedUserIds.value.includes(uid)) {
                    continue;
                }
                // 表示当前远程用户已被当前客户端建立音视频连接接通道，避免后续重复创建
                connectedUserIds.value.push(uid);
                if (uid === loginUser.value.userId) {
                    // 当前用户自己
                    continue;
                }
                let uname = onlineUsernames.value[uid];
                let peerConn = getPeerConnetion(uid);
                // 添加本地轨道（替代已废弃的 addStream）
                localStream.value.getTracks().forEach(track => {
                    peerConn.addTrack(track, localStream.value);
                });
                // 创建offer
                // 这里来保证每两个客户端之间只有一个端来发起offer
                // 对两个用户uid做自然排序，永远都只允许自排序更靠前的这个客户端来发起offer
                let p2pClients = [loginUser.value.userId, uid];
                let sortFirstUserId = p2pClients.sort()[0];
                if (uid == sortFirstUserId) {
                    const offer = await peerConn.createOffer();
                    peerConn.setLocalDescription(offer);
                    sendObjMessage({
                        type: "offer",
                        offer: offer,
                        userId: loginUser.value.userId,
                        targetUserId: uid,
                        groupId: selectChatUser.value.userId
                    });
                }
                
                // 监听获取远程流
                peerConn.ontrack = (event) => {
                    if (event.streams && event.streams.length > 0) {
                        const newStream = event.streams[0];
                        const existingVideoIndex = videos.value.findIndex(video => video.userId === uid);
                        if (existingVideoIndex !== -1) {
                            // 如果已经存在相同uid的对象，更新stream属性
                            videos.value[existingVideoIndex].stream = newStream;
                        } else {
                            // 如果不存在相同uid的对象，新增一个对象
                            videos.value.push({
                                userId: uid,
                                userName: uname,
                                stream: newStream
                            });
                        }
                    }
                };
                // ICE 候选处理
                peerConn.onicecandidate = (event) => {
                    console.log("ICE Candidate:", event.candidate?.candidate);
                    if (event.candidate) {
                        sendObjMessage({
                            type: "candidate",
                            candidate: event.candidate,
                            userId: loginUser.value.userId,
                            targetUserId: uid,
                            groupId: selectChatUser.value.userId
                        });
                    }
                };
                peerConn.oniceconnectionstatechange = () => {
                    console.log("ICE state:", peerConn.iceConnectionState);
                };
            }
        }

        // 5：完善处理 Offer 的逻辑
        const handleOffer = async (uid, offer) => {
            try {
                let peerConn = getPeerConnetion(uid);
                if (offer && offer.type && offer.sdp) {
                    await peerConn.setRemoteDescription(new RTCSessionDescription(offer));
                    const answer = await peerConn.createAnswer();
                    await peerConn.setLocalDescription(answer);
                    sendObjMessage({
                        type: "answer",
                        answer: answer,
                        userId: loginUser.value.userId,
                        targetUserId: uid,
                        groupId: selectChatUser.value.userId
                    });
                } else {
                    console.error("无效的 offer 参数");
                }
            } catch (error) {
                console.error("处理 Offer 失败:", error);
            }
        };

        // 完善处理 Answer 的逻辑
        const handleAnswer = async (uid, answer) => {
            try {
                let peerConn = getPeerConnetion(uid);
                // 检查状态是否为 have-local-offer
                if (peerConn.signalingState !== "have-local-offer") {
                    console.warn("状态错误，当前状态:", peerConn.signalingState);
                    return;
                }
                await peerConn.setRemoteDescription(new RTCSessionDescription(answer));
            } catch (error) {
                console.error("处理 Answer 失败:", error);
            }
        };

        const handleCandidate = async (uid, candidate) => {
            try {
                let peerConn = getPeerConnetion(uid);
                if (peerConn.iceConnectionState === 'closed') {
                    console.error("PeerConnection 已关闭，无法添加 ICE 候选");
                    return;
                }
                if (!candidate || typeof candidate !== 'object' || !candidate.candidate || !candidate.sdpMid) {
                    console.error("Invalid ICE candidate:", candidate);
                    return;
                }
                await peerConn.addIceCandidate(candidate);
                console.log("成功添加 ICE 候选");
            } catch (error) {
                console.error("处理 ICE 候选失败:", error);
            }
        };
    
        // 处理用户离线
        const handleUserOffline = (message) => {
            exchangeUserId.value = message.userId;
            onlineUserIds.value = message.onlineUserIds;
            videos.value = videos.value.filter(v => v.userId !== exchangeUserId.value);
            const mesage = onlineUsernames.value[message.userId] + "退出";
            const firstVideo = videos.value[0];
            if (message.userId === playerUserId.value) {
                playerUserId.value = firstVideo.userId;
                selectStream.value.scrObject = firstVideo.stream;
            }
        }

        const selectVideoPlay = (video) => {
            playerUserId.value = video.userId;
            selectStream.value.srcObject = video.stream;
        }

        const leave = () => {
            cleanup();
            // 触发关闭事件
            emit('close', 'close');
        }

        const cleanup = () => {
             // WebSocket 清理
            if (socket.value) {
                try {
                if ([WebSocket.OPEN, WebSocket.CONNECTING].includes(socket.value.readyState)) {
                    socket.value.close()
                }
                } catch (err) {
                    console.error('关闭 WebSocket 失败:', err)
                } finally {
                    socket.value = null
                }
            }
            // WebRTC 清理
            if (peerConnnections.value) {
                peerConnnections.value = null
            }
            // 媒体流清理 (关键补充)
            if (localStream.value) {
                localStream.value.getTracks().forEach(track => {
                    track.stop() // 必须停止每个媒体轨道
                })
                localStream.value = null
            }
            // 发送终止信令 (重要)
            // TODO
        }

        onBeforeUnmount(() => {
            cleanup();
        }) ;
        onMounted(() => {
        
        });
        onUnmounted(() => {
       
        });
      
      return {
        playerUserId,
        selectStream,
        onlineUserIds,
        selectChatUser,
        videos,
        onlineUsernames,
        leave,
        initLocalStream,
        getPeerConnetion,
        getPeerConnId,
        initSignalServerConnection,
        handleOffer,
        handleAnswer,
        handleCandidate,
        selectVideoPlay
      };
    }
  });

</script>

<style>
    .video-group-container {
        width: 1000px;
        height: 600px;
        overflow: hidden;
        background-color: black;
    }
    .video-list {
        position: absolute;
        padding: 15px;
        border-radius: 5px;
        background-color:rgb(18, 20, 21);
        top: 50px;
        right: 20px;
        width: 230px;
        height: 615px;
        overflow-y: scroll;
    }
    .group-video-container {
        position: relative;
        width: 200px;
        height: 150px;
        overflow: hidden;
        margin-bottom: 10px;
        border: 2px solid rgb(18, 20, 21);
    }
    .playerVideo {
        border: 2px solid white;
    }
    .group-video-container video {
        position: absolute;
        left: 0px;
        top: 0px;
        width: 200px;
    }
    .video-username {
        position: absolute;
        top: 20px;
        right: 20px;
        background-color: black;
        opacity: 0.5;
        color: white;
        padding: 3px 15px;
        border-radius: 50px;
    }
    .select-video {
        position: absolute;
        left: 25px;
        top: 50px;
        width: 750px;
    }
    .video-list::-webkit-scrollbar {/*滚动条整体样式*/
        width: 0px;     /*高宽分别对应横竖滚动条的尺寸*/
        height: 0px;
    }
    .video-list::-webkit-scrollbar-thumb {/*滚动条里面小方块*/
        border-radius: 10px;
        background-color: transparent;
        background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .2) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .2) 50%, rgba(255, 255, 255, .2) 75%, transparent 75%, transparent);
    }
    .video-list::-webkit-scrollbar-track {/*滚动条里面轨道*/
        -webkit-box-shadow: inset 0 0 1px rgba(221, 35, 35, 0.2);
        border-radius: 10px;
        background: #EDEDED;
    }
    .leave-btn {
        position: absolute;
        left: 48%;
        bottom: 20px;
        border: 2px solid rgb(239, 133, 133);
        border-radius: 100px;
    }
</style>