/* Mandera Portal — notification sounds (Web Audio, no files needed).
   Branded tones: calm, bell-like, unhurried — to match the luxury feel.
   - New message while the Messages screen is CLOSED  -> messageClosed() (a
     clear rising two-note chime, so you notice it).
   - New message while the Messages screen is OPEN     -> messageOpen() (a
     softer, lower single tone — different, less intrusive).
   - Any other notification (shoot, content, file...)  -> notification().
   A speaker toggle in the top bar mutes/unmutes (saved per browser). */

const MS_KEY = 'mandera_sound_enabled';

const MSound = {
  ctx: null,
  isEnabled() { try { return localStorage.getItem(MS_KEY) !== '0'; } catch (e) { return true; } },
  setEnabled(on) {
    try { localStorage.setItem(MS_KEY, on ? '1' : '0'); } catch (e) {}
    if (on) { MSound._resume(); MSound._play([{ f: 660, t: 0, d: 0.28, gain: 0.12, shimmer: true }]); } // little confirm blip
    try { window.dispatchEvent(new CustomEvent('msound-changed')); } catch (e) {}
  },
  _init() {
    if (!MSound.ctx) { try { const AC = window.AudioContext || window.webkitAudioContext; if (AC) MSound.ctx = new AC(); } catch (e) {} }
    return MSound.ctx;
  },
  _resume() { const c = MSound._init(); if (c && c.state === 'suspended') { try { c.resume(); } catch (e) {} } },

  /* Play a set of gentle sine "bell" notes. Each note: {f, t, d, gain, shimmer} */
  _play(notes, master = 1) {
    if (!MSound.isEnabled()) return;
    const c = MSound._init(); if (!c) return;
    if (c.state === 'suspended') { try { c.resume(); } catch (e) {} }
    const t0 = c.currentTime + 0.03;
    notes.forEach((n) => {
      const s = t0 + (n.t || 0);
      const d = n.d || 0.45;
      const peak = (n.gain || 0.14) * master;
      const o = c.createOscillator(); const g = c.createGain();
      o.type = n.type || 'sine'; o.frequency.value = n.f;
      g.gain.setValueAtTime(0.0001, s);
      g.gain.exponentialRampToValueAtTime(peak, s + 0.015);
      g.gain.exponentialRampToValueAtTime(0.0001, s + d);
      o.connect(g); g.connect(c.destination);
      o.start(s); o.stop(s + d + 0.05);
      if (n.shimmer) { // faint octave above for a bell-like sheen
        const o2 = c.createOscillator(); const g2 = c.createGain();
        o2.type = 'sine'; o2.frequency.value = n.f * 2;
        g2.gain.setValueAtTime(0.0001, s);
        g2.gain.exponentialRampToValueAtTime(peak * 0.22, s + 0.02);
        g2.gain.exponentialRampToValueAtTime(0.0001, s + d * 0.7);
        o2.connect(g2); g2.connect(c.destination);
        o2.start(s); o2.stop(s + d);
      }
    });
  },

  // New message, Messages screen not open — a clear rising chime (D5 → A5).
  messageClosed() { MSound._play([{ f: 587.33, t: 0, d: 0.55, gain: 0.17, shimmer: true }, { f: 880.0, t: 0.13, d: 0.6, gain: 0.14, shimmer: true }]); },
  // New message while you're already in Messages — soft, low, single note (Bb4).
  messageOpen() { MSound._play([{ f: 466.16, t: 0, d: 0.32, gain: 0.07 }]); },
  // Any other notification — a distinct softer bell pair (E5 → B5).
  notification() { MSound._play([{ f: 659.25, t: 0, d: 0.5, gain: 0.15, shimmer: true }, { f: 987.77, t: 0.15, d: 0.55, gain: 0.11, shimmer: true }]); },
};

/* Watches MData for NEW incoming items for the signed-in account and plays the
   matching sound. Baseline is set on mount so the existing backlog is silent —
   only things that arrive after you open the portal make a sound. */
function SoundWatcher() {
  React.useEffect(() => {
    const unlock = () => MSound._resume();
    ['pointerdown', 'keydown', 'touchstart'].forEach((ev) => document.addEventListener(ev, unlock, { passive: true }));

    let lastMsgTs = 0; const seenNotif = new Set(); let inited = false;

    const isIncomingMsg = (m, acc, isClient) => {
      if (m.fromId && m.fromId === acc.id) return false;
      return isClient ? m.fromRole !== 'client' : m.fromRole === 'client';
    };
    const check = () => {
      const acc = window.MAuth && window.MAuth.current(); if (!acc) return;
      const isClient = acc.role === 'client';
      if (isClient && !acc.clientId) return;
      const msgs = isClient ? window.MData.forClient('messages', acc.clientId) : window.MData.get('messages');
      const notes = isClient ? window.MData.forClient('notifications', acc.clientId) : window.MData.teamNotifications();

      if (!inited) {
        msgs.forEach((m) => { if (m.ts > lastMsgTs) lastMsgTs = m.ts; });
        notes.forEach((n) => seenNotif.add(n.id));
        inited = true; return;
      }
      let maxTs = lastMsgTs; let newMsg = false;
      msgs.forEach((m) => { if (m.ts > lastMsgTs && isIncomingMsg(m, acc, isClient)) newMsg = true; if (m.ts > maxTs) maxTs = m.ts; });
      lastMsgTs = maxTs;
      if (newMsg) { (window.__mpView === 'messages') ? MSound.messageOpen() : MSound.messageClosed(); }

      let newNote = false;
      notes.forEach((n) => { if (!seenNotif.has(n.id)) { seenNotif.add(n.id); if (n.type !== 'message') newNote = true; } });
      if (newNote) MSound.notification();
    };

    const onChange = () => check();
    window.addEventListener('mdata-changed', onChange);
    const iv = setInterval(check, 4000);
    check(); // set baseline immediately

    return () => {
      window.removeEventListener('mdata-changed', onChange);
      clearInterval(iv);
      ['pointerdown', 'keydown', 'touchstart'].forEach((ev) => document.removeEventListener(ev, unlock));
    };
  }, []);
  return null;
}

Object.assign(window, { MSound, SoundWatcher });
