<?php
require_once __DIR__ . '/../../includes/header.php';
require_once __DIR__ . '/../../mikrotik/includes/bandwidth.php';

$pdo = db();

$stmt = $pdo->prepare("
    SELECT d.*,
           COALESCE(SUM(ni.last_in_bps),  0) AS total_in_bps,
           COALESCE(SUM(ni.last_out_bps), 0) AS total_out_bps
    FROM nms_devices d
    LEFT JOIN nms_interfaces ni ON ni.device_id = d.id AND ni.monitored = TRUE
    WHERE d.user_id = ? AND d.map_lat IS NOT NULL AND d.map_lng IS NOT NULL
    GROUP BY d.id
    ORDER BY d.last_status ASC, d.name ASC
");
$stmt->execute([$user['id']]);
$devicesOnMap = $stmt->fetchAll();

$stmtAll = $pdo->prepare("
    SELECT COUNT(*),
           COALESCE(SUM(CASE WHEN last_status='online'  THEN 1 END), 0),
           COALESCE(SUM(CASE WHEN last_status='offline' THEN 1 END), 0)
    FROM nms_devices WHERE user_id=?
");
$stmtAll->execute([$user['id']]);
[$totalDevices, $totalOnline, $totalOffline] = array_values($stmtAll->fetch(PDO::FETCH_NUM));

$onMap  = count($devicesOnMap);
$semPos = $totalDevices - $onMap;

$jsDevices = array_values(array_map(fn($d) => [
    'id'       => (int)$d['id'],
    'name'     => $d['name'],
    'hostname' => $d['hostname'],
    'type'     => $d['type'],
    'location' => $d['location'] ?? '',
    'status'   => $d['last_status'] ?? 'unknown',
    'cpu'      => isset($d['last_cpu'])        ? (float)$d['last_cpu']        : null,
    'ram'      => isset($d['last_memory_pct']) ? (float)$d['last_memory_pct'] : null,
    'uptime'   => isset($d['uptime_seconds'])  ? (int)$d['uptime_seconds']    : null,
    'in_bps'   => (int)($d['total_in_bps']  ?? 0),
    'out_bps'  => (int)($d['total_out_bps'] ?? 0),
    'lat'      => (float)$d['map_lat'],
    'lng'      => (float)$d['map_lng'],
    'url'      => NMS_URL . '?page=nms_device_detail&id=' . (int)$d['id'],
    'edit_url' => NMS_URL . '?page=nms_device_form&id='   . (int)$d['id'],
], $devicesOnMap));

$apiUrl = NMS_URL . '?page=nms_api_map';
?>

<!-- Leaflet + MarkerCluster CSS -->
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css"/>
<link rel="stylesheet" href="https://unpkg.com/leaflet.markercluster@1.5.3/dist/MarkerCluster.css"/>
<link rel="stylesheet" href="https://unpkg.com/leaflet.markercluster@1.5.3/dist/MarkerCluster.Default.css"/>

<style>
/* ── Remove padding do container e footer apenas nesta página ── */
.container { padding: 0 !important; overflow: hidden; }
.footer    { display: none !important; }

/* ── Raiz do mapa: preenche todo espaço disponível ─────────── */
#mapRoot {
    position: relative;
    width: 100%;
    height: calc(100vh - 62px); /* 62px = topbar */
    overflow: hidden;
    font-family: 'Inter', system-ui, sans-serif;
}

#nmsMap {
    width: 100%;
    height: 100%;
    background: #dde2e8;
}

/* ── Painel flutuante base ──────────────────────────────────── */
.map-float {
    position: absolute;
    z-index: 1000;
    pointer-events: auto;
}

/* ── Barra de stats (topo esquerdo) ────────────────────────── */
#mapStatsBar {
    top: 14px; left: 14px;
    display: flex; gap: 8px; align-items: center;
    flex-wrap: wrap;
}

