(function () {
  const boot = window.UGFX_CHAT_BOOT || null;
  const app = document.getElementById('ugfxChatApp');
  if (!app || !boot) return;

  const feed = app.querySelector('[data-chat-feed]');
  const form = app.querySelector('[data-chat-form]');
  const attachments = app.querySelector('[data-chat-attachments]');
  const statusEl = app.querySelector('[data-chat-status]');
  const recordStatus = app.querySelector('[data-record-status]');
  const countEl = app.querySelector('[data-chat-count]');
  const nameInput = form.querySelector('[name="name"]');
  const messageInput = form.querySelector('[name="message"]');
  const gifInput = form.querySelector('[name="gif_url"]');
  const stickerInput = form.querySelector('[name="sticker"]');
  const voiceInput = form.querySelector('[name="voice_url"]');
  const voiceMimeInput = form.querySelector('[name="voice_mime"]');
  const panels = [...app.querySelectorAll('[data-panel]')];
  const panelButtons = [...app.querySelectorAll('[data-panel-toggle]')];
  const emojiGrid = app.querySelector('[data-emoji-grid]');
  const emojiSearch = app.querySelector('[data-emoji-search]');
  const emojiFilters = [...app.querySelectorAll('[data-emoji-filter]')];
  const stickerGrid = app.querySelector('[data-sticker-grid]');
  const gifUrlInput = app.querySelector('[data-gif-url-input]');
  const gifAttach = app.querySelector('[data-gif-attach]');
  const gifPresets = app.querySelector('[data-gif-presets]');
  const recordButton = app.querySelector('[data-record-toggle]');
  const getUrl = app.dataset.chatGet;
  const postUrl = app.dataset.chatPost;
  const uploadUrl = app.dataset.chatUpload;

  const EMOJIS = [
    ['😀','faces','grin smile happy'],['😃','faces','smile happy bright'],['😄','faces','grin happy laugh'],['😁','faces','teeth smile'],['😆','faces','laugh lol'],['😅','faces','sweat laugh'],['😂','faces','cry laugh lol'],['🤣','faces','rofl lol'],['😊','faces','blush smile'],['😍','love','heart eyes love'],['🥰','love','hearts adore'],['😘','love','kiss'],['😎','faces','cool shades'],['🤩','faces','star eyes'],['🥳','party','party celebrate'],['😇','faces','angel'],['😉','faces','wink'],['🤗','love','hug'],['🫶','love','heart hands'],['🤘','energy','rock hand'],['🔥','energy','fire hot'],['⚡','energy','electric power'],['🚀','energy','rocket launch'],['💥','energy','boom'],['🎧','music','headphones dj'],['🎤','music','microphone sing'],['🎶','music','notes music'],['🎵','music','note'],['📻','music','radio'],['🪩','party','disco dance'],['💃','party','dance'],['🕺','party','dance'],['🙌','party','celebrate hands'],['👏','party','clap'],['❤️','love','heart red'],['🧡','love','orange heart'],['💛','love','yellow heart'],['💚','love','green heart'],['💙','love','blue heart'],['💜','love','purple heart'],['🖤','love','black heart'],['🤍','love','white heart'],['🤎','love','brown heart'],['💯','energy','hundred'],['🎉','party','confetti'],['🎊','party','celebration'],['🥂','party','cheers'],['🍾','party','bottle'],['🌈','party','rainbow'],['🌟','energy','star'],['✨','energy','sparkles'],['🎚️','music','fader mixer'],['🎛️','music','control mixer'],['🔊','music','loud volume'],['🔈','music','speaker'],['📣','energy','megaphone'],['📀','music','disc'],['💿','music','cd'],['🫡','faces','respect salute'],['🤝','love','respect handshake'],['🙏','love','thanks please'],['😮‍💨','faces','relief'],['😤','faces','pumped'],['😈','energy','devil'],['👑','party','crown'],['☄️','energy','comet'],['🌙','party','night'],['☀️','party','sun'],['🌌','party','galaxy'],['🫶🏻','love','heart hands light'],['🫶🏽','love','heart hands medium'],['🫶🏿','love','heart hands dark'],['🤟','energy','love you hand'],['🤞','energy','fingers crossed'],['👌','faces','ok'],['👍','energy','thumbs up'],['👊','energy','fist'],['🙃','faces','silly'],['😜','faces','wink tongue'],['🤯','faces','mind blown'],['🥵','faces','hot'],['🥶','faces','cold'],['👀','faces','eyes'],['💫','energy','dizzy star'],['🎸','music','guitar'],['🥁','music','drums'],['🎹','music','piano'],['🎷','music','sax'],['🎺','music','trumpet'],['🪘','music','drum'],['🎻','music','violin'],['📺','party','watch'],['🍿','party','snack'],['☕','party','coffee'],['🍻','party','beer cheers'],['🧃','party','drink'],['🛸','energy','ufo'],['🪄','energy','magic wand']
  ];
  const STICKERS = ['🎧 LIVE NOW','🔥 BIG TUNE','🚀 FX HYPE','💥 DROP IT','🎤 DJ LOVE','📻 RADIO FAMILY','⚡ TURN IT UP','🪩 PARTY MODE','💙 NIGHT CREW','🙌 REQUEST TIME','👑 LEGEND ON AIR','🎶 FEEL THE FLOW'];
  const GIF_PRESETS = [
    'https://media.giphy.com/media/3oEjI6SIIHBdRxXI40/giphy.gif',
    'https://media.giphy.com/media/l0HlBO7eyXzSZkJri/giphy.gif',
    'https://media.giphy.com/media/26ufdipQqU2lhNA4g/giphy.gif',
    'https://media.giphy.com/media/5xaOcLGvzHxDKjufnLW/giphy.gif',
    'https://media.giphy.com/media/xTiTnuhyBF54B852nK/giphy.gif',
    'https://media.giphy.com/media/3ohs4BSacFKI7A717y/giphy.gif'
  ];

  let messages = Array.isArray(boot.initialMessages) ? boot.initialMessages.slice() : [];
  let currentEmojiFilter = 'all';
  let mediaRecorder = null;
  let recorderChunks = [];
  let recording = false;
  let selectedVoiceBlob = null;

  function escapeHtml(text) {
    return String(text || '').replace(/[&<>'"]/g, s => ({'&':'&amp;','<':'&lt;','>':'&gt;',"'":'&#039;','"':'&quot;'}[s]));
  }
  function autolink(text) {
    return escapeHtml(text).replace(/(https?:\/\/[^\s<]+)/gi, '<a href="$1" target="_blank" rel="noopener noreferrer nofollow">$1</a>').replace(/\n/g, '<br>');
  }
  function formatTime(ts) {
    if (!ts) return '';
    const d = new Date(ts.replace(' ', 'T'));
    if (Number.isNaN(d.getTime())) return ts;
    return d.toLocaleString([], { hour: 'numeric', minute: '2-digit', month: 'short', day: 'numeric' });
  }
  function initialFor(name) {
    return (name || 'G').trim().charAt(0).toUpperCase() || 'G';
  }
  function renderMessages(scroll = false) {
    feed.innerHTML = messages.map(msg => `
      <article class="ugfx-chat-bubble ${escapeHtml(msg.type || 'user')}">
        <div class="ugfx-chat-avatar">${escapeHtml(initialFor(msg.name || 'Guest'))}</div>
        <div class="ugfx-chat-bubble-main">
          <div class="ugfx-chat-bubble-head">
            <strong>${escapeHtml(msg.name || 'Guest')}</strong>
            <span>${escapeHtml(formatTime(msg.created_at || ''))}</span>
          </div>
          ${msg.message ? `<div class="ugfx-chat-text">${autolink(msg.message)}</div>` : ''}
          ${msg.sticker ? `<div class="ugfx-chat-sticker">${escapeHtml(msg.sticker)}</div>` : ''}
          ${msg.gif_url ? `<div class="ugfx-chat-media"><img src="${escapeHtml(msg.gif_url)}" alt="GIF"></div>` : ''}
          ${msg.voice_url ? `<div class="ugfx-chat-voice"><audio controls preload="none" src="${escapeHtml(msg.voice_url)}"></audio></div>` : ''}
        </div>
      </article>`).join('');
    countEl.textContent = String(messages.length);
    if (scroll) feed.scrollTop = feed.scrollHeight;
  }
  function renderEmojiGrid() {
    const term = (emojiSearch.value || '').trim().toLowerCase();
    const filtered = EMOJIS.filter(([emoji, cat, keywords]) => {
      const filterOk = currentEmojiFilter === 'all' || cat === currentEmojiFilter;
      const searchOk = !term || keywords.includes(term) || emoji.includes(term);
      return filterOk && searchOk;
    });
    emojiGrid.innerHTML = filtered.map(([emoji]) => `<button type="button" class="ugfx-emoji-btn">${emoji}</button>`).join('');
    emojiGrid.querySelectorAll('.ugfx-emoji-btn').forEach(btn => {
      btn.addEventListener('click', () => {
        messageInput.value += btn.textContent;
        messageInput.focus();
      });
    });
  }
  function renderStickers() {
    stickerGrid.innerHTML = STICKERS.map(text => `<button type="button" class="ugfx-sticker-btn">${escapeHtml(text)}</button>`).join('');
    stickerGrid.querySelectorAll('.ugfx-sticker-btn').forEach(btn => {
      btn.addEventListener('click', () => {
        stickerInput.value = btn.textContent;
        syncAttachments();
      });
    });
  }
  function renderGifPresets() {
    gifPresets.innerHTML = GIF_PRESETS.map(url => `<button type="button" class="ugfx-gif-thumb"><img src="${escapeHtml(url)}" alt="GIF preset"></button>`).join('');
    gifPresets.querySelectorAll('.ugfx-gif-thumb').forEach((btn, idx) => {
      btn.addEventListener('click', () => {
        gifInput.value = GIF_PRESETS[idx];
        syncAttachments();
      });
    });
  }
  function syncAttachments() {
    const cards = [];
    if (gifInput.value) cards.push(`<div class="ugfx-attach-card"><span>GIF attached</span><button type="button" data-clear="gif">×</button></div>`);
    if (stickerInput.value) cards.push(`<div class="ugfx-attach-card"><span>${escapeHtml(stickerInput.value)}</span><button type="button" data-clear="sticker">×</button></div>`);
    if (voiceInput.value || selectedVoiceBlob) cards.push(`<div class="ugfx-attach-card"><span>Voice clip ready</span><button type="button" data-clear="voice">×</button></div>`);
    attachments.innerHTML = cards.join('');
    attachments.querySelectorAll('[data-clear]').forEach(btn => {
      btn.addEventListener('click', () => {
        const type = btn.dataset.clear;
        if (type === 'gif') gifInput.value = '';
        if (type === 'sticker') stickerInput.value = '';
        if (type === 'voice') {
          voiceInput.value = '';
          voiceMimeInput.value = '';
          selectedVoiceBlob = null;
          recordStatus.textContent = '';
        }
        syncAttachments();
      });
    });
  }
  function setStatus(msg, isError) {
    statusEl.textContent = msg;
    statusEl.classList.toggle('text-danger', !!isError);
  }
  function openPanel(name) {
    panels.forEach(panel => {
      panel.hidden = panel.dataset.panel !== name ? true : !panel.hidden;
      if (panel.dataset.panel !== name) panel.hidden = true;
    });
    panelButtons.forEach(btn => btn.classList.toggle('active', btn.dataset.panelToggle === name && !app.querySelector(`[data-panel="${name}"]`).hidden));
  }
  async function refreshMessages(scroll = false) {
    try {
      const res = await fetch(getUrl, { cache: 'no-store' });
      const data = await res.json();
      if (data.ok && Array.isArray(data.messages)) {
        messages = data.messages;
        renderMessages(scroll);
      }
    } catch (err) {}
  }
  async function uploadVoiceIfNeeded() {
    if (!selectedVoiceBlob) return true;
    const fd = new FormData();
    fd.append('audio', selectedVoiceBlob, selectedVoiceBlob.name || 'voice.webm');
    recordStatus.textContent = 'Uploading voice clip…';
    const res = await fetch(uploadUrl, { method: 'POST', body: fd });
    const data = await res.json();
    if (!data.ok) throw new Error(data.message || 'Voice upload failed.');
    voiceInput.value = data.url || '';
    voiceMimeInput.value = data.mime || selectedVoiceBlob.type || 'audio/webm';
    recordStatus.textContent = 'Voice clip attached.';
    selectedVoiceBlob = null;
    syncAttachments();
    return true;
  }
  panelButtons.forEach(btn => btn.addEventListener('click', () => openPanel(btn.dataset.panelToggle)));
  emojiFilters.forEach(btn => btn.addEventListener('click', () => {
    currentEmojiFilter = btn.dataset.emojiFilter;
    emojiFilters.forEach(item => item.classList.toggle('active', item === btn));
    renderEmojiGrid();
  }));
  emojiSearch.addEventListener('input', renderEmojiGrid);
  gifAttach.addEventListener('click', () => {
    const url = (gifUrlInput.value || '').trim();
    if (!url) return;
    gifInput.value = url;
    syncAttachments();
    gifUrlInput.value = '';
  });
  form.addEventListener('submit', async (e) => {
    e.preventDefault();
    try {
      setStatus('Sending...', false);
      await uploadVoiceIfNeeded();
      const fd = new FormData(form);
      const res = await fetch(postUrl, { method: 'POST', body: fd });
      const data = await res.json();
      if (!data.ok) throw new Error(data.message || 'Message failed.');
      localStorage.setItem('ugfx-chat-name', nameInput.value.trim());
      form.reset();
      gifInput.value = '';
      stickerInput.value = '';
      voiceInput.value = '';
      voiceMimeInput.value = '';
      selectedVoiceBlob = null;
      syncAttachments();
      nameInput.value = localStorage.getItem('ugfx-chat-name') || '';
      setStatus('Message sent to chat.', false);
      await refreshMessages(true);
    } catch (err) {
      setStatus(err.message || 'Could not send message.', true);
    }
  });

  if (recordButton && navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
    recordButton.addEventListener('click', async () => {
      if (recording && mediaRecorder) {
        mediaRecorder.stop();
        return;
      }
      try {
        const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
        const mimeType = MediaRecorder.isTypeSupported('audio/webm;codecs=opus') ? 'audio/webm;codecs=opus' : '';
        mediaRecorder = new MediaRecorder(stream, mimeType ? { mimeType } : undefined);
        recorderChunks = [];
        mediaRecorder.ondataavailable = evt => { if (evt.data.size) recorderChunks.push(evt.data); };
        mediaRecorder.onstop = () => {
          const type = mediaRecorder.mimeType || 'audio/webm';
          selectedVoiceBlob = new File(recorderChunks, `voice-${Date.now()}.webm`, { type });
          voiceMimeInput.value = type;
          recording = false;
          recordButton.innerHTML = '<i class="bi bi-mic"></i> Voice';
          recordButton.classList.remove('recording');
          recordStatus.textContent = 'Voice clip ready to send.';
          syncAttachments();
          stream.getTracks().forEach(t => t.stop());
        };
        mediaRecorder.start();
        recording = true;
        recordButton.innerHTML = '<i class="bi bi-stop-circle"></i> Stop';
        recordButton.classList.add('recording');
        recordStatus.textContent = 'Recording… click again to stop.';
      } catch (err) {
        recordStatus.textContent = 'Microphone access blocked.';
      }
    });
  } else if (recordButton) {
    recordButton.disabled = true;
    recordStatus.textContent = 'Voice clips need a newer browser.';
  }

  const savedName = localStorage.getItem('ugfx-chat-name');
  if (savedName) nameInput.value = savedName;
  nameInput.addEventListener('change', () => localStorage.setItem('ugfx-chat-name', nameInput.value.trim()));
  renderMessages(true);
  renderEmojiGrid();
  renderStickers();
  renderGifPresets();
  syncAttachments();
  setInterval(() => refreshMessages(false), 5000);
})();
