{% extends "base.html" %}

{% block title %}SFM Event Data - Seismo Fleet Manager{% endblock %}

{% block content %}
<div class="mb-6 flex items-center justify-between">
    <div>
        <h1 class="text-3xl font-bold text-gray-900 dark:text-white">Events</h1>
        <p class="text-gray-600 dark:text-gray-400 mt-1">Fleet-wide event database. Filter by serial, date, false-trigger, or browse the units roster.</p>
    </div>
    <div class="flex items-center gap-3">
        <span id="sfm-status-badge" class="px-3 py-1 rounded-full text-sm font-medium bg-gray-100 text-gray-600 dark:bg-gray-700 dark:text-gray-400">
            Checking SFM…
        </span>
        <button onclick="checkSFMHealth()" class="px-3 py-1.5 text-sm rounded-lg border border-gray-300 dark:border-gray-600 hover:bg-gray-50 dark:hover:bg-gray-700 text-gray-700 dark:text-gray-300">
            ↻ Refresh
        </button>
    </div>
</div>

<!-- Stats bar -->
<div id="sfm-stats" class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6">
    <div class="bg-white dark:bg-slate-800 rounded-lg shadow p-4 flex flex-col">
        <span class="text-xs text-gray-500 dark:text-gray-400 uppercase tracking-wider">Known Units</span>
        <span id="stat-units" class="text-3xl font-bold text-gray-900 dark:text-white mt-1">—</span>
    </div>
    <div class="bg-white dark:bg-slate-800 rounded-lg shadow p-4 flex flex-col">
        <span class="text-xs text-gray-500 dark:text-gray-400 uppercase tracking-wider">Total Events</span>
        <span id="stat-events" class="text-3xl font-bold text-gray-900 dark:text-white mt-1">—</span>
    </div>
</div>

<!-- Tab navigation -->
<div class="bg-white dark:bg-slate-800 rounded-xl shadow-lg overflow-hidden">
    <div class="border-b border-gray-200 dark:border-gray-700">
        <nav class="flex overflow-x-auto" aria-label="Tabs">
            <button onclick="switchTab('events')" id="tab-events"
                class="sfm-tab active-tab shrink-0 px-6 py-4 text-sm font-medium border-b-2 transition-colors">
                Events
            </button>
            <button onclick="switchTab('units')" id="tab-units"
                class="sfm-tab shrink-0 px-6 py-4 text-sm font-medium border-b-2 transition-colors">
                Units
            </button>
        </nav>
    </div>

    <!-- ── Events Tab ─────────────────────────────────────────────────────── -->
    <div id="panel-events" class="sfm-panel p-6">
        <!-- Filters -->
        <div class="flex flex-wrap items-end gap-3 mb-4">
            <div class="flex flex-col gap-1">
                <label class="text-xs text-gray-500 dark:text-gray-400">Unit Serial</label>
                <select id="ev-serial" onchange="loadEvents()"
                        class="px-3 py-1.5 text-sm border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-slate-700 text-gray-900 dark:text-white">
                    <option value="">All Units</option>
                </select>
            </div>
            <div class="flex flex-col gap-1">
                <label class="text-xs text-gray-500 dark:text-gray-400">From</label>
                <input type="datetime-local" id="ev-from" onchange="loadEvents()"
                       class="px-3 py-1.5 text-sm border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-slate-700 text-gray-900 dark:text-white">
            </div>
            <div class="flex flex-col gap-1">
                <label class="text-xs text-gray-500 dark:text-gray-400">To</label>
                <input type="datetime-local" id="ev-to" onchange="loadEvents()"
                       class="px-3 py-1.5 text-sm border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-slate-700 text-gray-900 dark:text-white">
            </div>
            <div class="flex flex-col gap-1">
                <label class="text-xs text-gray-500 dark:text-gray-400">False Triggers</label>
                <select id="ev-false-trigger" onchange="loadEvents()"
                        class="px-3 py-1.5 text-sm border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-slate-700 text-gray-900 dark:text-white">
                    <option value="">All Events</option>
                    <option value="false">Real Events Only</option>
                    <option value="true">False Triggers Only</option>
                </select>
            </div>
            <div class="flex flex-col gap-1">
                <label class="text-xs text-gray-500 dark:text-gray-400">Limit</label>
                <select id="ev-limit" onchange="loadEvents()"
                        class="px-3 py-1.5 text-sm border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-slate-700 text-gray-900 dark:text-white">
                    <option value="100">100</option>
                    <option value="250">250</option>
                    <option value="500" selected>500</option>
                </select>
            </div>
            <button onclick="clearEventFilters()"
                    class="px-3 py-1.5 text-sm text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-white">
                Clear Filters
            </button>
            <button onclick="loadEvents()"
                    class="ml-auto px-4 py-1.5 text-sm bg-seismo-orange text-white rounded-lg hover:bg-orange-600">
                ↻ Reload
            </button>
        </div>

        <!-- Events table -->
        <div id="events-container" class="overflow-x-auto">
            <div class="text-center py-12 text-gray-500 dark:text-gray-400">
                <div class="animate-spin rounded-full h-8 w-8 border-b-2 border-seismo-orange mx-auto mb-3"></div>
                Loading events…
            </div>
        </div>
    </div>

    <!-- ── Units Tab ─────────────────────────────────────────────────────── -->
    <div id="panel-units" class="sfm-panel hidden p-6">
        <div id="units-container">
            <div class="text-center py-12 text-gray-500">
                <div class="animate-spin rounded-full h-8 w-8 border-b-2 border-seismo-orange mx-auto mb-3"></div>
                Loading units…
            </div>
        </div>
    </div>

