<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>ESP32 Recon</title>
  <link rel="preconnect" href="https://fonts.googleapis.com" />
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
  <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;700&display=swap" rel="stylesheet" />
  <link rel="stylesheet" href="/static/dashboard.css" />
</head>
<body>
<div id="app">

  <!-- Topbar -->
  <div id="topbar">
    <span class="title">ESP32 Recon</span>
    <span class="sep">/</span>
    <span class="build-info">WiFi Recon Cluster</span>
    <div id="live-dot"></div>
    <span id="live-label">LIVE</span>
  </div>

  <!-- Navbar -->
  <div id="navbar">
    <button class="tab-btn active" id="tab-feed"       onclick="showFeed()">Feed</button>
    <button class="tab-btn"        id="tab-networks"   onclick="showNetworks()">Networks</button>
    <button class="tab-btn"        id="tab-crossnode"  onclick="showCrossNode()">Cross-node</button>
    <button class="tab-btn"        id="tab-clients"    onclick="showClients()">Clients</button>
    <button class="tab-btn"        id="tab-presence"   onclick="showPresence()">Presence</button>
    <button class="tab-btn"        id="tab-alerts"     onclick="showAlerts()">Alerts</button>
    <button class="tab-btn"        id="tab-analysis"   onclick="showAnalysis()">Analysis</button>
    <button class="tab-btn"        id="tab-search"     onclick="showSearch()">Search</button>
  </div>

  <!-- Sidebar -->
  <div id="sidebar">
    <div class="sidebar-section">
      <div class="sidebar-label">Summary</div>
      <div class="stat-row"><span>nodes</span><span id="sum-nodes">—</span></div>
      <div class="stat-row"><span>online</span><span id="sum-online">—</span></div>
      <div class="stat-row"><span>events (session)</span><span id="sum-events">—</span></div>
    </div>
    <div class="sidebar-section">
      <div class="sidebar-label">Nodes</div>
      <div id="node-list"></div>
    </div>
  </div>

  <!-- Main -->
  <div id="main">

    <!-- Feed view -->
    <div id="view-general" class="view active">
      <div class="section-header">
        <span class="section-title">Live Feed</span>
        <span class="section-count" id="general-count"></span>
      </div>
      <div class="tbl-wrap">
        <table>
          <thead>
            <tr>
              <th>Time</th>
              <th>Node</th>
              <th>SSID</th>
              <th>BSSID</th>
              <th>RSSI</th>
              <th>Ch</th>
              <th>Enc</th>
              <th>Imp</th>
            </tr>
          </thead>
          <tbody id="general-tbody"></tbody>
        </table>
        <div class="empty" id="general-empty" style="display:none">No events yet.</div>
      </div>
    </div>

    <!-- Node detail view -->
    <div id="view-detail" class="view">
      <button id="back-btn" onclick="showGeneral()">&#8592; All nodes</button>

      <div class="section-header">
        <span class="section-title">Node</span>
        <span class="section-count" id="detail-node-id"></span>
      </div>

      <div id="detail-stats-grid">
        <div class="stat-outer"><div class="stat-dot"></div><div class="stat-card"><div class="stat-ray"></div><div class="label">Status</div><div class="value" id="ds-status">—</div><div class="line topl"></div><div class="line leftl"></div><div class="line bottoml"></div><div class="line rightl"></div></div></div>
        <div class="stat-outer"><div class="stat-dot"></div><div class="stat-card"><div class="stat-ray"></div><div class="label">Total Events</div><div class="value" id="ds-total">—</div><div class="line topl"></div><div class="line leftl"></div><div class="line bottoml"></div><div class="line rightl"></div></div></div>
        <div class="stat-outer"><div class="stat-dot"></div><div class="stat-card"><div class="stat-ray"></div><div class="label">Unique SSIDs</div><div class="value" id="ds-ssids">—</div><div class="line topl"></div><div class="line leftl"></div><div class="line bottoml"></div><div class="line rightl"></div></div></div>
        <div class="stat-outer"><div class="stat-dot"></div><div class="stat-card"><div class="stat-ray"></div><div class="label">Unique BSSIDs</div><div class="value" id="ds-bssids">—</div><div class="line topl"></div><div class="line leftl"></div><div class="line bottoml"></div><div class="line rightl"></div></div></div>
        <div class="stat-outer"><div class="stat-dot"></div><div class="stat-card"><div class="stat-ray"></div><div class="label">Avg RSSI</div><div class="value" id="ds-rssi-avg">—</div><div class="sub" id="ds-rssi-range"></div><div class="line topl"></div><div class="line leftl"></div><div class="line bottoml"></div><div class="line rightl"></div></div></div>
        <div class="stat-outer"><div class="stat-dot"></div><div class="stat-card"><div class="stat-ray"></div><div class="label">First Seen</div><div class="value value-sm" id="ds-first">—</div><div class="line topl"></div><div class="line leftl"></div><div class="line bottoml"></div><div class="line rightl"></div></div></div>
        <div class="stat-outer"><div class="stat-dot"></div><div class="stat-card"><div class="stat-ray"></div><div class="label">Last Seen</div><div class="value value-sm" id="ds-last">—</div><div class="line topl"></div><div class="line leftl"></div><div class="line bottoml"></div><div class="line rightl"></div></div></div>
        <div class="stat-outer"><div class="stat-dot"></div><div class="stat-card"><div class="stat-ray"></div><div class="label">Uptime</div><div class="value" id="ds-uptime">—</div><div class="line topl"></div><div class="line leftl"></div><div class="line bottoml"></div><div class="line rightl"></div></div></div>
        <div class="stat-outer"><div class="stat-dot"></div><div class="stat-card"><div class="stat-ray"></div><div class="label">Free Heap</div><div class="value" id="ds-heap">—</div><div class="line topl"></div><div class="line leftl"></div><div class="line bottoml"></div><div class="line rightl"></div></div></div>
        <div class="stat-outer"><div class="stat-dot"></div><div class="stat-card"><div class="stat-ray"></div><div class="label">AP Signal</div><div class="value" id="ds-ap-rssi">—</div><div class="sub">node → router</div><div class="line topl"></div><div class="line leftl"></div><div class="line bottoml"></div><div class="line rightl"></div></div></div>
      </div>

      <div class="section-header" style="margin-top:4px">
        <span class="section-title">Recent Events</span>
        <span class="section-count" id="detail-count"></span>
      </div>
      <div class="tbl-wrap">
        <table>
          <thead>
            <tr>
              <th>Time</th>
              <th>SSID</th>
              <th>BSSID</th>
              <th>RSSI</th>
              <th>Ch</th>
              <th>Enc</th>
              <th>Imp</th>
              <th>Conf</th>
            </tr>
          </thead>
          <tbody id="detail-tbody"></tbody>
        </table>
      </div>
    </div>

    <!-- Clients view -->
    <div id="view-clients" class="view">
      <div class="section-header">
        <span class="section-title">Client Devices</span>
        <span class="section-count" id="clients-count"></span>
        <span style="margin-left:auto; font-size:10px; color:var(--text-muted)">
          note: modern devices use randomised MACs — one physical device may appear as multiple entries
        </span>
      </div>
      <div class="tbl-wrap">
        <table>
          <thead>
            <tr>
              <th>MAC</th>
              <th>Vendor</th>
              <th>Probing for</th>
              <th>Best RSSI</th>
              <th>Avg RSSI</th>
              <th>Nodes</th>
              <th>Times Seen</th>
              <th>Last Seen</th>
            </tr>
          </thead>
          <tbody id="clients-tbody"></tbody>
        </table>
        <div class="empty" id="clients-empty" style="display:none">No probe events yet. Nodes need to be flashed with probe sniffing enabled.</div>
      </div>
    </div>

    <!-- Cross-node view -->
    <div id="view-crossnode" class="view">
      <div class="section-header">
        <span class="section-title">Cross-node RSSI</span>
        <span class="section-count" id="crossnode-count"></span>
        <label style="margin-left:auto; font-size:10px; color:var(--text-dim); display:flex; align-items:center; gap:6px; cursor:pointer;">
          <input type="checkbox" id="crossnode-filter" onchange="renderCrossNodeTable()" style="accent-color:var(--green-hi)">
          multi-node only
        </label>
      </div>
      <div class="tbl-wrap">
        <table id="crossnode-table">
          <thead id="crossnode-thead"></thead>
          <tbody id="crossnode-tbody"></tbody>
        </table>
        <div class="empty" id="crossnode-empty" style="display:none">No data yet.</div>
      </div>
    </div>

    <!-- Network RSSI chart view -->
    <div id="view-network-chart" class="view">
      <button class="back-btn" onclick="showNetworks()">&#8592; Networks</button>
      <div class="section-header">
        <span class="section-title" id="chart-title">RSSI History</span>
        <span class="section-count" id="chart-subtitle"></span>
        <div class="range-btns" style="margin-left:auto">
          <button class="range-btn" data-hours="1"  onclick="setChartRange(1)">1h</button>
          <button class="range-btn active" data-hours="2" onclick="setChartRange(2)">2h</button>
          <button class="range-btn" data-hours="6"  onclick="setChartRange(6)">6h</button>
          <button class="range-btn" data-hours="24" onclick="setChartRange(24)">24h</button>
        </div>
      </div>
      <div id="chart-legend"></div>
      <canvas id="rssi-chart" height="240"></canvas>
      <div class="empty" id="chart-empty" style="display:none">No data for this time range.</div>
    </div>

    <!-- Networks view -->
    <div id="view-networks" class="view">
      <div class="section-header">
        <span class="section-title">Networks</span>
        <span class="section-count" id="networks-count"></span>
      </div>
      <div class="tbl-wrap">
        <table>
          <thead>
            <tr>
              <th class="sortable" data-col="ssid"       data-arrow="">SSID</th>
              <th class="sortable" data-col="bssid"      data-arrow="">BSSID</th>
              <th class="sortable" data-col="best_rssi"  data-arrow="">Best RSSI</th>
              <th class="sortable" data-col="avg_rssi"   data-arrow="">Avg RSSI</th>
              <th class="sortable" data-col="channel"    data-arrow="">Ch</th>
              <th class="sortable" data-col="encryption" data-arrow="">Enc</th>
              <th class="sortable sort-active" data-col="times_seen" data-arrow="↓">Times Seen</th>
              <th class="sortable" data-col="node_count" data-arrow="">Nodes</th>
              <th class="sortable" data-col="last_seen"  data-arrow="">Last Seen</th>
              <th></th>
            </tr>
          </thead>
          <tbody id="networks-tbody"></tbody>
        </table>
        <div class="empty" id="networks-empty" style="display:none">No networks seen yet.</div>
      </div>
    </div>

    <!-- Presence view -->
    <div id="view-presence" class="view">

      <!-- Present now -->
      <div class="section-header">
        <span class="section-title">Present Now</span>
        <span class="section-count" id="present-count"></span>
        <span class="presence-sub">real MACs · seen 2+ times in last hour</span>
      </div>
      <div class="tbl-wrap">
        <table>
          <thead><tr>
            <th>MAC</th><th>Vendor</th><th>Best RSSI</th><th>Avg RSSI</th>
            <th>Times Seen</th><th>Nodes</th><th>Last Seen</th>
          </tr></thead>
          <tbody id="present-tbody"></tbody>
        </table>
        <div class="empty" id="present-empty" style="display:none">No devices currently present.</div>
      </div>

      <!-- New arrivals -->
      <div class="section-header" style="margin-top:8px">
        <span class="section-title">New Arrivals</span>
        <span class="section-count" id="arrivals-count"></span>
        <span class="presence-sub">first seen in last 24h</span>
      </div>
      <div class="presence-split">
        <div>
          <div class="presence-sub-label">Devices</div>
          <div class="tbl-wrap">
            <table>
              <thead><tr>
                <th>MAC</th><th>Vendor</th><th>First Seen</th>
                <th>Best RSSI</th><th>Times Seen</th>
              </tr></thead>
              <tbody id="arrivals-macs-tbody"></tbody>
            </table>
            <div class="empty" id="arrivals-macs-empty" style="display:none">No new devices.</div>
          </div>
        </div>
        <div>
          <div class="presence-sub-label">Networks</div>
          <div class="tbl-wrap">
            <table>
              <thead><tr>
                <th>SSID</th><th>BSSID</th><th>First Seen</th>
                <th>Best RSSI</th><th>Ch</th><th>Enc</th>
              </tr></thead>
              <tbody id="arrivals-nets-tbody"></tbody>
            </table>
            <div class="empty" id="arrivals-nets-empty" style="display:none">No new networks.</div>
          </div>
        </div>
      </div>

      <!-- Regulars -->
      <div class="section-header" style="margin-top:8px">
        <span class="section-title">Regulars</span>
        <span class="section-count" id="regulars-count"></span>
        <span class="presence-sub">seen on 2+ distinct days</span>
      </div>
      <div class="presence-split">
        <div>
          <div class="presence-sub-label">Devices</div>
          <div class="tbl-wrap">
            <table>
              <thead><tr>
                <th>MAC</th><th>Vendor</th><th>Days Seen</th>
                <th>First Seen</th><th>Last Seen</th><th>Best RSSI</th>
              </tr></thead>
              <tbody id="regulars-macs-tbody"></tbody>
            </table>
            <div class="empty" id="regulars-macs-empty" style="display:none">Regulars appear after 2+ days of data.</div>
          </div>
        </div>
        <div>
          <div class="presence-sub-label">Networks</div>
          <div class="tbl-wrap">
            <table>
              <thead><tr>
                <th>SSID</th><th>BSSID</th><th>Days Seen</th>
                <th>First Seen</th><th>Best RSSI</th><th>Ch</th>
              </tr></thead>
              <tbody id="regulars-nets-tbody"></tbody>
            </table>
            <div class="empty" id="regulars-nets-empty" style="display:none">Regulars appear after 2+ days of data.</div>
          </div>
        </div>
      </div>

    </div><!-- /#view-presence -->

    <!-- Alerts view -->
    <div id="view-alerts" class="view">

      <!-- Summary strip -->
      <div id="alerts-summary" class="alerts-summary"></div>

      <!-- Top targets / attackers -->
      <div class="presence-split" style="margin-top:8px">
        <div>
          <div class="section-header">
            <span class="section-title">Most Impersonated Networks</span>
            <span class="section-count" id="targets-count"></span>
            <span class="presence-sub">all time · APs spoofed as deauth source</span>
          </div>
          <div class="tbl-wrap">
            <table>
              <thead><tr>
                <th>BSSID</th><th>SSID</th><th>Frames</th>
                <th>Unique Srcs</th><th>Nodes</th><th>Last Seen</th>
              </tr></thead>
              <tbody id="targets-tbody"></tbody>
            </table>
            <div class="empty" id="targets-empty" style="display:none">No data yet.</div>
          </div>
        </div>
        <div>
          <div class="section-header">
            <span class="section-title">Most Targeted Devices</span>
            <span class="section-count" id="attackers-count"></span>
            <span class="presence-sub">all time · actual victim devices by dst MAC</span>
          </div>
          <div class="tbl-wrap">
            <table>
              <thead><tr>
                <th>Dst MAC</th><th>Vendor</th><th>Frames</th>
                <th>Networks Used</th><th>Nodes</th><th>Last Seen</th>
              </tr></thead>
              <tbody id="attackers-tbody"></tbody>
            </table>
            <div class="empty" id="attackers-empty" style="display:none">No data yet.</div>
          </div>
        </div>
      </div>

      <!-- Reason code breakdown -->
      <div class="section-header" style="margin-top:8px">
        <span class="section-title">Reason Code Breakdown</span>
        <span class="section-count" id="reasons-count"></span>
        <span class="presence-sub">all time · normal / suspicious / attack classification</span>
      </div>
      <div class="tbl-wrap">
        <table>
          <thead><tr>
            <th>Code</th><th>Description</th><th>Class</th>
            <th>Frames</th><th>Unique BSSIDs</th><th>Unique Targets</th><th>Last Seen</th>
          </tr></thead>
          <tbody id="reasons-tbody"></tbody>
        </table>
        <div class="empty" id="reasons-empty" style="display:none">No data yet.</div>
      </div>

      <!-- Detected bursts -->
      <div class="section-header">
        <span class="section-title">Detected Bursts</span>
        <span class="section-count" id="bursts-count"></span>
        <span class="presence-sub">≥10 deauth/disassoc frames for same BSSID in last 5 min</span>
      </div>
      <div class="tbl-wrap">
        <table>
          <thead><tr>
            <th>BSSID</th><th>SSID</th><th>Type</th><th>Frames</th>
            <th>Unique Srcs</th><th>Nodes</th><th>First</th><th>Last</th>
          </tr></thead>
          <tbody id="bursts-tbody"></tbody>
        </table>
        <div class="empty" id="bursts-empty" style="display:none">No bursts detected in last 5 minutes.</div>
      </div>

      <!-- Raw deauth feed -->
      <div class="section-header" style="margin-top:8px">
        <span class="section-title">Recent Deauth / Disassoc Events</span>
        <span class="section-count" id="deauth-count"></span>
      </div>
      <div class="tbl-wrap">
        <table>
          <thead><tr>
            <th>Time</th><th>Node</th><th>Type</th><th>Src</th>
            <th>Dst</th><th>BSSID</th><th>Reason</th><th>RSSI</th>
          </tr></thead>
          <tbody id="deauth-tbody"></tbody>
        </table>
        <div class="empty" id="deauth-empty" style="display:none">No deauth events yet. Nodes need to be reflashed with deauth detection enabled.</div>
      </div>

    </div><!-- /#view-alerts -->

    <!-- Analysis view -->
    <div id="view-analysis" class="view">

      <!-- Deauth activity heatmap -->
      <div class="section-header">
        <span class="section-title">Deauth Activity Heatmap</span>
        <span class="section-count" id="heatmap-subtitle"></span>
        <span class="presence-sub">frame count per day × hour — pattern reveals manual vs automated activity</span>
      </div>
      <canvas id="deauth-heatmap"></canvas>
      <div class="empty" id="heatmap-empty" style="display:none">No deauth data yet.</div>

    </div><!-- /#view-analysis -->

    <!-- Search view -->
    <div id="view-search" class="view">
      <div class="search-bar">
        <input type="text" id="search-input" class="search-input"
               placeholder="MAC address, SSID, BSSID — full or partial..."
               onkeydown="if(event.key==='Enter') doSearch()" />
        <button class="search-btn" onclick="doSearch()">Search</button>
      </div>
      <div id="search-results">
        <div class="empty" id="search-empty">Enter a value above to search across all collected data.</div>
      </div>
    </div>

  </div><!-- /#main -->
</div><!-- /#app -->

<script src="/static/dashboard.js"></script>
</body>
</html>
