<?php
// admin/_layout.php  —  call layout_start() / layout_end()

function layout_start(string $pageTitle = 'RSVP Admin', string $activePage = ''): void {
    $base      = BASE_URL;
    $adminName = $_SESSION['admin_name'] ?? 'Admin';
    $isSuperAdmin = isSuperAdmin();
    $csrf      = htmlspecialchars(csrfToken());
    // Event-scoped tools keep "Events" lit in the global nav; the event
    // sub-nav (event_tabs) carries the finer context.
    $eventScoped = ['events','guests','whatsapp','email','ticket','checkers','doorstaff'];
    $cDash    = $activePage === 'dashboard'      ? 'active' : '';
    $cEvents  = in_array($activePage, $eventScoped, true) ? 'active' : '';
    $cReports = $activePage === 'reports'        ? 'active' : '';
    $cImport  = $activePage === 'import_ebabe'   ? 'active' : '';
    $cAdmins  = $activePage === 'manage_admins'  ? 'active' : '';
    $cAudit   = $activePage === 'audit'          ? 'active' : '';
    echo <<<HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="csrf-token" content="{$csrf}">
<title>{$pageTitle} — RSVP System</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" media="print" onload="this.media='all'"
      href="https://fonts.googleapis.com/css2?family=Syne:wght@400;600;700;800&family=DM+Sans:wght@300;400;500&display=swap">
<link rel="stylesheet" href="{$base}/assets/css/main.css">
</head>
<body>

<!-- Global page-level loading overlay -->
<div id="page-loader">
  <div class="loader-ring"></div>
  <div class="loader-text" id="loader-text">Processing…</div>
</div>

<!-- Mobile top bar (shown < 760px) -->
<header class="mobile-topbar">
  <button class="mobile-menu-btn" id="mobile-menu-btn" aria-label="Menu" onclick="toggleSidebar()">
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="22" height="22"><line x1="3" y1="6" x2="21" y2="6"/><line x1="3" y1="12" x2="21" y2="12"/><line x1="3" y1="18" x2="21" y2="18"/></svg>
  </button>
  <div class="mobile-brand">RSVP</div>
  <a href="{$base}/admin/logout.php" class="mobile-icon-btn" style="margin-left:auto;color:var(--gold)" aria-label="Sign out" title="Sign out">
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="22" height="22"><path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"/><polyline points="16 17 21 12 16 7"/><line x1="21" y1="12" x2="9" y2="12"/></svg>
  </a>
</header>
<div class="sidebar-scrim" id="sidebar-scrim" onclick="toggleSidebar(false)"></div>

<div class="page-wrap">

  <aside class="sidebar" id="sidebar">
    <div class="sidebar-brand">
      <div class="brand-name">RSVP</div>
      <div class="brand-sub">Event Management</div>
    </div>
    <nav class="sidebar-nav">
      <a href="{$base}/admin/dashboard.php" class="{$cDash}">
        <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="3" width="7" height="7"/><rect x="14" y="3" width="7" height="7"/><rect x="3" y="14" width="7" height="7"/><rect x="14" y="14" width="7" height="7"/></svg>
        Dashboard
      </a>
      <a href="{$base}/admin/events.php" class="{$cEvents}">
        <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="4" width="18" height="18" rx="2"/><line x1="16" y1="2" x2="16" y2="6"/><line x1="8" y1="2" x2="8" y2="6"/><line x1="3" y1="10" x2="21" y2="10"/></svg>
        Events
      </a>
      <a href="{$base}/admin/reports.php" class="{$cReports}">
        <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="18" y1="20" x2="18" y2="10"/><line x1="12" y1="20" x2="12" y2="4"/><line x1="6" y1="20" x2="6" y2="14"/></svg>
        Reports
      </a>
      <a href="{$base}/admin/import_ebabe.php" class="{$cImport}">
        <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg>
        Import RSVPs
      </a>
HTML;
    if ($isSuperAdmin) {
        echo <<<HTML
      <a href="{$base}/admin/manage_admins.php" class="{$cAdmins}" style="border-top:1px solid var(--border);margin-top:8px;padding-top:16px">
        <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><line x1="19" y1="8" x2="19" y2="14"/><line x1="22" y1="11" x2="16" y2="11"/></svg>
        Manage Admins
      </a>
      <a href="{$base}/admin/audit.php" class="{$cAudit}">
        <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="16" y1="13" x2="8" y2="13"/><line x1="16" y1="17" x2="8" y2="17"/></svg>
        Audit Log
      </a>
HTML;
    }
    echo <<<HTML
    </nav>
    <div class="sidebar-footer">
      <div class="sidebar-user" style="color:var(--white);font-size:.82rem;font-weight:500;padding:0 8px 10px;margin-bottom:6px;border-bottom:1px solid var(--border)">{$adminName}</div>
      <a href="{$base}/admin/account.php" class="sidebar-foot-link" style="display:flex;align-items:center;gap:10px;padding:10px 8px;border-radius:6px;color:var(--gold);text-decoration:none;font-family:var(--font-ui);font-size:.78rem;font-weight:600">
        <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="16" height="16" style="flex-shrink:0"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/></svg>
        Account settings
      </a>
      <a href="{$base}/admin/logout.php" class="sidebar-foot-link danger" style="display:flex;align-items:center;gap:10px;padding:10px 8px;border-radius:6px;color:var(--muted);text-decoration:none;font-family:var(--font-ui);font-size:.78rem;font-weight:600">
        <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="16" height="16" style="flex-shrink:0"><path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"/><polyline points="16 17 21 12 16 7"/><line x1="21" y1="12" x2="9" y2="12"/></svg>
        Sign out
      </a>
    </div>
  </aside>

  <main class="main-content">
HTML;
}

