'use strict';
// ─── Notifications ──────────────────────────────────────────────────────────
//
// Unified notification store. All buddy events, toasts, and system messages
// funnel through pushNotification(). Max 100 kept; TTL-based expiry on init.
//
// Notification object shape:
//   { id, type, title, body, ts, read, tag, ephemeral, ttl, nav }
//
// nav: { tab, pubKeyB64?, entryId? }  — drives click-through navigation.
//
// ─────────────────────────────────────────────────────────────────────────────

const NOTIF_KEY          = 'frj_notifications';
const NOTIF_SETTINGS_KEY = 'frj_notif_settings';
const NOTIF_MAX          = 100;

// TTLs (ms)
const NOTIF_TTL_EPHEMERAL = 2  * 3600  * 1000;  // 2 h  — live tugging/retaining
const NOTIF_TTL_MONTH     = 30 * 86400 * 1000;  // 30 d — journal, CI, KOT
const NOTIF_TTL_WEEK      =  7 * 86400 * 1000;  // 7 d  — notes, system toasts

const NOTIF_TYPE_LABELS = {
  journal: 'Journal Entry',
  weekly:  'Weekly Session',
  note:    'Comment on your entry',
  kot:     'KOT Reaction',
  trust:   'Trust Update',
  gallery: 'Gallery',
  system:  'App Notification',
};

const _NOTIF_ICONS = {
  journal: '📔', weekly: '📅', note: '💬', kot: '✊', trust: '🤝', gallery: '🖼️', system: '💬',
};

// ── Storage ──────────────────────────────────────────────────────────────────

function getNotifications() {
  try { return JSON.parse(localStorage.getItem(NOTIF_KEY) || '[]'); } catch(e) { return []; }
}
function saveNotifications(notifs) {
  try { localStorage.setItem(NOTIF_KEY, JSON.stringify(notifs.slice(-NOTIF_MAX))); } catch(e) {}
}
function getNotifSettings() {
  const defaults = Object.fromEntries(Object.keys(NOTIF_TYPE_LABELS).map(k => [k, true]));
  try { return Object.assign(defaults, JSON.parse(localStorage.getItem(NOTIF_SETTINGS_KEY) || '{}')); }
  catch(e) { return defaults; }
}
function saveNotifSettings(settings) {
  localStorage.setItem(NOTIF_SETTINGS_KEY, JSON.stringify(settings));
}

// ── TTL pruning ───────────────────────────────────────────────────────────────

function _pruneNotifications() {
  const now    = Date.now();
  const before = getNotifications();
  const after  = before.filter(n => {
    const age = now - new Date(n.ts).getTime();
    return age < (n.ttl != null ? n.ttl : NOTIF_TTL_MONTH);
  });
  if (after.length !== before.length) saveNotifications(after);
  return after;
}

// ── Push ─────────────────────────────────────────────────────────────────────
//
// opts: { nav, ephemeral, ttl, tag }
//   nav  — { tab, pubKeyB64?, entryId? } for click-through
//   tag  — dedup key: skips push if an *unread* notif with same tag exists
//   ephemeral — if true, TTL = NOTIF_TTL_EPHEMERAL unless ttl is explicit
//   ttl  — milliseconds from ts before expiry

function pushNotification(type, title, body, opts = {}) {
  const settings = getNotifSettings();
  if (settings[type] === false) return;
  _pruneNotifications();
  const notifs = getNotifications();
  // Dedup: skip if same tag already has an unread entry
  if (opts.tag && notifs.some(n => n.tag === opts.tag && !n.read)) return;
  const id  = typeof uuid === 'function' ? uuid() : `${Date.now()}-${Math.random()}`;
  const ttl = opts.ttl != null ? opts.ttl
            : opts.ephemeral   ? NOTIF_TTL_EPHEMERAL
            : NOTIF_TTL_MONTH;
  notifs.push({
    id, type, title, body: body || '',
    ts:       new Date().toISOString(),
    read:     false,
    tag:      opts.tag  || null,
    nav:      opts.nav  || null,
    ephemeral: !!opts.ephemeral,
    ttl,
  });
  saveNotifications(notifs);
  _updateNotifDot();
  // Show a toast with the notification icon, unless suppressed or it's a system/event type
  if (!opts.silent && type !== 'system' && type !== 'event' && typeof toast === 'function') {
    const icon = _NOTIF_ICONS[type] || '';
    toast(icon ? `${icon} ${title}` : title, false, true);
  }
}

// ── Read state ────────────────────────────────────────────────────────────────

function hasUnreadNotifs() {
  return getNotifications().some(n => !n.read);
}

function markNotifsRead() {
  const notifs = getNotifications();
  let changed = false;
  notifs.forEach(n => { if (!n.read) { n.read = true; changed = true; } });
  if (changed) saveNotifications(notifs);
  _updateNotifDot();
}

function deleteNotif(id) {
  saveNotifications(getNotifications().filter(n => n.id !== id));
  _updateNotifDot();
  renderNotifDropdown();
}

function clearAllNotifs() {
  saveNotifications([]);
  _updateNotifDot();
  renderNotifDropdown();
}

// ── Dot + pill state ──────────────────────────────────────────────────────────
// Unread → entire pill turns soft blue.  No more pulse interval.

function _updateNotifDot() {
  const unread = hasUnreadNotifs();
  const dot    = document.getElementById('notifDot');
  const pill   = document.getElementById('hdrDotsPill');
  if (dot)  dot.classList.toggle('notif-unread', unread);
  if (pill) pill.classList.toggle('has-notif', unread);
}

// ── Navigation ────────────────────────────────────────────────────────────────

