</div><!-- /pc-page-body -->
</div><!-- /pc-content -->
</div><!-- /d-flex -->

<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
<script>
// Sidebar toggle
document.getElementById('sidebarToggle')?.addEventListener('click', () => {
  document.getElementById('pcSidebar').classList.toggle('collapsed');
  document.getElementById('pcContent').classList.toggle('expanded');
});

// Submenu toggles
document.querySelectorAll('.pc-has-sub').forEach(item => {
  item.addEventListener('click', () => {
    const subId = item.dataset.sub;
    const sub   = document.getElementById(subId);
    const chevron = item.querySelector('.pc-chevron');
    if (!sub) return;
    const isOpen = sub.classList.contains('open');
    // Close all
    document.querySelectorAll('.pc-subnav.open').forEach(s => s.classList.remove('open'));
    document.querySelectorAll('.pc-has-sub.expanded').forEach(i => i.classList.remove('expanded'));
    document.querySelectorAll('.pc-chevron').forEach(c => c.style.transform = '');
    if (!isOpen) {
      sub.classList.add('open');
      item.classList.add('expanded');
      if (chevron) chevron.style.transform = 'rotate(180deg)';
    }
  });
});

// Auto-open active submenu on page load
document.querySelectorAll('.pc-subnav-item.active').forEach(active => {
  const sub = active.closest('.pc-subnav');
  if (sub) {
    sub.classList.add('open');
    const parent = document.querySelector(`[data-sub="${sub.id}"]`);
    if (parent) {
      parent.classList.add('expanded');
      const c = parent.querySelector('.pc-chevron');
      if (c) c.style.transform = 'rotate(180deg)';
    }
  }
});

// Sidebar nav search
document.getElementById('navSearch')?.addEventListener('input', function() {
  const v = this.value.toLowerCase();
  document.querySelectorAll('.pc-nav-item, .pc-subnav-item').forEach(el => {
    el.style.display = !v || el.textContent.toLowerCase().includes(v) ? '' : 'none';
  });
});

// CSRF token for all AJAX
const CSRF_TOKEN = '<?= csrfToken() ?>';

// ── Global loading overlay ──────────────────────────────────────────────
// Shown automatically for every create / edit / delete action across the
// whole app (regular form submits AND pcAjax calls), so the user always
// gets feedback that something is happening instead of a frozen screen.
(function () {
  const overlay = document.getElementById('pcLoadingOverlay');
  const textEl  = document.getElementById('pcLoadingText');
  if (!overlay) return;
  let hideTimer = null;

  window.pcShowLoading = function (msg) {
    if (textEl) textEl.textContent = msg || 'Please wait…';
    overlay.style.display = 'flex';
    overlay.classList.add('show');
    // Safety net: never let the overlay get stuck forever if something
    // hangs (slow network, server error with no redirect, etc).
    clearTimeout(hideTimer);
    hideTimer = setTimeout(() => { overlay.style.display = 'none'; overlay.classList.remove('show'); }, 20000);
  };
  window.pcHideLoading = function () {
    clearTimeout(hideTimer);
    overlay.style.display = 'none';
    overlay.classList.remove('show');
  };

  // Catch every form submission on the page (Add / Edit / Delete forms
  // all use <form method="POST"> across the app). Runs in the capture
  // phase so it fires even if a form has its own submit handler, but only
  // shows the overlay once the browser has decided the submit is valid
  // (native "required" validation blocks the event from firing at all).
  document.addEventListener('submit', function (e) {
    const form = e.target;
    if (!(form instanceof HTMLFormElement)) return;
    if (form.hasAttribute('data-no-loading')) return; // opt-out escape hatch
    if (e.defaultPrevented) return; // a handler already cancelled this submit
    const action = (form.querySelector('[name="action"]')?.value || '').toLowerCase();
    const label = action === 'delete' ? 'Deleting…'
                : action === 'save' ? (form.querySelector('[name="id"]')?.value ? 'Updating…' : 'Saving…')
                : 'Please wait…';
    window.pcShowLoading(label);
  }, true);

  // Also cover plain submit buttons that trigger navigation via a
  // GET-based delete/confirm link pattern used in a few older screens.
  document.addEventListener('click', function (e) {
    const el = e.target.closest('[data-loading-on-click]');
    if (el) window.pcShowLoading(el.getAttribute('data-loading-on-click') || 'Please wait…');
  });
})();