.stat-pill {
    display: inline-flex; align-items: center; gap: 7px;
    padding: 7px 14px;
    background: rgba(255,255,255,0.96);
    border-radius: 50px;
    box-shadow: 0 2px 12px rgba(0,0,0,0.15);
    font-size: 0.82rem; font-weight: 700;
    backdrop-filter: blur(6px);
    border: 1px solid rgba(255,255,255,0.6);
    white-space: nowrap;
    cursor: default;
}
.stat-pill .dot {
    width: 9px; height: 9px; border-radius: 50%; flex-shrink: 0;
}

/* ── Barra de filtros (topo centro) ────────────────────────── */
#mapFilterBar {
    top: 14px;
    left: 50%; transform: translateX(-50%);
    display: flex; gap: 6px; align-items: center;
    background: rgba(255,255,255,0.96);
    border-radius: 50px;
    box-shadow: 0 2px 12px rgba(0,0,0,0.15);
    backdrop-filter: blur(6px);
    padding: 5px 8px;
    border: 1px solid rgba(255,255,255,0.6);
}

.filter-btn {
    padding: 6px 16px; border-radius: 50px;
    border: none; font-size: 0.8rem; font-weight: 700;
    cursor: pointer; transition: all .15s;
    background: transparent; color: #475569;
}
.filter-btn:hover { background: #f1f5f9; }
.filter-btn.f-active-all    { background: #4f46e5; color: #fff; }
.filter-btn.f-active-online { background: #22c55e; color: #fff; }
.filter-btn.f-active-off    { background: #ef4444; color: #fff; }

/* ── Botões de ação (topo direito, antes do layer switcher) ── */
#mapActionBar {
    top: 14px; right: 52px;
    display: flex; gap: 6px;
}

.map-action-btn {
    display: inline-flex; align-items: center; gap: 6px;
    padding: 7px 14px;
    background: rgba(255,255,255,0.96);
    border-radius: 50px;
    box-shadow: 0 2px 12px rgba(0,0,0,0.15);
    font-size: 0.8rem; font-weight: 700;
    backdrop-filter: blur(6px);
    border: 1px solid rgba(255,255,255,0.6);
    cursor: pointer; text-decoration: none; color: #0f172a;
    transition: background .15s;
    white-space: nowrap;
}
.map-action-btn:hover { background: #fff; text-decoration: none; }

/* ── Painel lateral de dispositivos (esquerda) ──────────────── */
#mapSidebar {
    top: 70px; left: 14px;
    width: 280px;
    background: rgba(255,255,255,0.97);
    border-radius: 16px;
    box-shadow: 0 4px 24px rgba(0,0,0,0.18);
    backdrop-filter: blur(8px);
    border: 1px solid rgba(255,255,255,0.7);
    display: flex; flex-direction: column;
    max-height: calc(100% - 100px);
    overflow: hidden;
    transition: transform .25s ease, opacity .25s ease;
}

#mapSidebar.collapsed {
    transform: translateX(-300px);
    opacity: 0;
    pointer-events: none;
}

#sidebarHeader {
    padding: 12px 14px 10px;
    border-bottom: 1px solid #f1f5f9;
    display: flex; gap: 8px; flex-direction: column;
}

#sidebarTitle {
    font-size: 0.82rem; font-weight: 800; color: #0f172a;
}

#mapSearch {
    width: 100%; padding: 8px 12px;
    border: 1px solid #e2e8f0; border-radius: 10px;
    font-size: 0.82rem; outline: none; color: #0f172a;
    background: #f8fafc;
}
#mapSearch:focus { border-color: #4f46e5; background: #fff; }

#deviceList {
    overflow-y: auto;
    flex: 1;
}

.dev-item {
    padding: 9px 14px;
    border-bottom: 1px solid #f1f5f9;
    cursor: pointer;
    transition: background .1s;
    display: flex; align-items: center; gap: 9px;
}
.dev-item:hover, .dev-item.active { background: #eff6ff; }
.dev-item.hidden { display: none; }

.dev-status-dot {
    width: 9px; height: 9px; border-radius: 50%; flex-shrink: 0;
}
.dev-name {
    font-size: 0.84rem; font-weight: 700; color: #0f172a;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex: 1;
}
.dev-bw {
    font-size: 0.7rem; color: #94a3b8; margin-top: 1px; white-space: nowrap;
}

#noResults {
    padding: 20px; text-align: center;
    color: #94a3b8; font-size: 0.84rem; display: none;
}

