/**
 * WebRTC client module for RoohAI.
 *
 * Manages RTCPeerConnection, data channel for status messages,
 * and remote audio track playback.
 */
(function () {
    "use strict";

    var pc = null;
    var dataChannel = null;
    var localStream = null;
    var remoteAudio = null;

    /**
     * Connect to the WebRTC server.
     * @param {string} deviceId - Audio input device ID
     * @param {function} onMessage - Callback for data channel messages (parsed JSON)
     * @param {function} onDisconnect - Callback when connection closes
     * @returns {Promise<void>}
     */
    async function connect(deviceId, onMessage, onDisconnect) {
        // Get microphone
        var constraints = { audio: true };
        if (deviceId) {
            constraints.audio = { deviceId: { exact: deviceId } };
        }
        localStream = await navigator.mediaDevices.getUserMedia(constraints);

        // Create peer connection
        pc = new RTCPeerConnection({
            iceServers: [{ urls: "stun:stun.l.google.com:19302" }]
        });

        // Add local audio track
        localStream.getAudioTracks().forEach(function (track) {
            pc.addTrack(track, localStream);
        });

        // Create data channel for status messages
        dataChannel = pc.createDataChannel("status");

        dataChannel.onopen = function () {
            // Data channel ready
        };

        dataChannel.onmessage = function (event) {
            var data;
            try {
                data = JSON.parse(event.data);
            } catch (e) {
                return;
            }
            if (onMessage) onMessage(data);
        };

        dataChannel.onclose = function () {
            if (onDisconnect) onDisconnect();
        };

        // Handle remote audio track (TTS output)
        pc.ontrack = function (event) {
            if (event.track.kind === "audio") {
                if (!remoteAudio) {
                    remoteAudio = document.createElement("audio");
                    remoteAudio.autoplay = true;
                    remoteAudio.id = "webrtc-remote-audio";
                    document.body.appendChild(remoteAudio);
                }
                remoteAudio.srcObject = event.streams[0];
            }
        };

        pc.onconnectionstatechange = function () {
            if (pc.connectionState === "failed" || pc.connectionState === "closed") {
                if (onDisconnect) onDisconnect();
            }
        };

        // Create and send SDP offer
        var offer = await pc.createOffer();
        await pc.setLocalDescription(offer);

        // Wait for ICE gathering to complete (or timeout)
        await waitForIceGathering(pc, 3000);

        var resp = await fetch("/api/webrtc/offer", {
            method: "POST",
            headers: { "Content-Type": "application/json" },
            body: JSON.stringify({
                sdp: pc.localDescription.sdp,
                type: pc.localDescription.type
            })
        });

        if (!resp.ok) {
            throw new Error("WebRTC offer failed: " + resp.status);
        }

        var answer = await resp.json();
        await pc.setRemoteDescription(new RTCSessionDescription({
            sdp: answer.sdp,
            type: answer.type
        }));
    }

    /**
     * Wait for ICE gathering to complete or timeout.
     */
    function waitForIceGathering(pc, timeoutMs) {
        return new Promise(function (resolve) {
            if (pc.iceGatheringState === "complete") {
                resolve();
                return;
            }
            var timer = setTimeout(resolve, timeoutMs);
            pc.onicegatheringstatechange = function () {
                if (pc.iceGatheringState === "complete") {
                    clearTimeout(timer);
                    resolve();
                }
            };
        });
    }

    /**
     * Pause audio capture without tearing down the connection.
     */
    function pause() {
        // Disable the local audio track (stops sending audio)
        if (localStream) {
            localStream.getAudioTracks().forEach(function (track) {
                track.enabled = false;
            });
        }
        // Notify server
        if (dataChannel && dataChannel.readyState === "open") {
            dataChannel.send(JSON.stringify({ type: "pause_audio" }));
        }
    }

    /**
     * Resume audio capture.
     */
    function resume() {
        if (localStream) {
            localStream.getAudioTracks().forEach(function (track) {
                track.enabled = true;
            });
        }
        if (dataChannel && dataChannel.readyState === "open") {
            dataChannel.send(JSON.stringify({ type: "resume_audio" }));
        }
    }

    /**
     * Disconnect and clean up.
     */
    function disconnect() {
        if (dataChannel) {
            dataChannel.close();
            dataChannel = null;
        }
        if (pc) {
            pc.close();
            pc = null;
        }
        if (localStream) {
            localStream.getTracks().forEach(function (t) { t.stop(); });
            localStream = null;
        }
        if (remoteAudio) {
            remoteAudio.srcObject = null;
            remoteAudio.remove();
            remoteAudio = null;
        }
    }

    /**
     * Send playback_done to server via data channel.
     */
    function sendPlaybackDone() {
        if (dataChannel && dataChannel.readyState === "open") {
            dataChannel.send(JSON.stringify({ type: "playback_done" }));
        }
    }

    /**
     * Mute/unmute remote audio briefly (used during barge-in).
     */
    function muteRemoteAudio(durationMs) {
        if (remoteAudio) {
            remoteAudio.muted = true;
            setTimeout(function () {
                if (remoteAudio) remoteAudio.muted = false;
            }, durationMs || 300);
        }
    }

    /**
     * Check if currently connected.
     */
    function isConnected() {
        return pc !== null && pc.connectionState === "connected";
    }

    // Expose as global
    window.WebRTCClient = {
        connect: connect,
        disconnect: disconnect,
        pause: pause,
        resume: resume,
        sendPlaybackDone: sendPlaybackDone,
        muteRemoteAudio: muteRemoteAudio,
        isConnected: isConnected
    };
})();
