(function () {
    'use strict';

    var recorders = Array.prototype.slice.call(document.querySelectorAll('[data-audio-recorder]'));
    if (!recorders.length) return;

    var MAX_AUDIO_BYTES = 25 * 1024 * 1024;
    var CHUNK_BYTES = 512 * 1024;

    function supportedMimeType() {
        if (!window.MediaRecorder || typeof MediaRecorder.isTypeSupported !== 'function') return '';
        var types = ['audio/webm;codecs=opus', 'audio/ogg;codecs=opus', 'audio/mp4', 'audio/webm'];
        for (var i = 0; i < types.length; i++) {
            if (MediaRecorder.isTypeSupported(types[i])) return types[i];
        }
        return '';
    }

    function extensionFor(type) {
        type = String(type || '').toLowerCase();
        if (type.indexOf('ogg') !== -1) return 'ogg';
        if (type.indexOf('mp4') !== -1 || type.indexOf('m4a') !== -1) return 'm4a';
        return 'webm';
    }

    function randomId() {
        if (window.crypto && window.crypto.getRandomValues) {
            var bytes = new Uint8Array(12);
            window.crypto.getRandomValues(bytes);
            return Array.prototype.map.call(bytes, function (value) { return value.toString(16).padStart(2, '0'); }).join('');
        }
        return String(Date.now()) + String(Math.random()).slice(2);
    }

    async function readJson(response) {
        var text = await response.text();
        var data;
        try { data = JSON.parse(text); } catch (error) { data = { ok: false, message: text || 'Resposta inválida do servidor.' }; }
        if (!response.ok || !data.ok) throw new Error(data.message || 'Não foi possível enviar o áudio.');
        return data;
    }

    recorders.forEach(function (box) {
        var form = box.closest('form');
        var input = box.querySelector('[data-audio-input]');
        var start = box.querySelector('[data-audio-record]');
        var stop = box.querySelector('[data-audio-stop]');
        var choose = box.querySelector('[data-audio-choose]');
        var clear = box.querySelector('[data-audio-clear]');
        var status = box.querySelector('[data-audio-status]');
        var preview = box.querySelector('[data-audio-preview]');
        var mediaRecorder = null;
        var stream = null;
        var chunks = [];
        var previewUrl = '';
        var startedAt = 0;
        var timer = null;
        var selectedFile = null;
        var sending = false;

        function setStatus(text, danger) {
            if (!status) return;
            status.textContent = text;
            status.classList.toggle('text-danger', !!danger);
            status.classList.toggle('text-muted', !danger);
        }

        function stopStream() {
            if (stream) stream.getTracks().forEach(function (track) { track.stop(); });
            stream = null;
        }

        function clearTimer() {
            if (timer) window.clearInterval(timer);
            timer = null;
        }

        function showSelected(file) {
            selectedFile = file || null;
            if (previewUrl) URL.revokeObjectURL(previewUrl);
            previewUrl = file ? URL.createObjectURL(file) : '';
            if (preview) {
                preview.src = previewUrl;
                preview.classList.toggle('d-none', !file);
            }
            if (clear) clear.classList.toggle('d-none', !file);
            setStatus(file ? 'Áudio pronto: ' + file.name : 'Nenhum áudio selecionado.');
        }

        function validFile(file) {
            if (!file) return false;
            if (file.size <= 0) {
                setStatus('O áudio selecionado está vazio.', true);
                return false;
            }
            if (file.size > MAX_AUDIO_BYTES) {
                setStatus('O áudio ultrapassa o limite de 25 MB.', true);
                return false;
            }
            return true;
        }

        function putFile(file) {
            if (!input || !validFile(file)) return false;
            showSelected(file);
            try {
                var transfer = new DataTransfer();
                transfer.items.add(file);
                input.files = transfer.files;
            } catch (error) {
                // Alguns navegadores móveis não permitem alterar input.files.
                // selectedFile mantém a gravação e o envio em partes funciona normalmente.
            }
            return true;
        }

        choose && choose.addEventListener('click', function () { input && input.click(); });
        input && input.addEventListener('change', function () {
            var file = input.files && input.files[0];
            if (file && validFile(file)) showSelected(file);
            else if (input) input.value = '';
        });
        clear && clear.addEventListener('click', function () {
            if (input) input.value = '';
            showSelected(null);
        });

        start && start.addEventListener('click', async function () {
            if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia || !window.MediaRecorder) {
                setStatus('A gravação direta não é compatível com este navegador. Use “Escolher áudio”.', true);
                return;
            }
            try {
                stream = await navigator.mediaDevices.getUserMedia({ audio: true });
                chunks = [];
                var mime = supportedMimeType();
                var options = { audioBitsPerSecond: 24000 };
                if (mime) options.mimeType = mime;
                try { mediaRecorder = new MediaRecorder(stream, options); }
                catch (error) { mediaRecorder = mime ? new MediaRecorder(stream, { mimeType: mime }) : new MediaRecorder(stream); }
                mediaRecorder.addEventListener('dataavailable', function (event) {
                    if (event.data && event.data.size > 0) chunks.push(event.data);
                });
                mediaRecorder.addEventListener('stop', function () {
                    clearTimer();
                    var actualType = mediaRecorder.mimeType || mime || 'audio/webm';
                    var blob = new Blob(chunks, { type: actualType });
                    var file = new File([blob], 'audio-' + Date.now() + '.' + extensionFor(actualType), { type: actualType, lastModified: Date.now() });
                    putFile(file);
                    stopStream();
                    start.classList.remove('d-none');
                    stop && stop.classList.add('d-none');
                });
                mediaRecorder.start(500);
                startedAt = Date.now();
                start.classList.add('d-none');
                stop && stop.classList.remove('d-none');
                setStatus('Gravando… 00:00');
                timer = window.setInterval(function () {
                    var seconds = Math.floor((Date.now() - startedAt) / 1000);
                    var minutes = String(Math.floor(seconds / 60)).padStart(2, '0');
                    var remainder = String(seconds % 60).padStart(2, '0');
                    setStatus('Gravando… ' + minutes + ':' + remainder);
                    if (seconds >= 300 && mediaRecorder && mediaRecorder.state === 'recording') mediaRecorder.stop();
                }, 500);
            } catch (error) {
                stopStream();
                setStatus('Permita o uso do microfone ou escolha um áudio do aparelho.', true);
            }
        });

        stop && stop.addEventListener('click', function () {
            if (mediaRecorder && mediaRecorder.state === 'recording') mediaRecorder.stop();
        });

        if (form) form.addEventListener('submit', async function (event) {
            if (sending) return;
            if (mediaRecorder && mediaRecorder.state === 'recording') {
                event.preventDefault();
                setStatus('Pare a gravação antes de enviar.', true);
                return;
            }
            if (!selectedFile) return;

            event.preventDefault();
            var chunkUrl = form.getAttribute('data-audio-chunk-url');
            var finalizeUrl = form.getAttribute('data-audio-finalize-url');
            if (!chunkUrl || !finalizeUrl) {
                setStatus('A página precisa ser atualizada para enviar o áudio.', true);
                return;
            }
            if (!validFile(selectedFile)) return;

            sending = true;
            var buttons = Array.prototype.slice.call(form.querySelectorAll('button[type="submit"], button:not([type])'));
            buttons.forEach(function (button) { button.disabled = true; });
            try {
                var csrf = form.querySelector('input[name="_csrf"]');
                var token = form.querySelector('input[name="token"]');
                var uploadId = randomId();
                var totalChunks = Math.ceil(selectedFile.size / CHUNK_BYTES);
                for (var index = 0; index < totalChunks; index++) {
                    var from = index * CHUNK_BYTES;
                    var to = Math.min(selectedFile.size, from + CHUNK_BYTES);
                    var part = selectedFile.slice(from, to, selectedFile.type || 'application/octet-stream');
                    var chunkData = new FormData();
                    chunkData.append('_csrf', csrf ? csrf.value : '');
                    if (token) chunkData.append('token', token.value);
                    chunkData.append('upload_id', uploadId);
                    chunkData.append('chunk_index', String(index));
                    chunkData.append('total_chunks', String(totalChunks));
                    chunkData.append('original_name', selectedFile.name || ('audio.' + extensionFor(selectedFile.type)));
                    chunkData.append('file_size', String(selectedFile.size));
                    chunkData.append('mime_type', selectedFile.type || 'audio/webm');
                    chunkData.append('audio_chunk', part, 'parte-' + index + '.bin');
                    setStatus('Enviando áudio… ' + Math.round((index / totalChunks) * 100) + '%');
                    await readJson(await fetch(chunkUrl, { method: 'POST', body: chunkData, credentials: 'same-origin', cache: 'no-store' }));
                }

                var finalData = new FormData();
                finalData.append('_csrf', csrf ? csrf.value : '');
                if (token) finalData.append('token', token.value);
                finalData.append('upload_id', uploadId);
                setStatus('Preparando áudio… 100%');
                var finalized = await readJson(await fetch(finalizeUrl, { method: 'POST', body: finalData, credentials: 'same-origin', cache: 'no-store' }));

                var messageData = new FormData(form);
                messageData.delete('message_audio');
                messageData.append('message_audio_token', finalized.token);
                setStatus('Enviando mensagem…');
                var response = await fetch(form.action, { method: 'POST', body: messageData, credentials: 'same-origin', cache: 'no-store', redirect: 'follow' });
                if (!response.ok) {
                    var responseText = await response.text();
                    throw new Error(responseText || 'Não foi possível enviar a mensagem.');
                }
                window.location.assign(response.url || form.action);
            } catch (error) {
                sending = false;
                buttons.forEach(function (button) { button.disabled = false; });
                setStatus(error && error.message ? error.message : 'Não foi possível enviar o áudio.', true);
            }
        });

        window.addEventListener('beforeunload', stopStream);
    });
})();