/**
 * Event workspace sub-navigation. Render just under layout_start() on any
 * event-scoped page so the whole event lives behind one consistent tab strip.
 * $active ∈ overview|guests|tickets|whatsapp|email|doorstaff|reports
 */
function event_tabs(int $eventId, string $active, string $eventTitle = ''): void {
    if (!$eventId) return;
    $base = BASE_URL;
    $title = htmlspecialchars($eventTitle);
    $tabs = [
        'overview'  => ['Overview',   "/admin/events.php?action=view&id={$eventId}"],
        'guests'    => ['Guests',     "/admin/guests.php?event_id={$eventId}"],
        'tickets'   => ['Tickets',    "/admin/ticket_designer.php?event_id={$eventId}"],
        'whatsapp'  => ['WhatsApp',   "/admin/whatsapp.php?event_id={$eventId}"],
        'email'     => ['Email',      "/admin/email.php?event_id={$eventId}"],
        'doorstaff' => ['Door Staff', "/admin/checkers.php?event_id={$eventId}"],
        'reports'   => ['Reports',    "/admin/reports.php?event_id={$eventId}"],
    ];
    echo '<div class="event-workspace-head">';
    if ($title !== '') {
        echo '<div class="event-workspace-title"><a href="' . $base . '/admin/events.php" class="ews-back">← Events</a>'
           . '<span class="ews-name">' . $title . '</span></div>';
    }
    echo '<nav class="event-tabs">';
    foreach ($tabs as $key => [$label, $href]) {
        $cls = $key === $active ? 'active' : '';
        echo '<a class="' . $cls . '" href="' . $base . $href . '">' . $label . '</a>';
    }
    echo '</nav></div>';
}