// Global AJAX helper
function pcAjax(url, data, onSuccess) {
  data.csrf_token = CSRF_TOKEN;
  const isWrite = ['save','delete','toggle','add','update','remove'].includes(String(data.action || '').toLowerCase());
  if (isWrite) window.pcShowLoading?.(data.action === 'delete' ? 'Deleting…' : 'Saving…');
  fetch(url, {
    method: 'POST',
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
    body: new URLSearchParams(data)
  })
  .then(r => r.json())
  .then(res => {
    window.pcHideLoading?.();
    if (res.success) {
      onSuccess(res);
    } else {
      showToast(res.message || 'An error occurred', 'danger');
    }
  })
  .catch(() => {
    window.pcHideLoading?.();
    showToast('Network error. Please try again.', 'danger');
  });
}

// Toast notification
function showToast(msg, type = 'success') {
  const wrap = document.getElementById('toastWrap') || (() => {
    const d = document.createElement('div');
    d.id = 'toastWrap';
    d.className = 'toast-container position-fixed bottom-0 end-0 p-3';
    d.style.zIndex = 9999;
    document.body.appendChild(d);
    return d;
  })();
  const id = 'toast_' + Date.now();
  wrap.insertAdjacentHTML('beforeend', `
    <div id="${id}" class="toast align-items-center text-bg-${type} border-0" role="alert">
      <div class="d-flex">
        <div class="toast-body">${msg}</div>
        <button type="button" class="btn-close btn-close-white me-2 m-auto" data-bs-dismiss="toast"></button>
      </div>
    </div>`);
  const t = new bootstrap.Toast(document.getElementById(id), { delay: 4000 });
  t.show();
}

// ── Bell notifications (leave / permission / late approvals) ─────────────
// Polls ajax/pending_counts.php every 30s. Replaces the old hardcoded bell
// dropdown that never reflected real data. A popup toast fires only when
// the pending total goes UP from what this browser last saw (tracked per
// logged-in user in localStorage), so re-opening a page doesn't re-alert
// about the same backlog every time.
(function () {
  const SEEN_KEY = 'pc_last_seen_approvals_<?= (int)($user['id'] ?? 0) ?>';
  const badge = document.getElementById('pcBellBadge');
  const menu  = document.getElementById('pcBellMenu');
  const empty = document.getElementById('pcBellEmpty');
  if (!badge || !menu) return;

  function timeAgo(iso) {
    const secs = Math.floor((Date.now() - new Date(iso.replace(' ', 'T'))) / 1000);
    if (secs < 60) return 'just now';
    if (secs < 3600) return Math.floor(secs / 60) + 'm ago';
    if (secs < 86400) return Math.floor(secs / 3600) + 'h ago';
    return Math.floor(secs / 86400) + 'd ago';
  }

  function render(data) {
    if (data.total > 0) {
      badge.textContent = data.total;
      badge.classList.remove('d-none');
    } else {
      badge.classList.add('d-none');
    }
    menu.querySelectorAll('.pc-bell-item').forEach(el => el.remove());
    if (empty) empty.style.display = data.items.length ? 'none' : '';
    data.items.forEach(item => {
      const li = document.createElement('li');
      li.className = 'pc-bell-item';
      li.innerHTML = `<a class="dropdown-item small py-2" href="${item.link}">
          <span class="badge bg-${item.badge} me-1">${item.label}</span> ${item.text}
          <div class="text-muted" style="font-size:10px">${timeAgo(item.time)}</div>
        </a>`;
      menu.appendChild(li);
    });
  }

  function poll() {
    fetch('<?= BASE_URL ?>/ajax/pending_counts.php', { credentials: 'same-origin' })
      .then(r => r.ok ? r.json() : null)
      .then(data => {
        if (!data) return;
        render(data);
        const lastSeen = parseInt(localStorage.getItem(SEEN_KEY) || '0', 10);
        if (data.total > lastSeen) {
          const diff = data.total - lastSeen;
          showToast((diff === 1 ? '1 new request needs' : diff + ' new requests need') + ' your approval', 'warning');
        }
        localStorage.setItem(SEEN_KEY, data.total);
      })
      .catch(() => {});
  }

  poll();
  setInterval(poll, 30000);

  // Opening the bell = acknowledged, but keep showing the list until it's
  // actually approved/rejected — only stops the popup toast from re-firing.
  document.getElementById('pcBellBtn')?.addEventListener('click', () => {
    const badgeText = parseInt(badge.textContent || '0', 10);
    if (badgeText) localStorage.setItem(SEEN_KEY, badgeText);
  });
})();

