<div class="mb-8">
    <div class="flex flex-col md:flex-row md:items-center md:justify-between gap-4">
        <div>
            <h1 class="text-3xl font-bold text-gray-900 dark:text-white mb-2">{{ project.name }}</h1>
            <div class="flex items-center gap-4">
                <div class="relative inline-block">
                    <select onchange="quickUpdateStatus(this.value)"
                            class="appearance-none cursor-pointer inline-flex items-center pl-3 pr-7 py-1 rounded-full text-sm font-medium border-0 focus:ring-2 focus:ring-offset-1 focus:ring-blue-500
                                   {% if project.status == 'upcoming' %}bg-purple-100 text-purple-800 dark:bg-purple-900 dark:text-purple-200
                                   {% elif project.status == 'active' %}bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200
                                   {% elif project.status == 'on_hold' %}bg-amber-100 text-amber-800 dark:bg-amber-900 dark:text-amber-200
                                   {% elif project.status == 'completed' %}bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-200
                                   {% else %}bg-gray-100 text-gray-800 dark:bg-gray-700 dark:text-gray-200{% endif %}">
                        <option value="upcoming" {% if project.status == 'upcoming' %}selected{% endif %}>Upcoming</option>
                        <option value="active" {% if project.status == 'active' %}selected{% endif %}>Active</option>
                        <option value="on_hold" {% if project.status == 'on_hold' %}selected{% endif %}>On Hold</option>
                        <option value="completed" {% if project.status == 'completed' %}selected{% endif %}>Completed</option>
                        <option value="archived" {% if project.status == 'archived' %}selected{% endif %}>Archived</option>
                    </select>
                    <span class="pointer-events-none absolute right-2 top-1/2 -translate-y-1/2 text-current opacity-60">
                        <svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/>
                        </svg>
                    </span>
                </div>
                <!-- Module badges -->
                <div id="module-badges" class="flex items-center gap-1.5 flex-wrap">
                    {% for m in modules %}
                    <span class="inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-xs font-medium
                        {% if m == 'sound_monitoring' %}bg-orange-100 text-orange-800 dark:bg-orange-900/40 dark:text-orange-300
                        {% elif m == 'vibration_monitoring' %}bg-blue-100 text-blue-800 dark:bg-blue-900/40 dark:text-blue-300
                        {% else %}bg-gray-100 text-gray-700 dark:bg-gray-700 dark:text-gray-300{% endif %}">
                        {% if m == 'sound_monitoring' %}
                        <svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15.536 8.464a5 5 0 010 7.072M12 6v12M9 8.464a5 5 0 000 7.072"/></svg>
                        Sound Monitoring
                        {% elif m == 'vibration_monitoring' %}
                        <svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M22 12h-4l-3 9L9 3l-3 9H2"/></svg>
                        Vibration Monitoring
                        {% else %}{{ m }}{% endif %}
                        <button onclick="removeModule('{{ m }}')" class="ml-0.5 hover:text-red-500 transition-colors" title="Remove module">
                            <svg class="w-2.5 h-2.5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2.5" d="M6 18L18 6M6 6l12 12"/></svg>
                        </button>
                    </span>
                    {% endfor %}
                    <button onclick="openAddModuleModal()" class="inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-xs font-medium border border-dashed border-gray-400 dark:border-gray-600 text-gray-500 dark:text-gray-400 hover:border-orange-400 hover:text-orange-500 transition-colors">
                        <svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4"/></svg>
                        Add Module
                    </button>
                </div>
                {% if project.data_collection_mode == 'remote' %}
                <span class="inline-flex items-center gap-1 px-2.5 py-0.5 rounded-full text-xs font-medium bg-blue-100 text-blue-800 dark:bg-blue-900/40 dark:text-blue-300">
                    <svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                        <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8.111 16.404a5.5 5.5 0 017.778 0M12 20h.01m-7.08-7.071c3.904-3.905 10.236-3.905 14.141 0M1.394 9.393c5.857-5.857 15.355-5.857 21.213 0"></path>
                    </svg>
                    Remote
                </span>
                {% else %}
                <span class="inline-flex items-center gap-1 px-2.5 py-0.5 rounded-full text-xs font-medium bg-amber-100 text-amber-800 dark:bg-amber-900/40 dark:text-amber-300">
                    <svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                        <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 8h14M5 8a2 2 0 110-4h14a2 2 0 110 4M5 8v10a2 2 0 002 2h10a2 2 0 002-2V8m-9 4h4"></path>
                    </svg>
                    Manual
                </span>
                {% endif %}
            </div>
        </div>
        <!-- Project Actions -->
        <div class="flex items-center gap-3">
            {% if 'sound_monitoring' in modules %}
            <a href="/api/projects/{{ project.id }}/combined-report-wizard"
               class="px-4 py-2 bg-emerald-600 text-white rounded-lg hover:bg-emerald-700 transition-colors flex items-center gap-2 text-sm">
                <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 17v-2m3 2v-4m3 4v-6m2 10H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"></path>
                </svg>
                Generate Combined Report
            </a>
            <button onclick="openNightReportModal()"
                    title="Last night's noise vs baseline, per location (FTP report pipeline)"
                    class="px-4 py-2 bg-indigo-600 text-white rounded-lg hover:bg-indigo-700 transition-colors flex items-center gap-2 text-sm">
                <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="M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z"></path>
                </svg>
                Night Report
            </button>
            <button onclick="openReportSettings('{{ project.id }}')"
                    title="Nightly report settings — schedule, baseline range, recipients"
                    class="px-3 py-2 border border-gray-300 dark:border-gray-600 text-gray-600 dark:text-gray-300 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors flex items-center text-sm">
                <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="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z"></path>
                    <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"></path>
                </svg>
            </button>
            {% endif %}
            <button onclick="openMergeModal()"
                    title="Merge this project into another (consolidates duplicates)"
                    class="px-4 py-2 border border-gray-300 dark:border-gray-600 text-gray-700 dark:text-gray-300 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors flex items-center gap-2 text-sm">
                <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="M17 8l4 4m0 0l-4 4m4-4H3"></path>
                </svg>
                Merge into…
            </button>
        </div>
    </div>
