// LiveKit integration for Fistchat
window.livekit = {
    room: null,
    localTrack: null,
    localVideoTrack: null,
    screenTrack: null,
    isMuted: false,
    isVideoEnabled: false,
    isScreenSharing: false,
    dotNetHelper: null,

    // Test Loop properties
    audioInterval: null,
    audioCtx: null,
    _resumeCtx: null,
    audioElement: null,
    audioUrl: null,

    // Mock Mode properties
    isMock: false,
    mockTimeouts: [],
    speakerInterval: null,

    async connect(url, token, roomName) {
        if (roomName === '3' || roomName === 'Test Voice' || roomName === '4' || roomName === 'Test Video' || window.location.search.includes('mockLiveKit=true') || url === 'mock' || url === 'dummy' || url.startsWith('mock:') || url.startsWith('dummy:') || token === 'mock-token' || token === 'dummy-token') {
            return this.connectMock(url, token, roomName);
        }

        try {
            const { Room, createLocalAudioTrack } = await import('https://cdn.jsdelivr.net/npm/livekit-client@2/dist/livekit-client.esm.js');

            this.room = new Room({ adaptiveStream: true, dynacast: true });

            this.room.on('participantConnected', p => this.handleParticipantConnected(p));
            this.room.on('participantDisconnected', p => this.handleParticipantDisconnected(p));
            this.room.on('trackSubscribed', (track, pub, p) => this.handleTrackSubscribed(track, p));
            this.room.on('trackUnsubscribed', (track, pub, p) => this.handleTrackUnsubscribed(track, p));
            this.room.on('trackMuted', (pub, p) => this.dotNetHelper?.invokeMethodAsync('OnParticipantMuted', p.identity, pub.kind));
            this.room.on('trackUnmuted', (pub, p) => this.dotNetHelper?.invokeMethodAsync('OnParticipantUnmuted', p.identity, pub.kind));
            this.room.on('disconnected', () => this.dotNetHelper?.invokeMethodAsync('OnRoomDisconnected'));
            this.room.on('activeSpeakersChanged', speakers => {
                this.dotNetHelper?.invokeMethodAsync('OnActiveSpeakersChanged', speakers.map(s => s.identity));
            });

            await this.room.connect(url, token);

            try {
                const localTrack = await createLocalAudioTrack();
                this.localTrack = localTrack;
                await this.room.localParticipant.publishTrack(localTrack);
            } catch (mediaError) {
                console.warn('Failed to publish local audio track (joining as listener/muted):', mediaError);
                this.isMuted = true;
                this.dotNetHelper?.invokeMethodAsync('OnLocalMutedStateChanged', true);
            }

            const participants = Array.from(this.room.participants.values()).map(p => ({
                identity: p.identity,
                name: p.name,
                isMuted: p.isMicrophoneEnabled === false
            }));

            return { success: true, participants };
        } catch (error) {
            console.error('Failed to connect to LiveKit room:', error);
            return { success: false, error: error.message };
        }
    },

    async connectMock(url, token, roomName) {
        console.log('[MOCK-LIVEKIT] Connecting to mock room:', roomName);
        this.isMock = true;
        this.mockTimeouts = [];

        // Simulate a delay before connecting
        await new Promise(resolve => setTimeout(resolve, 500));

        if (roomName === '3' || roomName === 'Test Voice' || roomName === '4' || roomName === 'Test Video') {
            this.startLocalTestLoop(roomName);
            const isVoice = roomName === '3' || roomName === 'Test Voice';
            return {
                success: true,
                participants: [
                    {
                        identity: isVoice ? 'test-voice-bot' : 'test-video-bot',
                        name: isVoice ? 'Voice Loop Bot' : 'Video Loop Bot',
                        isMuted: false
                    }
                ]
            };
        }

        // Setup mock participants joining
        const t1 = setTimeout(() => {
            console.log('[MOCK-LIVEKIT] Simulating Alice connection');
            this.handleParticipantConnected({ identity: 'dummy-alice', name: 'Alice', isMicrophoneEnabled: true });

            // Simulate Alice starting video after a bit
            const t2 = setTimeout(() => {
                console.log('[MOCK-LIVEKIT] Simulating Alice video track subscription');
                this.dotNetHelper?.invokeMethodAsync('OnParticipantVideoToggled', 'dummy-alice', true);

                setTimeout(() => {
                    const videoContainer = document.getElementById('video-container-dummy-alice');
                    if (videoContainer) {
                        const dummyVideo = document.createElement('div');
                        dummyVideo.className = 'participant-video dummy-video-stream';
                        dummyVideo.style.width = '100%';
                        dummyVideo.style.height = '100%';
                        dummyVideo.style.background = 'linear-gradient(135deg, #1f4068, #162447)';
                        dummyVideo.style.display = 'flex';
                        dummyVideo.style.flexDirection = 'column';
                        dummyVideo.style.alignItems = 'center';
                        dummyVideo.style.justifyContent = 'center';
                        dummyVideo.style.color = '#fff';
                        dummyVideo.style.position = 'relative';

                        const avatar = document.createElement('div');
                        avatar.style.width = '60px';
                        avatar.style.height = '60px';
                        avatar.style.borderRadius = '50%';
                        avatar.style.backgroundColor = '#e94560';
                        avatar.style.display = 'flex';
                        avatar.style.alignItems = 'center';
                        avatar.style.justifyContent = 'center';
                        avatar.style.fontSize = '1.5rem';
                        avatar.style.fontWeight = 'bold';
                        avatar.innerText = 'A';
                        avatar.style.boxShadow = '0 0 15px rgba(233, 69, 96, 0.5)';
                        dummyVideo.appendChild(avatar);

                        const label = document.createElement('div');
                        label.style.marginTop = '10px';
                        label.style.fontSize = '0.9rem';
                        label.style.opacity = '0.8';
                        label.innerText = 'Alice (Live Mock Feed)';
                        dummyVideo.appendChild(label);

                        videoContainer.appendChild(dummyVideo);
                    }
                }, 200);
            }, 1500);

            this.mockTimeouts.push(t2);
        }, 1000);

        const t3 = setTimeout(() => {
            console.log('[MOCK-LIVEKIT] Simulating Bob connection');
            this.handleParticipantConnected({ identity: 'dummy-bob', name: 'Bob', isMicrophoneEnabled: false });
        }, 2500);

        this.mockTimeouts.push(t1, t3);

        // Periodically toggle speaking indicator for Bob/Alice
        this.speakerInterval = setInterval(() => {
            if (this.dotNetHelper) {
                const active = [];
                const rand = Math.random();
                if (rand > 0.4) active.push('dummy-alice');
                if (rand > 0.7) active.push('dummy-bob');
                this.dotNetHelper.invokeMethodAsync('OnActiveSpeakersChanged', active);
            }
        }, 3000);

        return {
            success: true,
            participants: []
        };
    },

    async disconnect() {
        if (this._resumeCtx) {
            document.removeEventListener('click', this._resumeCtx);
            document.removeEventListener('touchstart', this._resumeCtx);
            this._resumeCtx = null;
        }
        if (this.audioInterval) {
            clearInterval(this.audioInterval);
            this.audioInterval = null;
        }
        if (this.audioCtx) {
            try {
                this.audioCtx.close();
            } catch (e) {}
            this.audioCtx = null;
        }
        if (this.audioElement) {
            try {
                this.audioElement.pause();
            } catch (e) {}
            this.audioElement = null;
        }
        if (this.audioUrl) {
            try {
                URL.revokeObjectURL(this.audioUrl);
            } catch (e) {}
            this.audioUrl = null;
        }

        if (this.isMock) {
            console.log('[MOCK-LIVEKIT] Disconnecting from mock room');
            this.mockTimeouts.forEach(t => clearTimeout(t));
            if (this.speakerInterval) clearInterval(this.speakerInterval);
            this.isMock = false;
            this.room = null;
            this.localTrack = null;
            this.localVideoTrack = null;
            this.screenTrack = null;
            this.isMuted = false;
            this.isVideoEnabled = false;
            this.isScreenSharing = false;
            return;
        }

        this.room?.disconnect();
        this.localTrack?.stop();
        this.localVideoTrack?.stop();
        this.screenTrack?.stop();
        this.room = null;
        this.localTrack = null;
        this.localVideoTrack = null;
        this.screenTrack = null;
        this.isMuted = false;
        this.isVideoEnabled = false;
        this.isScreenSharing = false;
    },

    async toggleMute() {
        if (this.isMock) {
            this.isMuted = !this.isMuted;
            return !this.isMuted;
        }

        if (!this.room || !this.localTrack) return false;
        this.isMuted = !this.isMuted;
        this.localTrack.enabled = !this.isMuted;
        return !this.isMuted;
    },

    async toggleVideo() {
        if (this.isMock) {
            this.isVideoEnabled = !this.isVideoEnabled;
            this.triggerMockLocalStream(this.isVideoEnabled, 'webcam');
            return this.isVideoEnabled;
        }

        if (!this.room) return false;
        this.isVideoEnabled = !this.isVideoEnabled;

        if (this.isVideoEnabled) {
            const { createLocalVideoTrack } = await import('https://cdn.jsdelivr.net/npm/livekit-client@2/dist/livekit-client.esm.js');
            const videoTrack = await createLocalVideoTrack();
            this.localVideoTrack = videoTrack;
            await this.room.localParticipant.publishTrack(videoTrack);

            setTimeout(() => {
                const localContainer = document.getElementById('video-container-CurrentUser');
                if (localContainer) {
                    const videoElement = videoTrack.attach();
                    videoElement.classList.add('participant-video');
                    localContainer.appendChild(videoElement);
                }
            }, 100);
            return true;
        } else {
            if (this.localVideoTrack) {
                await this.room.localParticipant.unpublishTrack(this.localVideoTrack);
                this.localVideoTrack.stop();
                this.localVideoTrack = null;
            }
            return false;
        }
    },

    async startScreenShare() {
        if (this.isMock) {
            this.isScreenSharing = true;
            this.triggerMockLocalStream(true, 'screenshare');
            return true;
        }

        if (!this.room) return false;
        try {
            const { createLocalScreenTrack } = await import('https://cdn.jsdelivr.net/npm/livekit-client@2/dist/livekit-client.esm.js');
            const screenTrack = await createLocalScreenTrack({
                selfBrowserSurface: 'include',
                surfaceSwitching: 'include',
                systemAudio: 'include'
            });
            this.screenTrack = screenTrack;
            await this.room.localParticipant.publishTrack(screenTrack);
            this.isScreenSharing = true;

            setTimeout(() => {
                const localContainer = document.getElementById('video-container-CurrentUser');
                if (localContainer) {
                    const videoElement = screenTrack.attach();
                    videoElement.classList.add('participant-video');
                    localContainer.appendChild(videoElement);
                }
            }, 100);
            return true;
        } catch (error) {
            console.error('Failed to start screen share:', error);
            return false;
        }
    },

    async stopScreenShare() {
        if (this.isMock) {
            this.isScreenSharing = false;
            this.triggerMockLocalStream(false, 'screenshare');
            return true;
        }

        if (!this.room || !this.screenTrack) return false;
        await this.room.localParticipant.unpublishTrack(this.screenTrack);
        this.screenTrack.stop();
        this.screenTrack = null;
        this.isScreenSharing = false;
        return true;
    },

    triggerMockLocalStream(enabled, type) {
        setTimeout(() => {
            const container = document.getElementById('video-container-CurrentUser');
            if (!container) return;

            // Remove existing mock stream if any
            const existing = container.querySelector('.dummy-video-stream');
            if (existing) existing.remove();

            if (enabled) {
                const dummyVideo = document.createElement('div');
                dummyVideo.className = 'participant-video dummy-video-stream';
                dummyVideo.style.width = '100%';
                dummyVideo.style.height = '100%';
                dummyVideo.style.background = 'linear-gradient(135deg, #0f3460, #162447)';
                dummyVideo.style.display = 'flex';
                dummyVideo.style.flexDirection = 'column';
                dummyVideo.style.alignItems = 'center';
                dummyVideo.style.justifyContent = 'center';
                dummyVideo.style.color = '#fff';

                const icon = document.createElement('i');
                icon.className = type === 'webcam' ? 'bi bi-camera-video-fill' : 'bi bi-display';
                icon.style.fontSize = '2.5rem';
                icon.style.color = '#e94560';
                icon.style.textShadow = '0 0 10px rgba(233, 69, 96, 0.4)';
                dummyVideo.appendChild(icon);

                const label = document.createElement('div');
                label.style.marginTop = '10px';
                label.style.fontSize = '0.9rem';
                label.innerText = type === 'webcam' ? 'Your Webcam (Mock)' : 'Your Screen Share (Mock)';
                dummyVideo.appendChild(label);

                container.appendChild(dummyVideo);
            }
        }, 100);
    },

    handleParticipantConnected(participant) {
        this.dotNetHelper?.invokeMethodAsync('OnParticipantConnected', participant.identity, participant.name, participant.isMicrophoneEnabled === false);
    },

    handleParticipantDisconnected(participant) {
        this.dotNetHelper?.invokeMethodAsync('OnParticipantDisconnected', participant.identity);
    },

    handleTrackSubscribed(track, participant) {
        if (track.kind === 'audio') {
            let element = document.getElementById(`audio-${participant.identity}`);
            if (element) track.attach(element);
            else {
                const audioElement = track.attach();
                audioElement.id = `audio-${participant.identity}`;
            }
        } else if (track.kind === 'video') {
            this.dotNetHelper?.invokeMethodAsync('OnParticipantVideoToggled', participant.identity, true);

            setTimeout(() => {
                const videoContainer = document.getElementById(`video-container-${participant.identity}`);
                if (videoContainer) {
                    const videoElement = track.attach();
                    videoElement.classList.add('participant-video');
                    videoContainer.appendChild(videoElement);
                }
            }, 100);
        }
    },

    handleTrackUnsubscribed(track, publication, participant) {
        track.detach();
        if (track.kind === 'video') {
            this.dotNetHelper?.invokeMethodAsync('OnParticipantVideoToggled', participant.identity, false);
        }
    },

    setDotNetHelper(helper) { this.dotNetHelper = helper; },

    createBeepWavBlob() {
        const sampleRate = 8000;
        const duration = 0.5; // 0.5 seconds
        const numSamples = sampleRate * duration;
        const buffer = new ArrayBuffer(44 + numSamples);
        const view = new DataView(buffer);

        /* RIFF identifier */
        view.setUint32(0, 0x52494646, false); // "RIFF"
        /* file length */
        view.setUint32(4, 36 + numSamples, true);
        /* RIFF type */
        view.setUint32(8, 0x57415645, false); // "WAVE"
        /* format chunk identifier */
        view.setUint32(12, 0x666d7420, false); // "fmt "
        /* format chunk length */
        view.setUint32(16, 16, true);
        /* sample format (raw) */
        view.setUint16(20, 1, true); // PCM
        /* channel count */
        view.setUint16(22, 1, true); // Mono
        /* sample rate */
        view.setUint32(24, sampleRate, true);
        /* byte rate = (sampleRate * bitsPerSample * channels) / 8 */
        view.setUint32(28, sampleRate, true); // 8000 * 8 * 1 / 8
        /* block align = (bitsPerSample * channels) / 8 */
        view.setUint16(32, 1, true);
        /* bits per sample */
        view.setUint16(34, 8, true);
        /* data chunk identifier */
        view.setUint32(36, 0x64617461, false); // "data"
        /* data chunk length */
        view.setUint32(40, numSamples, true);

        // Generate a simple sine wave decaying over time
        const frequency = 440; // 440 Hz (A4)
        for (let i = 0; i < numSamples; i++) {
            const t = i / sampleRate;
            const sampleValue = Math.sin(2 * Math.PI * frequency * t);
            const decay = Math.exp(-6 * t);
            const val = Math.floor((sampleValue * decay * 127) + 128);
            view.setUint8(44 + i, val);
        }

        return new Blob([buffer], { type: 'audio/wav' });
    },

     getParticipants() {
        if (this.audioInterval) {
            return [
                { identity: 'test-voice-bot', name: 'Voice Loop Bot', isMuted: false, isSpeaking: false }
            ];
        }
        if (document.querySelector('.test-video-canvas')) {
            return [
                { identity: 'test-video-bot', name: 'Video Loop Bot', isMuted: false, isSpeaking: false }
            ];
        }
        if (this.isMock) {
            return [
                { identity: 'dummy-alice', name: 'Alice', isMuted: false, isSpeaking: false },
                { identity: 'dummy-bob', name: 'Bob', isMuted: true, isSpeaking: false }
            ];
        }
        if (!this.room) return [];
        return Array.from(this.room.participants.values()).map(p => ({
            identity: p.identity,
            name: p.name,
            isMuted: p.isMicrophoneEnabled === false,
            isSpeaking: p.isSpeaking
        }));
    },

    getActiveSpeakers() {
        if (this.isMock) return ['dummy-alice'];
        return this.room?.activeSpeakers.map(s => s.identity) || [];
    },

     startLocalTestLoop(roomName) {
        console.log('[TEST-LOOP] Starting local media test loop for room:', roomName);
        
        if (roomName === '3' || roomName === 'Test Voice') {
            // Spawn Voice Test Bot
            this.dotNetHelper?.invokeMethodAsync('OnParticipantConnected', 'test-voice-bot', 'Voice Loop Bot', false);
            
            // Loop audio via HTML5 Audio element to bypass mobile hardware silent switch and autoplay policies
            try {
                const blob = this.createBeepWavBlob();
                this.audioUrl = URL.createObjectURL(blob);
                this.audioElement = new Audio(this.audioUrl);
                this.audioElement.volume = 0.2;
                
                // Attempt immediate play (might fail due to autoplay blocks)
                this.audioElement.play().catch(e => {
                    console.log('[TEST-LOOP] Initial autoplay blocked, waiting for user gesture');
                });
                
                // Event listener to unlock audio on user interaction
                const unlock = () => {
                    if (this.audioElement) {
                        this.audioElement.play()
                            .then(() => {
                                console.log('[TEST-LOOP] Audio unlocked and playing');
                                document.removeEventListener('click', unlock);
                                document.removeEventListener('touchstart', unlock);
                            })
                            .catch(e => {
                                console.warn('[TEST-LOOP] Failed to play on interaction:', e);
                            });
                    }
                };
                document.addEventListener('click', unlock);
                document.addEventListener('touchstart', unlock);
                this._resumeCtx = unlock;

                // Play the audio element every 2 seconds
                this.audioInterval = setInterval(() => {
                    if (this.audioElement) {
                        this.audioElement.currentTime = 0;
                        this.audioElement.play().catch(e => {
                            console.debug('[TEST-LOOP] Failed to play audio in interval:', e);
                        });
                    }
                    
                    // Trigger speaking indicator
                    this.dotNetHelper?.invokeMethodAsync('OnActiveSpeakersChanged', ['test-voice-bot']);
                    setTimeout(() => {
                        this.dotNetHelper?.invokeMethodAsync('OnActiveSpeakersChanged', []);
                    }, 400);
                }, 2000);
            } catch (e) {
                console.error('[TEST-LOOP] Failed to initialize Audio element:', e);
            }
        }
        
        if (roomName === '4' || roomName === 'Test Video') {
            // Spawn Video Test Bot
            this.dotNetHelper?.invokeMethodAsync('OnParticipantConnected', 'test-video-bot', 'Video Loop Bot', false);
            
            // Delay video toggle to avoid race condition in Blazor state update
            setTimeout(() => {
                this.dotNetHelper?.invokeMethodAsync('OnParticipantVideoToggled', 'test-video-bot', true);
            }, 300);
            
            // Render looping visualizer on canvas
            let attempts = 0;
            const tryAttachCanvas = () => {
                const container = document.getElementById('video-container-test-video-bot');
                if (!container) {
                    attempts++;
                    if (attempts < 50) {
                        setTimeout(tryAttachCanvas, 100);
                    } else {
                        console.error('[TEST-LOOP] Failed to find video-container-test-video-bot after 5s');
                    }
                    return;
                }
                
                const canvas = document.createElement('canvas');
                canvas.width = 320;
                canvas.height = 240;
                canvas.style.width = '100%';
                canvas.style.height = '100%';
                canvas.style.objectFit = 'cover';
                canvas.classList.add('participant-video', 'test-video-canvas');
                container.appendChild(canvas);
                
                const ctx = canvas.getContext('2d');
                let angle = 0;
                const render = () => {
                    if (!document.body.contains(canvas)) return; // Stop if removed
                    
                    ctx.fillStyle = '#111';
                    ctx.fillRect(0, 0, canvas.width, canvas.height);
                    
                    // Rainbow moving gradient
                    const grad = ctx.createLinearGradient(0, 0, canvas.width, canvas.height);
                    grad.addColorStop(0, '#e94560');
                    grad.addColorStop(0.5, '#0f3460');
                    grad.addColorStop(1, '#162447');
                    ctx.fillStyle = grad;
                    
                    const x = canvas.width / 2 + Math.cos(angle) * 60;
                    const y = canvas.height / 2 + Math.sin(angle) * 45;
                    ctx.beginPath();
                    ctx.arc(x, y, 25, 0, Math.PI * 2);
                    ctx.fill();
                    
                    // Draw nice target box
                    ctx.strokeStyle = '#e94560';
                    ctx.lineWidth = 2;
                    ctx.strokeRect(20, 20, canvas.width - 40, canvas.height - 40);
                    
                    ctx.fillStyle = '#fff';
                    ctx.font = 'bold 14px sans-serif';
                    ctx.textAlign = 'center';
                    ctx.fillText('VIDEO LOOP TEST', canvas.width / 2, 45);
                    ctx.font = '12px monospace';
                    ctx.fillText(new Date().toLocaleTimeString(), canvas.width / 2, canvas.height - 40);
                    
                    angle += 0.04;
                    requestAnimationFrame(render);
                };
                render();
            };
            setTimeout(tryAttachCanvas, 400);
        }
    }
};

window.streamHelper = {
    currentStream: null,
    async startCapture(videoElementId) {
        try {
            const stream = await navigator.mediaDevices.getDisplayMedia({
                video: {
                    frameRate: 60
                },
                audio: true
            });
            
            const video = document.getElementById(videoElementId);
            if (video) {
                video.srcObject = stream;
                video.onloadedmetadata = () => video.play();
                
                this.currentStream = stream;
                return true;
            }
        } catch (err) {
            console.error("Error capturing screen:", err);
        }
        return false;
    },
    stopCapture(videoElementId) {
        if (this.currentStream) {
            this.currentStream.getTracks().forEach(track => track.stop());
            this.currentStream = null;
        }
        const video = document.getElementById(videoElementId);
        if (video) {
            video.srcObject = null;
        }
    }
};