// ── Personal notifications bell (apply/approve/reject alerts) ──────────
// Separate from the pending-approvals bell above. Polls
// modules/notifications/ajax.php every 30s; a popup toast fires only
// when unread count goes UP from what this browser last saw.
// Works for every login: notifications are matched by employee_id OR
// user_id server-side, so superadmin logins with no linked employee
// still get (and can mark) their own notifications — see
// notifyAllSuperadmins() in includes/functions.php.
(function () {
  const SEEN_KEY = 'pc_last_seen_notifs_<?= (int)($user['id'] ?? 0) ?>';
  const badge = document.getElementById('notifBadge');
  const list  = document.getElementById('notifList');
  const btn   = document.getElementById('notifBellBtn');
  if (!badge || !list) return;

  const AJAX_URL = '<?= BASE_URL ?>/modules/notifications/ajax.php';

  function timeAgo(iso) {
    const secs = Math.floor((Date.now() - new Date(iso.replace(' ', 'T'))) / 1000);
    if (secs < 60) return 'just now';
    if (secs < 3600) return Math.floor(secs / 60) + 'm ago';
    if (secs < 86400) return Math.floor(secs / 3600) + 'h ago';
    return Math.floor(secs / 86400) + 'd ago';
  }

  function renderBadge(count) {
    if (count > 0) { badge.textContent = count; badge.classList.remove('d-none'); }
    else badge.classList.add('d-none');
  }

  function renderList(notifs) {
    if (!notifs.length) {
      list.innerHTML = '<div class="text-center text-muted small py-3">No notifications</div>';
      return;
    }
    list.innerHTML = notifs.map(n => `
      <div class="px-3 py-2 border-bottom notif-item ${n.is_read == 0 ? 'bg-light' : ''}" data-id="${n.id}" data-read="${n.is_read}">
        <div class="d-flex justify-content-between align-items-start gap-2">
          <div style="cursor:pointer" class="notif-body flex-fill">
            <div class="small fw-semibold">${n.title}</div>
            <div class="small text-muted">${n.message}</div>
            <div class="text-muted" style="font-size:10px">${timeAgo(n.created_at)}</div>
          </div>
          <a href="#" class="small notif-toggle text-nowrap">${n.is_read == 0 ? 'Mark read' : 'Mark unread'}</a>
        </div>
      </div>`).join('');
  }

  function fetchCount() {
    fetch(AJAX_URL + '?action=unread_count', { credentials: 'same-origin' })
      .then(r => r.ok ? r.json() : null)
      .then(data => {
        if (!data || !data.success) return;
        renderBadge(data.count);
        const lastSeen = parseInt(localStorage.getItem(SEEN_KEY) || '0', 10);
        if (data.count > lastSeen) {
          const diff = data.count - lastSeen;
          showToast((diff === 1 ? '1 new notification' : diff + ' new notifications'), 'primary');
        }
        localStorage.setItem(SEEN_KEY, data.count);
      })
      .catch(() => {});
  }

  function fetchList() {
    fetch(AJAX_URL + '?action=list', { credentials: 'same-origin' })
      .then(r => r.ok ? r.json() : null)
      .then(data => {
        if (data && data.success) { renderList(data.notifications); return; }
        // FIX: used to leave "Loading…" on screen forever for logins with
        // no linked employee record, or on any other failure. Now shows a
        // clear message instead of hanging silently.
        list.innerHTML = `<div class="text-center text-muted small py-3">${(data && data.message) || 'Notifications unavailable'}</div>`;
      })
      .catch(() => { list.innerHTML = '<div class="text-center text-muted small py-3">Could not load notifications</div>'; });
  }

  // Load list once when the dropdown is opened (avoids constant re-render
  // while polling in the background for the badge count).
  btn?.addEventListener('click', fetchList);

  list.addEventListener('click', (e) => {
    const toggle = e.target.closest('.notif-toggle');
    const body   = e.target.closest('.notif-body');
    if (!toggle && !body) return;
    e.preventDefault();
    const item = e.target.closest('.notif-item');
    const id   = item.dataset.id;
    const isUnread = item.dataset.read == '0';
    const targetAction = isUnread ? 'mark_read' : (toggle ? 'mark_unread' : null);
    if (!targetAction) return; // clicking body on an already-read item does nothing extra
    pcAjax(AJAX_URL, { action: targetAction, id }, () => { fetchList(); fetchCount(); });
  });

  document.getElementById('notifMarkAllRead')?.addEventListener('click', (e) => {
    e.preventDefault();
    pcAjax(AJAX_URL, { action: 'mark_all_read' }, () => { fetchList(); fetchCount(); });
  });

  document.getElementById('notifMarkAllUnread')?.addEventListener('click', (e) => {
    e.preventDefault();
    pcAjax(AJAX_URL, { action: 'mark_all_unread' }, () => { fetchList(); fetchCount(); });
  });

  fetchCount();
  setInterval(fetchCount, 30000);
})();
</script>
<?php if (isset($extraJs)) echo $extraJs; ?>
</body>
</html>