</div>

<!-- Night Report Modal -->
<div id="night-report-modal" class="hidden fixed inset-0 z-50 flex items-center justify-center bg-black/60 backdrop-blur-sm">
    <div class="bg-white dark:bg-slate-800 rounded-xl shadow-2xl w-full max-w-md mx-4">
        <div class="px-6 py-4 border-b border-gray-200 dark:border-gray-700 flex items-center justify-between">
            <h3 class="text-lg font-semibold text-gray-900 dark:text-white">Night Report</h3>
            <button onclick="closeNightReportModal()" class="text-gray-400 hover:text-gray-600 dark:hover:text-gray-200">
                <svg class="w-6 h-6" 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"></path></svg>
            </button>
        </div>
        <div class="px-6 py-5 space-y-4">
            <p class="text-xs text-gray-500 dark:text-gray-400">Last night's noise (7&nbsp;PM–7&nbsp;AM) vs a baseline range, per location. Opens in a new tab.</p>
            <div>
                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Night (evening date)</label>
                <input type="date" id="nr-night-date" class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-slate-700 text-gray-900 dark:text-white text-sm">
            </div>
            <div class="grid grid-cols-2 gap-3">
                <div>
                    <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Baseline start <span class="text-gray-400 font-normal">(optional)</span></label>
                    <input type="date" id="nr-baseline-start" class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-slate-700 text-gray-900 dark:text-white text-sm">
                </div>
                <div>
                    <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Baseline end</label>
                    <input type="date" id="nr-baseline-end" class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-slate-700 text-gray-900 dark:text-white text-sm">
                </div>
            </div>
            <div>
                <div class="flex items-center justify-between mb-1">
                    <label class="block text-sm font-medium text-gray-700 dark:text-gray-300">Recent reports</label>
                    <span id="nr-recent-count" class="text-xs text-gray-400"></span>
                </div>
                <div id="nr-recent" class="max-h-40 overflow-y-auto rounded-lg border border-gray-200 dark:border-gray-700 divide-y divide-gray-100 dark:divide-gray-700">
                    <div class="px-3 py-2 text-xs text-gray-400">Loading…</div>
                </div>
            </div>
            <p id="nr-status" class="text-xs"></p>
        </div>
        <div class="px-6 py-4 border-t border-gray-200 dark:border-gray-700 flex justify-end gap-2">
            <button onclick="closeNightReportModal()" class="px-4 py-2 border border-gray-300 dark:border-gray-600 text-gray-700 dark:text-gray-300 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors text-sm">Cancel</button>
            <button onclick="runNightReport('{{ project.id }}')" class="px-4 py-2 bg-emerald-600 text-white rounded-lg hover:bg-emerald-700 transition-colors text-sm">Run &amp; Email</button>
            <button onclick="viewNightReport('{{ project.id }}')" class="px-4 py-2 bg-indigo-600 text-white rounded-lg hover:bg-indigo-700 transition-colors text-sm">View Report</button>
        </div>
    </div>