</div><!-- end tab container -->

{# Shared event-detail modal — rendered by /static/event-modal.js #}
{% include 'partials/event_detail_modal.html' %}
<script src="/static/event-modal.js"></script>
<script>
    // Refresh the events table when the modal's review form saves —
    // keeps the FT badge in sync without a full page reload.
    window.addEventListener('sfm-event-review-saved', () => {
        if (typeof loadEvents === 'function') loadEvents();
    });
</script>

<style>
.sfm-tab {
    color: #6b7280;
    border-color: transparent;
}
.sfm-tab:hover {
    color: #374151;
    border-color: #d1d5db;
}
.dark .sfm-tab {
    color: #9ca3af;
}
.dark .sfm-tab:hover {
    color: #f3f4f6;
    border-color: #4b5563;
}
.sfm-tab.active-tab {
    color: #f48b1c;
    border-color: #f48b1c;
}
.dark .sfm-tab.active-tab {
    color: #f48b1c;
    border-color: #f48b1c;
}
.sfm-panel { display: block; }
.sfm-panel.hidden { display: none; }

/* PPV colour thresholds */
.ppv-low  { color: #10b981; }
.ppv-mid  { color: #f59e0b; }
.ppv-high { color: #ef4444; font-weight: 600; }
</style>

<script>
// ── State ───────────────────────────────────────────────────────────────────
let _knownSerials = [];

// ── Tabs ────────────────────────────────────────────────────────────────────
function switchTab(name) {
    document.querySelectorAll('.sfm-tab').forEach(t => t.classList.remove('active-tab'));
    document.querySelectorAll('.sfm-panel').forEach(p => p.classList.add('hidden'));
    document.getElementById('tab-' + name).classList.add('active-tab');
    document.getElementById('panel-' + name).classList.remove('hidden');

    // Lazy-load tabs on first visit
    if (name === 'units' && document.getElementById('units-container').innerHTML.includes('Loading')) loadUnits();
}

// ── SFM health ───────────────────────────────────────────────────────────────
async function checkSFMHealth() {
    const badge = document.getElementById('sfm-status-badge');
    badge.textContent = 'Checking…';
    badge.className = 'px-3 py-1 rounded-full text-sm font-medium bg-gray-100 text-gray-600 dark:bg-gray-700 dark:text-gray-400';
    try {
        const r = await fetch('/api/sfm/health');
        const d = await r.json();
        if (d.sfm_status === 'connected') {
            badge.textContent = '● SFM Connected';
            badge.className = 'px-3 py-1 rounded-full text-sm font-medium bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200';
            loadStats();
        } else {
            badge.textContent = '● SFM Offline';
            badge.className = 'px-3 py-1 rounded-full text-sm font-medium bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-200';
        }
    } catch (e) {
        badge.textContent = '● SFM Error';
        badge.className = 'px-3 py-1 rounded-full text-sm font-medium bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-200';
    }
}

// ── Stats ────────────────────────────────────────────────────────────────────
async function loadStats() {
    try {
        const r = await fetch('/api/sfm/db/units');
        if (!r.ok) return;
        const units = await r.json();
        _knownSerials = units.map(u => u.serial);

        const totalEvents = units.reduce((s, u) => s + (u.total_events || 0), 0);

        document.getElementById('stat-units').textContent  = units.length;
        document.getElementById('stat-events').textContent = totalEvents.toLocaleString();

        // Populate serial dropdowns
        ['ev-serial'].forEach(id => {
            const sel = document.getElementById(id);
            const cur = sel.value;
            while (sel.options.length > 1) sel.remove(1);
            _knownSerials.forEach(s => {
                const opt = document.createElement('option');
                opt.value = s; opt.textContent = s;
                sel.add(opt);
            });
            if (cur) sel.value = cur;
        });
    } catch (e) {
        console.error('Failed to load stats:', e);
    }
}

// ── Events tab ───────────────────────────────────────────────────────────────
// Module-level cache so sort can re-render without re-fetching.
let _eventsCache = [];
let _eventsTotal = 0;
let _eventsSortKey = 'timestamp';
let _eventsSortDir = 'desc';          // 'asc' | 'desc'

async function loadEvents() {
    const container = document.getElementById('events-container');
    container.innerHTML = '<div class="text-center py-8 text-gray-500"><div class="animate-spin rounded-full h-8 w-8 border-b-2 border-seismo-orange mx-auto mb-3"></div>Loading events…</div>';

    const params = new URLSearchParams();
    const serial  = document.getElementById('ev-serial').value;
    const from    = document.getElementById('ev-from').value;
    const to      = document.getElementById('ev-to').value;
    const ft      = document.getElementById('ev-false-trigger').value;
    const limit   = document.getElementById('ev-limit').value;

    if (serial) params.set('serial', serial);
    if (from)   params.set('from_dt', from.replace('T', ' '));
    if (to)     params.set('to_dt', to.replace('T', ' '));
    if (ft)     params.set('false_trigger', ft);
    params.set('limit', limit);

    try {
        const r = await fetch('/api/sfm/db/events?' + params.toString());
        if (!r.ok) { throw new Error('HTTP ' + r.status); }
        const d = await r.json();
        _eventsCache = d.events || [];
        _eventsTotal = d.count || 0;
        renderEventsTable(_eventsCache, _eventsTotal, container);
    } catch (e) {
        container.innerHTML = `<div class="text-center py-8 text-red-500">Failed to load events: ${e.message}</div>`;
    }
}

function sortEvents(key) {
    // Toggle direction if same column clicked; otherwise default to desc.
    if (_eventsSortKey === key) {
        _eventsSortDir = _eventsSortDir === 'desc' ? 'asc' : 'desc';
    } else {
        _eventsSortKey = key;
        _eventsSortDir = 'desc';
    }
    renderEventsTable(_eventsCache, _eventsTotal, document.getElementById('events-container'));
}

function _applySort(events) {
    const key = _eventsSortKey;
    const dir = _eventsSortDir === 'asc' ? 1 : -1;
    return [...events].sort((a, b) => {
        let av = a[key], bv = b[key];
        // Nulls always sort last regardless of dir.
        if (av == null && bv == null) return 0;
        if (av == null) return 1;
        if (bv == null) return -1;
        if (typeof av === 'number' && typeof bv === 'number') return (av - bv) * dir;
        return String(av).localeCompare(String(bv)) * dir;
    });
}

function _sortIndicator(key) {
    if (_eventsSortKey !== key) return '<span class="text-gray-400 opacity-50 ml-1">↕</span>';
    return _eventsSortDir === 'desc'
        ? '<span class="text-seismo-orange ml-1">↓</span>'
        : '<span class="text-seismo-orange ml-1">↑</span>';
}

function _sortableTh(label, key) {
    return `<th onclick="sortEvents('${key}')"
                class="px-4 py-3 text-xs font-medium text-gray-700 dark:text-gray-300 uppercase tracking-wider cursor-pointer select-none hover:bg-gray-100 dark:hover:bg-slate-600 transition-colors">
        ${label}${_sortIndicator(key)}
    </th>`;
}

function renderEventsTable(events, total, container) {
    if (!events || events.length === 0) {
        container.innerHTML = '<div class="text-center py-12 text-gray-500 dark:text-gray-400"><p class="text-sm">No events found matching the current filters.</p></div>';
        return;
    }

    const sorted = _applySort(events);
    const rows = sorted.map(ev => {
        const ts = ev.timestamp ? ev.timestamp.replace('T', ' ').slice(0, 19) : '—';
        const tran = fmtPPV(ev.tran_ppv);
        const vert = fmtPPV(ev.vert_ppv);
        const lng  = fmtPPV(ev.long_ppv);
        const pvs  = fmtPPV(ev.peak_vector_sum);
        const mic  = ev.mic_ppv != null ? ev.mic_ppv.toFixed(3) : '—';
        const ft   = ev.false_trigger ? `<span class="px-2 py-0.5 rounded text-xs bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-200">FT</span>` : '';
        const proj = ev.project ? `<span class="truncate max-w-[120px] inline-block" title="${esc(ev.project)}">${esc(ev.project)}</span>` : '<span class="text-gray-400">—</span>';

        return `<tr class="hover:bg-gray-50 dark:hover:bg-slate-700/50 cursor-pointer" onclick="showEventDetail('${esc(ev.id)}')">
            <td class="px-4 py-2.5 text-sm text-gray-900 dark:text-white whitespace-nowrap">${ts}</td>
            <td class="px-4 py-2.5 text-sm font-mono font-medium text-seismo-orange">${esc(ev.serial)}</td>
            <td class="px-4 py-2.5 text-sm text-gray-700 dark:text-gray-300 max-w-[140px]">${proj}</td>
            <td class="px-4 py-2.5 text-sm font-mono ${ppvClass(ev.tran_ppv)}">${tran}</td>
            <td class="px-4 py-2.5 text-sm font-mono ${ppvClass(ev.vert_ppv)}">${vert}</td>
            <td class="px-4 py-2.5 text-sm font-mono ${ppvClass(ev.long_ppv)}">${lng}</td>
            <td class="px-4 py-2.5 text-sm font-mono font-semibold ${ppvClass(ev.peak_vector_sum)}">${pvs}</td>
            <td class="px-4 py-2.5 text-sm font-mono text-gray-600 dark:text-gray-400">${mic}</td>
            <td class="px-4 py-2.5 text-sm">
                ${ft}
                <button onclick="event.stopPropagation(); toggleFalseTrigger('${ev.id}', ${ev.false_trigger ? 'false' : 'true'}, this)"
                        class="ml-1 px-2 py-0.5 rounded text-xs ${ev.false_trigger ? 'bg-gray-100 text-gray-600 dark:bg-gray-700 dark:text-gray-300 hover:bg-yellow-100' : 'bg-gray-100 text-gray-500 dark:bg-gray-700 dark:text-gray-400 hover:bg-yellow-50'}"
                        title="${ev.false_trigger ? 'Clear false trigger' : 'Mark as false trigger'}">
                    ${ev.false_trigger ? '✕ FT' : 'Flag FT'}
                </button>
            </td>
        </tr>`;
    }).join('');

    container.innerHTML = `
        <div class="text-xs text-gray-500 dark:text-gray-400 mb-2">Showing ${events.length} of ${total} events</div>
        <table class="w-full text-left">
            <thead class="bg-gray-50 dark:bg-slate-700 border-b border-gray-200 dark:border-gray-600">
                <tr>
                    ${_sortableTh('Timestamp', 'timestamp')}
                    ${_sortableTh('Serial', 'serial')}
                    ${_sortableTh('Project', 'project')}
                    ${_sortableTh('Tran', 'tran_ppv')}
                    ${_sortableTh('Vert', 'vert_ppv')}
                    ${_sortableTh('Long', 'long_ppv')}
                    ${_sortableTh('PVS', 'peak_vector_sum')}
                    ${_sortableTh('Mic', 'mic_ppv')}
                    ${_sortableTh('Flags', 'false_trigger')}
                </tr>
            </thead>
            <tbody class="divide-y divide-gray-200 dark:divide-gray-700">${rows}</tbody>
        </table>`;
}

function fmtPPV(v) {
    if (v == null) return '—';
    return v.toFixed(4);
}

function ppvClass(v) {
    if (v == null) return 'text-gray-400';
    if (v < 0.5) return 'ppv-low';
    if (v < 2.0) return 'ppv-mid';
    return 'ppv-high';
}

function clearEventFilters() {
    document.getElementById('ev-serial').value = '';
    document.getElementById('ev-from').value = '';
    document.getElementById('ev-to').value = '';
    document.getElementById('ev-false-trigger').value = '';
    document.getElementById('ev-limit').value = '500';
    loadEvents();
}

async function toggleFalseTrigger(id, newValue, btn) {
    btn.disabled = true;
    btn.textContent = '…';
    try {
        const r = await fetch(`/api/sfm/db/events/${id}/false_trigger?value=${newValue}`, { method: 'PATCH' });
        if (r.ok) {
            // Refresh the table after short delay
            setTimeout(loadEvents, 300);
        } else {
            btn.textContent = 'Error';
            btn.disabled = false;
        }
    } catch (e) {
        btn.textContent = 'Error';
        btn.disabled = false;
    }
}

// Event detail modal now lives in /static/event-modal.js (shared component).
// `showEventDetail(eventId)` is exposed globally; row onclick handlers call it.

// ── Units tab ────────────────────────────────────────────────────────────────
async function loadUnits() {
    const container = document.getElementById('units-container');
    try {
        const r = await fetch('/api/sfm/db/units');
        if (!r.ok) throw new Error('HTTP ' + r.status);
        const units = await r.json();

        if (units.length === 0) {
            container.innerHTML = '<div class="text-center py-12 text-gray-500 text-sm">No units in database. Waiting for series3-watcher to forward events from Blastware ACH.</div>';
            return;
        }

        const rows = units.map(u => {
            const lastSeen = u.last_seen ? u.last_seen.slice(0, 19).replace('T', ' ') : '—';
            return `<tr class="hover:bg-gray-50 dark:hover:bg-slate-700/50">
                <td class="px-4 py-3 text-sm font-mono font-semibold text-seismo-orange">${esc(u.serial)}</td>
                <td class="px-4 py-3 text-sm text-gray-700 dark:text-gray-300">${lastSeen}</td>
                <td class="px-4 py-3 text-sm text-gray-700 dark:text-gray-300">${(u.total_events || 0).toLocaleString()}</td>
                <td class="px-4 py-3 text-sm">
                    <button onclick="filterEventsBySerial('${esc(u.serial)}')"
                            class="px-3 py-1 text-xs rounded-lg border border-gray-300 dark:border-gray-600 hover:bg-gray-50 dark:hover:bg-gray-700 text-gray-700 dark:text-gray-300">
                        View Events
                    </button>
                </td>
            </tr>`;
        }).join('');

        container.innerHTML = `
            <div class="overflow-x-auto">
                <table class="w-full">
                    <thead class="bg-gray-50 dark:bg-slate-700 border-b border-gray-200 dark:border-gray-600">
                        <tr>
                            <th class="px-4 py-3 text-xs font-medium text-gray-700 dark:text-gray-300 uppercase tracking-wider text-left">Serial</th>
                            <th class="px-4 py-3 text-xs font-medium text-gray-700 dark:text-gray-300 uppercase tracking-wider text-left">Last Seen</th>
                            <th class="px-4 py-3 text-xs font-medium text-gray-700 dark:text-gray-300 uppercase tracking-wider text-left">Events</th>
                            <th class="px-4 py-3 text-xs font-medium text-gray-700 dark:text-gray-300 uppercase tracking-wider text-left">Actions</th>
                        </tr>
                    </thead>
                    <tbody class="divide-y divide-gray-200 dark:divide-gray-700">${rows}</tbody>
                </table>
            </div>`;
    } catch (e) {
        container.innerHTML = `<div class="text-center py-8 text-red-500 text-sm">Failed to load units: ${e.message}</div>`;
    }
}

function filterEventsBySerial(serial) {
    document.getElementById('ev-serial').value = serial;
    switchTab('events');
    loadEvents();
}


// ── Helpers ───────────────────────────────────────────────────────────────────
function esc(s) {
    if (s == null) return '';
    return String(s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/"/g,'&quot;');
}

// ── Init ──────────────────────────────────────────────────────────────────────
document.addEventListener('DOMContentLoaded', () => {
    checkSFMHealth();
    loadEvents();
});
</script>
{% endblock %}
