class VoiceChannel {
    constructor(ws) {
        this.ws = ws;
        this.localStream = null;
        this.screenStream = null;
        this.peers = {}; // userId -> RTCPeerConnection
        this.participants = {}; // userId -> username
        this.currentChannelId = null;
        this.isScreenSharing = false;
    }

    async join(channelId) {
        if (this.currentChannelId === channelId) return;
        if (this.currentChannelId) this.leave();

        console.log('Joining voice channel:', channelId);
        this.currentChannelId = channelId;

        try {
            this.localStream = await navigator.mediaDevices.getUserMedia({ audio: true, video: false });
            
            this.ws.send(JSON.stringify({
                type: 'voice_join',
                channel_id: channelId,
                user_id: window.currentUserId,
                username: window.currentUsername
            }));

            this.updateVoiceUI();
        } catch (e) {
            console.error('Failed to get local stream:', e);
            alert('Could not access microphone.');
            this.currentChannelId = null;
        }
    }

    async toggleScreenShare() {
        if (!this.currentChannelId) return;

        if (this.isScreenSharing) {
            this.stopScreenShare();
        } else {
            try {
                this.screenStream = await navigator.mediaDevices.getDisplayMedia({ video: true });
                this.isScreenSharing = true;
                
                const videoTrack = this.screenStream.getVideoTracks()[0];
                videoTrack.onended = () => this.stopScreenShare();

                // Replace or add track to all peers
                Object.values(this.peers).forEach(pc => {
                    pc.addTrack(videoTrack, this.screenStream);
                    // Renegotiate
                    this.renegotiate(pc);
                });

                this.updateVoiceUI();
                this.showLocalVideo();
            } catch (e) {
                console.error('Failed to share screen:', e);
            }
        }
    }

    stopScreenShare() {
        if (this.screenStream) {
            this.screenStream.getTracks().forEach(track => track.stop());
            this.screenStream = null;
        }
        this.isScreenSharing = false;
        
        // Remove video track from all peers
        Object.entries(this.peers).forEach(([userId, pc]) => {
            const senders = pc.getSenders();
            const videoSender = senders.find(s => s.track && s.track.kind === 'video');
            if (videoSender) {
                pc.removeTrack(videoSender);
                this.renegotiate(pc);
            }
        });

        this.updateVoiceUI();
        const localVideo = document.getElementById('local-video-container');
        if (localVideo) localVideo.innerHTML = '';
    }

    renegotiate(pc) {
        // Find which user this PC belongs to
        const userId = Object.keys(this.peers).find(key => this.peers[key] === pc);
        if (!userId) return;

        pc.createOffer().then(offer => {
            return pc.setLocalDescription(offer);
        }).then(() => {
            this.ws.send(JSON.stringify({
                type: 'voice_offer',
                to: userId,
                from: window.currentUserId,
                username: window.currentUsername,
                offer: pc.localDescription,
                channel_id: this.currentChannelId
            }));
        });
    }

    leave() {
        if (!this.currentChannelId) return;

        this.stopScreenShare();

        this.ws.send(JSON.stringify({
            type: 'voice_leave',
            channel_id: this.currentChannelId,
            user_id: window.currentUserId
        }));

        if (this.localStream) {
            this.localStream.getTracks().forEach(track => track.stop());
            this.localStream = null;
        }

        Object.values(this.peers).forEach(pc => pc.close());
        this.peers = {};
        this.participants = {};
        this.currentChannelId = null;
        this.updateVoiceUI();
    }

    async handleSignaling(data) {
        const { type, from, to, offer, answer, candidate, channel_id, username } = data;

        if (channel_id != this.currentChannelId) return;
        if (to && to != window.currentUserId) return;

        switch (type) {
            case 'voice_join':
                if (from != window.currentUserId) {
                    this.participants[from] = username || `User ${from}`;
                    this.createPeerConnection(from, true);
                    this.updateVoiceUI();
                }
                break;
            case 'voice_offer':
                this.participants[from] = username || `User ${from}`;
                await this.handleOffer(from, offer);
                this.updateVoiceUI();
                break;
            case 'voice_answer':
                await this.handleAnswer(from, answer);
                break;
            case 'voice_ice_candidate':
                await this.handleCandidate(from, candidate);
                break;
            case 'voice_leave':
                if (this.peers[from]) {
                    this.peers[from].close();
                    delete this.peers[from];
                }
                delete this.participants[from];
                this.updateVoiceUI();
                const remoteVideo = document.getElementById(`remote-video-${from}`);
                if (remoteVideo) remoteVideo.remove();
                break;
        }
    }

    createPeerConnection(userId, isOfferor) {
        if (this.peers[userId]) return this.peers[userId];

        const pc = new RTCPeerConnection({
            iceServers: [{ urls: 'stun:stun.l.google.com:19302' }]
        });

        this.peers[userId] = pc;

        if (this.localStream) {
            this.localStream.getTracks().forEach(track => {
                pc.addTrack(track, this.localStream);
            });
        }

        if (this.screenStream) {
            this.screenStream.getTracks().forEach(track => {
                pc.addTrack(track, this.screenStream);
            });
        }

        pc.onicecandidate = (event) => {
            if (event.candidate) {
                this.ws.send(JSON.stringify({
                    type: 'voice_ice_candidate',
                    to: userId,
                    from: window.currentUserId,
                    candidate: event.candidate,
                    channel_id: this.currentChannelId
                }));
            }
        };

        pc.ontrack = (event) => {
            if (event.track.kind === 'audio') {
                const remoteAudio = new Audio();
                remoteAudio.srcObject = event.streams[0];
                remoteAudio.play();
            } else if (event.track.kind === 'video') {
                this.handleRemoteVideo(userId, event.streams[0]);
            }
        };

        if (isOfferor) {
            pc.createOffer().then(offer => {
                return pc.setLocalDescription(offer);
            }).then(() => {
                this.ws.send(JSON.stringify({
                    type: 'voice_offer',
                    to: userId,
                    from: window.currentUserId,
                    username: window.currentUsername,
                    offer: pc.localDescription,
                    channel_id: this.currentChannelId
                }));
            });
        }

        return pc;
    }

