// Shared helpers for chat UIs

async function apiCall(endpoint, options = {}) {
    const defaultOptions = { method: 'GET', headers: { 'Content-Type': 'application/json' } };
    const finalOptions = { ...defaultOptions, ...options };
    if (options.body && typeof options.body === 'object') {
        finalOptions.method = 'POST';
        finalOptions.body = JSON.stringify(options.body);
    }

    let url = endpoint;
    if (!/^https?:\/\//i.test(url) && !url.startsWith('api/')) url = 'api/' + url;

    const resp = await fetch(url, finalOptions);
    const text = await resp.text();

    if (!resp.ok) {
        const snippet = text && text.length ? (text.length > 2000 ? text.substr(0,2000)+'... (truncated)' : text) : '<no body>';
        console.error('apiCall HTTP error', resp.status, url, snippet);
        throw new Error('HTTP error! status: ' + resp.status + ' -- ' + snippet);
    }

    if (!text || text.trim() === '') return null;
    try {
        return JSON.parse(text);
    } catch (err) {
        console.error('apiCall parse error for', url, err);
        const snippet = text.length > 1000 ? text.substr(0,1000) : text;
        throw new Error('Invalid JSON response from ' + url + ': ' + err.message + ' -- response snippet: ' + snippet);
    }
}

function isValidMediaUrl(u) {
    return (typeof u === 'string') && u.trim() !== '' && u !== 'null' && u !== 'undefined';
}

function ensureProxyUrl(u, download = false) {
    if (!isValidMediaUrl(u)) return '';
    if (u.startsWith('/') || u.indexOf('/api/version/media-url.php') === 0) return u;
    // Si empieza con api/ agregar / al inicio
    if (u.startsWith('api/')) return '/' + u;
    try {
        const parsed = new URL(u);
        const host = parsed.host.toLowerCase();
        if (host.includes('lookaside.fbsbx.com') || host.includes('facebook.com') || host.includes('graph.facebook.com')) {
            return `/api/version/media-url.php?url=${encodeURIComponent(u)}${download ? '&download=1' : ''}`;
        }
    } catch (e) {}
    return u;
}

function renderMediaMessage(msg) {
    if (!msg) return '';
    const mediaType = msg.message_type || msg.media_type || 'text';
    const content = msg.content || '';
    const mediaExternal = msg.media_url_external || msg.media_url || '';
    const localFile = msg.local_file || '';
    const localThumb = msg.local_thumb || '';

    const effective = isValidMediaUrl(mediaExternal) ? mediaExternal : (isValidMediaUrl(localFile) ? `/`+localFile : (isValidMediaUrl(localThumb) ? `/`+localThumb : (isValidMediaUrl(msg.media_url) ? msg.media_url : '')));

    switch (mediaType) {
        case 'image': {
            // Compute thumbnail and full image URL following chat_window heuristics
            let thumbUrl = '';
            if (isValidMediaUrl(localThumb)) {
                thumbUrl = `/${localThumb}`;
            } else if (isValidMediaUrl(localFile)) {
                thumbUrl = `/${localFile}`;
            } else if (isValidMediaUrl(effective) || isValidMediaUrl(mediaExternal)) {
                const external = isValidMediaUrl(effective) ? effective : mediaExternal;
                if (/lookaside\.fbsbx\.com|graph\.facebook\.com|facebook\.com/i.test(external)) {
                    const m = external.match(/[?&]mid=([^&]+)/i);
                    if (m && m[1]) {
                        thumbUrl = `/api/version/media-url.php?id=${encodeURIComponent(m[1])}`;
                    } else {
                        thumbUrl = `/api/version/media-url.php?url=${encodeURIComponent(external)}`;
                    }
                } else {
                    // Route through media-url.php proxy (handles caching + auth)
                    if (external.indexOf('api/get_media.php?id=') !== -1 || external.indexOf('api/version/media-url.php?id=') !== -1) {
                        const parts = external.split('id=');
                        const mid = parts[1] ? decodeURIComponent(parts[1]) : '';
                        thumbUrl = mid ? `/api/version/media-url.php?id=${encodeURIComponent(mid)}` : external;
                    } else {
                        thumbUrl = ensureProxyUrl(external) || external;
                    }
                }
            } else if (isValidMediaUrl(msg.media_url)) {
                thumbUrl = msg.media_url;
            }

            // Full URL for opening (prefer local file then external with id or url)
            let fullUrl = '';
            if (isValidMediaUrl(localFile)) {
                // Usar archivo local directamente sin proxy
                fullUrl = localFile.startsWith('/') ? localFile : `/${localFile}`;
            } else if (isValidMediaUrl(mediaExternal)) {
                let mid = '';
                if (mediaExternal.indexOf('api/get_media.php?id=') !== -1 || mediaExternal.indexOf('api/version/media-url.php?id=') !== -1) {
                    const parts = mediaExternal.split('id='); mid = parts[1] ? decodeURIComponent(parts[1]) : '';
                } else {
                    const m = mediaExternal.match(/[?&]mid=([^&]+)/i); if (m && m[1]) mid = decodeURIComponent(m[1]);
                }
                if (mid) fullUrl = `/api/version/media-url.php?id=${encodeURIComponent(mid)}`;
                else if (/^https?:\/\//i.test(mediaExternal)) fullUrl = `/api/version/media-url.php?url=${encodeURIComponent(mediaExternal)}`;
                else fullUrl = `/api/version/media-url.php?url=${encodeURIComponent(mediaExternal)}`;
            } else {
                fullUrl = '';
            }

            if (isValidMediaUrl(fullUrl)) {
                return `<div class="message-media"><a href="#" data-fullurl="${escapeHtml(fullUrl)}" onclick="openImageLightbox(this.dataset.fullurl); return false;" title="Abrir imagen"><img src="${escapeHtml(thumbUrl || fullUrl)}" alt="Imagen" class="message-media-image"></a></div>${content?`<div>${escapeHtml(content)}</div>`:''}`;
            } else if (isValidMediaUrl(thumbUrl)) {
                return `<div class="message-media"><img src="${escapeHtml(thumbUrl)}" alt="Imagen" class="message-media-image"></div>${content?`<div>${escapeHtml(content)}</div>`:''}`;
            }

            return `<div class="text-muted"><em>Imagen no disponible</em></div>`;
        }
        case 'video': {
            // Priorizar local_file sobre otras fuentes
            let src = '';
            if (isValidMediaUrl(localFile)) {
                src = localFile.startsWith('/') ? localFile : `/${localFile}`;
            } else {
                src = ensureProxyUrl(effective || msg.media_url || '');
            }
            if (src) return `<div class="message-media"><video controls><source src="${escapeHtml(src)}" type="video/mp4">Tu navegador no soporta video.</video></div>${content?`<div>${escapeHtml(content)}</div>`:''}`;
            return `<div class="text-muted"><em>Video no disponible</em></div>`;
        }
        case 'audio': {
            // Priorizar local_file sobre otras fuentes
            let src = '';
            if (isValidMediaUrl(localFile)) {
                src = localFile.startsWith('/') ? localFile : `/${localFile}`;
            } else {
                src = ensureProxyUrl(effective || msg.media_url || '');
            }
            if (!src) return `<div class="text-muted"><em>Audio no disponible</em></div>`;
            // build download link when possible (api/get_media.php?id=... or direct url or local file)
            let audioDownload = null;
            const candidate = isValidMediaUrl(localFile) ? localFile : (isValidMediaUrl(effective) ? effective : (isValidMediaUrl(msg.media_url) ? msg.media_url : null));
            if (candidate && candidate.indexOf && candidate.indexOf('api/get_media.php?id=') !== -1) {
                const parts = candidate.split('id=');
                const mid = parts[1] ? parts[1] : '';
                audioDownload = `/api/version/media-url.php?id=${encodeURIComponent(mid)}&download=1`;
            } else if (candidate && /^https?:\/\//i.test(candidate)) {
                audioDownload = `/api/version/media-url.php?url=${encodeURIComponent(candidate)}&download=1`;
            } else if (candidate && candidate === localFile) {
                // Usar archivo local directamente sin proxy
                audioDownload = localFile.startsWith('/') ? localFile : `/${localFile}`;
            }

            let html = `<div class="message-media"><audio controls><source src="${escapeHtml(src)}" type="audio/mpeg">Tu navegador no soporta audio.</audio></div>`;
            if (audioDownload) {
                html += `<div class="mt-2"><a href="${escapeHtml(audioDownload)}" class="btn btn-sm btn-outline-secondary" target="_blank" rel="noopener noreferrer">Descargar audio</a></div>`;
            }
            return html;
        }
        case 'document': {
            const filename = msg.filename || content || 'Documento';
            let docUrl = '';
            if (isValidMediaUrl(mediaExternal) && mediaExternal.indexOf('api/get_media.php?id=') !== -1) {
                const parts = mediaExternal.split('id=');
                docUrl = `/api/version/media-url.php?id=${encodeURIComponent(parts[1])}&download=1`;
            } else if (isValidMediaUrl(mediaExternal) && /^https?:\/\//i.test(mediaExternal)) {
                docUrl = `/api/version/media-url.php?url=${encodeURIComponent(mediaExternal)}&download=1`;
            } else if (isValidMediaUrl(localFile)) {
                // Usar archivo local directamente sin proxy
                docUrl = localFile.startsWith('/') ? localFile : `/${localFile}`;
            }
            if (docUrl) return `<a href="${docUrl}" class="message-document" target="_blank" rel="noopener noreferrer"><i class="fas fa-file-pdf"></i><span>${escapeHtml(filename)}</span></a>`;
            return `<div class="message-document" style="opacity:0.6;"><i class="fas fa-file-pdf"></i><span>${escapeHtml(filename)} (No disponible)</span></div>`;
        }
        default:
            return escapeHtml(content || '');
    }
}

async function loadTemplatesInto(selector) {
    try {
        const resp = await apiCall('check_templates.php');
        const sel = document.querySelector(selector);
        if (!sel) return;
        sel.innerHTML = '<option value="">Seleccionar plantilla...</option>';
        if (resp && resp.templates && Array.isArray(resp.templates)) {
            resp.templates.forEach(t => {
                const opt = document.createElement('option');
                opt.value = t.name;
                const lang = t.language_code || t.language || 'en_US';
                opt.textContent = `${t.display_name || t.name} (${lang})`;
                opt.dataset.language = lang;
                sel.appendChild(opt);
            });
        }
    } catch (e) {
        console.error('loadTemplatesInto error', e);
    }
}

// FFmpeg helpers (client-side conversion)
let _ffmpegInstance = null;
let _ffmpegLoaded = false;
async function ensureFFmpeg() {
    if (_ffmpegLoaded) return;
    if (typeof WebAssembly === 'undefined') throw new Error('WebAssembly no disponible');
    if (!window.FFmpeg || !window.FFmpeg.createFFmpeg) {
        await new Promise((resolve, reject) => {
            const s = document.createElement('script');
            s.src = 'https://unpkg.com/@ffmpeg/ffmpeg@0.11.8/dist/ffmpeg.min.js';
            s.onload = resolve; s.onerror = reject; document.head.appendChild(s);
        });
    }
    const { createFFmpeg, fetchFile } = window.FFmpeg;
    _ffmpegInstance = createFFmpeg({ log: false });
    await _ffmpegInstance.load();
    _ffmpegInstance._fetchFile = fetchFile;
    _ffmpegLoaded = true;
}

async function convertWebmToOgg(file) {
    await ensureFFmpeg();
    const inName = 'input.webm';
    const outName = 'output.ogg';
    let data;
    if (_ffmpegInstance._fetchFile) data = await _ffmpegInstance._fetchFile(file);
    else data = new Uint8Array(await file.arrayBuffer());
    _ffmpegInstance.FS('writeFile', inName, data);
    // Parámetros compatibles con WhatsApp Voice Messages:
    // -c:a libopus = códec OPUS (requerido)
    // -b:a 32k = bitrate bajo para mantener archivo < 512KB (ícono play)
    // -ar 48000 = sample rate 48kHz (estándar OPUS)
    // -ac 1 = mono (reduce tamaño)
    // -vbr on = variable bitrate para mejor calidad
    await _ffmpegInstance.run('-i', inName, '-c:a', 'libopus', '-b:a', '32k', '-ar', '48000', '-ac', '1', '-vbr', 'on', outName);
    const outData = _ffmpegInstance.FS('readFile', outName);
    const blob = new Blob([outData.buffer], { type: 'audio/ogg; codecs=opus' });
    const newFile = new File([blob], (file.name || 'audio').replace(/\.[^/.]+$/, '') + '.ogg', { type: 'audio/ogg; codecs=opus' });
    return newFile;
}

// Expose
window.apiCall = apiCall;
window.isValidMediaUrl = isValidMediaUrl;
window.ensureProxyUrl = ensureProxyUrl;
window.renderMediaMessage = renderMediaMessage;
window.loadTemplatesInto = loadTemplatesInto;
window.ensureFFmpeg = ensureFFmpeg;
window.convertWebmToOgg = convertWebmToOgg;

// small utility
function escapeHtml(text) {
    if (!text) return '';
    return (''+text).replace(/[&<>"']/g, function(m){ return ({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#039;'})[m]; });
}
window.escapeHtml = escapeHtml;