</div>
<script>
var NR_PROJECT_ID = '{{ project.id }}';
function openNightReportModal() {
    var el = document.getElementById('nr-night-date');
    if (el && !el.value) {                       // default to last night
        var d = new Date(); d.setDate(d.getDate() - 1);
        el.value = d.getFullYear() + '-'
                 + String(d.getMonth() + 1).padStart(2, '0') + '-'
                 + String(d.getDate()).padStart(2, '0');
    }
    document.getElementById('nr-status').textContent = '';
    document.getElementById('night-report-modal').classList.remove('hidden');
    loadRecentReports(NR_PROJECT_ID);
}
function closeNightReportModal() {
    document.getElementById('night-report-modal').classList.add('hidden');
}
function _nrParams() {
    var night = document.getElementById('nr-night-date').value;
    var bs = document.getElementById('nr-baseline-start').value;
    var be = document.getElementById('nr-baseline-end').value;
    if (!night) { alert('Pick a night (evening date).'); return null; }
    if ((bs && !be) || (be && !bs)) { alert('Provide both baseline dates, or leave both empty.'); return null; }
    var qs = 'night_date=' + night;
    if (bs && be) qs += '&baseline_start=' + bs + '&baseline_end=' + be;
    return qs;
}
function viewNightReport(projectId) {
    var qs = _nrParams(); if (!qs) return;
    window.open('/api/projects/' + projectId + '/reports/nightly/view?' + qs, '_blank');
}
function runNightReport(projectId) {
    var qs = _nrParams(); if (!qs) return;
    var st = document.getElementById('nr-status');
    st.style.color = ''; st.textContent = 'Running…';
    fetch('/api/projects/' + projectId + '/reports/nightly/run?' + qs + '&send=true', { method: 'POST' })
        .then(function (r) { return r.json().then(function (j) { return { ok: r.ok, j: j }; }); })
        .then(function (res) {
            if (!res.ok) { st.style.color = '#b00020'; st.textContent = 'Error: ' + (res.j.detail || 'run failed'); return; }
            var em = res.j.email || {};
            var emailMsg = em.sent ? 'emailed' : (em.dry_run ? 'email dry-run (SMTP not set)' : (em.error || 'email skipped'));
            st.style.color = '#1a7f37';
            st.innerHTML = 'Done — saved &amp; ' + _mergeEsc(emailMsg) + '. <a href="' + _mergeEsc(res.j.view_url) + '" target="_blank" class="underline">view</a>';
            loadRecentReports(projectId);
        })
        .catch(function (e) { st.style.color = '#b00020'; st.textContent = 'Error: ' + e; });
}
function loadRecentReports(projectId) {
    var box = document.getElementById('nr-recent');
    var cnt = document.getElementById('nr-recent-count');
    fetch('/api/projects/' + projectId + '/reports/list')
        .then(function (r) { return r.json(); })
        .then(function (j) {
            cnt.textContent = (j.count || 0) + ' generated';
            if (!j.reports || !j.reports.length) {
                box.innerHTML = '<div class="px-3 py-2 text-xs text-gray-400">None yet. Run one above.</div>';
                return;
            }
            box.innerHTML = j.reports.map(function (rp) {
                var when = (rp.generated_at || '').replace('T', ' ').slice(0, 16);
                var xlsx = rp.xlsx_url ? ' · <a href="' + _mergeEsc(rp.xlsx_url) + '" class="text-indigo-600 dark:text-indigo-400 hover:underline">Excel</a>' : '';
                return '<div class="flex items-center justify-between px-3 py-2 text-sm">'
                     + '<a href="' + _mergeEsc(rp.view_url) + '" target="_blank" class="font-medium text-gray-800 dark:text-gray-200 hover:underline">Night of ' + _mergeEsc(rp.night_date) + '</a>'
                     + '<span class="text-xs text-gray-400">' + _mergeEsc(when) + ' UTC' + xlsx + '</span></div>';
            }).join('');
        })
        .catch(function () { box.innerHTML = '<div class="px-3 py-2 text-xs text-red-500">Failed to load.</div>'; });
}
</script>

