<!DOCTYPE html>
<html lang="en">
<head>
  <script>
    (function(){
      var t=localStorage.getItem('theme');
      if(!t){t=window.matchMedia('(prefers-color-scheme:dark)').matches?'original-dark':'original-light';}
      document.documentElement.setAttribute('data-theme',t);
      if(localStorage.getItem('sidebar-collapsed')) document.documentElement.classList.add('collapsed');
    })();
  </script>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>{% block title %}SimpleX Manager{% endblock %}</title>
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
  <link rel="preconnect" href="https://fonts.googleapis.com">
  <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;700&display=swap" rel="stylesheet">
  <script src="https://unpkg.com/htmx.org@1.9.12/dist/htmx.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/qrcode/build/qrcode.min.js"></script>
  <script>
    document.addEventListener('htmx:configRequest', function(evt) {
      const m = document.cookie.match(/(?:^|;\s*)token=([^;]+)/);
      if (m) evt.detail.headers['X-Token'] = m[1];
    });
  </script>
  <style>
    *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

    /* ── Original Light ─────────────────────────────────────────────── */
    [data-theme="original-light"] {
      --bg:               #f5f5f7;
      --card:             #ffffff;
      --text:             #1d1d1f;
      --muted:            #6e6e73;
      --accent:           #0053D0;
      --green:            #20BD3D;
      --red:              #DD0000;
      --border:           #e0e0e5;
      --shadow:           0 2px 12px rgba(0,0,0,0.08);
      --btn-light-text:   #fff;
      --badge-green-bg:   #d1fae5;
      --badge-green-text: #065f46;
      --badge-red-bg:     #fee2e2;
      --badge-red-text:   #991b1b;
    }

    /* ── Original Dark ──────────────────────────────────────────────── */
    [data-theme="original-dark"] {
      --bg:               #111827;
      --card:             #0B2A59;
      --text:             #f5f5f7;
      --muted:            #9ca3af;
      --accent:           #70F0F9;
      --green:            #20BD3D;
      --red:              #DD0000;
      --border:           #1e3a5f;
      --shadow:           none;
      --btn-light-text:   #000;
      --badge-green-bg:   #064e3b;
      --badge-green-text: #6ee7b7;
      --badge-red-bg:     #7f1d1d;
      --badge-red-text:   #fca5a5;
    }

    /* ── Matrix ─────────────────────────────────────────────────────── */
    [data-theme="matrix"] {
      --bg:               #000000;
      --card:             #050d05;
      --text:             #00ff41;
      --muted:            #2e8b57;
      --accent:           #00ff41;
      --green:            #00ff41;
      --red:              #ff3b3b;
      --border:           #0f3d0f;
      --shadow:           0 0 14px rgba(0,255,65,0.12);
      --btn-light-text:   #000000;
      --badge-green-bg:   #002200;
      --badge-green-text: #00ff41;
      --badge-red-bg:     #220000;
      --badge-red-text:   #ff6b6b;
    }

    body { font-family: 'Roboto', -apple-system, BlinkMacSystemFont, 'Segoe UI', Arial, sans-serif;
           background: var(--bg); color: var(--text); min-height: 100vh; }

    /* Material-ish elevation: cards lift slightly on hover */
    .card { transition: box-shadow 0.18s ease, transform 0.05s ease; }
    .card:hover { box-shadow: 0 4px 18px rgba(0,0,0,0.14); }
    [data-theme="matrix"] .card:hover { box-shadow: 0 0 18px rgba(0,255,65,0.22); }
    .btn { box-shadow: 0 1px 3px rgba(0,0,0,0.18); letter-spacing: 0.2px; }
    .btn-ghost { box-shadow: none; }

    [data-theme="matrix"] body {
      font-family: 'SF Mono', 'Consolas', 'Courier New', monospace;
      text-shadow: 0 0 2px rgba(0,255,65,0.4);
    }

    /* ── Layout: sidebar + main ─────────────────────────────────────── */
    .app { display: flex; min-height: 100vh; }

    .sidebar {
      width: 220px; flex-shrink: 0;
      background: var(--card); border-right: 1px solid var(--border);
      display: flex; flex-direction: column;
      position: sticky; top: 0; height: 100vh;
      overflow-y: auto;            /* scroll within the sidebar if it's taller than the screen */
      transition: width 0.2s ease, transform 0.2s ease;
      z-index: 50;
    }
    html.collapsed .sidebar { width: 64px; }

    .side-head { display: flex; align-items: center; border-bottom: 1px solid var(--border); }
    .collapse-toggle {
      flex-shrink: 0; background: none; border: none; cursor: pointer;
      color: var(--muted); font-size: 17px; padding: 18px;
    }
    .collapse-toggle:hover { color: var(--text); }
    .nav-brand {
      display: flex; align-items: center; gap: 10px;
      padding: 18px 18px 18px 0; font-size: 16px; font-weight: 700;
      color: var(--accent); text-decoration: none;
      white-space: nowrap; overflow: hidden;
    }
    .nav-brand .brand-icon { font-size: 18px; flex-shrink: 0; }
    html.collapsed .nav-brand { display: none; }
    html.collapsed .side-head { justify-content: center; }

    .side-nav { display: flex; flex-direction: column; padding: 8px 0; }
    .side-nav a {
      position: relative;
      display: flex; align-items: center; gap: 12px;
      padding: 11px 18px; color: var(--muted); text-decoration: none;
      font-size: 14px; font-weight: 600; white-space: nowrap; overflow: hidden;
      border-left: 3px solid transparent;
    }
    .notif-badge {
      margin-left: auto; min-width: 18px; height: 18px; padding: 0 5px;
      border-radius: 9px; background: var(--red); color: #fff;
      font-size: 11px; font-weight: 700;
      display: inline-flex; align-items: center; justify-content: center;
    }
    html.collapsed .side-nav .notif-badge {
      position: absolute; top: 5px; right: 8px; margin: 0;
      min-width: 16px; height: 16px; font-size: 10px; padding: 0 4px;
    }
    .side-nav a:hover { color: var(--text); background: var(--bg); }
    .side-nav a.active { color: var(--accent); border-left-color: var(--accent); }
    .side-nav .ico { width: 20px; text-align: center; font-size: 16px; flex-shrink: 0; }
    .side-nav a.nav-sep { margin-top: 10px; padding-top: 17px; border-top: 1px solid var(--border); }

    .side-foot { margin-top: auto; padding: 8px 0; border-top: 1px solid var(--border); }

    .side-clock { padding: 12px 18px 10px; border-bottom: 1px solid var(--border); text-align: center; }
    .side-clock .clk-time { font-size: 20px; font-weight: 700; color: var(--text);
                            font-variant-numeric: tabular-nums; letter-spacing: 0.5px; }
    .side-clock .clk-date { font-size: 11px; color: var(--muted); margin-top: 2px; }
    html.collapsed .side-clock { padding: 10px 0; }
    html.collapsed .side-clock .clk-time { font-size: 12px; }
    html.collapsed .side-clock .clk-date { display: none; }

    .side-status { padding: 10px 18px 12px; font-size: 12px; color: var(--muted);
                   border-bottom: 1px solid var(--border); }
    .side-status .ss-row { display: flex; align-items: center; gap: 6px; margin-top: 3px;
                           white-space: nowrap; overflow: hidden; }
    .ss-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--muted); flex-shrink: 0; }
    .ss-dot.online  { background: var(--green); box-shadow: 0 0 5px var(--green); }
    .ss-dot.offline { background: var(--red); }
    /* collapsed: keep only the status dot, centered */
    html.collapsed .side-status { padding: 12px 0; }
    html.collapsed .side-status .ss-text { display: none; }
    html.collapsed .side-status .ss-row { justify-content: center; margin-top: 0; }
    html.collapsed .side-status .ss-row.ss-text { display: none; }

    html.collapsed .lbl, html.collapsed .brand-text { display: none; }

    .main { flex: 1; min-width: 0; display: flex; flex-direction: column; }
    .container { max-width: 960px; margin: 0 auto; padding: 32px 20px; width: 100%; flex: 1 0 auto; }

    .site-footer {
      flex-shrink: 0; text-align: center;
      padding: 18px 20px; border-top: 1px solid var(--border);
      color: var(--muted); font-size: 12px; line-height: 1.6;
    }
    .site-footer a { color: var(--accent); text-decoration: none; font-weight: 600; }
    .site-footer a:hover { text-decoration: underline; }
    .site-footer .sep { margin: 0 8px; opacity: 0.5; }

    .mobile-menu-btn {
      display: none; position: fixed; top: 12px; left: 12px; z-index: 40;
      width: 40px; height: 40px; border-radius: 8px; border: 1px solid var(--border);
      background: var(--card); color: var(--text); font-size: 18px; cursor: pointer;
      align-items: center; justify-content: center;
    }
    .backdrop { display: none; position: fixed; inset: 0; background: rgba(0,0,0,0.5); z-index: 45; }

    /* ── Mobile: off-canvas sidebar ─────────────────────────────────── */
    @media (max-width: 768px) {
      .sidebar {
        position: fixed; left: 0; top: 0; width: 240px;
        height: 100vh; height: 100dvh;   /* dvh tracks the visible area incl. browser toolbar */
        overflow-y: auto; -webkit-overflow-scrolling: touch;
        transform: translateX(-100%);
      }
      html.collapsed .sidebar { width: 240px; }       /* ignore collapse on mobile */
      html.collapsed .lbl, html.collapsed .brand-text { display: inline; }
      html.collapsed .nav-brand { display: flex; }    /* keep brand visible on mobile */
      html.collapsed .side-head { justify-content: flex-start; }
      body.sidebar-open .sidebar { transform: translateX(0); }
      body.sidebar-open .backdrop { display: block; }
      .mobile-menu-btn { display: flex; }
      .collapse-toggle { display: none; }             /* mobile uses the drawer toggle instead */
      .container { padding-top: 64px; }
    }

    h1 { font-size: 28px; font-weight: 700; margin-bottom: 24px; }
    h2 { font-size: 20px; font-weight: 600; margin-bottom: 16px; }

    .card { background: var(--card); border-radius: 10px; padding: 20px;
             box-shadow: var(--shadow); margin-bottom: 16px; }

    .btn { display: inline-flex; align-items: center; gap: 6px;
           padding: 8px 18px; border-radius: 8px; font-size: 14px; font-weight: 600;
           font-family: inherit; cursor: pointer; border: none; text-decoration: none;
           transition: opacity 0.15s; }
    .btn:hover { opacity: 0.85; }
    .btn-primary { background: var(--accent); color: var(--btn-light-text); }
    .btn-danger  { background: var(--red); color: #fff; }
    .btn-success { background: var(--green); color: var(--btn-light-text); }
    .btn-ghost   { background: transparent; border: 1px solid var(--border); color: var(--text); }

    .badge { display: inline-block; padding: 2px 8px; border-radius: 10px;
             font-size: 12px; font-weight: 600; }
    .badge-green { background: var(--badge-green-bg); color: var(--badge-green-text); }
    .badge-red   { background: var(--badge-red-bg);   color: var(--badge-red-text); }

    input, select, textarea {
      width: 100%; padding: 9px 12px; font-size: 14px; font-family: inherit;
      border: 1px solid var(--border); border-radius: 8px;
      background: var(--bg); color: var(--text); outline: none;
      transition: border-color 0.15s;
    }
    input:focus, select:focus, textarea:focus { border-color: var(--accent); }

    label { display: block; font-size: 13px; font-weight: 600;
            color: var(--muted); margin-bottom: 4px; }

    .field { margin-bottom: 14px; }

    .grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
    @media (max-width: 640px) { .grid-2 { grid-template-columns: 1fr; } }

    .monospace { font-family: monospace; font-size: 12px; }

    .log-box { background: #0a0a0f; color: #70F0F9; border-radius: 8px;
               padding: 12px; font-family: monospace; font-size: 12px;
               height: 200px; overflow-y: auto; white-space: pre-wrap; }

    .tag { display: inline-block; padding: 2px 8px; border-radius: 6px;
           font-size: 12px; background: var(--border); color: var(--muted); }
    .tag-user { background: rgba(0,83,208,0.12); color: var(--accent); }
    [data-theme="original-dark"] .tag-user { background: rgba(112,240,249,0.12); color: var(--accent); }
    [data-theme="matrix"] .tag-user { background: rgba(0,255,65,0.12); color: var(--accent); }

    .flex { display: flex; align-items: center; gap: 10px; }
    .flex-between { display: flex; align-items: center; justify-content: space-between; }
    .gap-8 { gap: 8px; }
    .mt-8 { margin-top: 8px; }
    .mt-16 { margin-top: 16px; }
    .muted { color: var(--muted); font-size: 13px; }

    table { width: 100%; border-collapse: collapse; font-size: 14px; }
    th { text-align: left; color: var(--muted); font-size: 12px; font-weight: 600;
         padding: 8px 12px; border-bottom: 1px solid var(--border); }
    td { padding: 10px 12px; border-bottom: 1px solid var(--border); }
    tr:last-child td { border-bottom: none; }

    .htmx-indicator { opacity: 0; transition: opacity 0.2s; }
    .htmx-request .htmx-indicator { opacity: 1; }

    dialog { background: var(--card); color: var(--text); border: 1px solid var(--border);
             border-radius: 12px; padding: 28px; max-width: 480px; width: 90%; }
    dialog::backdrop { background: rgba(0,0,0,0.5); }

    /* reusable SimpleX link box: Link + QR toggles, both hidden by default */
    .lb-btn { display: inline-flex; align-items: center; gap: 6px;
              padding: 4px 10px; font-size: 12px; font-weight: 600; border-radius: 6px;
              background: transparent; border: 1px solid var(--border); color: var(--accent);
              cursor: pointer; font-family: inherit; }
    .lb-btn:hover { background: var(--bg); }
    .lb-btn.on { background: var(--accent); color: var(--btn-light-text); border-color: var(--accent); }
    .lb-link { display: flex; align-items: center; gap: 8px; margin-top: 8px; }
    .lb-link .addr-link { flex: 1; min-width: 0; color: var(--muted); font-family: monospace;
                          font-size: 12px; text-decoration: none; word-break: break-all; }
    .lb-link .addr-link:hover { color: var(--accent); text-decoration: underline; }
    .lb-qr { margin-top: 10px; }
    .lb-qr canvas { background: #fff; border-radius: 8px; padding: 8px; }
  </style>
  {% block head %}{% endblock %}
</head>
<body>
<button class="mobile-menu-btn" onclick="toggleSidebar()" aria-label="Menu"><i class="fa-solid fa-bars"></i></button>
<div class="app">
  <aside class="sidebar" id="sidebar">
    <div class="side-head">
      <button class="collapse-toggle" onclick="toggleCollapse()" title="Collapse sidebar" aria-label="Collapse sidebar"><i class="fa-solid fa-bars"></i></button>
      <a class="nav-brand" href="/">
        <span class="brand-text">SimpleX Manager</span>
      </a>
    </div>
    <nav class="side-nav">
      <!-- Group 1: accounts -->
      <a href="/users"    {% if nav_active == 'users'    %}class="active"{% endif %}><span class="ico"><i class="fa-solid fa-user"></i></span><span class="lbl">Users</span></a>
      <a href="/bots"     {% if nav_active == 'bots'     %}class="active"{% endif %}><span class="ico"><i class="fa-solid fa-robot"></i></span><span class="lbl">Bots</span></a>
      <a href="/businesses" {% if nav_active == 'businesses' %}class="active"{% endif %}><span class="ico"><i class="fa-solid fa-briefcase"></i></span><span class="lbl">Business Groups</span></a>
      <a href="https://simplex.chat/file/" target="_blank" rel="noopener"><span class="ico"><i class="fa-solid fa-upload"></i></span><span class="lbl">File Upload</span></a>
      <a href="/rss-bots" {% if nav_active == 'rss-bots' %}class="active"{% endif %}><span class="ico"><i class="fa-solid fa-rss"></i></span><span class="lbl">RSS</span></a>
      <!-- Group 2: relays -->
      <a href="/relays/chat"    class="nav-sep {% if nav_active == 'relays' and kind == 'chat'    %}active{% endif %}"><span class="ico"><i class="fa-solid fa-comments"></i></span><span class="lbl">Chat Relay</span></a>
      <a href="/relays/file"    {% if nav_active == 'relays' and kind == 'file'    %}class="active"{% endif %}><span class="ico"><i class="fa-solid fa-file-export"></i></span><span class="lbl">File Relay</span></a>
      <a href="/relays/message" {% if nav_active == 'relays' and kind == 'message' %}class="active"{% endif %}><span class="ico"><i class="fa-solid fa-envelope"></i></span><span class="lbl">Message Relay</span></a>
      <!-- Group 3: system -->
      <a href="/network" class="nav-sep {% if nav_active == 'network' %}active{% endif %}"><span class="ico"><i class="fa-solid fa-tower-broadcast"></i></span><span class="lbl">Network</span></a>
      <a href="/notifications" {% if nav_active == 'notifications' %}class="active"{% endif %}><span class="ico"><i class="fa-solid fa-bell"></i></span><span class="lbl">Notifications</span><span class="notif-badge" id="notif-badge" style="display:none;"></span></a>
      <a href="/settings" {% if nav_active == 'settings' %}class="active"{% endif %}><span class="ico"><i class="fa-solid fa-gear"></i></span><span class="lbl">Settings</span></a>
      <!-- Group 4: external -->
      <a href="https://simplex.chat/downloads/" target="_blank" rel="noopener" class="nav-sep"><span class="ico"><i class="fa-solid fa-download"></i></span><span class="lbl">Get App</span></a>
    </nav>
    <div class="side-foot">
      <a href="/network" class="side-status" id="side-status" title="View SimpleX network &amp; servers"
         style="display:block;text-decoration:none;{% if nav_active == 'network' %}background:var(--bg);{% endif %}">
        <div class="ss-row"><span class="ss-dot" id="ss-dot"></span><span class="ss-text"><span id="ss-running">–/–</span>&nbsp;running</span></div>
        <div class="ss-row ss-text"><i class="fa-solid fa-server" style="width:14px;text-align:center;"></i>&nbsp;<span id="ss-servers">–</span></div>
        <div class="ss-row ss-text" id="ss-ops" style="opacity:0.8;"></div>
      </a>
      <div class="side-clock" id="side-clock">
        <div class="clk-time" id="clk-time">--:--</div>
        <div class="clk-date ss-text" id="clk-date">—</div>
      </div>
      <nav class="side-nav">
        <a href="/logout"><span class="ico"><i class="fa-solid fa-right-from-bracket"></i></span><span class="lbl">Logout</span></a>
      </nav>
    </div>
  </aside>
  <div class="backdrop" id="backdrop" onclick="closeSidebar()"></div>
  <main class="main">
    <div class="container">
      {% block content %}{% endblock %}
    </div>
    <footer class="site-footer">
      © <a href="https://bournemouthtechnology.co.uk" target="_blank" rel="noopener">Bournemouth Technology Ltd</a>
      <span class="sep">·</span>
      built on © <a href="https://simplex.chat" target="_blank" rel="noopener">SimpleX Network</a>
      <span class="sep">·</span>
      <a href="https://simplex.chat/downloads/" target="_blank" rel="noopener">Get SimpleX App</a>
    </footer>
  </main>
</div>
<script>
  function toggleSidebar() { document.body.classList.toggle('sidebar-open'); }
  function closeSidebar()  { document.body.classList.remove('sidebar-open'); }
  function toggleCollapse() {
    const collapsed = document.documentElement.classList.toggle('collapsed');
    localStorage.setItem('sidebar-collapsed', collapsed ? '1' : '');
  }

  // Clipboard that also works over plain-HTTP LAN (navigator.clipboard needs a secure context).
  function robustCopy(text) {
    if (navigator.clipboard && window.isSecureContext) {
      return navigator.clipboard.writeText(text).catch(() => fallbackCopy(text));
    }
    return Promise.resolve(fallbackCopy(text));
  }
  function fallbackCopy(text) {
    const ta = document.createElement('textarea');
    ta.value = text; ta.style.position = 'fixed'; ta.style.opacity = '0';
    document.body.appendChild(ta); ta.focus(); ta.select();
    try { document.execCommand('copy'); } catch (e) {}
    document.body.removeChild(ta);
  }
  function flashCheck(btn) {
    const o = btn.innerHTML;
    btn.innerHTML = '<i class="fa-solid fa-check"></i>';
    setTimeout(() => btn.innerHTML = o, 1500);
  }

  // Reusable SimpleX link box: Link + QR toggles (both hidden by default).
  function _sxUrl(id) { const a = document.getElementById('lb-url-' + id); return a ? a.getAttribute('href') : ''; }
  function sxToggleLink(id, btn) {
    const el = document.getElementById('lb-link-' + id); if (!el) return;
    const show = el.style.display === 'none';
    el.style.display = show ? '' : 'none';
    btn.classList.toggle('on', show);
  }
  function sxToggleQr(id, btn) {
    const w = document.getElementById('lb-qr-' + id); if (!w) return;
    const show = w.style.display === 'none';
    w.style.display = show ? '' : 'none';
    btn.classList.toggle('on', show);
    if (show && !w.dataset.r && window.QRCode) {
      QRCode.toCanvas(document.getElementById('lb-qrc-' + id), _sxUrl(id), {width: 180}, () => {});
      w.dataset.r = '1';
    }
  }
  function sxCopy(id, btn) { robustCopy(_sxUrl(id)).then(() => flashCheck(btn)); }

  // Sidebar clock: 24h time + day-of-week date
  function tickClock() {
    const now = new Date();
    const te = document.getElementById('clk-time');
    const de = document.getElementById('clk-date');
    if (te) te.textContent = now.toLocaleTimeString('en-GB', {hour: '2-digit', minute: '2-digit', hour12: false});
    if (de) de.textContent = now.toLocaleDateString('en-GB', {weekday: 'short', day: '2-digit', month: 'short', year: 'numeric'});
  }
  tickClock();
  setInterval(tickClock, 1000);

  // Poll for unread notifications and update the sidebar badge
  async function pollNotifications() {
    try {
      const t = document.cookie.match(/(?:^|;\s*)token=([^;]+)/)?.[1] || '';
      const r = await fetch('/api/notifications', { headers: { 'X-Token': t } });
      if (!r.ok) return;
      const d = await r.json();
      const label = d.unread > 99 ? '99+' : d.unread;
      // update every badge (sidebar nav + homepage card) from the one source
      document.querySelectorAll('.notif-badge').forEach(b => {
        if (d.unread > 0) { b.textContent = label; b.style.display = 'inline-flex'; }
        else { b.style.display = 'none'; }
      });
    } catch (e) {}
  }
  pollNotifications();
  setInterval(pollNotifications, 5000);

  // Poll global SimpleX/network status for the sidebar widget
  async function pollStatus() {
    try {
      const t = document.cookie.match(/(?:^|;\s*)token=([^;]+)/)?.[1] || '';
      const r = await fetch('/api/status', { headers: { 'X-Token': t } });
      if (!r.ok) return;
      const d = await r.json();
      document.getElementById('ss-running').textContent = d.profiles_running + '/' + d.profiles_total;
      const dot = document.getElementById('ss-dot');
      dot.className = 'ss-dot ' + (d.online ? 'online' : 'offline');
      document.getElementById('ss-servers').textContent =
        d.online ? `${d.smp_servers} SMP · ${d.xftp_servers} XFTP` : 'no profile running';
      document.getElementById('ss-ops').textContent =
        (d.operators && d.operators.length) ? d.operators.join(', ') : '';
    } catch (e) {}
  }
  pollStatus();
  setInterval(pollStatus, 15000);
</script>
</body>
</html>
