{% extends "base.html" %}

{% block title %}Deployment History - Seismo Fleet Manager{% endblock %}

{% block extra_head %}
<style>
.dh-calendar-grid {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 1rem;
}
@media (max-width: 1280px) { .dh-calendar-grid { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 768px)  { .dh-calendar-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 480px)  { .dh-calendar-grid { grid-template-columns: 1fr; } }

.dh-month-card {
    background: white;
    border-radius: 0.5rem;
    padding: 0.75rem;
    box-shadow: 0 1px 3px rgba(0,0,0,0.1);
}
.dark .dh-month-card { background: rgb(30 41 59); }

.dh-day-grid {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    gap: 2px;
    font-size: 0.75rem;
}
.dh-day-header {
    text-align: center;
    font-weight: 600;
    color: #6b7280;
    padding: 0.25rem 0;
}
.dark .dh-day-header { color: #9ca3af; }

.dh-day-cell {
    aspect-ratio: 1;
    display: flex;
    flex-direction: column;
    align-items: stretch;
    justify-content: flex-start;
    border-radius: 0.25rem;
    position: relative;
    transition: all 0.15s ease;
    font-size: 0.7rem;
    padding-top: 2px;
    background-color: #f3f4f6;
    color: #374151;
    cursor: pointer;
}
.dh-day-cell:hover {
    transform: scale(1.1);
    z-index: 10;
}
.dh-day-cell.empty {
    background: transparent;
    cursor: default;
}
.dh-day-cell.empty:hover { transform: none; }
.dh-day-cell.today {
    ring-color: #f48b1c;
    font-weight: 700;
    color: #b84a12;
}
.dark .dh-day-cell {
    background-color: rgba(55, 65, 81, 0.5);
    color: #d1d5db;
}
.dh-day-cell .dh-day-num {
    text-align: center;
    flex-shrink: 0;
}
.dh-day-cell .dh-bars {
    display: flex;
    flex-direction: column;
    gap: 1px;
    margin: 2px 2px 0 2px;
}
.dh-bar {
    height: 3px;
    border-radius: 1px;
}
</style>
{% endblock %}

{% block content %}
<div class="mb-6 flex items-center justify-between flex-wrap gap-3">
    <div>
        <a href="/tools" class="text-sm text-seismo-orange hover:text-seismo-burgundy">← Back to Tools</a>
        <h1 class="text-3xl font-bold text-gray-900 dark:text-white mt-1">Deployment History</h1>
        <p class="text-gray-600 dark:text-gray-400 mt-1">
            Where every unit has been — actual assignment windows, color-coded by project.
            For future / planned deployments use the <a href="/fleet-calendar" class="text-seismo-orange hover:text-seismo-burgundy">Job Planner</a>.
        </p>
    </div>
</div>

<!-- View tabs: Calendar | Gantt (by project) | By Unit (gantt by unit) -->
<div class="flex rounded-lg bg-gray-100 dark:bg-gray-700 p-1 mb-6 w-fit">
    <button id="dh-tab-calendar" onclick="switchDhView('calendar')"
            class="px-4 py-2 rounded-md text-sm font-medium transition-colors bg-white dark:bg-slate-600 text-gray-900 dark:text-white shadow">
        Calendar
    </button>
    <button id="dh-tab-gantt" onclick="switchDhView('gantt')"
            class="px-4 py-2 rounded-md text-sm font-medium transition-colors text-gray-600 dark:text-gray-300 hover:text-gray-900 dark:hover:text-white">
        Gantt by Project
    </button>
    <button id="dh-tab-byunit" onclick="switchDhView('byunit')"
            class="px-4 py-2 rounded-md text-sm font-medium transition-colors text-gray-600 dark:text-gray-300 hover:text-gray-900 dark:hover:text-white">
        Gantt by Unit
    </button>
</div>

<!-- KPI strip -->
<div class="flex flex-wrap items-center gap-4 mb-6">
    <div class="flex items-center gap-3 text-sm bg-white dark:bg-slate-800 rounded-lg px-4 py-2 shadow">
        <span class="text-gray-500 dark:text-gray-400">{{ calendar.projects | length }} project{{ '' if calendar.projects | length == 1 else 's' }}</span>
        <span class="text-gray-300 dark:text-gray-600">|</span>
        <span class="text-gray-500 dark:text-gray-400">{{ calendar.total_active_units }} unique units</span>
        <span class="text-gray-300 dark:text-gray-600">|</span>
        <span class="text-gray-500 dark:text-gray-400">{{ calendar.total_assignments }} assignment{{ '' if calendar.total_assignments == 1 else 's' }} in window</span>
    </div>
    {% if calendar.projects %}
    <details class="bg-white dark:bg-slate-800 rounded-lg shadow px-4 py-2">
        <summary class="cursor-pointer text-sm font-medium text-gray-700 dark:text-gray-300 select-none">Project legend</summary>
        <div class="flex flex-wrap items-center gap-x-4 gap-y-2 mt-3 pt-3 border-t border-gray-200 dark:border-gray-700">
            {% for p in calendar.projects %}
            <a href="/projects/{{ p.id }}"
               class="flex items-center gap-1.5 text-sm text-gray-700 dark:text-gray-300 hover:text-seismo-orange">
                <span class="w-3 h-1.5 rounded-full flex-shrink-0" style="background-color: {{ p.color }};"></span>
                {{ p.name }}
                <span class="text-xs text-gray-400 dark:text-gray-500">·</span>
                <span class="text-xs text-gray-500 dark:text-gray-400">{{ p.assignment_count }}</span>
            </a>
            {% endfor %}
        </div>
    </details>
    {% endif %}
</div>

<!-- ─── Calendar view ─── -->
<div id="dh-view-calendar">

<!-- Calendar grid -->
{% if calendar.projects %}
<div class="dh-calendar-grid mb-6">
    {% for month_data in calendar.months %}
    <div class="dh-month-card">
        <h3 class="font-semibold text-gray-900 dark:text-white mb-2 text-center">
            {{ month_data.short_name }} '{{ month_data.year_short }}
        </h3>
        <div class="dh-day-grid">
            <div class="dh-day-header">S</div>
            <div class="dh-day-header">M</div>
            <div class="dh-day-header">T</div>
            <div class="dh-day-header">W</div>
            <div class="dh-day-header">T</div>
            <div class="dh-day-header">F</div>
            <div class="dh-day-header">S</div>

            {# Sunday-first alignment: shift Monday=0 → Sunday=0 #}
            {% set first_offset = (month_data.first_weekday + 1) % 7 %}
            {% for i in range(first_offset) %}
                <div class="dh-day-cell empty"></div>
            {% endfor %}

            {% for day_num in range(1, month_data.num_days + 1) %}
                {% set date_str = '%04d-%02d-%02d' | format(month_data.year, month_data.month, day_num) %}
                {% set is_today = date_str == today %}
                {% set day_proj_ids = month_data.active_days.get(day_num, []) %}
                <div class="dh-day-cell{% if is_today %} today ring-2 ring-seismo-orange{% endif %}"
                     onclick="openDhDay('{{ date_str }}')"
                     title="{{ date_str }} — {{ day_proj_ids | length }} project{{ '' if day_proj_ids | length == 1 else 's' }}">
                    <span class="dh-day-num">{{ day_num }}</span>
                    {% if day_proj_ids %}
                    <span class="dh-bars">
                        {% for pid in day_proj_ids[:4] %}
                            {% set p = (calendar.projects | selectattr('id', 'equalto', pid) | first) %}
                            {% if p %}
                            <span class="dh-bar" style="background-color: {{ p.color }};"
                                  title="{{ p.name }}"></span>
                            {% endif %}
                        {% endfor %}
                        {% if day_proj_ids | length > 4 %}
                            <span class="text-[8px] text-gray-500 leading-none">+{{ day_proj_ids | length - 4 }}</span>
                        {% endif %}
                    </span>
                    {% endif %}
                </div>
            {% endfor %}
        </div>
    </div>
    {% endfor %}
</div>

<!-- Month navigation -->
<div class="flex items-center justify-center gap-3 mb-8">
    <a href="/tools/deployment-history?year={{ prev_year }}&month={{ prev_month }}"
       class="px-3 py-2 rounded-lg bg-gray-100 dark:bg-gray-700 hover:bg-gray-200 dark:hover:bg-gray-600 text-gray-700 dark:text-gray-300"
       title="Previous month">
        <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7"/>
        </svg>
    </a>
    <span class="text-lg font-bold text-gray-900 dark:text-white px-3">
        {{ calendar.months[0].short_name }} '{{ calendar.months[0].year_short }} – {{ calendar.months[11].short_name }} '{{ calendar.months[11].year_short }}
    </span>
    <a href="/tools/deployment-history?year={{ next_year }}&month={{ next_month }}"
       class="px-3 py-2 rounded-lg bg-gray-100 dark:bg-gray-700 hover:bg-gray-200 dark:hover:bg-gray-600 text-gray-700 dark:text-gray-300"
       title="Next month">
        <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"/>
        </svg>
    </a>
    <a href="/tools/deployment-history"
       class="ml-2 px-4 py-2 rounded-lg bg-seismo-orange text-white hover:bg-orange-600">
        Recent
    </a>
</div>

{% else %}
<div class="bg-white dark:bg-slate-800 rounded-xl shadow-lg p-8 text-center text-gray-500 dark:text-gray-400">
    <svg class="w-12 h-12 mx-auto mb-3 opacity-40" fill="none" stroke="currentColor" viewBox="0 0 24 24">
        <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"/>
    </svg>
    <p class="text-sm">No deployments in this window.</p>
    <p class="text-xs mt-1">Try the navigation buttons below to look at a different range.</p>
</div>
{% endif %}

</div>  {# /#dh-view-calendar #}

<!-- ─── Gantt view ─── -->
<div id="dh-view-gantt" class="hidden">
{% if calendar.projects %}
    <div class="bg-white dark:bg-slate-800 rounded-xl shadow-lg p-4 mb-6 overflow-x-auto">
        <p class="text-xs text-gray-500 dark:text-gray-400 mb-3">
            One row per project.  Each bar is one assignment window (unit at a location).
            Hover for details, click to open the project.
            Active deployments end at "now" with a small white tip.
        </p>
        <svg id="dh-gantt-svg" preserveAspectRatio="none"
             style="width: 100%; min-width: 800px;"></svg>
    </div>

    <!-- Same nav as calendar view, repeated here so the Gantt view has its own. -->
    <div class="flex items-center justify-center gap-3 mb-8">
        <a href="/tools/deployment-history?year={{ prev_year }}&month={{ prev_month }}#gantt"
           class="px-3 py-2 rounded-lg bg-gray-100 dark:bg-gray-700 hover:bg-gray-200 dark:hover:bg-gray-600 text-gray-700 dark:text-gray-300"
           title="Previous month">
            <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7"/>
            </svg>
        </a>
        <span class="text-lg font-bold text-gray-900 dark:text-white px-3">
            {{ calendar.months[0].short_name }} '{{ calendar.months[0].year_short }} – {{ calendar.months[11].short_name }} '{{ calendar.months[11].year_short }}
        </span>
        <a href="/tools/deployment-history?year={{ next_year }}&month={{ next_month }}#gantt"
           class="px-3 py-2 rounded-lg bg-gray-100 dark:bg-gray-700 hover:bg-gray-200 dark:hover:bg-gray-600 text-gray-700 dark:text-gray-300"
           title="Next month">
            <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"/>
            </svg>
        </a>
        <a href="/tools/deployment-history#gantt"
           class="ml-2 px-4 py-2 rounded-lg bg-seismo-orange text-white hover:bg-orange-600">
            Recent
        </a>
    </div>
{% else %}
    <div class="bg-white dark:bg-slate-800 rounded-xl shadow-lg p-8 text-center text-gray-500 dark:text-gray-400">
        <p class="text-sm">No deployments in this window.</p>
    </div>
{% endif %}
</div>  {# /#dh-view-gantt #}

<!-- ─── Gantt-by-Unit view ─── -->
<div id="dh-view-byunit" class="hidden">
{% if calendar.units %}
    <div class="bg-white dark:bg-slate-800 rounded-xl shadow-lg p-4 mb-6 overflow-x-auto">
        <p class="text-xs text-gray-500 dark:text-gray-400 mb-3">
            One row per seismograph that had ≥1 assignment in this window.
            Bars are colored by <strong>project</strong>, so an operator can read where each unit travelled
            across jobs.  Active deployments end at "now" with a small white tip.
            Click a unit ID to open its detail page; click a bar to open the bar's project.
        </p>
        <svg id="dh-byunit-svg" preserveAspectRatio="none"
             style="width: 100%; min-width: 800px;"></svg>
    </div>

    <div class="flex items-center justify-center gap-3 mb-8">
        <a href="/tools/deployment-history?year={{ prev_year }}&month={{ prev_month }}#byunit"
           class="px-3 py-2 rounded-lg bg-gray-100 dark:bg-gray-700 hover:bg-gray-200 dark:hover:bg-gray-600 text-gray-700 dark:text-gray-300"
           title="Previous month">
            <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7"/>
            </svg>
        </a>
        <span class="text-lg font-bold text-gray-900 dark:text-white px-3">
            {{ calendar.months[0].short_name }} '{{ calendar.months[0].year_short }} – {{ calendar.months[11].short_name }} '{{ calendar.months[11].year_short }}
        </span>
        <a href="/tools/deployment-history?year={{ next_year }}&month={{ next_month }}#byunit"
           class="px-3 py-2 rounded-lg bg-gray-100 dark:bg-gray-700 hover:bg-gray-200 dark:hover:bg-gray-600 text-gray-700 dark:text-gray-300"
           title="Next month">
            <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"/>
            </svg>
        </a>
        <a href="/tools/deployment-history#byunit"
           class="ml-2 px-4 py-2 rounded-lg bg-seismo-orange text-white hover:bg-orange-600">
            Recent
        </a>
    </div>
{% else %}
    <div class="bg-white dark:bg-slate-800 rounded-xl shadow-lg p-8 text-center text-gray-500 dark:text-gray-400">
        <p class="text-sm">No unit deployments in this window.</p>
    </div>
{% endif %}
</div>  {# /#dh-view-byunit #}

<!-- Day-detail side panel -->
<div id="dh-day-panel-backdrop"
     class="fixed inset-0 bg-black/30 z-40 hidden transition-opacity"
     onclick="closeDhDayPanel()"></div>
<div id="dh-day-panel"
     class="fixed top-0 right-0 h-screen w-full max-w-md bg-white dark:bg-slate-800 shadow-2xl z-50 hidden transform translate-x-full transition-transform duration-300 overflow-y-auto">
    <div class="sticky top-0 bg-white dark:bg-slate-800 border-b border-gray-200 dark:border-gray-700 px-5 py-4 flex items-center justify-between">
        <div>
            <h2 class="text-lg font-semibold text-gray-900 dark:text-white" id="dh-day-panel-title">Deployments on…</h2>
            <p class="text-xs text-gray-500 dark:text-gray-400" id="dh-day-panel-subtitle"></p>
        </div>
        <button onclick="closeDhDayPanel()" class="text-gray-400 hover:text-gray-700 dark:hover:text-gray-200">
            <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/>
            </svg>
        </button>
    </div>
    <div id="dh-day-panel-body" class="p-5 space-y-3">
        <div class="text-center py-8 text-gray-500 dark:text-gray-400 text-sm">
            <div class="animate-spin rounded-full h-6 w-6 border-b-2 border-seismo-orange mx-auto mb-2"></div>
            Loading…
        </div>
    </div>
</div>

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

async function openDhDay(dateStr) {
    const panel    = document.getElementById('dh-day-panel');
    const backdrop = document.getElementById('dh-day-panel-backdrop');
    const title    = document.getElementById('dh-day-panel-title');
    const sub      = document.getElementById('dh-day-panel-subtitle');
    const body     = document.getElementById('dh-day-panel-body');

    title.textContent = 'Deployments on ' + dateStr;
    sub.textContent   = '';
    body.innerHTML    = `<div class="text-center py-8 text-gray-500 dark:text-gray-400 text-sm">
        <div class="animate-spin rounded-full h-6 w-6 border-b-2 border-seismo-orange mx-auto mb-2"></div>
        Loading…
    </div>`;

    panel.classList.remove('hidden');
    backdrop.classList.remove('hidden');
    requestAnimationFrame(() => panel.classList.remove('translate-x-full'));

    try {
        const r = await fetch(`/api/admin/deployment-history/day?target_date=${encodeURIComponent(dateStr)}`);
        if (!r.ok) throw new Error('HTTP ' + r.status);
        const d = await r.json();
        renderDhDayPanel(d, dateStr);
    } catch (e) {
        body.innerHTML = `<p class="text-sm text-red-500">Failed to load: ${_dhEsc(e.message)}</p>`;
    }
}

function renderDhDayPanel(d, dateStr) {
    const sub  = document.getElementById('dh-day-panel-subtitle');
    const body = document.getElementById('dh-day-panel-body');

    sub.textContent = `${d.count} active deployment${d.count === 1 ? '' : 's'}`;

    if (d.count === 0) {
        body.innerHTML = '<p class="text-sm text-gray-500 dark:text-gray-400">No active deployments on this date.</p>';
        return;
    }

    // Group by project for cleaner display.
    const byProj = {};
    for (const dep of d.deployments) {
        const key = dep.project_id || '_none';
        if (!byProj[key]) byProj[key] = { name: dep.project_name, color: dep.project_color, items: [] };
        byProj[key].items.push(dep);
    }

    let html = '';
    for (const pid of Object.keys(byProj)) {
        const proj = byProj[pid];
        html += `<div class="space-y-1">
            <div class="flex items-center justify-between">
                <a href="/projects/${_dhEsc(pid)}" class="flex items-center gap-2 font-medium text-gray-900 dark:text-white hover:text-seismo-orange">
                    <span class="w-3 h-3 rounded-full" style="background-color: ${proj.color};"></span>
                    ${_dhEsc(proj.name)}
                </a>
                <span class="text-xs text-gray-500 dark:text-gray-400">${proj.items.length} unit${proj.items.length === 1 ? '' : 's'}</span>
            </div>
            <div class="space-y-1 ml-5">`;
        for (const dep of proj.items) {
            const activeBadge = dep.is_active
                ? '<span class="text-[10px] uppercase tracking-wider px-1 py-0.5 rounded bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-300">active</span>'
                : '';
            const sourceTag = dep.source === 'metadata_backfill'
                ? '<span class="text-[10px] text-blue-600 dark:text-blue-400 italic">auto-backfilled</span>'
                : '';
            const windowEnd = dep.is_active ? 'present' : (dep.assigned_until || '').slice(0, 10);
            const windowStart = (dep.assigned_at || '').slice(0, 10);
            html += `<div class="flex items-center justify-between gap-2 py-1 text-sm">
                <div class="min-w-0 flex-1">
                    <div class="flex items-center gap-2 flex-wrap">
                        <a href="/unit/${_dhEsc(dep.unit_id)}" class="font-mono font-medium text-seismo-orange hover:text-seismo-navy">${_dhEsc(dep.unit_id)}</a>
                        ${activeBadge}
                        ${sourceTag}
                    </div>
                    <div class="text-xs text-gray-500 dark:text-gray-400 truncate">
                        📍 <a href="/projects/${_dhEsc(pid)}/nrl/${_dhEsc(dep.location_id)}" class="hover:text-seismo-orange">${_dhEsc(dep.location_name)}</a>
                    </div>
                    <div class="text-[11px] text-gray-400 dark:text-gray-500 font-mono">${windowStart} → ${windowEnd}</div>
                </div>
            </div>`;
        }
        html += `</div></div>`;
    }
    body.innerHTML = html;
}

function closeDhDayPanel() {
    const panel    = document.getElementById('dh-day-panel');
    const backdrop = document.getElementById('dh-day-panel-backdrop');
    panel.classList.add('translate-x-full');
    setTimeout(() => {
        panel.classList.add('hidden');
        backdrop.classList.add('hidden');
    }, 300);
}

document.addEventListener('keydown', (e) => {
    if (e.key === 'Escape') closeDhDayPanel();
});

// ── Tab switcher ────────────────────────────────────────────────────
const _DH_TABS = {
    calendar: { view: 'dh-view-calendar', btn: 'dh-tab-calendar', hash: '',         render: null },
    gantt:    { view: 'dh-view-gantt',    btn: 'dh-tab-gantt',    hash: '#gantt',   render: () => renderDhGantt() },
    byunit:   { view: 'dh-view-byunit',   btn: 'dh-tab-byunit',   hash: '#byunit',  render: () => renderDhByUnit() },
};

function switchDhView(which) {
    const target = _DH_TABS[which] || _DH_TABS.calendar;
    const activeCls = ['bg-white', 'dark:bg-slate-600', 'text-gray-900', 'dark:text-white', 'shadow'];
    const dormantCls = ['text-gray-600', 'dark:text-gray-300', 'hover:text-gray-900', 'dark:hover:text-white'];
    // Hide all views, dormant-style all tabs, then activate the chosen one.
    for (const key of Object.keys(_DH_TABS)) {
        const t = _DH_TABS[key];
        const v = document.getElementById(t.view);
        const b = document.getElementById(t.btn);
        if (v) v.classList.add('hidden');
        if (b) { b.classList.remove(...activeCls); b.classList.add(...dormantCls); }
    }
    const v = document.getElementById(target.view);
    const b = document.getElementById(target.btn);
    if (v) v.classList.remove('hidden');
    if (b) { b.classList.add(...activeCls); b.classList.remove(...dormantCls); }
    // URL hash sync.
    const wanted = target.hash;
    const cur    = window.location.hash || '';
    if (cur !== wanted) {
        history.replaceState(null, '', window.location.pathname + window.location.search + wanted);
    }
    if (target.render) target.render();
}

// Land on the requested view if the URL hash matches.
const _initialHash = window.location.hash;
if (_initialHash === '#gantt' || _initialHash === '#byunit') {
    document.addEventListener('DOMContentLoaded', () => switchDhView(_initialHash.slice(1)));
}

// ── Gantt renderer ──────────────────────────────────────────────────
// Server-rendered data: per-project list with each project's bars
// (assignment windows clipped to the visible window).
const _dhProjects = {{ calendar.projects | tojson }};
const _dhWindowStart = {{ calendar.window.first_date | tojson }};
const _dhWindowEnd   = {{ calendar.window.last_date  | tojson }};

let _ganttRendered = false;
function renderDhGantt() {
    if (_ganttRendered) return;   // build once; data doesn't change after page load
    _ganttRendered = true;
    const svg = document.getElementById('dh-gantt-svg');
    if (!svg) return;
    if (!_dhProjects || _dhProjects.length === 0) {
        svg.innerHTML = '';
        return;
    }

    const isDark = document.documentElement.classList.contains('dark');
    const labelColor = isDark ? '#9ca3af' : '#6b7280';
    const gridColor  = isDark ? '#374151' : '#e5e7eb';
    const rowAltBg   = isDark ? '#1e293b' : '#f9fafb';
    const todayColor = '#f48b1c';

    // Geometry.  The Gantt SVG has a left "labels" gutter and a right
    // time-axis area.  Width is fluid (matches container); height grows
    // with the number of project rows.
    const containerW = svg.parentElement.clientWidth || 1000;
    const width      = Math.max(containerW, 800);
    const labelW     = 220;
    const padTop     = 36;       // room for month labels above
    const padBottom  = 16;
    const rowH       = 36;
    const barH       = 18;
    const height     = padTop + padBottom + _dhProjects.length * rowH;

    const usableW = width - labelW - 8;

    const tStart = new Date(_dhWindowStart + 'T00:00:00Z').getTime();
    const tEnd   = new Date(_dhWindowEnd   + 'T23:59:59Z').getTime();
    const tRange = tEnd - tStart;
    const xFor = (d) => {
        const ms = (typeof d === 'string') ? new Date(d + 'T00:00:00Z').getTime() : d;
        return labelW + Math.max(0, Math.min(usableW, (ms - tStart) / tRange * usableW));
    };

    // Month gridlines + month labels along the top.
    // Walk every 1st-of-month inside the window.
    const monthsParts = [];
    const cursor = new Date(_dhWindowStart + 'T00:00:00Z');
    cursor.setUTCDate(1);
    while (cursor.getTime() <= tEnd) {
        const x = xFor(cursor);
        const label = cursor.toLocaleDateString('en-US', { month: 'short', year: '2-digit', timeZone: 'UTC' });
        monthsParts.push(`<line x1="${x}" y1="${padTop}" x2="${x}" y2="${height - padBottom}" stroke="${gridColor}" stroke-width="1"/>`);
        monthsParts.push(`<text x="${x + 2}" y="${padTop - 6}" font-size="10" fill="${labelColor}" font-family="system-ui,sans-serif">${label}</text>`);
        cursor.setUTCMonth(cursor.getUTCMonth() + 1);
    }

    // Today marker.
    const now = Date.now();
    let todayMarker = '';
    if (now >= tStart && now <= tEnd) {
        const x = xFor(now);
        todayMarker = `<line x1="${x}" y1="${padTop}" x2="${x}" y2="${height - padBottom}" stroke="${todayColor}" stroke-width="2" stroke-dasharray="3 2" opacity="0.85"/>
            <text x="${x + 3}" y="${padTop - 20}" font-size="9" fill="${todayColor}" font-family="system-ui,sans-serif">today</text>`;
    }

    // Build rows.
    const rowParts = [];
    _dhProjects.forEach((proj, idx) => {
        const y = padTop + idx * rowH;
        // Alternating row background.
        if (idx % 2 === 1) {
            rowParts.push(`<rect x="0" y="${y}" width="${width}" height="${rowH}" fill="${rowAltBg}"/>`);
        }
        // Project label (clipped to gutter, clickable).
        const labelText = proj.name.length > 28 ? proj.name.slice(0, 26) + '…' : proj.name;
        rowParts.push(`<a href="/projects/${_dhEsc(proj.id)}" target="_top">
            <rect x="0" y="${y}" width="${labelW}" height="${rowH}" fill="transparent"/>
            <circle cx="14" cy="${y + rowH / 2}" r="4" fill="${proj.color}"/>
            <text x="24" y="${y + rowH / 2 + 4}" font-size="12" fill="${labelColor}"
                  font-family="system-ui,sans-serif"
                  title="${_dhEsc(proj.name)}">
                ${_dhEsc(labelText)}
            </text>
        </a>`);
        // Bars for each assignment in this project.
        for (const bar of (proj.bars || [])) {
            const x1 = xFor(bar.start);
            const x2 = xFor(bar.end);
            const barW = Math.max(x2 - x1, 2);
            const by = y + (rowH - barH) / 2;
            const tip = `${bar.unit_id} @ ${bar.location_name}\n${bar.start} → ${bar.is_active ? 'present' : bar.end}`;
            rowParts.push(`<g style="cursor: pointer;">
                <title>${_dhEsc(tip)}</title>
                <rect x="${x1}" y="${by}" width="${barW}" height="${barH}"
                      rx="3"
                      fill="${proj.color}" opacity="${bar.is_active ? 1.0 : 0.75}"
                      ${bar.source === 'metadata_backfill' ? 'stroke="#3b82f6" stroke-width="1.5"' : ''}/>
                ${bar.is_active ? `<rect x="${x2 - 3}" y="${by}" width="3" height="${barH}" fill="#ffffff" opacity="0.8"/>` : ''}
            </g>`);
        }
    });

    svg.setAttribute('viewBox', `0 0 ${width} ${height}`);
    svg.setAttribute('height', height);
    svg.innerHTML = monthsParts.join('') + rowParts.join('') + todayMarker;
}

// ── Gantt-by-Unit renderer ──────────────────────────────────────────
// Inverts the Gantt: rows = seismographs, bars = assignment windows
// colored by project (so an operator can read where each unit went
// across jobs).  Shares the time-axis geometry with renderDhGantt().
const _dhUnits = {{ calendar.units | tojson }};
let _byunitRendered = false;
function renderDhByUnit() {
    if (_byunitRendered) return;
    _byunitRendered = true;
    const svg = document.getElementById('dh-byunit-svg');
    if (!svg) return;
    if (!_dhUnits || _dhUnits.length === 0) {
        svg.innerHTML = '';
        return;
    }

    const isDark = document.documentElement.classList.contains('dark');
    const labelColor = isDark ? '#9ca3af' : '#6b7280';
    const labelStrong = isDark ? '#e5e7eb' : '#111827';
    const gridColor  = isDark ? '#374151' : '#e5e7eb';
    const rowAltBg   = isDark ? '#1e293b' : '#f9fafb';
    const todayColor = '#f48b1c';

    const containerW = svg.parentElement.clientWidth || 1000;
    const width      = Math.max(containerW, 800);
    const labelW     = 160;
    const padTop     = 36;
    const padBottom  = 16;
    const rowH       = 32;
    const barH       = 16;
    const height     = padTop + padBottom + _dhUnits.length * rowH;

    const usableW = width - labelW - 8;
    const tStart = new Date(_dhWindowStart + 'T00:00:00Z').getTime();
    const tEnd   = new Date(_dhWindowEnd   + 'T23:59:59Z').getTime();
    const tRange = tEnd - tStart;
    const xFor = (d) => {
        const ms = (typeof d === 'string') ? new Date(d + 'T00:00:00Z').getTime() : d;
        return labelW + Math.max(0, Math.min(usableW, (ms - tStart) / tRange * usableW));
    };

    // Month gridlines + labels (same as renderDhGantt).
    const monthsParts = [];
    const cursor = new Date(_dhWindowStart + 'T00:00:00Z');
    cursor.setUTCDate(1);
    while (cursor.getTime() <= tEnd) {
        const x = xFor(cursor);
        const label = cursor.toLocaleDateString('en-US', { month: 'short', year: '2-digit', timeZone: 'UTC' });
        monthsParts.push(`<line x1="${x}" y1="${padTop}" x2="${x}" y2="${height - padBottom}" stroke="${gridColor}" stroke-width="1"/>`);
        monthsParts.push(`<text x="${x + 2}" y="${padTop - 6}" font-size="10" fill="${labelColor}" font-family="system-ui,sans-serif">${label}</text>`);
        cursor.setUTCMonth(cursor.getUTCMonth() + 1);
    }

    const now = Date.now();
    let todayMarker = '';
    if (now >= tStart && now <= tEnd) {
        const x = xFor(now);
        todayMarker = `<line x1="${x}" y1="${padTop}" x2="${x}" y2="${height - padBottom}" stroke="${todayColor}" stroke-width="2" stroke-dasharray="3 2" opacity="0.85"/>
            <text x="${x + 3}" y="${padTop - 20}" font-size="9" fill="${todayColor}" font-family="system-ui,sans-serif">today</text>`;
    }

    const rowParts = [];
    _dhUnits.forEach((unit, idx) => {
        const y = padTop + idx * rowH;
        if (idx % 2 === 1) {
            rowParts.push(`<rect x="0" y="${y}" width="${width}" height="${rowH}" fill="${rowAltBg}"/>`);
        }
        // Unit label: opens /unit/{id} when clicked.  Active-now dot.
        const activeDot = unit.any_active
            ? `<circle cx="12" cy="${y + rowH / 2}" r="3.5" fill="#22c55e"/>`
            : `<circle cx="12" cy="${y + rowH / 2}" r="3.5" fill="${labelColor}" opacity="0.4"/>`;
        rowParts.push(`<a href="/unit/${_dhEsc(unit.id)}" target="_top">
            <rect x="0" y="${y}" width="${labelW}" height="${rowH}" fill="transparent"/>
            ${activeDot}
            <text x="22" y="${y + rowH / 2 + 4}" font-size="12" fill="${labelStrong}"
                  font-family="system-ui,sans-serif" font-weight="500">
                ${_dhEsc(unit.id)}
            </text>
            <text x="${labelW - 8}" y="${y + rowH / 2 + 4}" font-size="10" fill="${labelColor}"
                  text-anchor="end" font-family="system-ui,sans-serif">
                ${unit.assignment_count}
            </text>
        </a>`);
        // Bars — colored by the bar's project (not the row).
        for (const bar of (unit.bars || [])) {
            const x1 = xFor(bar.start);
            const x2 = xFor(bar.end);
            const barW = Math.max(x2 - x1, 2);
            const by = y + (rowH - barH) / 2;
            const tip = `${bar.project_name}\n${bar.location_name}\n${bar.start} → ${bar.is_active ? 'present' : bar.end}`;
            rowParts.push(`<a href="/projects/${_dhEsc(bar.project_id)}" target="_top">
                <g style="cursor: pointer;">
                    <title>${_dhEsc(tip)}</title>
                    <rect x="${x1}" y="${by}" width="${barW}" height="${barH}"
                          rx="3"
                          fill="${bar.project_color}" opacity="${bar.is_active ? 1.0 : 0.75}"
                          ${bar.source === 'metadata_backfill' ? 'stroke="#3b82f6" stroke-width="1.5"' : ''}/>
                    ${bar.is_active ? `<rect x="${x2 - 3}" y="${by}" width="3" height="${barH}" fill="#ffffff" opacity="0.8"/>` : ''}
                </g>
            </a>`);
        }
    });

    svg.setAttribute('viewBox', `0 0 ${width} ${height}`);
    svg.setAttribute('height', height);
    svg.innerHTML = monthsParts.join('') + rowParts.join('') + todayMarker;
}
</script>
{% endblock %}