<!-- Nightly Report Settings Modal -->
<div id="report-settings-modal" class="hidden fixed inset-0 z-50 flex items-center justify-center bg-black/60 backdrop-blur-sm">
    <div class="bg-white dark:bg-slate-800 rounded-xl shadow-2xl w-full max-w-md mx-4 max-h-[90vh] overflow-y-auto">
        <div class="px-6 py-4 border-b border-gray-200 dark:border-gray-700 flex items-center justify-between">
            <h3 class="text-lg font-semibold text-gray-900 dark:text-white">Nightly Report Settings</h3>
            <button onclick="closeReportSettings()" class="text-gray-400 hover:text-gray-600 dark:hover:text-gray-200">
                <svg class="w-6 h-6" 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"></path></svg>
            </button>
        </div>
        <div class="px-6 py-5 space-y-4">
            <div id="rs-schedule-status" class="text-xs text-gray-500 dark:text-gray-400 bg-gray-50 dark:bg-gray-900/40 rounded-lg px-3 py-2"></div>
            <label class="flex items-center gap-2 text-sm font-medium text-gray-800 dark:text-gray-200">
                <input type="checkbox" id="rs-enabled" class="rounded border-gray-300 text-indigo-600 focus:ring-indigo-500">
                Email the report automatically each morning
            </label>
            <div>
                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Report time (local)</label>
                <input type="time" id="rs-report-time" class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-slate-700 text-gray-900 dark:text-white text-sm">
                <p class="text-xs text-gray-400 mt-1">Runs after this time for the night that just ended.</p>
            </div>
            <div>
                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Baseline source</label>
                <div class="flex gap-4 text-sm mb-2">
                    <label class="flex items-center gap-1.5"><input type="radio" name="rs-baseline-mode" value="captured" onchange="rsToggleBaselineMode()" class="text-indigo-600"> Captured nights</label>
                    <label class="flex items-center gap-1.5"><input type="radio" name="rs-baseline-mode" value="reference" onchange="rsToggleBaselineMode()" class="text-indigo-600"> Fixed values</label>
                </div>
                <div id="rs-baseline-captured" class="grid grid-cols-2 gap-3">
                    <div>
                        <label class="block text-xs text-gray-500 dark:text-gray-400 mb-1">Range start</label>
                        <input type="date" id="rs-baseline-start" class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-slate-700 text-gray-900 dark:text-white text-sm">
                    </div>
                    <div>
                        <label class="block text-xs text-gray-500 dark:text-gray-400 mb-1">Range end</label>
                        <input type="date" id="rs-baseline-end" class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-slate-700 text-gray-900 dark:text-white text-sm">
                    </div>
                </div>
                <div id="rs-baseline-reference" class="hidden">
                    <p class="text-xs text-gray-400 mb-2">Values to compare against (a spec limit like L10 = 85, or a prior report's averages). Blank cells aren't compared.</p>
                    <div class="flex justify-end mb-1"><button type="button" onclick="rsCopyFirstNrl()" class="text-xs text-indigo-600 dark:text-indigo-400 hover:underline">Copy first NRL → all</button></div>
                    <div id="rs-ref-grid" class="space-y-3"></div>
                </div>
            </div>
            <div>
                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Metrics</label>
                <input type="text" id="rs-metrics" placeholder="lmax,l01,l10,l90" class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-slate-700 text-gray-900 dark:text-white text-sm">
                <p class="text-xs text-gray-400 mt-1">Comma list. Options: lmax, l01, l10, l50, l90, l95, leq.</p>
            </div>
            <div>
                <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Recipients</label>
                <input type="text" id="rs-recipients" placeholder="brian@…, dad@…" class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-slate-700 text-gray-900 dark:text-white text-sm">
                <p class="text-xs text-gray-400 mt-1">Comma list. Blank → the default SMTP recipients.</p>
            </div>
            <div>
                <button type="button" onclick="sendTestEmail('{{ project.id }}')" class="text-sm text-indigo-600 dark:text-indigo-400 hover:underline">Send test email</button>
                <span id="rs-test-status" class="text-xs ml-2"></span>
            </div>
            <p id="rs-status" class="text-xs"></p>
        </div>
        <div class="px-6 py-4 border-t border-gray-200 dark:border-gray-700 flex justify-end gap-2">
            <button onclick="closeReportSettings()" class="px-4 py-2 border border-gray-300 dark:border-gray-600 text-gray-700 dark:text-gray-300 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors text-sm">Cancel</button>
            <button onclick="saveReportSettings('{{ project.id }}')" class="px-4 py-2 bg-indigo-600 text-white rounded-lg hover:bg-indigo-700 transition-colors text-sm">Save</button>
        </div>
    </div>
</div>
<script>
function openReportSettings(projectId) {
    var show = function () { document.getElementById('report-settings-modal').classList.remove('hidden'); };
    document.getElementById('rs-status').textContent = '';
    fetch('/api/projects/' + projectId + '/reports/config')
        .then(function (r) { return r.json(); })
        .then(function (c) {
            document.getElementById('rs-enabled').checked = !!c.enabled;
            document.getElementById('rs-report-time').value = c.report_time || '08:00';
            document.getElementById('rs-baseline-start').value = c.baseline_start || '';
            document.getElementById('rs-baseline-end').value = c.baseline_end || '';
            document.getElementById('rs-metrics').value = c.metric_keys || 'lmax,l01,l10,l90';
            document.getElementById('rs-recipients').value = c.recipients || '';
            var ss = document.getElementById('rs-schedule-status');
            var last = c.last_run_date || '—';
            if (c.enabled) {
                ss.innerHTML = '<span style="color:#1a7f37">●</span> Automatic — runs daily at ' + (c.report_time || '08:00') + '. Last reported night: ' + last + '.';
            } else {
                ss.innerHTML = '<span style="color:#9ca3af">●</span> Automatic sending is off. Last reported night: ' + last + '.';
            }
            document.getElementById('rs-test-status').textContent = '';
            rsSetMode(c.baseline_mode || 'captured');
            loadBaselineEditor(projectId);
            show();
        })
        .catch(show);
}
function closeReportSettings() {
    document.getElementById('report-settings-modal').classList.add('hidden');
}
function saveReportSettings(projectId) {
    var st = document.getElementById('rs-status');
    var mode = rsGetMode();
    var bs = document.getElementById('rs-baseline-start').value;
    var be = document.getElementById('rs-baseline-end').value;
    if (mode === 'captured' && ((bs && !be) || (be && !bs))) {
        st.style.color = '#b00020'; st.textContent = 'Provide both baseline dates, or neither.'; return;
    }
    var body = {
        enabled: document.getElementById('rs-enabled').checked,
        report_time: document.getElementById('rs-report-time').value || '08:00',
        metric_keys: document.getElementById('rs-metrics').value || 'lmax,l01,l10,l90',
        baseline_mode: mode,
        baseline_start: bs || null,
        baseline_end: be || null,
        recipients: document.getElementById('rs-recipients').value || ''
    };
    st.style.color = ''; st.textContent = 'Saving…';
    fetch('/api/projects/' + projectId + '/reports/config', {
        method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body)
    }).then(function (r) { return r.json().then(function (j) { return { ok: r.ok, j: j }; }); })
      .then(function (res) {
          if (!res.ok) { st.style.color = '#b00020'; st.textContent = 'Error: ' + (res.j.detail || 'save failed'); return; }
          if (mode === 'reference') {
              return fetch('/api/projects/' + projectId + '/reports/baseline', {
                  method: 'PUT', headers: { 'Content-Type': 'application/json' },
                  body: JSON.stringify({ locations: gatherRefValues() })
              }).then(function (r2) {
                  if (!r2.ok) throw new Error('baseline values failed to save');
                  st.style.color = '#1a7f37'; st.textContent = 'Saved.'; setTimeout(closeReportSettings, 700);
              });
          }
          st.style.color = '#1a7f37'; st.textContent = 'Saved.'; setTimeout(closeReportSettings, 700);
      })
      .catch(function (e) { st.style.color = '#b00020'; st.textContent = 'Error: ' + e; });
}
var RS_BASELINE = { metrics: [], windows: [], locations: [] };
function rsGetMode() {
    var r = document.querySelector('input[name="rs-baseline-mode"]:checked');
    return r ? r.value : 'captured';
}
function rsSetMode(mode) {
    document.querySelectorAll('input[name="rs-baseline-mode"]').forEach(function (el) { el.checked = (el.value === mode); });
    rsToggleBaselineMode();
}
function rsToggleBaselineMode() {
    var ref = rsGetMode() === 'reference';
    document.getElementById('rs-baseline-captured').classList.toggle('hidden', ref);
    document.getElementById('rs-baseline-reference').classList.toggle('hidden', !ref);
}
function loadBaselineEditor(projectId) {
    fetch('/api/projects/' + projectId + '/reports/baseline')
        .then(function (r) { return r.json(); })
        .then(function (d) { RS_BASELINE = d; renderRefGrid(); })
        .catch(function () {});
}
function _refId(loc, w, m) { return 'ref__' + loc + '__' + w + '__' + m; }
function renderRefGrid() {
    var box = document.getElementById('rs-ref-grid');
    if (!RS_BASELINE.locations || !RS_BASELINE.locations.length) {
        box.innerHTML = '<div class="text-xs text-gray-400">No NRLs in this project yet.</div>'; return;
    }
    var W = RS_BASELINE.windows, M = RS_BASELINE.metrics;
    box.innerHTML = RS_BASELINE.locations.map(function (loc) {
        var head = '<tr><th></th>' + W.map(function (w) {
            return '<th class="text-xs text-gray-400 font-normal pb-1 px-1">' + w.label.replace(/\s*\(.*\)/, '') + '</th>';
        }).join('') + '</tr>';
        var rows = M.map(function (m) {
            var cells = W.map(function (w) {
                var v = (loc.values[w.key] && loc.values[w.key][m.key] != null) ? loc.values[w.key][m.key] : '';
                return '<td class="px-1"><input type="number" step="0.1" id="' + _refId(loc.id, w.key, m.key) + '" value="' + _mergeEsc(v) + '" class="w-16 px-1.5 py-1 border border-gray-300 dark:border-gray-600 rounded bg-white dark:bg-slate-700 text-gray-900 dark:text-white text-sm text-center"></td>';
            }).join('');
            return '<tr><td class="text-sm text-gray-700 dark:text-gray-300 pr-2">' + m.label + '</td>' + cells + '</tr>';
        }).join('');
        return '<div class="border border-gray-200 dark:border-gray-700 rounded-lg p-2">'
             + '<div class="text-sm font-medium text-gray-800 dark:text-gray-200 mb-1">' + _mergeEsc(loc.name) + '</div>'
             + '<table class="w-full">' + head + rows + '</table></div>';
    }).join('');
}
function gatherRefValues() {
    var out = {};
    (RS_BASELINE.locations || []).forEach(function (loc) {
        var wins = {};
        RS_BASELINE.windows.forEach(function (w) {
            var mv = {};
            RS_BASELINE.metrics.forEach(function (m) {
                var el = document.getElementById(_refId(loc.id, w.key, m.key));
                if (el && el.value !== '') mv[m.key] = el.value;
            });
            if (Object.keys(mv).length) wins[w.key] = mv;
        });
        out[loc.id] = wins;
    });
    return out;
}
function rsCopyFirstNrl() {
    if (!RS_BASELINE.locations || RS_BASELINE.locations.length < 2) return;
    var first = RS_BASELINE.locations[0].id;
    RS_BASELINE.locations.slice(1).forEach(function (loc) {
        RS_BASELINE.windows.forEach(function (w) {
            RS_BASELINE.metrics.forEach(function (m) {
                var src = document.getElementById(_refId(first, w.key, m.key));
                var dst = document.getElementById(_refId(loc.id, w.key, m.key));
                if (src && dst) dst.value = src.value;
            });
        });
    });
}
function sendTestEmail(projectId) {
    var st = document.getElementById('rs-test-status');
    st.style.color = ''; st.textContent = 'Sending…';
    var recips = document.getElementById('rs-recipients').value;
    fetch('/api/projects/' + projectId + '/reports/test-email', {
        method: 'POST', headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(recips ? { recipients: recips } : {})
    }).then(function (r) { return r.json(); })
      .then(function (j) {
          if (j.sent) { st.style.color = '#1a7f37'; st.textContent = 'Sent to ' + (j.recipients || []).join(', '); }
          else if (j.dry_run) { st.style.color = '#b8860b'; st.textContent = 'Dry-run (SMTP not set) — would send to ' + (j.recipients || []).join(', '); }
          else { st.style.color = '#b00020'; st.textContent = 'Error: ' + (j.error || 'failed'); }
      })
      .catch(function (e) { st.style.color = '#b00020'; st.textContent = 'Error: ' + e; });
}
</script>

