{% extends 'base.html' %}
{% block title %}Snapshots VM{% endblock %}
{% block content %}
<div class="flex justify-between items-center mb-4">
    <div>
        <h2 class="text-xl font-bold text-cyber-accent">Gestion des snapshots VM</h2>
        <p class="text-xs text-gray-500 mt-1">
            Liste les snapshots existants sur les vCenters configurés. Filtre par auteur (préfixe nom = intervenant) et âge.
            La suppression est définitive — confirmation requise.
        </p>
    </div>
</div>

<style>
    .ss-row.dim { opacity: 0.4; }
    .ss-row.selected { background: rgba(245,158,11,.1); }
    .badge-age-old   { background: rgba(239,68,68,.20); color: #ef4444; border: 1px solid #ef4444; }
    .badge-age-warn  { background: rgba(245,158,11,.20); color: #f59e0b; border: 1px solid #f59e0b; }
    .badge-age-fresh { background: rgba(34,197,94,.20); color: #22c55e; border: 1px solid #22c55e; }
    .filters-card label { display: flex; align-items: center; gap: 0.5rem; }
    /* Overlay plein page pendant les actions async */
    #busy-overlay {
        position: fixed; inset: 0; z-index: 9999;
        background: rgba(10,14,23,0.75); backdrop-filter: blur(2px);
        display: none; align-items: center; justify-content: center;
        flex-direction: column; gap: 1rem;
    }
    #busy-overlay.active { display: flex; }
    .spinner {
        width: 64px; height: 64px;
        border: 4px solid rgba(245,158,11,0.2);
        border-top-color: #f59e0b;
        border-radius: 50%;
        animation: spin 0.9s linear infinite;
    }
    @keyframes spin { to { transform: rotate(360deg); } }
    #busy-text { color: #f59e0b; font-size: 1.05rem; font-weight: 600; text-shadow: 0 0 12px rgba(245,158,11,0.6); }
    #busy-sub  { color: #9ca3af; font-size: 0.85rem; }
</style>

<div id="busy-overlay">
    <div class="spinner"></div>
    <div id="busy-text">Action en cours…</div>
    <div id="busy-sub">Ne ferme pas la page, ne navigue pas ailleurs.</div>
</div>

<div class="card p-4 mb-4 filters-card">
    <div class="grid grid-cols-12 gap-3 items-end">
        <div class="col-span-3">
            <label class="text-xs text-gray-500">vCenter</label>
            <select id="f-vcenter" class="w-full">
                <option value="">— Tous les vCenters actifs —</option>
                {% for vc in vcenters %}
                <option value="{{ vc.id }}">{{ vc.name }} ({{ vc.endpoint }})</option>
                {% endfor %}
            </select>
        </div>
        <div class="col-span-3">
            <label class="text-xs text-gray-500">Intervenant</label>
            <select id="f-intervenant" class="w-full">
                {% for u in intervenants_list %}
                <option value="{{ u.username }}"{% if u.username == intervenant_default %} selected{% endif %}>{{ u.username }}{% if u.username == intervenant_default %} (toi){% endif %}{% if u.display_name and u.display_name != u.username %} — {{ u.display_name }}{% endif %}</option>
                {% endfor %}
                {% if intervenant_default and intervenant_default not in intervenants_list|map(attribute='username')|list %}
                <option value="{{ intervenant_default }}" selected>{{ intervenant_default }} (toi, hors liste)</option>
                {% endif %}
            </select>
            <p class="text-xs text-gray-500 mt-1">Users actifs (hors admins) — défaut = toi.</p>
        </div>
        <div class="col-span-3">
            <label class="text-xs text-gray-500">Âge minimum (jours)</label>
            <input type="number" id="f-min-age" value="3" min="0" class="w-full">
        </div>
        <div class="col-span-3 flex gap-2 items-end">
            <button id="btn-refresh" class="btn-action btn-pre" type="button" style="
                padding: 6px 14px; font-size: 0.8rem; font-weight: 700;
                border-radius: 6px; cursor: pointer; border: 1px solid #f59e0b;
                background: rgba(245,158,11,.18); color: #f59e0b;
                box-shadow: 0 0 8px #f59e0b; text-transform: uppercase;">
                ⟳ Charger / Rafraîchir
            </button>
            {% if can_delete %}
            <button id="btn-delete" type="button" style="
                padding: 6px 14px; font-size: 0.8rem; font-weight: 700;
                border-radius: 6px; cursor: pointer; border: 1px solid #ef4444;
                background: rgba(239,68,68,.18); color: #ef4444;
                box-shadow: 0 0 8px #ef4444; text-transform: uppercase;
                opacity: 0.5;">
                ✕ Supprimer la sélection
            </button>
            {% endif %}
        </div>
    </div>
</div>

<div id="status" class="mb-3 text-xs text-gray-400">Cliquer "Charger" pour scanner les vCenters.</div>

<div class="card overflow-hidden">
    <table class="w-full text-xs" id="snap-table">
        <thead class="text-cyber-accent border-b border-cyber-border">
            <tr>
                <th class="p-2 text-left"><input type="checkbox" id="sel-all"></th>
                <th class="p-2 text-left">vCenter</th>
                <th class="p-2 text-left">VM</th>
                <th class="p-2 text-left">Snapshot</th>
                <th class="p-2 text-left">Origine</th>
                <th class="p-2 text-left">Auteur</th>
                <th class="p-2 text-left">Créé le</th>
                <th class="p-2 text-left">Âge</th>
                <th class="p-2 text-left">Description</th>
            </tr>
        </thead>
        <tbody id="tbody"></tbody>
    </table>
</div>

<script>
(function() {
    const fVc = document.getElementById('f-vcenter');
    const fIntervenant = document.getElementById('f-intervenant');
    const fMinAge = document.getElementById('f-min-age');
    const intervenantDefault = "{{ intervenant_default|e }}";
    const btnRefresh = document.getElementById('btn-refresh');
    const btnDelete = document.getElementById('btn-delete');
    const status = document.getElementById('status');
    const tbody = document.getElementById('tbody');
    const selAll = document.getElementById('sel-all');

    let allSnaps = [];

    function escapeHTML(s) {
        return String(s||'').replace(/[&<>"']/g, c => ({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'})[c]);
    }

    function ageBadge(ageDays) {
        if (ageDays === null || ageDays === undefined) return '<span class="text-gray-500">–</span>';
        const d = Number(ageDays);
        let cls = 'badge-age-fresh';
        if (d >= 7) cls = 'badge-age-old';
        else if (d >= 3) cls = 'badge-age-warn';
        return `<span class="badge ${cls}">${d.toFixed(1)} j</span>`;
    }

    function applyFilters() {
        // Toujours: snapshots PatchCenter uniquement (origin === 'patchcenter')
        // + intervenant choisi dans le dropdown
        // + age minimum
        const intervenant = (fIntervenant.value || '').trim().toLowerCase();
        const minAge = parseFloat(fMinAge.value) || 0;
        return allSnaps.filter(s => {
            if (s.origin !== 'patchcenter') return false;
            if (intervenant && (!s.author || s.author.toLowerCase() !== intervenant)) return false;
            if (minAge > 0 && (s.age_days === null || s.age_days < minAge)) return false;
            return true;
        });
    }

    // Note: la liste des intervenants est désormais figée au pageload (cf template,
    // alimentée depuis la table users actifs hors admin). On ne la reconstruit plus
    // dynamiquement après scan vCenter — un user qui aurait fait un snapshot mais
    // serait inactif/admin ne sera pas filtrable nominativement, tant pis pour ce cas.

    function fmtDateFR(iso) {
        // ISO 8601 -> 'jj/mm/aaaa HH:MM' (heure locale du navigateur)
        if (!iso) return '–';
        try {
            const d = new Date(iso);
            if (isNaN(d.getTime())) return iso;
            const pad = n => String(n).padStart(2, '0');
            return `${pad(d.getDate())}/${pad(d.getMonth()+1)}/${d.getFullYear()} ${pad(d.getHours())}:${pad(d.getMinutes())}`;
        } catch (e) { return iso; }
    }

    function updateFilterSummary(visibleCount) {
        // Affiche combien sont cachés et la cible
        const baseStatus = status.dataset.baseMsg || '';
        const intervenant = (fIntervenant.value || '').trim();
        const minAge = parseFloat(fMinAge.value) || 0;
        const filterDesc = `intervenant=${intervenant || 'tous'}` + (minAge > 0 ? `, âge≥${minAge}j` : '');
        status.innerHTML = baseStatus + ` <span class="text-cyber-accent">→ ${visibleCount} affiché(s) (filtre : ${escapeHTML(filterDesc)})</span>`;
    }

    function render() {
        const rows = applyFilters();
        updateFilterSummary(rows.length);
        if (!rows.length) {
            const total = allSnaps.length;
            tbody.innerHTML = total === 0
                ? '<tr><td colspan="9" class="p-4 text-center text-gray-500">Aucun snapshot dans le scan. Vérifie credentials vCenter.</td></tr>'
                : `<tr><td colspan="9" class="p-4 text-center text-cyber-yellow">${total} snapshot(s) trouvé(s) mais tous filtrés. Ajuste les filtres ci-dessus.</td></tr>`;
            updateDeleteBtn();
            return;
        }
        tbody.innerHTML = rows.map((s, idx) => {
            const authorCell = s.author
                ? escapeHTML(s.author)
                : '<i class="text-gray-500">inconnu</i>';   // bypass escape pour ce litteral HTML
            let originBadge;
            if (s.origin === 'patchcenter') originBadge = '<span class="badge badge-blue">PatchCenter</span>';
            else if (s.origin === 'slpm') originBadge = '<span class="badge badge-gray">SLPM (.exe)</span>';
            else originBadge = '<span class="badge badge-orange">manuel</span>';
            return `
            <tr class="ss-row border-b border-cyber-border/30" data-idx="${allSnaps.indexOf(s)}">
                <td class="p-2"><input type="checkbox" class="row-cb"></td>
                <td class="p-2 font-mono">${escapeHTML(s.vcenter_name)}</td>
                <td class="p-2 font-mono">${escapeHTML(s.vm_name)}</td>
                <td class="p-2 font-mono">${escapeHTML(s.snap_name)}</td>
                <td class="p-2">${originBadge}</td>
                <td class="p-2">${authorCell}</td>
                <td class="p-2 font-mono text-[10px]">${escapeHTML(fmtDateFR(s.created_at))}</td>
                <td class="p-2">${ageBadge(s.age_days)}</td>
                <td class="p-2 text-gray-400">${escapeHTML(s.description || '–')}</td>
            </tr>`;
        }).join('');
        tbody.querySelectorAll('.row-cb').forEach(cb => {
            cb.addEventListener('change', () => {
                cb.closest('tr').classList.toggle('selected', cb.checked);
                updateDeleteBtn();
            });
        });
        updateDeleteBtn();
    }

    function updateDeleteBtn() {
        if (!btnDelete) return;
        const n = tbody.querySelectorAll('.row-cb:checked').length;
        btnDelete.style.opacity = n > 0 ? '1' : '0.5';
        btnDelete.textContent = n > 0 ? `✕ SUPPRIMER ${n} SNAPSHOT${n>1?'S':''}` : '✕ SUPPRIMER LA SÉLECTION';
    }

    // Overlay plein page : bloque toute interaction pendant les actions async.
    // Empêche aussi la navigation accidentelle via beforeunload.
    const overlay = document.getElementById('busy-overlay');
    const busyText = document.getElementById('busy-text');
    const busySub = document.getElementById('busy-sub');
    let busyActive = false;

    function setBusy(msg, btn, sub) {
        status.innerHTML = '<span class="text-cyber-yellow">⏳ ' + escapeHTML(msg) + '</span>';
        busyText.textContent = '⏳ ' + msg;
        busySub.textContent = sub || 'Ne ferme pas la page, ne navigue pas ailleurs.';
        overlay.classList.add('active');
        busyActive = true;
        if (btn) {
            btn.disabled = true;
            btn._origText = btn._origText || btn.textContent;
            btn.textContent = '⏳ ' + msg;
        }
    }
    function clearBusy(btn) {
        overlay.classList.remove('active');
        busyActive = false;
        if (btn && btn._origText) {
            btn.disabled = false;
            btn.textContent = btn._origText;
        }
    }
    // Avertit si l'utilisateur tente de quitter la page pendant une action
    window.addEventListener('beforeunload', (e) => {
        if (busyActive) {
            e.preventDefault();
            e.returnValue = 'Une action est en cours. Quitter maintenant peut interrompre la requête.';
            return e.returnValue;
        }
    });

    btnRefresh.addEventListener('click', async () => {
        setBusy('Recherche en cours… (peut prendre 10-30 s selon les vCenters)', btnRefresh);
        try {
            const fd = new FormData();
            if (fVc.value) fd.append('vcenter_id', fVc.value);
            const r = await fetch('/snapshots/list', {method: 'POST', credentials: 'same-origin', body: fd});
            const j = await r.json();
            if (!j.ok) {
                status.innerHTML = '<span class="text-cyber-red">Erreur : ' + escapeHTML(j.msg || 'inconnue') + '</span>';
                return;
            }
            allSnaps = j.snapshots || [];
            const errs = (j.errors || []).map(e => `${e.vcenter}: ${e.msg}`).join(' · ');
            const pcCount = allSnaps.filter(s => s.origin === 'patchcenter').length;
            const baseMsg = `${j.snap_count} snapshot(s) trouvé(s) sur ${j.vcenter_count} vCenter(s) (dont ${pcCount} PatchCenter).` +
                            (errs ? ` <span class="text-cyber-yellow">⚠ ${escapeHTML(errs)}</span>` : '');
            status.dataset.baseMsg = baseMsg;
            status.innerHTML = baseMsg;
            render();
        } catch (e) {
            status.innerHTML = '<span class="text-cyber-red">Erreur réseau : ' + escapeHTML(String(e)) + '</span>';
        } finally {
            clearBusy(btnRefresh);
        }
    });

    [fIntervenant, fMinAge].forEach(el => el.addEventListener('input', render));
    fIntervenant.addEventListener('change', render);

    selAll.addEventListener('change', () => {
        tbody.querySelectorAll('.row-cb').forEach(cb => {
            cb.checked = selAll.checked;
            cb.closest('tr').classList.toggle('selected', cb.checked);
        });
        updateDeleteBtn();
    });

    if (btnDelete) btnDelete.addEventListener('click', async () => {
        const checked = Array.from(tbody.querySelectorAll('.row-cb:checked'));
        if (!checked.length) { alert('Sélectionne au moins un snapshot.'); return; }
        const items = checked.map(cb => {
            const idx = parseInt(cb.closest('tr').dataset.idx, 10);
            const s = allSnaps[idx];
            return {
                vcenter_id: s.vcenter_id, vm_moid: s.vm_moid, snap_id: s.snap_id,
                vm_name: s.vm_name, snap_name: s.snap_name,
            };
        });
        const lines = items.slice(0, 15).map(i => `  • ${i.vm_name} → ${i.snap_name}`).join('\n');
        const more = items.length > 15 ? `\n  … et ${items.length - 15} autre(s)` : '';
        if (!confirm(`⚠ Supprimer ${items.length} snapshot(s) ? Cette action est DÉFINITIVE.\n\n${lines}${more}`)) return;
        if (!confirm(`Confirme une 2e fois : suppression définitive de ${items.length} snapshot(s)`)) return;

        setBusy(`Suppression en cours… (${items.length} snapshot(s))`, btnDelete);
        try {
            const r = await fetch('/snapshots/delete', {
                method: 'POST', credentials: 'same-origin',
                headers: {'Content-Type':'application/json'},
                body: JSON.stringify({items}),
            });
            const j = await r.json();
            const okCount = (j.results || []).filter(x => x.ok).length;
            const failed = (j.results || []).filter(x => !x.ok);
            let msg = `${okCount}/${items.length} supprimés.`;
            if (failed.length) {
                msg += '\n\nÉchecs :\n' + failed.slice(0,10).map(f => `  ${f.vm_name} → ${f.snap_name}: ${f.msg}`).join('\n');
            }
            alert(msg);
            clearBusy(btnDelete);
            // Re-scanne pour refleter l'etat reel cote vCenter
            btnRefresh.click();
        } catch (e) {
            alert('Erreur réseau : ' + e);
            clearBusy(btnDelete);
        }
    });
})();
</script>
{% endblock %}