/* ── Botão toggle da sidebar ────────────────────────────────── */
#sidebarToggle {
    top: 70px; left: 14px;
    width: 36px; height: 36px;
    background: rgba(255,255,255,0.96);
    border-radius: 10px;
    box-shadow: 0 2px 10px rgba(0,0,0,0.15);
    border: 1px solid rgba(255,255,255,0.6);
    cursor: pointer; display: none;
    align-items: center; justify-content: center;
    font-size: 1rem; transition: background .15s;
}
#sidebarToggle:hover { background: #fff; }
#sidebarToggle.visible { display: flex; }

/* ── Painel de info do device (direita) ─────────────────────── */
#mapInfoPanel {
    bottom: 24px; right: 14px;
    width: 320px;
    background: rgba(255,255,255,0.97);
    border-radius: 16px;
    box-shadow: 0 4px 24px rgba(0,0,0,0.2);
    backdrop-filter: blur(8px);
    border: 1px solid rgba(255,255,255,0.7);
    padding: 18px;
    display: none;
    animation: slideUp .2s ease;
}
#mapInfoPanel.show { display: block; }

@keyframes slideUp {
    from { opacity: 0; transform: translateY(10px); }
    to   { opacity: 1; transform: translateY(0); }
}

.info-close {
    position: absolute; top: 10px; right: 12px;
    background: none; border: none; font-size: 1rem;
    cursor: pointer; color: #94a3b8; line-height: 1;
}
.info-close:hover { color: #ef4444; }

/* ── Indicador de atualização (canto inferior esquerdo) ─────── */
#mapUpdateBadge {
    bottom: 24px; left: 14px;
    display: flex; align-items: center; gap: 7px;
    padding: 6px 12px;
    background: rgba(15,23,42,0.75);
    border-radius: 50px;
    color: #fff; font-size: 0.74rem; font-weight: 600;
    backdrop-filter: blur(4px);
}

#refreshDot {
    width: 7px; height: 7px; border-radius: 50%;
    background: #22c55e; flex-shrink: 0;
    transition: background .3s;
}
#refreshDot.syncing { background: #f59e0b; }
#refreshDot.error   { background: #ef4444; }

/* ── Empty state ────────────────────────────────────────────── */
#mapEmpty {
    position: absolute; inset: 0; z-index: 900;
    display: flex; align-items: center; justify-content: center;
    background: rgba(238,242,247,0.95);
}

/* ── Leaflet overrides ──────────────────────────────────────── */
.leaflet-control-layers {
    border-radius: 12px !important;
    box-shadow: 0 2px 12px rgba(0,0,0,0.15) !important;
    border: 1px solid rgba(255,255,255,0.6) !important;
}
.leaflet-control-zoom {
    border-radius: 12px !important;
    box-shadow: 0 2px 12px rgba(0,0,0,0.15) !important;
    border: none !important;
    overflow: hidden;
}
.leaflet-control-zoom a {
    border-radius: 0 !important;
}
</style>