<!-- Merge Modal —
     min-h on the body ensures the typeahead dropdown has room to render
     below the input without forcing the operator to scroll inside the
     modal.  overflow-visible on the body lets the dropdown extend
     beyond the body's natural height when needed. -->
<div id="merge-modal" class="hidden fixed inset-0 z-50 flex items-center justify-center bg-black/60 backdrop-blur-sm">
    <div class="bg-white dark:bg-slate-800 rounded-xl shadow-2xl w-full max-w-2xl mx-4 max-h-[90vh] flex flex-col"
         style="min-height: 480px;">
        <!-- Header -->
        <div class="px-6 py-4 border-b border-gray-200 dark:border-gray-700 flex items-center justify-between">
            <div>
                <h3 class="text-lg font-semibold text-gray-900 dark:text-white">Merge "{{ project.name }}" into another project</h3>
                <p class="text-sm text-gray-500 dark:text-gray-400 mt-0.5">
                    Source project gets soft-deleted.  All its locations, assignments, sessions, and files move to the target.
                </p>
            </div>
            <button onclick="closeMergeModal()" class="text-gray-400 hover:text-gray-600 dark:hover:text-gray-200 shrink-0 ml-3">
                <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>

        <!-- Body -->
        <div class="px-6 py-4 overflow-y-auto flex-1 min-h-[320px]">
            <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
                Target project
            </label>
            <div class="relative">
                <input type="text"
                       id="merge-target-input"
                       placeholder="Type to search for the project to merge INTO…"
                       autocomplete="off"
                       oninput="onMergeTargetInput()"
                       onfocus="onMergeTargetInput()"
                       onblur="setTimeout(() => document.getElementById('merge-target-dropdown').classList.add('hidden'), 150)"
                       class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-slate-700 text-gray-900 dark:text-white text-sm">
                <input type="hidden" id="merge-target-id" value="">
                <div id="merge-target-dropdown"
                     class="hidden absolute z-20 left-0 right-0 mt-1 bg-white dark:bg-slate-800 border border-gray-200 dark:border-gray-700 rounded-lg shadow-lg max-h-64 overflow-y-auto"></div>
            </div>

            <!-- Preview pane -->
            <div id="merge-preview" class="mt-4 hidden">
                <h4 class="text-xs font-semibold text-gray-500 dark:text-gray-400 uppercase tracking-wider mb-2">What will move</h4>
                <div id="merge-preview-body" class="space-y-3"></div>
            </div>

            <div id="merge-error" class="hidden mt-3 text-sm text-red-600"></div>
        </div>

        <!-- Footer -->
        <div class="px-6 py-4 border-t border-gray-200 dark:border-gray-700 flex justify-end gap-2">
            <button onclick="closeMergeModal()"
                    class="px-4 py-2 border border-gray-300 dark:border-gray-600 text-gray-700 dark:text-gray-300 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-700 text-sm">
                Cancel
            </button>
            <button id="merge-confirm-btn"
                    onclick="confirmMerge()"
                    disabled
                    class="px-4 py-2 bg-red-600 hover:bg-red-700 text-white rounded-lg text-sm font-medium disabled:opacity-40 disabled:cursor-not-allowed">
                Merge (permanent)
            </button>
        </div>
    </div>