function layout_end(): void {
    echo <<<HTML
  </main>
</div>

<script>
// ── CSRF: attach token to AJAX + POST forms ────────────────
(function() {
  const meta = document.querySelector('meta[name="csrf-token"]');
  const TOKEN = meta ? meta.getAttribute('content') : '';
  window.CSRF_TOKEN = TOKEN;

  // Auto-add header to same-origin fetch POST/PUT/DELETE
  if (window.fetch && TOKEN) {
    const _fetch = window.fetch;
    window.fetch = function(input, init) {
      init = init || {};
      const method = (init.method || (typeof input !== 'string' && input.method) || 'GET').toUpperCase();
      const url = typeof input === 'string' ? input : (input && input.url) || '';
      const sameOrigin = !/^https?:\/\//i.test(url) || url.indexOf(location.origin) === 0;
      if (sameOrigin && method !== 'GET' && method !== 'HEAD') {
        const h = new Headers(init.headers || (typeof input !== 'string' && input.headers) || {});
        if (!h.has('X-CSRF-Token')) h.set('X-CSRF-Token', TOKEN);
        init.headers = h;
      }
      return _fetch(input, init);
    };
  }

  // Inject hidden csrf_token into every POST form that lacks one
  function injectForms(root) {
    (root || document).querySelectorAll('form').forEach(f => {
      if ((f.method || '').toLowerCase() !== 'post') return;
      if (f.querySelector('input[name="csrf_token"]')) return;
      const i = document.createElement('input');
      i.type = 'hidden'; i.name = 'csrf_token'; i.value = TOKEN;
      f.appendChild(i);
    });
  }
  document.addEventListener('DOMContentLoaded', () => injectForms(document));
  // Also inject just before submit in case a form was added dynamically
  document.addEventListener('submit', function(e) {
    if ((e.target.method || '').toLowerCase() === 'post') injectForms(e.target.parentNode || document);
  }, true);
})();

// ── Global button + form loading system ────────────────────
(function() {
  const MESSAGES = {
    'generate':'Generating tickets…','upload':'Uploading…',
    'import':'Importing guests…','apply':'Applying to all tickets…',
    'save':'Saving…','create':'Creating…','delete':'Deleting…',
    'sign':'Signing in…','login':'Signing in…','reset':'Resetting…',
    'export':'Exporting…','mark':'Updating…','submit':'Submitting…',
  };

  function loaderMsg(btn) {
    if (btn && btn.dataset.loaderText) return btn.dataset.loaderText;
    const t = (btn ? (btn.textContent || btn.value || '') : '').toLowerCase();
    for (const [k,v] of Object.entries(MESSAGES)) if (t.includes(k)) return v;
    return 'Processing…';
  }

  function showLoader(msg) {
    const el = document.getElementById('page-loader');
    const lb = document.getElementById('loader-text');
    if (el) el.classList.add('active');
    if (lb) lb.textContent = msg || 'Processing…';
  }
  window.showPageLoader = showLoader;
  window.hidePageLoader = function() {
    const el = document.getElementById('page-loader');
    if (el) el.classList.remove('active');
  };

  // ── Per-button loading state ──────────────────────────────
  window.btnLoading = function(btn, text) {
    if (!btn) return;
    if (!btn.dataset.origHtml) btn.dataset.origHtml = btn.innerHTML;
    btn.dataset.origDisabled = btn.disabled;
    btn.classList.add('btn-loading');
    btn.disabled = true;
  };
  window.btnReset = function(btn) {
    if (!btn) return;
    btn.classList.remove('btn-loading');
    btn.disabled = (btn.dataset.origDisabled === 'true');
    if (btn.dataset.origHtml) {
      btn.innerHTML = btn.dataset.origHtml;
      delete btn.dataset.origHtml;
    }
  };

  // ── Toast notifications ───────────────────────────────────
  window.showToast = function(message, type, duration) {
    type     = type     || 'info';
    duration = duration || 3500;
    let container = document.getElementById('toast-container');
    if (!container) {
      container = document.createElement('div');
      container.id = 'toast-container';
      document.body.appendChild(container);
    }
    const colors = {success:'var(--success)',error:'var(--danger)',info:'var(--gold)'};
    const toast  = document.createElement('div');
    toast.className = 'toast toast-' + type;
    toast.innerHTML =
      '<span style="width:8px;height:8px;border-radius:50%;background:' +
      (colors[type]||'var(--muted)') + ';flex-shrink:0;display:inline-block"></span>' +
      '<span>' + String(message||'').replace(/[&<>"']/g, c =>
        ({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[c])) + '</span>';
    container.appendChild(toast);
    requestAnimationFrame(() => requestAnimationFrame(() => toast.classList.add('show')));
    setTimeout(() => {
      toast.classList.remove('show');
      setTimeout(() => toast.remove(), 350);
    }, duration);
  };

  // ── Auto-attach to POST forms ─────────────────────────────
  document.addEventListener('submit', function(e) {
    const f = e.target;
    if (f.dataset.noLoader || (f.method||'').toLowerCase() === 'get') return;
    const btn = f.querySelector('button[type=submit]:focus, input[type=submit]:focus')
             || f.querySelector('button[type=submit], input[type=submit]');
    // Add visual loading class but do NOT disable — disabled buttons don't submit their name value
    if (btn) btn.classList.add('btn-loading');
    showLoader(loaderMsg(btn));
  }, true);

  // ── Anchor buttons: spinner on navigate ───────────────────
  document.addEventListener('click', function(e) {
    const btn = e.target.closest('a.btn');
    if (!btn || btn.dataset.noLoader || btn.dataset.ui) return;
    if (btn.target === '_blank' || !btn.href || btn.href.includes('#')) return;
    window.btnLoading(btn);
  });

  // ── Reset on browser back ─────────────────────────────────
  window.addEventListener('pageshow', function(ev) {
    if (ev.persisted) {
      window.hidePageLoader();
      document.querySelectorAll('.btn-loading').forEach(b => window.btnReset(b));
    }
  });
})();

// ── Rich-text markup toolbar ────────────────────────────────
// Wraps the current selection in a marker (*bold*, _italic_, ~strike~, `mono`).
// Same syntax works in WhatsApp natively and is converted to HTML for email.
window.fmtWrap = function(textareaId, marker) {
  const ta = document.getElementById(textareaId);
  if (!ta) return;
  const start = ta.selectionStart, end = ta.selectionEnd;
  const sel   = ta.value.slice(start, end);

  if (!sel) {  // nothing selected — insert the pair and put the caret inside
    ta.setRangeText(marker + marker, start, end, 'end');
    ta.selectionStart = ta.selectionEnd = start + marker.length;
    ta.focus();
    return;
  }
  // Toggle off if already wrapped
  const already = sel.length > marker.length * 1 &&
                  sel.startsWith(marker) && sel.endsWith(marker);
  const out = already ? sel.slice(marker.length, -marker.length) : marker + sel + marker;
  ta.setRangeText(out, start, end, 'select');
  ta.focus();
};

// Insert a placeholder (e.g. {name}) at the caret.
window.fmtInsert = function(textareaId, snippet) {
  const ta = document.getElementById(textareaId);
  if (!ta) return;
  const start = ta.selectionStart, end = ta.selectionEnd;
  ta.setRangeText(snippet, start, end, 'end');
  ta.focus();
};

// ── Mobile sidebar drawer ───────────────────────────────────
window.toggleSidebar = function(force) {
  const sb = document.getElementById('sidebar');
  const sc = document.getElementById('sidebar-scrim');
  if (!sb) return;
  const open = force === undefined ? !sb.classList.contains('open') : force;
  sb.classList.toggle('open', open);
  if (sc) sc.classList.toggle('show', open);
};

// ── Themed confirm modal (replaces native confirm) ──────────
// Usage: uiConfirm({title, message, confirmText, danger}).then(ok => { if (ok) … })
window.uiConfirm = function(opts) {
  opts = opts || {};
  return new Promise(resolve => {
    const esc = s => String(s || '').replace(/[&<>"']/g, c => ({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[c]));
    const wrap = document.createElement('div');
    wrap.className = 'ui-modal-scrim';
    wrap.innerHTML =
      '<div class="ui-modal" role="dialog" aria-modal="true">' +
        '<div class="ui-modal-title">' + esc(opts.title || 'Are you sure?') + '</div>' +
        (opts.message ? '<div class="ui-modal-body">' + esc(opts.message) + '</div>' : '') +
        '<div class="ui-modal-actions">' +
          '<button class="btn btn-outline btn-sm" data-act="cancel">' + esc(opts.cancelText || 'Cancel') + '</button>' +
          '<button class="btn ' + (opts.danger ? 'btn-danger' : 'btn-gold') + ' btn-sm" data-act="ok">' + esc(opts.confirmText || 'Confirm') + '</button>' +
        '</div>' +
      '</div>';
    document.body.appendChild(wrap);
    requestAnimationFrame(() => wrap.classList.add('show'));
    const done = v => { wrap.classList.remove('show'); setTimeout(() => wrap.remove(), 200); resolve(v); };
    wrap.addEventListener('click', e => {
      if (e.target === wrap) return done(false);
      const act = e.target.closest('[data-act]');
      if (act) done(act.dataset.act === 'ok');
    });
    document.addEventListener('keydown', function onKey(e) {
      if (e.key === 'Escape') { document.removeEventListener('keydown', onKey); done(false); }
    });
    wrap.querySelector('[data-act=ok]').focus();
  });
};
</script>
</body>
</html>
HTML;
}