<!-- ── Root do mapa ─────────────────────────────────────────────────── -->
<div id="mapRoot">

    <!-- Mapa Leaflet -->
    <div id="nmsMap"></div>

    <?php if (empty($devicesOnMap)): ?>
    <!-- Estado vazio -->
    <div id="mapEmpty">
        <div style="text-align:center;max-width:380px;padding:32px;">
            <div style="font-size:3.5rem;margin-bottom:16px;">📍</div>
            <div style="font-size:1.2rem;font-weight:800;color:#1e293b;margin-bottom:8px;">Nenhum equipamento no mapa</div>
            <p style="color:#64748b;font-size:0.9rem;margin-bottom:24px;">
                Edite um equipamento e defina a localização geográfica para ele aparecer aqui.
            </p>
            <a href="<?= NMS_URL ?>?page=nms_devices"
               style="display:inline-block;padding:12px 28px;background:#4f46e5;color:#fff;border-radius:12px;font-weight:700;text-decoration:none;box-shadow:0 4px 14px rgba(79,70,229,0.4);">
                🖥️ Ir para Dispositivos →
            </a>
        </div>
    </div>
    <?php else: ?>

    <!-- ── Stats bar (topo esquerdo) ──────────────────────────────────── -->
    <div class="map-float" id="mapStatsBar">
        <div class="stat-pill">
            <span class="dot" style="background:#22c55e;"></span>
            <span id="statOnline"><?= $totalOnline ?></span> Online
        </div>
        <div class="stat-pill">
            <span class="dot" style="background:#ef4444;"></span>
            <span id="statOffline"><?= $totalOffline ?></span> Offline
        </div>
        <?php if ($semPos > 0): ?>
        <div class="stat-pill" style="color:#64748b;">
            <span class="dot" style="background:#94a3b8;"></span>
            <span id="statSemPos"><?= $semPos ?></span> Sem posição
        </div>
        <?php endif; ?>
    </div>

    <!-- ── Filtros (topo centro) ───────────────────────────────────────── -->
    <div class="map-float" id="mapFilterBar">
        <button class="filter-btn f-active-all" id="btnAll"    onclick="applyFilter('all',this)">Todos</button>
        <button class="filter-btn"              id="btnOnline" onclick="applyFilter('online',this)">● Online</button>
        <button class="filter-btn"              id="btnOffline"onclick="applyFilter('offline',this)">● Offline</button>
    </div>

    <!-- ── Botões de ação (topo direito) ──────────────────────────────── -->
    <div class="map-float" id="mapActionBar">
        <a href="<?= NMS_URL ?>?page=nms_devices" class="map-action-btn">🖥️ Dispositivos</a>
        <a href="<?= NMS_URL ?>?page=nms_device_form" class="map-action-btn" style="background:rgba(79,70,229,0.9);color:#fff;border-color:rgba(79,70,229,0.5);">➕ Novo</a>
    </div>

    <!-- ── Sidebar de devices (esquerda, collapsível) ─────────────────── -->
    <div class="map-float" id="mapSidebar">
        <div id="sidebarHeader">
            <div style="display:flex;align-items:center;justify-content:space-between;">
                <span id="sidebarTitle">Equipamentos (<?= $onMap ?>)</span>
                <button onclick="toggleSidebar()" title="Ocultar lista"
                    style="background:none;border:none;cursor:pointer;color:#94a3b8;font-size:1rem;line-height:1;padding:2px;">✕</button>
            </div>
            <input id="mapSearch" type="text" placeholder="🔍  Pesquisar…" oninput="filterList(this.value)">
        </div>
        <div id="deviceList">
            <?php foreach ($devicesOnMap as $dev):
                $sc = $dev['last_status'] === 'online' ? '#22c55e' : ($dev['last_status'] === 'offline' ? '#ef4444' : '#94a3b8');
            ?>
            <div class="dev-item" data-id="<?= (int)$dev['id'] ?>" data-status="<?= h($dev['last_status'] ?? 'unknown') ?>"
                 onclick="focusDevice(<?= (int)$dev['id'] ?>)">
                <span class="dev-status-dot" style="background:<?= $sc ?>;"></span>
                <div style="min-width:0;flex:1;">
                    <div class="dev-name"><?= h($dev['name']) ?></div>
                    <div class="dev-bw">↓ <?= format_bps((int)($dev['total_in_bps'] ?? 0)) ?> &nbsp;↑ <?= format_bps((int)($dev['total_out_bps'] ?? 0)) ?></div>
                </div>
            </div>
            <?php endforeach; ?>
            <div id="noResults">Nenhum resultado</div>
        </div>
    </div>

    <!-- Toggle da sidebar (aparece quando sidebar está oculta) -->
    <button class="map-float" id="sidebarToggle" onclick="toggleSidebar()" title="Mostrar lista">☰</button>

    <!-- ── Painel de info do device (direita, flutuante) ──────────────── -->
    <div class="map-float" id="mapInfoPanel">
        <button class="info-close" onclick="closeInfo()">✕</button>
        <div id="mapInfoContent"></div>
    </div>

    <!-- ── Indicador de atualização (baixo esquerdo) ──────────────────── -->
    <div class="map-float" id="mapUpdateBadge">
        <span id="refreshDot"></span>
        <span>Atualizado: <span id="mapLastTs"><?= date('H:i:s') ?></span></span>
    </div>

    <?php endif; ?>