    async handleOffer(from, offer) {
        const pc = this.createPeerConnection(from, false);
        await pc.setRemoteDescription(new RTCSessionDescription(offer));
        const answer = await pc.createAnswer();
        await pc.setLocalDescription(answer);
        this.ws.send(JSON.stringify({
            type: 'voice_answer',
            to: from,
            from: window.currentUserId,
            answer: pc.localDescription,
            channel_id: this.currentChannelId
        }));
    }

    async handleAnswer(from, answer) {
        const pc = this.peers[from];
        if (pc) await pc.setRemoteDescription(new RTCSessionDescription(answer));
    }

    async handleCandidate(from, candidate) {
        const pc = this.peers[from];
        if (pc) await pc.addIceCandidate(new RTCIceCandidate(candidate));
    }

    handleRemoteVideo(userId, stream) {
        let container = document.getElementById('video-grid');
        if (!container) {
            container = document.createElement('div');
            container.id = 'video-grid';
            container.className = 'video-grid';
            const chatContainer = document.querySelector('.chat-container');
            if (chatContainer) {
                chatContainer.insertBefore(container, document.getElementById('messages-list'));
            } else {
                document.body.appendChild(container);
            }
        }

        let video = document.getElementById(`remote-video-${userId}`);
        if (!video) {
            video = document.createElement('video');
            video.id = `remote-video-${userId}`;
            video.autoplay = true;
            video.playsinline = true;
            container.appendChild(video);
        }
        video.srcObject = stream;
    }

    showLocalVideo() {
        let container = document.getElementById('video-grid');
        if (!container) {
            container = document.createElement('div');
            container.id = 'video-grid';
            container.className = 'video-grid';
            const chatContainer = document.querySelector('.chat-container');
            if (chatContainer) {
                chatContainer.insertBefore(container, document.getElementById('messages-list'));
            } else {
                document.body.appendChild(container);
            }
        }

        let video = document.getElementById('local-video');
        if (!video) {
            video = document.createElement('video');
            video.id = 'local-video';
            video.autoplay = true;
            video.playsinline = true;
            video.muted = true;
            container.appendChild(video);
        }
        video.srcObject = this.screenStream;
    }

    updateVoiceUI() {
        document.querySelectorAll('.voice-users-list').forEach(el => el.innerHTML = '');
        
        if (this.currentChannelId) {
            const channelEl = document.querySelector(`.voice-item[data-channel-id="${this.currentChannelId}"]`);
            if (channelEl) {
                let listEl = channelEl.querySelector('.voice-users-list');
                if (!listEl) {
                    listEl = document.createElement('div');
                    listEl.className = 'voice-users-list ms-3';
                    channelEl.appendChild(listEl);
                }
                
                // Me
                this.addVoiceUserToUI(listEl, window.currentUserId, window.currentUsername);
                
                // Others
                Object.entries(this.participants).forEach(([uid, name]) => {
                    this.addVoiceUserToUI(listEl, uid, name);
                });
            }

            // Show voice controls if not already there
            if (!document.querySelector('.voice-controls')) {
                const controls = document.createElement('div');
                controls.className = 'voice-controls p-2 d-flex justify-content-between align-items-center border-top bg-dark';
                controls.innerHTML = `
                    <div class="d-flex align-items-center">
                        <div class="voice-status-icon text-success me-2">●</div>
                        <div class="small">Voice Connected</div>
                    </div>
                    <div>
                        <button class="btn btn-sm btn-outline-light me-2" id="btn-screen-share">
                            <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="2" y="3" width="20" height="14" rx="2" ry="2"></rect><line x1="8" y1="21" x2="16" y2="21"></line><line x1="12" y1="17" x2="12" y2="21"></line></svg>
                        </button>
                        <button class="btn btn-sm btn-danger" id="btn-voice-leave">
                            <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M10.68 13.31a16 16 0 0 0 3.41 2.6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7 2 2 0 0 1 1.72 2v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.42 19.42 0 0 1-3.33-2.67m-2.67-3.34a19.79 19.79 0 0 1-3.07-8.63A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91"></path><line x1="23" y1="1" x2="1" y2="23"></line></svg>
                        </button>
                    </div>
                `;
                document.querySelector('.channels-sidebar').appendChild(controls);

                document.getElementById('btn-screen-share').onclick = () => this.toggleScreenShare();
                document.getElementById('btn-voice-leave').onclick = () => this.leave();
            }
        } else {
            const controls = document.querySelector('.voice-controls');
            if (controls) controls.remove();
            const grid = document.getElementById('video-grid');
            if (grid) grid.remove();
        }
    }

    addVoiceUserToUI(container, userId, username) {
        const userEl = document.createElement('div');
        userEl.className = 'voice-user small text-muted d-flex align-items-center mb-1';
        userEl.innerHTML = `
            <div class="message-avatar me-2" style="width: 16px; height: 16px;"></div>
            <span>${username}</span>
        `;
        container.appendChild(userEl);
    }
}
