/**
 * Fichier  : assets/js/pages/alerts.js
 * Auteur   : KREMER Régis
 * Version  : 2.4.0
 * Date     : 2026-03-01
 * Description : JS — Page alertes — modal unifié Min+Max, tableau groupé par produit
 *
 * Changelog :
 *   v2.1.0 — Version initiale
 *   v2.2.0 — Permissions magasins
 *   v2.3.15 — Filtres Catégorie + Statut, tri colonnes
 *   v2.4.0 — Modal unifié Min+Max (1 seule manip), tableau groupé Produit+Magasin
 */

// ================================================================
// alerts.js — Alert rules CRUD, tableau groupé, modal unifié
// ================================================================

const AltPage = {

    whs:    [],
    prods:  [],
    cats:   [],
    alerts: [],
    _lastFiltered: [], // groupes pour le tableau

    // ══════════════════════════════════════════════════════════════
    // INIT
    // ══════════════════════════════════════════════════════════════
    async init(){
        const [whs, prods, cats] = await Promise.all([
            Api.warehouses(),
            Api.products(),
            Api.categories()
        ]);
        this.whs   = whs   || [];
        this.prods = prods || [];
        this.cats  = cats  || [];

        // Filtre Magasin
        const whF = document.getElementById('alertWhFilter');
        if(whF){
            whF.innerHTML = '<option value="">Tous les magasins</option>' +
                whs.map(w => `<option value="${w.id}">${w.name}</option>`).join('');
            whF.onchange = () => { this._updateCatFilter(whF.value); this.load(); };
        }

        this._updateCatFilter('');
        const catF = document.getElementById('alertCatFilter');
        if(catF) catF.onchange = () => this.load();

        const stF = document.getElementById('alertStatusFilter');
        if(stF) stF.onchange = () => this.load();

        document.getElementById('alertSearch')?.addEventListener('input', () => this.load());
        document.getElementById('btnNewAlert').onclick = () => this.openModal();

        await this.load();

        // Tri colonnes — opère sur les groupes
        if(typeof TableSort !== 'undefined'){
            TableSort.init('alertTable',
                () => this._lastFiltered || [],
                sorted => { this._lastFiltered = sorted; this.renderTable(sorted); },
                {
                    defaultKey: '__warehouse',
                    defaultDir: 'asc',
                    getters: {
                        __warehouse: g => (this.whs.find(w  => String(w.id)  === String(g.warehouseId)) || {}).name || '',
                        __product:   g => (this.prods.find(p => String(p.id) === String(g.productId))   || {}).name || '',
                        __sku:       g => (this.prods.find(p => String(p.id) === String(g.productId))   || {}).sku  || '',
                        __minThr:    g => g.min ? g.min.threshold : -Infinity,
                        __maxThr:    g => g.max ? g.max.threshold :  Infinity,
                        __status:    g => ((g.min?.triggered ? 1 : 0) + (g.max?.triggered ? 1 : 0)) > 0 ? 0 : 1,
                    }
                }
            );
        }
    },

    // ══════════════════════════════════════════════════════════════
    // CHARGEMENT + GROUPEMENT
    // ══════════════════════════════════════════════════════════════
    async load(){
        const wid  = document.getElementById('alertWhFilter')?.value   || '';
        const cat  = document.getElementById('alertCatFilter')?.value  || '';
        const stat = document.getElementById('alertStatusFilter')?.value || '';
        const q    = (document.getElementById('alertSearch')?.value    || '').toLowerCase();

        try {
            const alerts = await Api.alerts(wid);
            this.alerts  = alerts;

            // ── KPI (inchangé — basé sur les alertes individuelles) ──
            const triggered = alerts.filter(a => a.triggered);
            const critical  = triggered.filter(a => a.type === 'min');
            const warnings  = triggered.filter(a => a.type === 'max');
            const ok        = alerts.filter(a => !a.triggered);

            const cEl = document.getElementById('alertCriticalCount');
            const wEl = document.getElementById('alertWarningCount');
            const oEl = document.getElementById('alertOkCount');
            if(cEl) cEl.textContent = critical.length;
            if(wEl) wEl.textContent = warnings.length;
            if(oEl) oEl.textContent = ok.length;

            // ── Statut actuel (inchangé) ──
            const statusList = document.getElementById('alertStatusList');
            if(statusList){
                if(!triggered.length){
                    statusList.innerHTML = '<div style="padding:18px;color:var(--green);display:flex;align-items:center;gap:8px"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M22 11.08V12a10 10 0 11-5.93-9.14"/><polyline points="22 4 12 14.01 9 11.01"/></svg> Aucune alerte active — tout est en ordre</div>';
                } else {
                    statusList.innerHTML = triggered.map(a => {
                        const p = this.prods.find(x => String(x.id) === String(a.productId));
                        const w = this.whs.find(x  => String(x.id) === String(a.warehouseId));
                        const isMin = a.type === 'min';
                        return `<div style="display:flex;align-items:center;gap:12px;padding:12px;border-bottom:1px solid var(--border)">
                            <span class="badge ${isMin ? 'badge-red' : 'badge-orange'}">${isMin ? '⬇ MIN' : '⬆ MAX'}</span>
                            <div style="flex:1"><strong>${p ? p.name : '?'}</strong>
                                <span style="color:var(--text-muted);margin-left:8px">${w ? w.name : ''}</span></div>
                            <div style="text-align:right">
                                <span style="font-size:18px;font-weight:700;color:${isMin ? 'var(--red)' : 'var(--orange)'}">${a.currentQty}</span>
                                <span style="color:var(--text-muted)"> / ${a.threshold}</span>
                            </div></div>`;
                    }).join('');
                }
            }

            // ── Groupement par produit+magasin ──
            const map = {};
            for(const a of alerts){
                const key = `${a.productId}_${a.warehouseId}`;
                if(!map[key]) map[key] = { productId: a.productId, warehouseId: a.warehouseId, min: null, max: null };
                if(a.type === 'min') map[key].min = a;
                if(a.type === 'max') map[key].max = a;
            }
            let groups = Object.values(map);

            // Filtres
            if(q) groups = groups.filter(g => {
                const p = this.prods.find(x => String(x.id) === String(g.productId));
                return (p && (p.name||'').toLowerCase().includes(q)) ||
                       (p && (p.sku ||'').toLowerCase().includes(q));
            });
            if(cat) groups = groups.filter(g => {
                const p = this.prods.find(x => String(x.id) === String(g.productId));
                return p && p.category === cat;
            });
            if(stat === 'triggered') groups = groups.filter(g => g.min?.triggered || g.max?.triggered);
            if(stat === 'ok')        groups = groups.filter(g => !g.min?.triggered && !g.max?.triggered);

            // Tri actif
            if(typeof TableSort !== 'undefined'){
                groups = TableSort.sortData('alertTable', groups);
            }

            this._lastFiltered = groups;
            this.renderTable(groups);

        } catch(e){
            toast(e.message, 'error');
        }
    },

    // ══════════════════════════════════════════════════════════════
    // TABLEAU GROUPÉ — 1 ligne = 1 produit dans 1 magasin
    // Colonnes : Magasin | Produit | SKU | Seuil Min | Seuil Max | Qté | Statut | Actions
    // ══════════════════════════════════════════════════════════════
    renderTable(groups){
        const tbody = document.getElementById('alertBody');
        if(!tbody) return;

        if(!groups.length){
            tbody.innerHTML = '<tr><td colspan="8" class="tbl-empty">Aucune règle d\'alerte</td></tr>';
            return;
        }

        tbody.innerHTML = groups.map(g => {
            const p   = this.prods.find(x => String(x.id) === String(g.productId));
            const w   = this.whs.find(x  => String(x.id) === String(g.warehouseId));
            const qty = g.min?.currentQty ?? g.max?.currentQty ?? '—';

            // Cellule seuil MIN
            const minCell = g.min
                ? `<span class="alert-seuil alert-seuil-min${g.min.triggered ? ' is-active' : ''}">
                      <svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3"><line x1="12" y1="19" x2="12" y2="5"/><polyline points="5 12 12 5 19 12"/></svg>
                      ${g.min.threshold}
                   </span>`
                : `<span class="alert-seuil alert-seuil-none">—</span>`;

            // Cellule seuil MAX
            const maxCell = g.max
                ? `<span class="alert-seuil alert-seuil-max${g.max.triggered ? ' is-active' : ''}">
                      <svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3"><line x1="12" y1="5" x2="12" y2="19"/><polyline points="19 12 12 19 5 12"/></svg>
                      ${g.max.threshold}
                   </span>`
                : `<span class="alert-seuil alert-seuil-none">—</span>`;

            const anyTriggered = g.min?.triggered || g.max?.triggered;
            const statusBadge  = anyTriggered
                ? '<span class="badge badge-red">⚠ Activée</span>'
                : '<span class="badge badge-green">✓ OK</span>';

            return `<tr>
                <td>${w ? w.name : '?'}</td>
                <td><strong>${p ? p.name : '?'}</strong></td>
                <td class="col-mono">${p ? (p.sku || '—') : '—'}</td>
                <td class="cell-number">${minCell}</td>
                <td class="cell-number">${maxCell}</td>
                <td class="cell-number"><strong>${qty}</strong></td>
                <td>${statusBadge}</td>
                <td style="display:flex;gap:4px">
                    <button class="btn btn-sm btn-secondary" title="Modifier" onclick="AltPage.openModal('${g.productId}','${g.warehouseId}')">${Icons.edit}</button>
                    <button class="btn btn-sm btn-danger"    title="Supprimer" onclick="AltPage.delGroup('${g.productId}','${g.warehouseId}')">${Icons.trash}</button>
                </td>
            </tr>`;
        }).join('');
    },

    // ══════════════════════════════════════════════════════════════
    // MODAL UNIFIÉ — Min + Max dans le même formulaire
    // openModal() sans argument = création
    // openModal(productId, warehouseId) = édition
    // ══════════════════════════════════════════════════════════════
    async openModal(productId, warehouseId){
        const isEdit  = !!(productId && warehouseId);
        const whOpts  = this.whs.map(w  => `<option value="${w.id}">${w.name}</option>`).join('');
        const catOpts = this.cats.map(c => `<option value="${c}">${c}</option>`).join('');

        // Récupérer les alertes existantes pour ce couple
        const existMin = isEdit
            ? (this.alerts.find(a => String(a.productId) === String(productId) && String(a.warehouseId) === String(warehouseId) && a.type === 'min') || null)
            : null;
        const existMax = isEdit
            ? (this.alerts.find(a => String(a.productId) === String(productId) && String(a.warehouseId) === String(warehouseId) && a.type === 'max') || null)
            : null;

        Modal.show(isEdit ? 'Modifier les seuils' : 'Nouvelle alerte', `
            <label class="lbl">Magasin *</label>
            <select class="sel" id="amWh" onchange="AltPage._onWhChange()" ${isEdit ? 'disabled' : ''}>
                <option value="">— Choisir —</option>
                ${whOpts}
            </select>

            <label class="lbl" style="margin-top:10px">Catégorie</label>
            <select class="sel" id="amCat" onchange="AltPage._onCatChange()">
                <option value="">— Toutes catégories —</option>
                ${catOpts}
            </select>

            <label class="lbl" style="margin-top:10px">Produit *</label>
            <select class="sel" id="amProd" ${isEdit ? 'disabled' : ''}>
                <option value="">— Choisir un magasin d'abord —</option>
            </select>

            <div style="display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-top:16px">

                <div class="am-block" id="amBlockMin">
                    <label class="am-block-toggle">
                        <input type="checkbox" id="amMinOn" onchange="AltPage._syncBlocks()">
                        <span class="am-block-icon am-block-icon--min">
                            <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3"><line x1="12" y1="19" x2="12" y2="5"/><polyline points="5 12 12 5 19 12"/></svg>
                        </span>
                        <span style="font-weight:800;font-size:13px;color:var(--red)">Seuil minimum</span>
                    </label>
                    <div class="am-block-body" id="amMinBody">
                        <input type="number" class="inp" id="amMinVal" min="0" value="${existMin ? existMin.threshold : 5}" placeholder="ex : 5">
                        <div style="font-size:11px;color:var(--text-muted);margin-top:4px">⚠ Alerte si stock ≤ seuil</div>
                    </div>
                </div>

                <div class="am-block" id="amBlockMax">
                    <label class="am-block-toggle">
                        <input type="checkbox" id="amMaxOn" onchange="AltPage._syncBlocks()">
                        <span class="am-block-icon am-block-icon--max">
                            <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3"><line x1="12" y1="5" x2="12" y2="19"/><polyline points="19 12 12 19 5 12"/></svg>
                        </span>
                        <span style="font-weight:800;font-size:13px;color:var(--orange)">Seuil maximum</span>
                    </label>
                    <div class="am-block-body" id="amMaxBody">
                        <input type="number" class="inp" id="amMaxVal" min="0" value="${existMax ? existMax.threshold : 15}" placeholder="ex : 15">
                        <div style="font-size:11px;color:var(--text-muted);margin-top:4px">⚠ Alerte si stock ≥ seuil</div>
                    </div>
                </div>

            </div>

            <style>
            .am-block{border:1.5px solid var(--border);border-radius:var(--r-xl);padding:12px;transition:border-color .15s,background .15s}
            .am-block.on-min{border-color:rgba(239,68,68,.5);background:rgba(239,68,68,.03)}
            .am-block.on-max{border-color:rgba(249,115,22,.5);background:rgba(249,115,22,.03)}
            .am-block-toggle{display:flex;align-items:center;gap:8px;cursor:pointer;user-select:none}
            .am-block-toggle input[type=checkbox]{width:16px;height:16px;cursor:pointer;accent-color:var(--blue);flex-shrink:0}
            .am-block-icon{display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px;border-radius:50%;flex-shrink:0}
            .am-block-icon--min{background:rgba(239,68,68,.12);color:var(--red)}
            .am-block-icon--max{background:rgba(249,115,22,.12);color:var(--orange)}
            .am-block-body{overflow:hidden;max-height:0;opacity:0;transition:max-height .2s ease,opacity .2s ease;pointer-events:none}
            .am-block-body.visible{max-height:100px;opacity:1;pointer-events:auto;margin-top:10px}
            </style>
        `, [
            {label: 'Annuler',                        cls: 'btn-secondary', onclick: () => Modal.close()},
            {label: isEdit ? 'Sauvegarder' : 'Créer', cls: 'btn-primary',   onclick: () => AltPage.saveGroup(productId, warehouseId)},
            ...(isEdit ? [{label: 'Supprimer', cls: 'btn-danger', onclick: () => AltPage.delGroup(productId, warehouseId)}] : [])
        ], 'warning');

        // Initialiser les cases + valeurs
        setTimeout(() => {
            const minCb = document.getElementById('amMinOn');
            const maxCb = document.getElementById('amMaxOn');
            if(minCb) minCb.checked = !!existMin;
            if(maxCb) maxCb.checked = !!existMax;
            this._syncBlocks();

            if(isEdit){
                const whSel = document.getElementById('amWh');
                if(whSel){ whSel.value = warehouseId; this._onWhChange(); }
                setTimeout(() => {
                    const prodSel = document.getElementById('amProd');
                    if(prodSel) prodSel.value = productId;
                    const p = this.prods.find(x => String(x.id) === String(productId));
                    if(p?.category){
                        const catSel = document.getElementById('amCat');
                        if(catSel) catSel.value = p.category;
                    }
                }, 80);
            }
        }, 50);
    },

    // Synchronise apparence des blocs selon l'état des checkboxes
    _syncBlocks(){
        const minOn   = document.getElementById('amMinOn')?.checked;
        const maxOn   = document.getElementById('amMaxOn')?.checked;
        const minBody = document.getElementById('amMinBody');
        const maxBody = document.getElementById('amMaxBody');
        const blkMin  = document.getElementById('amBlockMin');
        const blkMax  = document.getElementById('amBlockMax');

        minBody?.classList.toggle('visible', !!minOn);
        maxBody?.classList.toggle('visible', !!maxOn);
        blkMin?.classList.toggle('on-min', !!minOn);
        blkMax?.classList.toggle('on-max', !!maxOn);
    },

    // ══════════════════════════════════════════════════════════════
    // SAUVEGARDE GROUPÉE — 1 seul click pour Min + Max
    // ══════════════════════════════════════════════════════════════
    async saveGroup(existPid, existWid){
        const pid = existPid || document.getElementById('amProd')?.value;
        const wid = existWid || document.getElementById('amWh')?.value;

        if(!wid){ toast('Choisissez un magasin', 'error'); return; }
        if(!pid){ toast('Choisissez un produit',  'error'); return; }

        const minOn  = document.getElementById('amMinOn')?.checked;
        const maxOn  = document.getElementById('amMaxOn')?.checked;
        const minVal = parseInt(document.getElementById('amMinVal')?.value) || 0;
        const maxVal = parseInt(document.getElementById('amMaxVal')?.value) || 0;

        if(!minOn && !maxOn){
            toast('Activez au moins un seuil', 'warning');
            return;
        }

        // Alertes existantes
        const curMin = this.alerts.find(a => String(a.productId) === String(pid) && String(a.warehouseId) === String(wid) && a.type === 'min');
        const curMax = this.alerts.find(a => String(a.productId) === String(pid) && String(a.warehouseId) === String(wid) && a.type === 'max');

        try {
            const ops = [];

            // Seuil MIN
            if(minOn && curMin)  ops.push(Api.alertEdit({ id: parseInt(curMin.id), threshold: minVal }));
            if(minOn && !curMin) ops.push(Api.alertAdd({ productId: parseInt(pid), warehouseId: parseInt(wid), type: 'min', threshold: minVal }));
            if(!minOn && curMin) ops.push(Api.alertDel(curMin.id));

            // Seuil MAX
            if(maxOn && curMax)  ops.push(Api.alertEdit({ id: parseInt(curMax.id), threshold: maxVal }));
            if(maxOn && !curMax) ops.push(Api.alertAdd({ productId: parseInt(pid), warehouseId: parseInt(wid), type: 'max', threshold: maxVal }));
            if(!maxOn && curMax) ops.push(Api.alertDel(curMax.id));

            await Promise.all(ops);
            toast(existPid ? 'Alertes mises à jour' : 'Alertes créées', 'success');
            Modal.close();
            this.load();

        } catch(e){
            toast(e.message, 'error');
        }
    },

    // ══════════════════════════════════════════════════════════════
    // SUPPRESSION D'UN GROUPE COMPLET (min + max)
    // ══════════════════════════════════════════════════════════════
    async delGroup(productId, warehouseId){
        if(!confirm('Supprimer toutes les alertes pour ce produit dans ce magasin ?')) return;
        const toDelete = this.alerts.filter(a =>
            String(a.productId) === String(productId) &&
            String(a.warehouseId) === String(warehouseId) &&
            (a.type === 'min' || a.type === 'max')
        );
        try {
            await Promise.all(toDelete.map(a => Api.alertDel(a.id)));
            toast('Alertes supprimées', 'success');
            Modal.close();
            this.load();
        } catch(e){ toast(e.message, 'error'); }
    },

    // Rétrocompatibilité (utilisé dans l'ancien renderTable)
    async delAlert(id){
        if(!confirm('Supprimer cette alerte ?')) return;
        try {
            await Api.alertDel(id);
            toast('Alerte supprimée', 'success');
            Modal.close();
            this.load();
        } catch(e){ toast(e.message, 'error'); }
    },

    // ══════════════════════════════════════════════════════════════
    // HELPERS CASCADE MAGASIN → CATÉGORIE → PRODUIT
    // ══════════════════════════════════════════════════════════════
    _updateCatFilter(wid){
        const catF = document.getElementById('alertCatFilter');
        if(!catF) return;
        let avail = this.prods;
        if(wid && window.StockCascade){
            avail = StockCascade.getProductsForWarehouse(this.prods || [], wid, true);
        } else if(wid){
            const id = parseInt(wid);
            avail = this.prods.filter(p => {
                let al = p.allowedWarehouses;
                if(typeof al === 'string') try { al = JSON.parse(al||'[]'); } catch(e){ al=[]; }
                if(!Array.isArray(al)||!al.length) return true;
                return al.includes(id);
            });
        }
        const cats = window.StockCascade
            ? StockCascade.getWarehouseCategories(this.whs || [], wid || '', this.prods || [], [])
            : [...new Set(avail.map(p => p.category).filter(Boolean))].sort();
        const cur  = catF.value;
        catF.innerHTML = '<option value="">Toutes catégories</option>' +
            cats.map(c => `<option value="${c}"${c === cur ? ' selected' : ''}>${c}</option>`).join('');
    },

    _onWhChange(){
        const whId    = document.getElementById('amWh')?.value;
        const catSel  = document.getElementById('amCat');
        const prodSel = document.getElementById('amProd');
        if(!whId){ prodSel.innerHTML = '<option value="">— Choisir un magasin d\'abord —</option>'; return; }

        const filteredBase = window.StockCascade
            ? StockCascade.getProductsForWarehouse(this.prods || [], whId, true)
            : this.prods.filter(p => {
                let al = p.allowedWarehouses;
                if(typeof al === 'string') try { al = JSON.parse(al||'[]'); } catch(e){ al=[]; }
                if(!Array.isArray(al)||!al.length) return true;
                return al.includes(parseInt(whId));
            });

        let filtered = filteredBase;
        const cats = window.StockCascade
            ? StockCascade.getWarehouseCategories(this.whs || [], whId || '', this.prods || [], [])
            : [...new Set(filtered.map(p => p.category).filter(Boolean))].sort();
        const curCat  = catSel?.value || '';
        if(catSel){
            catSel.innerHTML = '<option value="">— Toutes catégories —</option>' +
                cats.map(c => `<option value="${c}"${c === curCat ? ' selected' : ''}>${c}</option>`).join('');
        }
        if(curCat) filtered = filtered.filter(p => p.category === curCat);

        prodSel.innerHTML = '<option value="">— Choisir —</option>' +
            filtered.map(p => `<option value="${p.id}">${p.name} (${p.sku || '—'})</option>`).join('');
    },

    _onCatChange(){
        const whId    = document.getElementById('amWh')?.value;
        const cat     = document.getElementById('amCat')?.value;
        const prodSel = document.getElementById('amProd');
        if(!whId) return;

        let filtered = window.StockCascade
            ? StockCascade.getProductsForWarehouse(this.prods || [], whId, true)
            : this.prods.filter(p => {
                let al = p.allowedWarehouses;
                if(typeof al === 'string') try { al = JSON.parse(al||'[]'); } catch(e){ al=[]; }
                if(!Array.isArray(al)||!al.length) return true;
                return al.includes(parseInt(whId));
            });
        if(cat) filtered = filtered.filter(p => p.category === cat);

        prodSel.innerHTML = '<option value="">— Choisir —</option>' +
            filtered.map(p => `<option value="${p.id}">${p.name} (${p.sku || '—'})</option>`).join('');
    },

};