</div>

<script>
const _SOURCE_PROJECT_ID   = "{{ project.id }}";
const _SOURCE_PROJECT_NAME = {{ project.name|tojson }};

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

function openMergeModal() {
    document.getElementById('merge-target-input').value = '';
    document.getElementById('merge-target-id').value = '';
    document.getElementById('merge-preview').classList.add('hidden');
    document.getElementById('merge-error').classList.add('hidden');
    document.getElementById('merge-confirm-btn').disabled = true;
    document.getElementById('merge-modal').classList.remove('hidden');
    setTimeout(() => document.getElementById('merge-target-input').focus(), 50);
}

function closeMergeModal() {
    document.getElementById('merge-modal').classList.add('hidden');
}

let _mergeTargetDebounce = null;
async function onMergeTargetInput() {
    if (_mergeTargetDebounce) clearTimeout(_mergeTargetDebounce);
    _mergeTargetDebounce = setTimeout(_mergeFetchTargets, 150);
}

async function _mergeFetchTargets() {
    const q = document.getElementById('merge-target-input').value.trim();
    const dropdown = document.getElementById('merge-target-dropdown');

    let data;
    try {
        // Reuse the metadata-backfill projects_search endpoint — works for
        // any caller, returns existing-only (no create-new option needed here).
        const r = await fetch(`/api/admin/metadata_backfill/projects_search?q=${encodeURIComponent(q)}&limit=12`);
        if (!r.ok) throw new Error('HTTP ' + r.status);
        data = await r.json();
    } catch (e) {
        dropdown.innerHTML = `<div class="px-3 py-2 text-sm text-red-500">Search failed: ${_mergeEsc(e.message)}</div>`;
        dropdown.classList.remove('hidden');
        return;
    }

    // Filter out self.
    const candidates = (data.matches || []).filter(m => m.id !== _SOURCE_PROJECT_ID);

    if (candidates.length === 0) {
        dropdown.innerHTML = `<div class="px-3 py-2 text-sm text-gray-500 dark:text-gray-400 italic">No matches.</div>`;
        dropdown.classList.remove('hidden');
        return;
    }

    // Stash target id + name in data-* attributes (NOT inline JS args)
    // to avoid the quote-collision that breaks click binding when the
    // project name contains characters JSON.stringify quotes.  Same
    // pattern as the backfill typeahead dropdown.
    dropdown.innerHTML = candidates.map(m => {
        const scoreBadge = m.score >= 0.99
            ? '<span class="text-xs text-green-600 dark:text-green-400 ml-2">exact</span>'
            : `<span class="text-xs text-gray-500 dark:text-gray-400 ml-2">${(m.score*100).toFixed(0)}%</span>`;
        const meta = [];
        if (m.project_number) meta.push(_mergeEsc(m.project_number));
        if (m.client_name)    meta.push(_mergeEsc(m.client_name));
        if (m.location_count > 0) meta.push(`${m.location_count} location${m.location_count === 1 ? '' : 's'}`);
        const metaLine = meta.length ? `<div class="text-xs text-gray-500 dark:text-gray-400">${meta.join(' · ')}</div>` : '';
        return `<button type="button"
            data-target-id="${_mergeEsc(m.id)}"
            data-target-name="${_mergeEsc(m.name)}"
            onmousedown="event.preventDefault()"
            onclick="_mergePickFromButton(this)"
            class="w-full text-left px-3 py-2 hover:bg-gray-50 dark:hover:bg-slate-700 border-b border-gray-100 dark:border-gray-700 last:border-b-0">
            <div class="text-sm font-medium text-gray-900 dark:text-white">${_mergeEsc(m.name)}${scoreBadge}</div>
            ${metaLine}
        </button>`;
    }).join('');
    dropdown.classList.remove('hidden');
}

