<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width,initial-scale=1" />
  <meta name="theme-color" content="#0EA5E9" />
  <title>Active sessions — takedowns</title>
  <link rel="stylesheet" href="/public/css/glass.css?v=2-light" />
  <style>
    .session-row { display: flex; gap: .85rem; align-items: flex-start; padding: .85rem; border: 1px solid var(--border); border-radius: 8px; background: var(--bg-3); margin-bottom: .65rem; }
    .session-row.current { border-color: var(--accent); background: rgba(14, 165, 233, 0.08); }
    .session-icon { width: 38px; height: 38px; border-radius: 8px; background: var(--card); border: 1px solid var(--border); display: flex; align-items: center; justify-content: center; flex-shrink: 0; font-size: 1.1rem; }
    .session-icon.desktop { background: rgba(14, 165, 233, 0.15); }
    .session-icon.mobile  { background: rgba(2, 132, 199, 0.18); }
    .session-info { flex: 1; min-width: 0; }
    .session-info .label { font-weight: 600; font-size: 0.95rem; color: var(--fg); }
    .session-info .meta { color: var(--fg-2); font-size: 0.82rem; margin-top: 2px; line-height: 1.45; }
    .session-info .meta .ip { font-family: var(--mono); font-size: 0.78rem; }
    .session-info .current-pill { display: inline-block; padding: 1px 7px; background: var(--accent); color: #06222a; border-radius: 99px; font-size: 0.7rem; font-weight: 700; margin-left: .5rem; vertical-align: 1px; }
    .session-actions { flex-shrink: 0; }
    .session-actions button { padding: .4rem .7rem; font-size: 0.8rem; }
    .session-row.current .session-actions { color: var(--fg-2); font-size: 0.78rem; }
    .empty-state { text-align: center; padding: 2rem 1rem; color: var(--fg-2); }
    .bulk-bar { display: flex; gap: .65rem; align-items: center; padding: .85rem; background: var(--bg-3); border: 1px solid var(--border); border-radius: 8px; margin-bottom: 1rem; flex-wrap: wrap; }
    .bulk-bar .muted { flex: 1; min-width: 200px; font-size: 0.88rem; }
    .geo-badge { display: inline-block; padding: 1px 7px; background: var(--bg-3); border: 1px solid var(--border); border-radius: 99px; font-size: 0.78rem; margin-right: 4px; }
  </style>
</head>
<body>
  <div class="app">
    <aside>
      <a href="/" class="brand" aria-label="takedowns home"><img src="/public/og/logo-mark.png" alt="" width="28" height="28" /><span class="brand-wordmark">takedowns<small>by vesamuni</small></span></a>
      <nav>
        <a href="/dashboard/">Dashboard</a>
        <a href="/cases/">My cases</a>
        <a href="/scan/">Run a scan</a>
        <a href="/takedown/">Takedowns</a>
        <a href="/billing/">Billing &amp; plan</a>
        <a href="/dashboard/sessions/" class="active">Active sessions</a>
        <a href="/admin/" data-admin-only class="hidden">Admin panel</a>
        <a href="#" id="logout">Sign out</a>
      </nav>
    </aside>

    <main>
      <header class="topbar">
        <div>
          <h1>Active sessions</h1>
          <div class="muted">Where you're signed in. Revoke any device you don't recognize.</div>
        </div>
        <div class="user-pill">
          <span class="avatar" id="avatar">U</span>
          <span id="planPill" class="pill">…</span>
          <span id="siteHealthDot" class="site-health-dot unknown" title="checking…"></span>
        </div>
      </header>

      <div id="flash"></div>

      <section class="panel">
        <div class="between">
          <h2>Devices &amp; browsers</h2>
          <span class="muted" id="count"></span>
        </div>

        <div class="bulk-bar">
          <div class="muted">Sign out everywhere except this device.</div>
          <button id="revokeAllBtn" class="secondary">Sign out other sessions</button>
        </div>

        <div id="sessionsList">
          <div class="muted">Loading…</div>
        </div>

        <p class="muted" style="font-size:.85rem; margin-top:1.25rem">
          Tip: if you see a device you don't recognize, revoke it and change your password
          (<a href="/dashboard/">back to dashboard</a>). You'll get a "password was changed" email
          confirmation at your account address.
        </p>
      </section>
    </main>
  </div>

  <script>
    function esc(s){return String(s==null?'':s).replace(/[&<>"']/g,c=>({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[c]));}
    function csrf(){const m=document.cookie.match(/(?:^|; )ncsrf=([^;]+)/);return m?m[1]:'';}
    async function api(p,o={}){const r=await fetch(p,{...o,headers:{'content-type':'application/json','x-csrf-token':csrf(),...(o.headers||{})}});if(r.status===401){location.href='/login?next='+encodeURIComponent(location.pathname);return null;}return r.json().catch(()=>({}));}
    function flash(t,m){const el=document.getElementById('flash');el.innerHTML=`<div class="flash ${esc(t)}">${esc(m)}</div>`;setTimeout(()=>el.innerHTML='',5000);}
    function fmtAgo(ms){if(!ms)return'—';const s=Math.floor((Date.now()-ms)/1000);if(s<60)return s+'s ago';if(s<3600)return Math.floor(s/60)+'m ago';if(s<86400)return Math.floor(s/3600)+'h ago';return Math.floor(s/86400)+'d ago';}
    function fmtExp(ms){if(!ms)return'—';return new Date(ms).toLocaleString();}
    function deviceIcon(d){if(d==='iPhone'||d==='iPad'||d==='Android phone'||d==='Android tablet')return {cls:'mobile',icon:'📱'};return {cls:'desktop',icon:'🖥️'};}

    async function loadSessions() {
      const d = await api('/auth/sessions');
      if (!d) return;
      const list = document.getElementById('sessionsList');
      document.getElementById('count').textContent = d.sessions.length + ' active';
      if (!d.sessions.length) {
        list.innerHTML = '<div class="empty-state">No active sessions.</div>';
        return;
      }
      list.innerHTML = d.sessions.map(s => {
        const ic = deviceIcon(s.device.device);
        const ip = s.ip ? `<span class="ip">${esc(s.ip)}</span>` : '<span class="muted">unknown IP</span>';
        const ua = s.user_agent ? esc(s.user_agent.slice(0, 80)) + (s.user_agent.length > 80 ? '…' : '') : '<span class="muted">unknown agent</span>';
        const cur = s.is_current ? '<span class="current-pill">This device</span>' : '';
        const revokeBtn = s.is_current
          ? '<span class="muted">Use "Sign out" in the sidebar</span>'
          : `<button class="secondary" data-sid="${esc(s.sid)}">Sign out</button>`;
        // Geo: server returns { country, country_name, region, city, timezone, ll }
        let geoBadge = '';
        if (s.geo) {
          const flag = s.geo.country ? String.fromCodePoint(0x1F1E6 + s.geo.country.charCodeAt(0) - 65, 0x1F1E6 + s.geo.country.charCodeAt(1) - 65) : '';
          const label = s.geo.city ? `${s.geo.city}, ${s.geo.country_name || s.geo.country}` : (s.geo.country_name || s.geo.country || '');
          if (label) geoBadge = `<span class="geo-badge" title="${esc(s.geo.timezone || s.geo.country || '')}">${flag} ${esc(label)}</span> `;
        }
        return `
          <div class="session-row ${s.is_current ? 'current' : ''}">
            <div class="session-icon ${ic.cls}">${ic.icon}</div>
            <div class="session-info">
              <div class="label">${esc(s.device.label)}${cur}</div>
              <div class="meta">${geoBadge}${ip} &middot; last seen ${fmtAgo(s.last_seen_at)} &middot; expires ${fmtExp(s.expires_at)}</div>
              <div class="meta" style="font-size:.78rem; opacity:.7">${ua}</div>
            </div>
            <div class="session-actions">${revokeBtn}</div>
          </div>`;
      }).join('');

      // Wire revoke buttons
      list.querySelectorAll('button[data-sid]').forEach(btn => {
        btn.onclick = async () => {
          if (!confirm('Sign out this device?')) return;
          const r = await fetch('/auth/sessions/' + encodeURIComponent(btn.dataset.sid), {
            method: 'DELETE',
            headers: { 'content-type': 'application/json', 'x-csrf-token': csrf() },
          });
          const data = await r.json().catch(() => ({}));
          if (r.ok) { flash('ok', 'Session signed out.'); loadSessions(); }
          else flash('err', data.message || data.error || 'Could not sign out');
        };
      });
    }

    document.getElementById('revokeAllBtn').onclick = async () => {
      if (!confirm('Sign out ALL other sessions? You will stay signed in here.')) return;
      const r = await fetch('/auth/sessions/revoke-others', {
        method: 'POST',
        headers: { 'content-type': 'application/json', 'x-csrf-token': csrf() },
      });
      const data = await r.json().catch(() => ({}));
      if (r.ok) { flash('ok', `Signed out ${data.revoked || 0} other session(s).`); loadSessions(); }
      else flash('err', data.message || data.error || 'Could not sign out other sessions');
    };

    // Load plan pill from /auth/me
    (async () => {
      const d = await api('/auth/me');
      if (d && d.user) {
        document.getElementById('avatar').textContent = (d.user.name || '?').charAt(0).toUpperCase();
        document.getElementById('planPill').textContent = d.user.plan || 'free';
      }
    })();

    document.getElementById('logout').onclick = async (e) => {
      e.preventDefault();
      await api('/auth/logout', { method: 'POST' });
      location.href = '/';
    };

    loadSessions();
  </script>
  <script src="/public/js/siteHealth.js" defer></script>
</body>
</html>