</div><!-- #mapRoot -->

<!-- Leaflet + MarkerCluster JS -->
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
<script src="https://unpkg.com/leaflet.markercluster@1.5.3/dist/leaflet.markercluster.js"></script>

<script>
(function () {
    let devices = <?= json_encode($jsDevices, JSON_UNESCAPED_UNICODE) ?>;
    const API_URL = <?= json_encode($apiUrl) ?>;

    if (!devices.length) return;

    // ── Helpers ────────────────────────────────────────────────────────
    function fmtBps(v) {
        if (!v || v <= 0) return '0 bps';
        if (v >= 1e9) return (v / 1e9).toFixed(2) + ' Gbps';
        if (v >= 1e6) return (v / 1e6).toFixed(2) + ' Mbps';
        if (v >= 1e3) return (v / 1e3).toFixed(1) + ' Kbps';
        return v + ' bps';
    }

    function fmtUptime(s) {
        if (!s) return '—';
        const d = Math.floor(s / 86400), h = Math.floor((s % 86400) / 3600), m = Math.floor((s % 3600) / 60);
        if (d > 0) return d + 'd ' + h + 'h';
        if (h > 0) return h + 'h ' + m + 'm';
        return m + 'm';
    }

    const colorMap   = { online: '#22c55e', offline: '#ef4444', unknown: '#94a3b8' };
    const labelMap   = { online: 'Online',  offline: 'Offline', unknown: 'Desconhecido' };
    const typeLabels = { mikrotik: 'MikroTik', cisco: 'Cisco', olt: 'OLT', switch: 'Switch', server: 'Servidor', other: 'Outro' };

    // ── Ícone do marker ────────────────────────────────────────────────
    function makeIcon(d) {
        const color = colorMap[d.status] || '#94a3b8';
        const label = d.name.length > 14 ? d.name.slice(0, 13) + '…' : d.name;
        const html = `
        <div style="position:relative;display:inline-block;background:#fff;border:2px solid ${color};
                    border-radius:10px;box-shadow:0 4px 16px rgba(0,0,0,0.22);min-width:148px;
                    font-family:inherit;cursor:pointer;white-space:nowrap;">
            <div style="height:4px;background:${color};border-radius:8px 8px 0 0;"></div>
            <div style="padding:5px 9px 5px;">
                <div style="font-size:0.78rem;font-weight:800;color:#0f172a;margin-bottom:4px;">${label}</div>
                <div style="display:flex;gap:8px;">
                    <span style="display:inline-flex;align-items:center;gap:2px;font-size:0.68rem;font-weight:700;color:#16a34a;">
                        <svg width="9" height="9" viewBox="0 0 24 24" fill="none" stroke="#16a34a" stroke-width="3"><path d="M12 19V5M5 12l7 7 7-7"/></svg>${fmtBps(d.in_bps)}
                    </span>
                    <span style="display:inline-flex;align-items:center;gap:2px;font-size:0.68rem;font-weight:700;color:#dc2626;">
                        <svg width="9" height="9" viewBox="0 0 24 24" fill="none" stroke="#dc2626" stroke-width="3"><path d="M12 5v14M5 12l7-7 7 7"/></svg>${fmtBps(d.out_bps)}
                    </span>
                </div>
            </div>
            <div style="position:absolute;bottom:-10px;left:50%;transform:translateX(-50%);width:0;height:0;
                        border-left:9px solid transparent;border-right:9px solid transparent;border-top:10px solid ${color};"></div>
            <div style="position:absolute;bottom:-7px;left:50%;transform:translateX(-50%);width:0;height:0;
                        border-left:7px solid transparent;border-right:7px solid transparent;border-top:8px solid #fff;"></div>
        </div>`;
        return L.divIcon({ html, className: '', iconSize: [148, 60], iconAnchor: [74, 60], popupAnchor: [0, -64] });
    }

    // ── Mapa ───────────────────────────────────────────────────────────
    const avgLat = devices.reduce((s, d) => s + d.lat, 0) / devices.length;
    const avgLng = devices.reduce((s, d) => s + d.lng, 0) / devices.length;

    const map = L.map('nmsMap', { zoomControl: false }).setView([avgLat, avgLng], 6);

    // Zoom control no lado direito (não conflita com sidebar)
    L.control.zoom({ position: 'bottomright' }).addTo(map);

    // Camadas de tile
    const tileOSM = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
        attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>', maxZoom: 19
    });
    const tileDark = L.tileLayer('https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png', {
        attribution: '© <a href="https://carto.com/">CARTO</a>', maxZoom: 19
    });
    const tileSat = L.tileLayer('https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', {
        attribution: '© Esri', maxZoom: 18
    });
    tileOSM.addTo(map);
    L.control.layers({ 'Padrão': tileOSM, 'Dark Mode': tileDark, 'Satélite': tileSat }, null,
        { position: 'topright' }).addTo(map);

    const bounds = L.latLngBounds(devices.map(d => [d.lat, d.lng]));
    map.fitBounds(bounds, { padding: [80, 80] });

    // ── MarkerCluster ──────────────────────────────────────────────────
    const cluster = L.markerClusterGroup({
        showCoverageOnHover: false,
        maxClusterRadius: 55,
        iconCreateFunction(grp) {
            const n = grp.getChildCount();
            const hasOff = grp.getAllChildMarkers().some(m => m._dev && m._dev.status === 'offline');
            const bg = hasOff ? '#ef4444' : '#22c55e';
            return L.divIcon({
                html: `<div style="background:${bg};color:#fff;border-radius:50%;width:38px;height:38px;
                               display:flex;align-items:center;justify-content:center;
                               font-weight:800;font-size:0.88rem;border:3px solid rgba(255,255,255,0.9);
                               box-shadow:0 3px 10px rgba(0,0,0,0.3);">${n}</div>`,
                className: '', iconSize: [38, 38], iconAnchor: [19, 19]
            });
        }
    });

    // ── Markers ────────────────────────────────────────────────────────
    const byId = {};

    devices.forEach(d => {
        const m = L.marker([d.lat, d.lng], { icon: makeIcon(d) });
        m._dev = d;
        m.on('click', () => { showInfo(d); highlightItem(d.id); });
        cluster.addLayer(m);
        byId[d.id] = { m, d };
    });
    map.addLayer(cluster);

    // ── Fechar painel ao clicar no mapa ───────────────────────────────
    map.on('click', () => closeInfo());

    // ── Painel de info ─────────────────────────────────────────────────
    function showInfo(d) {
        const sc = colorMap[d.status] || '#94a3b8';
        document.getElementById('mapInfoContent').innerHTML = `
            <div style="margin-bottom:12px;padding-right:20px;">
                <div style="font-size:1.05rem;font-weight:900;color:#0f172a;margin-bottom:2px;">${d.name}</div>
                <div style="font-size:0.76rem;color:#64748b;">${typeLabels[d.type]||d.type}${d.location?' · '+d.location:''}</div>
                <code style="display:inline-block;margin-top:5px;background:#ea580c;color:#fff;padding:2px 9px;border-radius:5px;font-size:0.78rem;font-weight:700;">${d.hostname}</code>
            </div>
            <div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:12px;">
                <span style="padding:4px 12px;background:${sc}18;color:${sc};border:1.5px solid ${sc};border-radius:20px;font-weight:800;font-size:0.8rem;">● ${labelMap[d.status]||d.status}</span>
                <span style="font-size:0.73rem;color:#94a3b8;">Up: ${fmtUptime(d.uptime)}</span>
            </div>
            <div style="display:grid;grid-template-columns:1fr 1fr;gap:7px;margin-bottom:12px;">
                <div style="background:#f0fdf4;border-radius:9px;padding:9px;text-align:center;">
                    <div style="font-size:0.62rem;color:#64748b;font-weight:700;text-transform:uppercase;letter-spacing:.05em;margin-bottom:2px;">↓ Download</div>
                    <div style="font-size:0.92rem;font-weight:900;color:#16a34a;">${fmtBps(d.in_bps)}</div>
                </div>
                <div style="background:#fef2f2;border-radius:9px;padding:9px;text-align:center;">
                    <div style="font-size:0.62rem;color:#64748b;font-weight:700;text-transform:uppercase;letter-spacing:.05em;margin-bottom:2px;">↑ Upload</div>
                    <div style="font-size:0.92rem;font-weight:900;color:#dc2626;">${fmtBps(d.out_bps)}</div>
                </div>
                ${d.cpu!==null?`<div style="background:#eff6ff;border-radius:9px;padding:9px;text-align:center;">
                    <div style="font-size:0.62rem;color:#64748b;font-weight:700;text-transform:uppercase;letter-spacing:.05em;margin-bottom:2px;">CPU</div>
                    <div style="font-size:0.92rem;font-weight:900;color:#1d4ed8;">${d.cpu}%</div>
                </div>`:''}
                ${d.ram!==null?`<div style="background:#faf5ff;border-radius:9px;padding:9px;text-align:center;">
                    <div style="font-size:0.62rem;color:#64748b;font-weight:700;text-transform:uppercase;letter-spacing:.05em;margin-bottom:2px;">RAM</div>
                    <div style="font-size:0.92rem;font-weight:900;color:#7c3aed;">${d.ram}%</div>
                </div>`:''}
            </div>
            <div style="display:flex;gap:7px;">
                <a href="${d.url}" style="flex:1;padding:9px;background:#4f46e5;color:#fff;border-radius:9px;font-size:0.82rem;font-weight:700;text-decoration:none;text-align:center;">📊 Dashboard</a>
                <a href="${d.edit_url}" style="padding:9px 12px;background:#f5f3ff;color:#7c3aed;border-radius:9px;font-size:0.82rem;font-weight:700;text-decoration:none;border:1px solid #e9d5ff;">✏️ Editar</a>
            </div>`;
        const panel = document.getElementById('mapInfoPanel');
        panel.classList.add('show');
    }

    window.closeInfo = function () {
        document.getElementById('mapInfoPanel').classList.remove('show');
        document.querySelectorAll('.dev-item').forEach(e => e.classList.remove('active'));
    };

    function highlightItem(id) {
        document.querySelectorAll('.dev-item').forEach(e => e.classList.remove('active'));
        const el = document.querySelector('.dev-item[data-id="' + id + '"]');
        if (el) { el.classList.add('active'); el.scrollIntoView({ behavior: 'smooth', block: 'nearest' }); }
    }

    // ── Focus ao clicar na lista ───────────────────────────────────────
    window.focusDevice = function (id) {
        const entry = byId[id];
        if (!entry) return;
        cluster.zoomToShowLayer(entry.m, () => entry.m.fire('click'));
        map.setView([entry.d.lat, entry.d.lng], Math.max(map.getZoom(), 13), { animate: true });
    };

    // ── Sidebar toggle ─────────────────────────────────────────────────
    let sidebarOpen = true;
    window.toggleSidebar = function () {
        sidebarOpen = !sidebarOpen;
        document.getElementById('mapSidebar').classList.toggle('collapsed', !sidebarOpen);
        const toggle = document.getElementById('sidebarToggle');
        toggle.classList.toggle('visible', !sidebarOpen);
    };

    // ── Filtros ────────────────────────────────────────────────────────
    let activeFilter = 'all';
    window.applyFilter = function (f, btn) {
        activeFilter = f;
        document.querySelectorAll('.filter-btn').forEach(b => b.className = 'filter-btn');
        if (btn) btn.className = 'filter-btn ' + (f==='all'?'f-active-all':f==='online'?'f-active-online':'f-active-off');

        Object.values(byId).forEach(({ m, d }) => {
            const show = f === 'all' || d.status === f;
            if (show && !cluster.hasLayer(m)) cluster.addLayer(m);
            if (!show && cluster.hasLayer(m)) cluster.removeLayer(m);
        });

        document.querySelectorAll('.dev-item').forEach(el => {
            el.classList.toggle('hidden', f !== 'all' && el.dataset.status !== f);
        });

        checkNoResults();
        closeInfo();
    };

    // ── Busca ──────────────────────────────────────────────────────────
    window.filterList = function (q) {
        q = q.toLowerCase().trim();
        document.querySelectorAll('.dev-item').forEach(el => {
            const name  = (el.querySelector('.dev-name')?.textContent || '').toLowerCase();
            const filt  = activeFilter !== 'all' && el.dataset.status !== activeFilter;
            el.classList.toggle('hidden', filt || (q !== '' && !name.includes(q)));
        });
        checkNoResults();
    };

    function checkNoResults() {
        const v = document.querySelectorAll('.dev-item:not(.hidden)').length;
        document.getElementById('noResults').style.display = v === 0 ? 'block' : 'none';
    }

    // ── AJAX refresh a cada 30s ────────────────────────────────────────
    function fetchData() {
        const dot = document.getElementById('refreshDot');
        if (dot) dot.className = 'syncing';

        fetch(API_URL)
            .then(r => r.ok ? r.json() : Promise.reject())
            .then(data => {
                // Atualiza pills de stats
                const so = document.getElementById('statOnline');
                const sf = document.getElementById('statOffline');
                const sp = document.getElementById('statSemPos');
                if (so) so.textContent = data.total_online  ?? 0;
                if (sf) sf.textContent = data.total_offline ?? 0;
                if (sp) sp.textContent = (data.total_devices - data.total_on_map) ?? 0;
                const ts = document.getElementById('mapLastTs');
                if (ts) ts.textContent = data.ts ?? '';

                // Atualiza markers e lista
                (data.devices || []).forEach(nd => {
                    const entry = byId[nd.id];
                    if (!entry) return;
                    const od = entry.d;
                    if (od.status !== nd.status || od.in_bps !== nd.in_bps || od.out_bps !== nd.out_bps) {
                        entry.m.setIcon(makeIcon(nd));
                        entry.m._dev = nd;
                        entry.d = nd;

                        // Lista
                        const item = document.querySelector('.dev-item[data-id="' + nd.id + '"]');
                        if (item) {
                            item.dataset.status = nd.status;
                            const dotEl = item.querySelector('.dev-status-dot');
                            if (dotEl) dotEl.style.background = colorMap[nd.status] || '#94a3b8';
                            const bw = item.querySelector('.dev-bw');
                            if (bw) bw.textContent = '↓ ' + fmtBps(nd.in_bps) + '  ↑ ' + fmtBps(nd.out_bps);
                        }

                        // Painel aberto?
                        const panel = document.getElementById('mapInfoPanel');
                        if (panel?.classList.contains('show')) {
                            const active = document.querySelector('.dev-item.active');
                            if (active && parseInt(active.dataset.id) === nd.id) showInfo(nd);
                        }
                    }
                });

                devices = data.devices || devices;
                if (dot) dot.className = '';
            })
            .catch(() => { if (dot) dot.className = 'error'; });
    }

    setInterval(fetchData, 30000);
})();
</script>

<?php require_once __DIR__ . '/../../includes/footer.php'; ?>