// Trampoline — reads the button's data attributes and forwards.  Keeps
// the inline onclick free of any string interpolation that could break
// HTML quoting (see notes on the same pattern in metadata_backfill.html).
function _mergePickFromButton(btn) {
    onMergePickTarget(btn.dataset.targetId, btn.dataset.targetName);
}

async function onMergePickTarget(targetId, targetName) {
    document.getElementById('merge-target-input').value = targetName;
    document.getElementById('merge-target-id').value = targetId;
    document.getElementById('merge-target-dropdown').classList.add('hidden');
    await _loadMergePreview(targetId);
}

async function _loadMergePreview(targetId) {
    const previewEl = document.getElementById('merge-preview');
    const bodyEl    = document.getElementById('merge-preview-body');
    const errorEl   = document.getElementById('merge-error');
    const confirmBtn = document.getElementById('merge-confirm-btn');

    previewEl.classList.add('hidden');
    errorEl.classList.add('hidden');
    confirmBtn.disabled = true;
    bodyEl.innerHTML = '<div class="text-center py-3 text-sm text-gray-500"><div class="animate-spin rounded-full h-5 w-5 border-b-2 border-seismo-orange mx-auto mb-2"></div>Loading preview…</div>';
    previewEl.classList.remove('hidden');

    let d;
    try {
        const r = await fetch(`/api/projects/${_SOURCE_PROJECT_ID}/merge_preview?target_id=${encodeURIComponent(targetId)}`);
        if (!r.ok) {
            const err = await r.json().catch(() => ({detail: 'HTTP ' + r.status}));
            throw new Error(err.detail || ('HTTP ' + r.status));
        }
        d = await r.json();
    } catch (e) {
        errorEl.textContent = e.message;
        errorEl.classList.remove('hidden');
        previewEl.classList.add('hidden');
        return;
    }

    let html = `<div class="text-sm text-gray-700 dark:text-gray-300">
        Merging <strong>"${_mergeEsc(d.source_project_name)}"</strong> into <strong>"${_mergeEsc(d.target_project_name)}"</strong>:
    </div>
    <div class="grid grid-cols-3 gap-2 mt-2">
        <div class="bg-gray-50 dark:bg-slate-900/50 rounded p-2"><div class="text-xs text-gray-500 dark:text-gray-400">Assignments</div><div class="text-lg font-bold">${d.total_assignments_moving}</div></div>
        <div class="bg-gray-50 dark:bg-slate-900/50 rounded p-2"><div class="text-xs text-gray-500 dark:text-gray-400">Sessions</div><div class="text-lg font-bold">${d.total_sessions_moving}</div></div>
        <div class="bg-gray-50 dark:bg-slate-900/50 rounded p-2"><div class="text-xs text-gray-500 dark:text-gray-400">Data files</div><div class="text-lg font-bold">${d.total_data_files_moving}</div></div>
    </div>`;

    if (d.location_plans.length > 0) {
        html += `<div class="mt-3">
            <h5 class="text-xs font-semibold text-gray-500 dark:text-gray-400 uppercase tracking-wider mb-1">Locations</h5>
            <div class="space-y-1 text-sm">`;
        for (const p of d.location_plans) {
            if (p.action === 'consolidate') {
                html += `<div class="text-gray-700 dark:text-gray-300">
                    🔀 <strong>${_mergeEsc(p.source_name)}</strong> → consolidates into existing target <strong>"${_mergeEsc(p.target_name)}"</strong>
                    <span class="text-xs text-gray-500 dark:text-gray-400 ml-1">(${p.assignments_moving} assignments + ${p.sessions_moving} sessions move)</span>
                </div>`;
            } else {
                html += `<div class="text-gray-700 dark:text-gray-300">
                    → <strong>${_mergeEsc(p.source_name)}</strong> moves to target as-is
                    <span class="text-xs text-gray-500 dark:text-gray-400 ml-1">(${p.assignments_moving} assignments + ${p.sessions_moving} sessions)</span>
                </div>`;
            }
        }
        html += '</div></div>';
    }

    if (d.modules_to_add.length > 0) {
        html += `<div class="mt-3 text-sm text-gray-700 dark:text-gray-300">
            Modules to add to target: ${d.modules_to_add.map(m => `<code class="px-1 py-0.5 rounded bg-gray-100 dark:bg-gray-700 text-xs">${_mergeEsc(m)}</code>`).join(' ')}
        </div>`;
    }

    if (d.warnings.length > 0) {
        html += '<div class="mt-3 space-y-2">';
        for (const w of d.warnings) {
            html += `<div class="bg-amber-50 dark:bg-amber-900/20 border border-amber-200 dark:border-amber-800 rounded p-2 text-xs text-amber-800 dark:text-amber-300">⚠ ${_mergeEsc(w)}</div>`;
        }
        html += '</div>';
    }

    html += `<div class="mt-3 bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded p-2 text-xs text-red-800 dark:text-red-300">
        <strong>⚠ This action is destructive.</strong>  Source project will be soft-deleted (status='deleted').
        Audit rows will be written to unit_history for every moved assignment.
    </div>`;

    bodyEl.innerHTML = html;
    confirmBtn.disabled = false;
}

