{% extends 'base.html' %}
{% block title %}Importer planning patching{% endblock %}
{% block content %}
<div class="flex justify-between items-center mb-4">
    <div>
        <h2 class="text-xl font-bold text-cyber-accent">Importer planning de patching</h2>
        <p class="text-xs text-gray-500 mt-1">
            Upload du fichier Excel "Plan de Patching serveurs YYYY". Une feuille = une semaine (S02..S52).
            Les onglets historiques (Histo-XXXX) sont ignorés.
        </p>
    </div>
    {% if current_import %}
        <a href="/patching/import" class="btn-sm bg-cyber-border text-cyber-accent px-4 py-2">← Liste imports</a>
    {% endif %}
</div>

{% if msg == 'ok' %}<div class="bg-cyber-green/20 text-cyber-green p-2 mb-3 text-xs rounded">Import réussi.</div>{% endif %}
{% if msg == 'deleted' %}<div class="bg-cyber-blue/20 text-cyber-blue p-2 mb-3 text-xs rounded">Import supprimé.</div>{% endif %}
{% if err == 'ext' %}<div class="bg-cyber-red/20 text-cyber-red p-2 mb-3 text-xs rounded">Le fichier doit être un .xlsx.</div>{% endif %}
{% if err == 'parse' %}<div class="bg-cyber-red/20 text-cyber-red p-2 mb-3 text-xs rounded">Impossible de parser le fichier.</div>{% endif %}
{% if err == 'denied' %}<div class="bg-cyber-red/20 text-cyber-red p-2 mb-3 text-xs rounded">Permission refusée.</div>{% endif %}
{% if err == 'notfound' %}<div class="bg-cyber-red/20 text-cyber-red p-2 mb-3 text-xs rounded">Import introuvable.</div>{% endif %}
{% if err == 'openpyxl_missing' %}<div class="bg-cyber-red/20 text-cyber-red p-2 mb-3 text-xs rounded">Lib openpyxl manquante côté serveur.</div>{% endif %}

