<script>
const BASE_URL_JS = <?= json_encode(BASE_URL) ?>;
</script>
<script>
// ============================================================
// Notification bell dropdown, live polling, and a sound alert when a new
// notification arrives while the app is open.
// ============================================================
(function () {
  let lastUnread = <?= (int)($unread ?? 0) ?>;
  let audioCtx = null;
  let audioPrimed = false;

  // Browsers block audio from starting without a prior user gesture. We
  // "prime" the AudioContext on the very first click/keypress anywhere on
  // the page (silently, no sound played), so later polling-triggered
  // beeps are allowed to play.
  function primeAudio() {
    if (audioPrimed) return;
    try {
      audioCtx = new (window.AudioContext || window.webkitAudioContext)();
      audioPrimed = true;
    } catch (e) { /* Web Audio unsupported - sound simply won't play */ }
  }
  document.addEventListener('click', primeAudio, { once: true });
  document.addEventListener('keydown', primeAudio, { once: true });

  function playNotificationSound() {
    if (!audioCtx) return;
    try {
      const now = audioCtx.currentTime;
      // Two quick soft tones, pleasant rather than jarring
      [880, 1108].forEach((freq, i) => {
        const osc = audioCtx.createOscillator();
        const gain = audioCtx.createGain();
        osc.type = 'sine';
        osc.frequency.value = freq;
        gain.gain.setValueAtTime(0, now + i * 0.12);
        gain.gain.linearRampToValueAtTime(0.15, now + i * 0.12 + 0.02);
        gain.gain.exponentialRampToValueAtTime(0.001, now + i * 0.12 + 0.25);
        osc.connect(gain).connect(audioCtx.destination);
        osc.start(now + i * 0.12);
        osc.stop(now + i * 0.12 + 0.26);
      });
    } catch (e) { /* ignore playback errors */ }
  }

  function escapeHtml(s) {
    const d = document.createElement('div');
    d.textContent = s;
    return d.innerHTML;
  }

  // --- Dropdown panel (single shared element, portal-style so it can never
  // be clipped by a scrollable ancestor - same technique as the autocomplete
  // dropdowns elsewhere in the app) ---
  const panel = document.createElement('div');
  panel.id = 'notifPanel';
  panel.style.cssText = 'display:none;position:fixed;z-index:9999;width:340px;max-width:90vw;background:#fff;border:1px solid #e2e8f0;border-radius:0.75rem;box-shadow:0 20px 40px rgba(0,0,0,.18);overflow:hidden;';
  document.addEventListener('DOMContentLoaded', () => document.body.appendChild(panel));
  if (document.readyState !== 'loading') document.body.appendChild(panel);

  function renderPanel(data) {
    const items = (data.recent || []).map(n => `
      <a href="${n.link}" class="block px-4 py-3 hover:bg-slate-50 border-b border-slate-100 last:border-0 ${n.is_read == 0 ? 'bg-blue-50/60' : ''}">
        <div class="flex items-start gap-2">
          <span class="mt-1.5 w-1.5 h-1.5 rounded-full shrink-0 ${n.is_read == 0 ? 'bg-blue-600' : 'bg-transparent'}"></span>
          <span class="flex-1 min-w-0">
            <span class="block text-sm text-slate-700 leading-snug">${escapeHtml(n.message)}</span>
            <span class="block text-xs text-slate-400 mt-0.5">${escapeHtml(n.time_ago)}</span>
          </span>
        </div>
      </a>`).join('');

    panel.innerHTML = `
      <div class="flex items-center justify-between px-4 py-3 border-b border-slate-100 bg-slate-50">
        <span class="font-semibold text-sm text-slate-700">Notifications</span>
        <button id="notifMarkAll" class="text-xs text-blue-600 hover:underline">Mark all read</button>
      </div>
      <div class="max-h-96 overflow-y-auto">
        ${items || '<div class="px-4 py-8 text-center text-sm text-slate-400">No notifications yet.</div>'}
      </div>
      <a href="${BASE_URL_JS}notifications.php" class="block text-center text-sm text-blue-600 hover:underline py-2.5 border-t border-slate-100">View all notifications</a>`;

    document.getElementById('notifMarkAll').addEventListener('click', async function (e) {
      e.preventDefault();
      await fetch(BASE_URL_JS + 'notifications_feed.php?mark_all=1', { headers: { 'X-Requested-With': 'XMLHttpRequest' } });
      poll(true);
    });
  }

  function positionPanel(bellEl) {
    const panelWidth = Math.min(340, window.innerWidth - 16);
    const sidebarEl = document.getElementById('sidebarNav');
    let left, top;

    if (sidebarEl && sidebarEl.contains(bellEl) && window.innerWidth >= 768) {
      // Desktop sidebar bell: it sits flush against the left edge of the
      // screen with no room to its left, so anchor the panel as a flyout
      // just to the right of the whole sidebar instead (this is what was
      // rendering "under the sidebar" before - the old logic tried to
      // right-align the panel with the bell, which pushed it to a negative
      // x position that got clamped underneath the sidebar itself).
      const sidebarRect = sidebarEl.getBoundingClientRect();
      const bellRect = bellEl.getBoundingClientRect();
      left = sidebarRect.right + 8;
      top = bellRect.top;
    } else {
      // Mobile top-bar bell (or any other future bell): normal dropdown anchored under it
      const rect = bellEl.getBoundingClientRect();
      left = rect.right - panelWidth;
      if (left < 8) left = rect.left;
      top = rect.bottom + 8;
    }

    if (left + panelWidth > window.innerWidth - 8) left = window.innerWidth - panelWidth - 8;
    if (left < 8) left = 8;
    if (top + 400 > window.innerHeight) top = Math.max(8, window.innerHeight - 420);

    panel.style.left = left + 'px';
    panel.style.top = top + 'px';
  }

  let panelOpen = false;
  function togglePanel(bellEl) {
    if (panelOpen) { closePanel(); return; }
    positionPanel(bellEl);
    panel.style.display = 'block';
    panelOpen = true;
    poll(true);
  }
  function closePanel() {
    panel.style.display = 'none';
    panelOpen = false;
  }

  document.addEventListener('click', function (e) {
    const bell = e.target.closest('.notif-bell');
    if (bell) {
      e.preventDefault();
      togglePanel(bell);
      return;
    }
    if (panelOpen && !panel.contains(e.target)) closePanel();
  });

  function updateBadges(count) {
    document.querySelectorAll('.notif-badge').forEach(el => {
      if (count > 0) { el.textContent = count; el.classList.remove('hidden'); }
      else { el.classList.add('hidden'); }
    });
  }

  async function poll(forceRenderPanel) {
    try {
      const res = await fetch(BASE_URL_JS + 'notifications_feed.php', { headers: { 'X-Requested-With': 'XMLHttpRequest' } });
      const data = await res.json();
      updateBadges(data.unread);

      if (data.unread > lastUnread) {
        playNotificationSound();
        if (!panelOpen) showToast('You have a new notification', 'info');
      }
      lastUnread = data.unread;

      if (panelOpen || forceRenderPanel) renderPanel(data);
    } catch (e) { /* silent - next poll will retry */ }
  }

  window.addEventListener('DOMContentLoaded', function () {
    poll(false);
    setInterval(function () { poll(false); }, 20000); // check every 20s
  });
})();
</script>