async function confirmMerge() {
    const targetId = document.getElementById('merge-target-id').value;
    if (!targetId) return;
    const confirmBtn = document.getElementById('merge-confirm-btn');
    confirmBtn.disabled = true;
    confirmBtn.textContent = 'Merging…';
    try {
        const r = await fetch(`/api/projects/${_SOURCE_PROJECT_ID}/merge_into?target_id=${encodeURIComponent(targetId)}`, {
            method: 'POST',
        });
        if (!r.ok) {
            const err = await r.json().catch(() => ({detail: 'HTTP ' + r.status}));
            throw new Error(err.detail || ('HTTP ' + r.status));
        }
        const d = await r.json();
        // Redirect to the target project — source no longer exists in active state.
        window.location.href = `/projects/${d.target_project_id}`;
    } catch (e) {
        const errorEl = document.getElementById('merge-error');
        errorEl.textContent = 'Merge failed: ' + e.message;
        errorEl.classList.remove('hidden');
        confirmBtn.disabled = false;
        confirmBtn.textContent = 'Merge (permanent)';
    }
}
</script>

<!-- Add Module Modal -->
<div id="add-module-modal" class="hidden fixed inset-0 z-50 flex items-center justify-center bg-black/60 backdrop-blur-sm">
    <div class="bg-white dark:bg-slate-800 rounded-xl shadow-2xl w-full max-w-sm mx-4 p-6">
        <div class="flex items-center justify-between mb-4">
            <h3 class="text-lg font-semibold text-gray-900 dark:text-white">Add Module</h3>
            <button onclick="closeAddModuleModal()" class="text-gray-400 hover:text-gray-600 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="add-module-options" class="space-y-2">
            <!-- Populated by JS -->
        </div>
        <p id="add-module-none" class="hidden text-sm text-gray-500 dark:text-gray-400 text-center py-4">All available modules are already enabled.</p>
    </div>
</div>

<script>
const _MODULE_META = {
    sound_monitoring:     { name: "Sound Monitoring",     color: "orange", icon: "M15.536 8.464a5 5 0 010 7.072M12 6v12M9 8.464a5 5 0 000 7.072" },
    vibration_monitoring: { name: "Vibration Monitoring", color: "blue",   icon: "M22 12h-4l-3 9L9 3l-3 9H2" },
};

async function openAddModuleModal() {
    const resp = await fetch(`/api/projects/${projectId}/modules`);
    const data = await resp.json();
    const container = document.getElementById('add-module-options');
    const none = document.getElementById('add-module-none');
    container.innerHTML = '';
    if (!data.available || data.available.length === 0) {
        none.classList.remove('hidden');
    } else {
        none.classList.add('hidden');
        data.available.forEach(m => {
            const meta = _MODULE_META[m.module_type] || { name: m.module_type, color: 'gray' };
            const btn = document.createElement('button');
            btn.className = `w-full text-left px-4 py-3 rounded-lg border border-gray-200 dark:border-gray-700 hover:border-${meta.color}-400 hover:bg-${meta.color}-50 dark:hover:bg-${meta.color}-900/20 transition-colors flex items-center gap-3`;
            btn.innerHTML = `<span class="flex-1 font-medium text-gray-900 dark:text-white">${meta.name}</span>`;
            btn.onclick = () => addModule(m.module_type);
            container.appendChild(btn);
        });
    }
    document.getElementById('add-module-modal').classList.remove('hidden');
}

function closeAddModuleModal() {
    document.getElementById('add-module-modal').classList.add('hidden');
}

async function addModule(moduleType) {
    await fetch(`/api/projects/${projectId}/modules`, {
        method: 'POST',
        headers: {'Content-Type': 'application/json'},
        body: JSON.stringify({ module_type: moduleType }),
    });
    closeAddModuleModal();
    window.location.reload();
}

async function removeModule(moduleType) {
    const meta = _MODULE_META[moduleType] || { name: moduleType };
    if (!confirm(`Remove the ${meta.name} module? The data will not be deleted, but the related tabs will be hidden.`)) return;
    await fetch(`/api/projects/${projectId}/modules/${moduleType}`, { method: 'DELETE' });
    window.location.reload();
}
</script>