function _notifNavigate(id) {
  closeNotifDropdown();
  const n = getNotifications().find(x => x.id === id);
  if (!n?.nav) return;
  const nav = n.nav;
  if (typeof tab === 'function') tab(nav.tab || 'dash');
  const delay = 80;
  if (nav.tab === 'contacts' && nav.pubKeyB64) {
    setTimeout(() => {
      if (typeof openBuddyProfile === 'function') openBuddyProfile(nav.pubKeyB64);
    }, delay);
  } else if (nav.tab === 'journal') {
    if (nav.pubKeyB64 && nav.entryId) {
      setTimeout(() => {
        if (typeof selectBuddyEntry === 'function') selectBuddyEntry(nav.pubKeyB64, nav.entryId);
      }, delay);
    } else if (nav.entryId) {
      setTimeout(() => {
        if (typeof selectEntry === 'function') selectEntry(nav.entryId);
      }, delay);
    }
  }
}

// ── Dropdown ─────────────────────────────────────────────────────────────────

function toggleNotifDropdown() {
  const dd = document.getElementById('notifDropdown');
  if (!dd) return;
  const open = dd.style.display !== 'none';
  const devDd = document.getElementById('deviceDropdown');
  const buDd  = document.getElementById('buddyDropdown');
  if (devDd) devDd.style.display = 'none';
  if (buDd)  buDd.style.display  = 'none';
  if (open) {
    dd.style.display = 'none';
    if (typeof _hideDropdownBackdrop === 'function') _hideDropdownBackdrop();
  } else {
    markNotifsRead();
    renderNotifDropdown();
    dd.style.display = '';
    if (typeof _showDropdownBackdrop === 'function') _showDropdownBackdrop();
  }
}

function closeNotifDropdown() {
  const dd = document.getElementById('notifDropdown');
  if (dd) dd.style.display = 'none';
  if (typeof _hideDropdownBackdrop === 'function') _hideDropdownBackdrop();
}

function renderNotifDropdown() {
  const dd = document.getElementById('notifDropdown');
  if (!dd) return;
  _pruneNotifications();
  const notifs = getNotifications().slice().reverse();
  const escFn  = typeof esc === 'function' ? esc : s => String(s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/"/g,'&quot;');
  const timeFn = typeof timeAgo === 'function' ? timeAgo : ts => ts;

  const itemsHtml = notifs.length
    ? notifs.map(n => {
        const icon   = _NOTIF_ICONS[n.type] || '●';
        const ago    = n.ts ? timeFn(n.ts) : '';
        const hasNav = !!n.nav;
        const bg     = !n.read ? 'background:var(--accent2);' : '';
        const cursor = hasNav  ? 'cursor:pointer;' : '';
        const nav    = hasNav  ? `data-action="notifNavigate" data-a0="${escFn(n.id)}"` : '';
        return `<div class="notif-item" style="${bg}${cursor}" ${nav}>
          <span class="notif-icon">${icon}</span>
          <div class="notif-body">
            <div class="notif-title">${escFn(n.title)}</div>
            ${n.body ? `<div class="notif-desc">${escFn(n.body)}</div>` : ''}
            <div class="notif-time">${ago}</div>
          </div>
          <button class="notif-del" data-action="deleteNotif" data-a0="${escFn(n.id)}" title="Dismiss" onclick="event.stopPropagation()">✕</button>
        </div>`;
      }).join('')
    : `<div style="padding:20px 14px;font-family:var(--mono);font-size:10px;color:var(--muted2);text-align:center">No notifications</div>`;

  dd.innerHTML =
    `<div style="display:flex;align-items:center;padding:10px 14px 8px;border-bottom:1px solid var(--border2)">
      <span style="font-family:var(--mono);font-size:11px;font-weight:600;flex:1">Notifications</span>
      <button data-action="closeNotifDropdown" style="background:none;border:none;cursor:pointer;font-size:16px;color:var(--muted2);padding:0 0 0 8px;line-height:1">✕</button>
    </div>
    <div style="max-height:340px;overflow-y:auto">${itemsHtml}</div>
    ${notifs.length ? `<div style="padding:8px 12px;border-top:1px solid var(--border2)">
      <button class="btn btn-danger btn-sm" style="width:100%;font-size:11px" data-action="clearAllNotifs">✕ Clear all</button>
    </div>` : ''}`;
}

// ── Settings panel ────────────────────────────────────────────────────────────

function renderNotifSettingsPanel() {
  const settings = getNotifSettings();
  const rows = Object.entries(NOTIF_TYPE_LABELS).map(([k, label]) => {
    const checked = settings[k] !== false ? 'checked' : '';
    return `<label style="display:flex;align-items:center;gap:10px;padding:6px 0;cursor:pointer;font-size:13px;color:var(--text)">
      <input type="checkbox" id="notif-setting-${k}" ${checked} style="accent-color:var(--accent);width:15px;height:15px">
      <span>${label}</span>
    </label>`;
  }).join('');
  return `<div class="panel">
    <div class="ph"><h2>Notifications</h2></div>
    <div class="pb">
      <p style="font-size:12px;color:var(--muted);margin:0 0 12px;line-height:1.6">Choose which activity generates a notification.</p>
      ${rows}
      <button class="btn btn-primary btn-sm" style="margin-top:12px" data-action="saveNotifSettings">Save</button>
    </div>
  </div>`;
}

function saveNotifSettingsUI() {
  const settings = {};
  Object.keys(NOTIF_TYPE_LABELS).forEach(k => {
    const el = document.getElementById(`notif-setting-${k}`);
    settings[k] = el ? el.checked : true;
  });
  saveNotifSettings(settings);
  if (typeof toast === 'function') toast('Notification settings saved');
}

// ── Init ──────────────────────────────────────────────────────────────────────

function initNotifications() {
  _pruneNotifications();
  _updateNotifDot();
}