{# ──────────── Upload form ──────────── #}
{% if can_import %}
<div class="card p-4 mb-4">
    <h3 class="text-sm font-bold text-cyber-accent mb-2">Nouvel import</h3>
    <form method="POST" action="/patching/import/upload" enctype="multipart/form-data" class="flex flex-wrap gap-2 items-center">
        <input type="file" name="file" accept=".xlsx" required class="text-xs">
        <input type="text" name="note" placeholder="Note (optionnelle)" class="text-xs px-2 py-1 flex-1 min-w-[200px]">
        <button type="submit" class="btn-primary px-3 py-1 text-xs">Importer</button>
    </form>
</div>
{% endif %}

{# ──────────── Liste des imports ──────────── #}
<div class="card p-3 mb-4">
    <h3 class="text-sm font-bold text-cyber-accent mb-2">Imports récents ({{ imports|length }})</h3>
    {% if imports %}
    <table class="w-full text-xs">
        <thead class="text-cyber-accent border-b border-cyber-border">
            <tr>
                <th class="text-left p-1">ID</th>
                <th class="text-left p-1">Fichier</th>
                <th class="text-left p-1">Année</th>
                <th class="text-right p-1">Feuilles</th>
                <th class="text-right p-1">Lignes</th>
                <th class="text-left p-1">Date</th>
                <th class="text-left p-1">Par</th>
                <th class="text-right p-1">Actions</th>
            </tr>
        </thead>
        <tbody>
            {% for i in imports %}
            <tr class="border-b border-cyber-border/30 {% if current_import and current_import.id == i.id %}bg-cyber-border/30{% endif %}">
                <td class="p-1">#{{ i.id }}</td>
                <td class="p-1"><a href="/patching/import/{{ i.id }}" class="text-cyber-accent hover:underline">{{ i.filename }}</a></td>
                <td class="p-1">{{ i.year or '–' }}</td>
                <td class="p-1 text-right">{{ i.sheet_count }}</td>
                <td class="p-1 text-right">{{ i.row_count }}</td>
                <td class="p-1">{{ i.uploaded_at.strftime('%Y-%m-%d %H:%M') }}</td>
                <td class="p-1">{{ i.uploaded_by_name or '–' }}</td>
                <td class="p-1 text-right">
                    <a href="/patching/import/{{ i.id }}" class="text-cyber-blue hover:underline">Voir</a>
                    {% if can_import %}
                    · <form method="POST" action="/patching/import/{{ i.id }}/delete" class="inline" onsubmit="return confirm('Supprimer cet import ?')">
                        <button type="submit" class="text-cyber-red hover:underline">Suppr</button>
                    </form>
                    {% endif %}
                </td>
            </tr>
            {% endfor %}
        </tbody>
    </table>
    {% else %}
        <p class="text-xs text-gray-500">Aucun import pour le moment.</p>
    {% endif %}
</div>

{# ──────────── Détail de l'import courant ──────────── #}
{% if current_import %}
<div class="card p-4 mb-4">
    <div class="flex justify-between items-start mb-3">
        <div>
            <h3 class="text-sm font-bold text-cyber-accent">Import #{{ current_import.id }} : {{ current_import.filename }}</h3>
            <p class="text-xs text-gray-500 mt-1">
                {{ current_import.sheet_count }} feuilles · {{ current_import.row_count }} lignes ·
                {{ current_import.uploaded_at.strftime('%Y-%m-%d %H:%M') }}
                {% if current_import.note %} · <em>{{ current_import.note }}</em>{% endif %}
            </p>
        </div>
    </div>

    {# Sélecteur de semaine #}
    <div class="flex gap-2 items-center mb-3 flex-wrap">
        <label class="text-xs text-gray-400">Semaine :</label>
        <select id="sheet-select" class="text-xs px-2 py-1">
            <option value="">— Choisir —</option>
            {% for s in sheets %}
            <option value="{{ s.sheet_name }}">{{ s.sheet_name }} (S{{ '%02d' % s.week_number }}) — {{ s.nb }} serveur(s)</option>
            {% endfor %}
        </select>
        <span id="sheet-summary" class="text-xs text-gray-500"></span>
    </div>

    {# Tableau dynamique #}
    <div id="sheet-table-wrap" class="overflow-x-auto" style="display:none;">
        {# Filtres client-side #}
        <div class="flex gap-2 items-center mb-2 flex-wrap">
            <select id="filter-intervenant" class="text-xs px-2 py-1">
                <option value="">— Tous intervenants —</option>
            </select>
            <select id="filter-env" class="text-xs px-2 py-1">
                <option value="">— Tous environnements —</option>
            </select>
            <button id="filter-reset" class="text-xs text-gray-500 hover:text-cyber-accent">Reset</button>
            <span class="text-xs text-gray-400" id="filter-count"></span>
        </div>
        <div class="flex gap-2 items-center mb-2 flex-wrap">
            <label class="text-xs">
                <input type="checkbox" id="select-all" class="mr-1"> Tout sélectionner (visibles)
            </label>
            <span class="text-xs text-gray-400" id="selection-count">0 sélectionné(s)</span>
            <div class="flex-1"></div>
            {% if can_import %}
            <button id="btn-add-eligible" class="btn-sm bg-cyber-green/20 text-cyber-green px-3 py-1 text-xs" disabled title="Marque les lignes comme éligibles au patching">
                + Ajouter au patching
            </button>
            <button id="btn-report" class="btn-sm bg-cyber-blue/20 text-cyber-blue px-3 py-1 text-xs" disabled title="Reporter à une autre semaine">
                ⤳ Reporter
            </button>
            <button id="btn-unset" class="btn-sm bg-cyber-border text-gray-400 px-3 py-1 text-xs" disabled title="Annuler éligibilité / report">
                Annuler
            </button>
            {% endif %}
            <button id="btn-prepatch" class="btn-sm bg-cyber-yellow/20 text-cyber-yellow px-3 py-1 text-xs" disabled title="Lancer le pré-patching (rows éligibles uniquement)">
                Pré-patching →
            </button>
        </div>
        <table class="w-full text-xs" id="sheet-table">
            <thead class="text-cyber-accent border-b border-cyber-border">
                <tr>
                    <th class="text-left p-1 w-6"><input type="checkbox" id="select-all-head"></th>
                    <th class="text-left p-1">État</th>
                    <th class="text-left p-1 cursor-pointer select-none hover:text-cyber-accent" id="th-asset" title="Cliquer pour trier">
                        Asset <span id="th-asset-arrow" class="text-[10px] opacity-50">↕</span>
                    </th>
                    <th class="text-left p-1">Env</th>
                    <th class="text-left p-1">Domaine</th>
                    <th class="text-left p-1">OS</th>
                    <th class="text-left p-1">Version OS</th>
                    <th class="text-left p-1">Application</th>
                    <th class="text-left p-1">Intervenant</th>
                    <th class="text-left p-1">Valideur RA</th>
                    <th class="text-left p-1">Resp. Domaine DTS</th>
                    <th class="text-left p-1">Référent tech.</th>
                    <th class="text-left p-1 cursor-pointer select-none hover:text-cyber-accent" id="th-date" title="Cliquer pour trier par date+heure">
                        Date <span id="th-date-arrow" class="text-[10px] opacity-50">↕</span>
                    </th>
                    <th class="text-left p-1">Heure</th>
                </tr>
            </thead>
            <tbody id="sheet-table-body"></tbody>
        </table>
    </div>
    <div id="sheet-empty" class="text-xs text-gray-500" style="display:none;">Aucune ligne pour cette feuille.</div>
</div>

<script>
(function(){
    const importId = {{ current_import.id }};
    const sel = document.getElementById('sheet-select');
    const wrap = document.getElementById('sheet-table-wrap');
    const empty = document.getElementById('sheet-empty');
    const tbody = document.getElementById('sheet-table-body');
    const summary = document.getElementById('sheet-summary');
    const selAll = document.getElementById('select-all');
    const selAllHead = document.getElementById('select-all-head');
    const selCount = document.getElementById('selection-count');
    const btnPre = document.getElementById('btn-prepatch');
    const btnAddElig = document.getElementById('btn-add-eligible');
    const btnReport = document.getElementById('btn-report');
    const btnUnset = document.getElementById('btn-unset');
    const fInter = document.getElementById('filter-intervenant');
    const fEnv = document.getElementById('filter-env');
    const fReset = document.getElementById('filter-reset');
    const fCount = document.getElementById('filter-count');
    const thAsset = document.getElementById('th-asset');
    const thAssetArrow = document.getElementById('th-asset-arrow');
    const thDate = document.getElementById('th-date');
    const thDateArrow = document.getElementById('th-date-arrow');

    let currentRows = [];
    // sortKey ∈ {null, 'asset', 'date'} ; sortDir ∈ {1 asc, -1 desc}
    let sortKey = null;
    let sortDir = 1;

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

    function dateFR(iso){
        // 'YYYY-MM-DD' -> 'DD/MM/YYYY'
        if (!iso) return '';
        const m = String(iso).match(/^(\d{4})-(\d{2})-(\d{2})/);
        return m ? (m[3] + '/' + m[2] + '/' + m[1]) : iso;
    }

    function shortOSVersion(v){
        if (!v) return '';
        const s = String(v);
        let m = s.match(/red\s*hat[^0-9]+(\d+)/i);
        if (m) return 'RedHat ' + m[1];
        m = s.match(/centos[^0-9]+(\d+)/i);
        if (m) return 'CentOS ' + m[1];
        m = s.match(/oracle\s*linux[^0-9]+(\d+)/i);
        if (m) return 'Oracle ' + m[1];
        m = s.match(/ubuntu[^0-9]+(\d+(?:\.\d+)?)/i);
        if (m) return 'Ubuntu ' + m[1];
        m = s.match(/debian[^0-9]+(\d+)/i);
        if (m) return 'Debian ' + m[1];
        m = s.match(/windows\s*server\s*(\d{4})/i);
        if (m) return 'Win ' + m[1];
        m = s.match(/windows\s*(\d+)/i);
        if (m) return 'Win ' + m[1];
        // Fallback : 30 premiers chars
        return s.length > 30 ? s.slice(0, 30) + '…' : s;
    }

    function refreshSelection(){
        const visible = tbody.querySelectorAll('tr:not(.row-hidden)');
        const visibleCb = tbody.querySelectorAll('tr:not(.row-hidden) input.row-cb');
        const checkedCb = Array.from(tbody.querySelectorAll('input.row-cb:checked'));
        const checked = checkedCb.length;
        const eligibleSelected = checkedCb.filter(cb => cb.dataset.eligible === '1').length;
        selCount.textContent = checked + ' sélectionné(s) · ' + visible.length + ' visible(s)' + (eligibleSelected ? ' · ' + eligibleSelected + ' éligible(s)' : '');
        const allVisibleChecked = visibleCb.length > 0 && Array.from(visibleCb).every(cb => cb.checked);
        selAll.checked = allVisibleChecked;
        selAllHead.checked = allVisibleChecked;
        const hasSel = checked > 0;
        if (btnAddElig) btnAddElig.disabled = !hasSel;
        if (btnReport) btnReport.disabled = !hasSel;
        if (btnUnset) btnUnset.disabled = !hasSel;
        // Pré-patching : actif uniquement si au moins 1 row éligible sélectionnée
        btnPre.disabled = eligibleSelected === 0;
    }

    function getSelectedRowIds(){
        return Array.from(tbody.querySelectorAll('input.row-cb:checked')).map(cb => parseInt(cb.dataset.id, 10)).filter(x => x);
    }

    async function postAction(payload){
        const r = await fetch('/patching/import/' + importId + '/rows/action', {
            method: 'POST', headers: {'Content-Type':'application/json'},
            body: JSON.stringify(payload),
        });
        const j = await r.json();
        if (!j.ok) { alert('Erreur : ' + (j.msg || 'inconnue')); return false; }
        return true;
    }

    async function reloadCurrentSheet(){
        if (sel.value) await loadSheet(sel.value);
    }

    function applyFilters(){
        const fi = (fInter.value || '').trim();
        const fe = (fEnv.value || '').trim();
        let visibleCount = 0;
        tbody.querySelectorAll('tr').forEach(tr => {
            const i = tr.dataset.intervenant || '';
            const e = tr.dataset.env || '';
            const ok = (!fi || i === fi) && (!fe || e === fe);
            if (ok) { tr.classList.remove('row-hidden'); tr.style.display=''; visibleCount++; }
            else    { tr.classList.add('row-hidden'); tr.style.display='none'; }
        });
        fCount.textContent = visibleCount + ' / ' + currentRows.length + ' affichées';
        refreshSelection();
    }

    function rebuildSelectOptions(sel, values, placeholder){
        const cur = sel.value;
        const opts = Array.from(new Set(values.filter(x => x))).sort((a,b) => a.localeCompare(b, 'fr', {sensitivity:'base'}));
        sel.innerHTML = '<option value="">' + placeholder + '</option>'
            + opts.map(v => '<option value="' + escapeHTML(v) + '"' + (cur === v ? ' selected' : '') + '>' + escapeHTML(v) + '</option>').join('');
    }

    function updateSortArrow(){
        const arrow = sortDir === 1 ? '▲' : '▼';
        thAssetArrow.textContent = sortKey === 'asset' ? arrow : '↕';
        thAssetArrow.classList.toggle('opacity-50', sortKey !== 'asset');
        thDateArrow.textContent = sortKey === 'date' ? arrow : '↕';
        thDateArrow.classList.toggle('opacity-50', sortKey !== 'date');
    }

    function cycleSort(key){
        if (sortKey !== key) { sortKey = key; sortDir = 1; }
        else if (sortDir === 1) { sortDir = -1; }
        else { sortKey = null; sortDir = 1; }
    }

    async function loadSheet(name){
        if (!name) { wrap.style.display='none'; empty.style.display='none'; return; }
        summary.textContent = 'Chargement…';
        const r = await fetch('/patching/import/' + importId + '/sheet/' + encodeURIComponent(name));
        const j = await r.json();
        if (!j.ok) { summary.textContent = j.msg || 'Erreur'; return; }
        if (!j.rows.length) {
            wrap.style.display='none'; empty.style.display=''; summary.textContent='';
            return;
        }
        empty.style.display='none'; wrap.style.display='';
        summary.textContent = j.count + ' lignes';
        currentRows = j.rows;
        rebuildSelectOptions(fInter, currentRows.map(r => r.intervenant), '— Tous intervenants —');
        rebuildSelectOptions(fEnv, currentRows.map(r => r.environnement), '— Tous environnements —');
        sortKey = null; sortDir = 1;
        updateSortArrow();
        renderTable();
    }

    function renderTable(){
        let rows = currentRows.slice();
        if (sortKey === 'asset') {
            rows.sort((a, b) => {
                const av = (a.asset_name || '').toLowerCase();
                const bv = (b.asset_name || '').toLowerCase();
                if (av < bv) return -sortDir;
                if (av > bv) return sortDir;
                return 0;
            });
        } else if (sortKey === 'date') {
            rows.sort((a, b) => {
                // Lignes sans start_iso (date texte libre) en fin
                const av = a.start_iso || '';
                const bv = b.start_iso || '';
                if (!av && !bv) return 0;
                if (!av) return 1;
                if (!bv) return -1;
                if (av < bv) return -sortDir;
                if (av > bv) return sortDir;
                return 0;
            });
        }
        tbody.innerHTML = rows.map(r => {
            const display = escapeHTML(r.resolved_hostname || r.asset_name || '');
            const assetCell = r.server_id
              ? '<a href="/servers?search=' + encodeURIComponent(r.resolved_hostname || r.asset_name) + '" target="_blank" rel="noopener" class="text-cyber-blue hover:underline">' + display + '</a>'
              : '<span class="text-cyber-yellow" title="Pas matché en base PatchCenter">' + escapeHTML(r.asset_name || '') + ' ⚠</span>';
            let badge = '';
            if (r.is_eligible) {
                badge = '<span class="text-cyber-green" title="Éligible au patching">✓ ÉLIG.</span>';
            } else if (r.reported_to_sheet) {
                const t = r.report_reason ? ('Reporté → ' + r.reported_to_sheet + ' : ' + r.report_reason) : ('Reporté → ' + r.reported_to_sheet);
                badge = '<span class="text-cyber-blue" title="' + escapeHTML(t) + '">⤳ ' + escapeHTML(r.reported_to_sheet) + '</span>';
            }
            return '<tr class="border-b border-cyber-border/20 hover:bg-cyber-border/10"'
                + ' data-asset="' + escapeHTML(r.asset_name||'') + '"'
                + ' data-intervenant="' + escapeHTML(r.intervenant||'') + '"'
                + ' data-env="' + escapeHTML(r.environnement||'') + '">'
                + '<td class="p-1"><input type="checkbox" class="row-cb" data-id="' + r.id + '" data-asset="' + escapeHTML(r.asset_name||'') + '" data-server-id="' + (r.server_id||'') + '" data-eligible="' + (r.is_eligible ? '1':'0') + '"></td>'
                + '<td class="p-1 text-[10px]">' + badge + '</td>'
                + '<td class="p-1 font-mono">' + assetCell + '</td>'
                + '<td class="p-1">' + escapeHTML(r.environnement||'') + '</td>'
                + '<td class="p-1">' + escapeHTML(r.domaine||'') + '</td>'
                + '<td class="p-1">' + escapeHTML(r.os||'') + '</td>'
                + '<td class="p-1" title="' + escapeHTML(r.os_version||'') + '">' + escapeHTML(shortOSVersion(r.os_version)) + '</td>'
                + '<td class="p-1">' + escapeHTML(r.application_name||'') + '</td>'
                + '<td class="p-1">' + escapeHTML(r.intervenant||'') + '</td>'
                + '<td class="p-1">' + escapeHTML(r.valideur_ra||'') + '</td>'
                + '<td class="p-1">' + escapeHTML(r.responsable_domaine_dts||'') + '</td>'
                + '<td class="p-1">' + escapeHTML(r.referent_technique||'') + '</td>'
                + '<td class="p-1">' + (r.jour ? escapeHTML(dateFR(r.jour)) : (r.jour_text ? '<span class="text-cyber-yellow" title="Texte libre">' + escapeHTML(r.jour_text) + '</span>' : '')) + '</td>'
                + '<td class="p-1">' + escapeHTML(r.heure||'') + '</td>'
                + '</tr>';
        }).join('');
        tbody.querySelectorAll('input.row-cb').forEach(cb => cb.addEventListener('change', refreshSelection));
        applyFilters();
    }

    sel.addEventListener('change', () => loadSheet(sel.value));
    function toggleAll(state){
        tbody.querySelectorAll('tr:not(.row-hidden) input.row-cb').forEach(cb => cb.checked = state);
        refreshSelection();
    }
    selAll.addEventListener('change', () => toggleAll(selAll.checked));
    selAllHead.addEventListener('change', () => toggleAll(selAllHead.checked));

    [fInter, fEnv].forEach(el => el.addEventListener('change', applyFilters));
    fReset.addEventListener('click', () => {
        fInter.value = ''; fEnv.value = '';
        sortKey = null; sortDir = 1;
        updateSortArrow();
        renderTable();
    });
    thAsset.addEventListener('click', () => { cycleSort('asset'); updateSortArrow(); renderTable(); });
    thDate.addEventListener('click', () => { cycleSort('date'); updateSortArrow(); renderTable(); });

    if (btnAddElig) btnAddElig.addEventListener('click', async () => {
        const ids = getSelectedRowIds();
        if (!ids.length) return;
        if (!confirm('Marquer ' + ids.length + ' ligne(s) comme éligibles au patching ?')) return;
        if (await postAction({row_ids: ids, action: 'eligible'})) await reloadCurrentSheet();
    });
    if (btnReport) btnReport.addEventListener('click', async () => {
        const ids = getSelectedRowIds();
        if (!ids.length) return;
        const target = (prompt('Reporter vers quelle semaine ? (ex: S23)') || '').trim();
        if (!target) return;
        if (!/^S\d{1,2}$/i.test(target)) { alert('Format attendu : Sxx (ex S23)'); return; }
        const reason = (prompt('Raison du report (optionnel) :') || '').trim();
        if (await postAction({row_ids: ids, action: 'report', target_sheet: target.toUpperCase(), reason})) await reloadCurrentSheet();
    });
    if (btnUnset) btnUnset.addEventListener('click', async () => {
        const ids = getSelectedRowIds();
        if (!ids.length) return;
        if (!confirm('Annuler éligibilité ET report sur ' + ids.length + ' ligne(s) ?')) return;
        if (await postAction({row_ids: ids, action: 'unset_eligible'})) {
            await postAction({row_ids: ids, action: 'unset_report'});
            await reloadCurrentSheet();
        }
    });
    btnPre.addEventListener('click', () => {
        const ids = Array.from(tbody.querySelectorAll('input.row-cb:checked'))
            .filter(cb => cb.dataset.eligible === '1')
            .map(cb => cb.dataset.id);
        if (!ids.length) { alert('Aucune ligne éligible sélectionnée.'); return; }
        // Étape B : workflow iexec à brancher
        window.location.href = '/patching/iexec?row_ids=' + ids.join(',');
    });
})();
</script>
{% endif %}
{% endblock %}
