/**
 * Fichier  : assets/js/pages/reports.js
 * Auteur   : KREMER Régis
 * Version  : 2.3.0
 * Date     : 2026-02-24
 * Description : JS — Rapports : stock, valorisation, mouvements, alertes, marques,
 *               écarts inventaire, historique prix
 *
 * Changelog :
 *   v2.1.0 — Version initiale
 *   v2.2.0 — Permissions magasins, rapport d'écart, historique prix
 *   v2.3.0 — Refonte : impression ciblée par onglet, webdesign homogène,
 *            mise en page print propre (seul l'onglet actif est imprimé)
 */
// ================================================================
// reports.js — Rapports avec impression ciblée
// ================================================================
const ReportPage = {
    warehouses: [],
    products: [],
    stock: [],
    movements: [],
    brands: [],
    suppliers: [],
    currentTab: 'stock',

    async init() {
        await this.loadData();
        this.setupTabs();
        await this.loadStockReport();
    },

    async loadData() {
        try {
            [this.warehouses, this.products, this.stock, this.movements, this.brands, this.suppliers] = await Promise.all([
                Api.warehouses(),
                Api.products(),
                Api.stock(),
                Api.movements(),
                Api.brands(),
                Api.suppliers()
            ]);
        } catch(e) {
            console.error('[Reports] Error loading data:', e);
            toast('Erreur chargement données', 'error');
        }
    },

    setupTabs() {
        document.querySelectorAll('.report-tab').forEach(tab => {
            tab.onclick = () => this.switchTab(tab.dataset.tab);
        });
    },

    async switchTab(tabName) {
        document.querySelectorAll('.report-tab').forEach(t => t.classList.remove('active'));
        document.querySelector(`.report-tab[data-tab="${tabName}"]`)?.classList.add('active');

        document.querySelectorAll('.report-tab-content').forEach(c => c.classList.remove('active'));
        const tabEl = document.getElementById(`tab${tabName.charAt(0).toUpperCase() + tabName.slice(1)}`);
        if(tabEl) tabEl.classList.add('active');

        this.currentTab = tabName;

        switch(tabName) {
            case 'stock':      await this.loadStockReport(); break;
            case 'value':      await this.loadValueReport(); break;
            case 'movements':  await this.loadMovementsReport(); break;
            case 'alerts':     await this.loadAlertsReport(); break;
            case 'brands':     await this.loadBrandsReport(); break;
            case 'gap':        await this.loadGapReport(); break;
            case 'prices':     await this.loadPricesReport(); break;
        }
    },

    // ══════════════════════════════════════════════════════════════
    // IMPRESSION CIBLÉE — N'imprime que l'onglet actif
    // ══════════════════════════════════════════════════════════════
    printCurrentTab() {
        const tabId = `tab${this.currentTab.charAt(0).toUpperCase() + this.currentTab.slice(1)}`;
        const tabEl = document.getElementById(tabId);
        if(!tabEl) { window.print(); return; }

        // Titre du rapport pour l'en-tête print
        const h2 = tabEl.querySelector('h2');
        const title = h2 ? h2.textContent : 'Rapport';

        // Collecter le HTML du tableau + summary (pas les filtres/boutons)
        const summaryEl = tabEl.querySelector('.report-summary');
        const tableEl = tabEl.querySelector('table');

        if(!tableEl) { toast('Aucun tableau à imprimer', 'warning'); return; }

        // Compter les lignes de données (pas les lignes vides)
        const dataRows = tableEl.querySelectorAll('tbody tr:not(.tbl-empty)');
        if(dataRows.length === 0) {
            toast('Aucune donnée à imprimer', 'warning');
            return;
        }

        // Construire le HTML print
        let printHTML = `<!DOCTYPE html>
<html lang="fr">
<head>
    <meta charset="utf-8">
    <title>${this._esc(title)} — StockMaster Pro</title>
    <style>
        * { margin:0; padding:0; box-sizing:border-box; }
        body { font-family: Arial, Helvetica, sans-serif; color: #1a1a1a; padding: 12mm; }
        
        /* En-tête */
        .print-header {
            display: flex; justify-content: space-between; align-items: flex-end;
            border-bottom: 2px solid #333; padding-bottom: 10px; margin-bottom: 16px;
        }
        .print-header h1 { font-size: 16pt; font-weight: 700; }
        .print-header .print-meta { font-size: 9pt; color: #666; text-align: right; }

        /* Summary cards */
        .print-summary {
            display: flex; gap: 16px; margin-bottom: 16px; flex-wrap: wrap;
        }
        .print-summary-card {
            flex: 1; min-width: 120px;
            border: 1px solid #ddd; border-radius: 6px; padding: 10px 14px;
        }
        .print-summary-value { font-size: 14pt; font-weight: 700; }
        .print-summary-label { font-size: 8pt; color: #666; text-transform: uppercase; letter-spacing: 0.5px; margin-top: 2px; }

        /* Tableau */
        table { width: 100%; border-collapse: collapse; font-size: 9pt; }
        thead th {
            padding: 8px 10px; text-align: left;
            font-size: 8pt; font-weight: 600; color: #444;
            text-transform: uppercase; letter-spacing: 0.3px;
            background: #f5f5f5; border-bottom: 2px solid #ccc;
        }
        tbody td {
            padding: 7px 10px; border-bottom: 1px solid #eee;
            vertical-align: middle;
        }
        tbody tr:nth-child(even) { background: #fafafa; }
        tbody tr:hover { background: #f0f0f0; }
        strong { font-weight: 600; }

        /* Badge */
        .badge {
            display: inline-block; padding: 2px 8px; border-radius: 10px;
            font-size: 8pt; font-weight: 600; color: #fff;
        }

        /* Pied de page */
        .print-footer {
            margin-top: 20px; padding-top: 8px; border-top: 1px solid #ccc;
            font-size: 8pt; color: #999; display: flex; justify-content: space-between;
        }

        @page { size: A4 landscape; margin: 10mm; }
        @media print {
            body { padding: 0; }
        }
    </style>
</head>
<body>
    <div class="print-header">
        <h1>${this._esc(title)}</h1>
        <div class="print-meta">
            StockMaster Pro<br>
            Imprimé le ${new Date().toLocaleDateString('fr-FR')} à ${new Date().toLocaleTimeString('fr-FR', {hour:'2-digit', minute:'2-digit'})}
        </div>
    </div>`;

        // Ajouter les KPI summary si présents
        if(summaryEl) {
            const cards = summaryEl.querySelectorAll('.summary-card');
            if(cards.length > 0) {
                printHTML += '<div class="print-summary">';
                cards.forEach(card => {
                    const val = card.querySelector('.summary-value')?.textContent || '';
                    const lbl = card.querySelector('.summary-label')?.textContent || '';
                    printHTML += `<div class="print-summary-card"><div class="print-summary-value">${this._esc(val)}</div><div class="print-summary-label">${this._esc(lbl)}</div></div>`;
                });
                printHTML += '</div>';
            }
        }

        // Ajouter le tableau
        printHTML += `<table>${tableEl.innerHTML}</table>`;

        // Footer
        printHTML += `
    <div class="print-footer">
        <span>StockMaster Pro — ${this._esc(title)}</span>
        <span>Page 1</span>
    </div>
</body>
</html>`;

        // Ouvrir fenêtre impression
        const printWin = window.open('', '_blank', 'width=1100,height=700');
        if(!printWin) {
            toast('Popup bloquée — autorisez les popups.', 'error');
            return;
        }
        printWin.document.write(printHTML);
        printWin.document.close();

        // Auto-print après chargement
        printWin.onload = () => {
            setTimeout(() => {
                printWin.focus();
                printWin.print();
                setTimeout(() => printWin.close(), 400);
            }, 200);
        };
    },

    _esc(s) {
        if(!s) return '';
        const d = document.createElement('div');
        d.textContent = s;
        return d.innerHTML;
    },

    
    // ================================================================
    // SMART KPIs (Lot 3) — inject into Stock tab without changing the view
    // ================================================================
    async loadSmartKpis() {
        const host = document.getElementById('tabStock') || document.querySelector('.report-tab-content.active') || document.body;
        if(!host) return;

        // Avoid duplicates
        if(document.getElementById('smartKpisBox')) return;

        const box = document.createElement('div');
        box.id = 'smartKpisBox';
        box.className = 'card';
        box.style.marginBottom = '12px';
        box.innerHTML = `
            <div style="display:flex;align-items:center;justify-content:space-between;gap:10px;flex-wrap:wrap">
                <div>
                    <div style="font-weight:700">Pilotage intelligent</div>
                    <div style="font-size:12px;color:var(--text-muted)">Consommation moyenne (90j), risques de rupture (90j), produits dormants.</div>
                </div>
                <a class="btn btn-secondary" href="analytics">Voir détail</a>
            </div>
            <div id="smartKpisGrid" style="display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:10px;margin-top:10px"></div>
        `;

        // Insert at top of Stock tab
        host.prepend(box);

        try{
            const res = await fetch('api/analytics.php?windowDays=90&horizonDays=90&top=10', { headers:{'Accept':'application/json'} });
            const data = await res.json();
            const k = data.kpi || {};
            const stockValue = (k.stockValue===null || k.stockValue===undefined) ? '—' : (Number(k.stockValue).toLocaleString('fr-FR',{maximumFractionDigits:2})+' €');
            const grid = document.getElementById('smartKpisGrid');
            if(!grid) return;
            grid.innerHTML = `
                <div class="kpi"><div class="kpi-lbl">Valeur stock</div><div class="kpi-val">${stockValue}</div></div>
                <div class="kpi"><div class="kpi-lbl">Risques</div><div class="kpi-val">${k.riskCount ?? 0}</div></div>
                <div class="kpi"><div class="kpi-lbl">Critiques</div><div class="kpi-val">${k.criticalCount ?? 0}</div></div>
                <div class="kpi"><div class="kpi-lbl">Dormants</div><div class="kpi-val">${k.dormantCount ?? 0}</div></div>
            `;
        }catch(e){
            // fail-soft
        }
    },
// ================================================================
    // STOCK REPORT
    // ================================================================
    async loadStockReport() {
        const whSelect = document.getElementById('stockWarehouse');
        whSelect.innerHTML = '<option value="">🏢 Tous les magasins</option>' +
            this.warehouses.map(w => `<option value="${w.id}">${w.name}</option>`).join('');

        const catSelect = document.getElementById('stockCategory');
        const brandSelect = document.getElementById('stockBrand');

        // Cascade magasin → catégories filtrées (mêmes produits que le tableau)
        const refreshStockCats = (wid) => {
            const cats = window.StockCascade
                ? StockCascade.getWarehouseCategories(this.warehouses || [], wid || '', this.products || [], [])
                : [...new Set(this.products.map(p => p.category).filter(Boolean))].sort();
            const prev = catSelect.value;
            catSelect.innerHTML = '<option value="">📦 Toutes les catégories</option>' +
                cats.map(c => `<option value="${c}"${c===prev?' selected':''}>${c}</option>`).join('');
        };
        const refreshStockBrands = () => {
            const prev = brandSelect.value;
            const brandNames = window.StockCascade
                ? StockCascade.getBrandNamesForScope(this.products || [], this.suppliers || [], this.brands || [], {
                    warehouseId: whSelect.value || '',
                    category: catSelect.value || '',
                    includeUnrestricted: true
                })
                : (this.brands || []).map(b => b.name).filter(Boolean).sort();
            brandSelect.innerHTML = '<option value="">🏷️ Toutes les marques</option>' +
                brandNames.map(name => `<option value="${name}"${name===prev?' selected':''}>${name}</option>`).join('');
        };

        refreshStockCats('');
        refreshStockBrands();
        whSelect.addEventListener('change', () => { refreshStockCats(whSelect.value); refreshStockBrands(); this.renderStockTable(); });

        ['stockSearch', 'stockThreshold'].forEach(id => {
            document.getElementById(id).addEventListener('input', () => this.renderStockTable());
        });
        catSelect.addEventListener('input', () => { refreshStockBrands(); this.renderStockTable(); });
        brandSelect.addEventListener('input', () => this.renderStockTable());

        document.getElementById('btnStockReset').onclick = () => {
            document.getElementById('stockSearch').value = '';
            document.getElementById('stockWarehouse').value = '';
            document.getElementById('stockCategory').value = '';
            document.getElementById('stockBrand').value = '';
            document.getElementById('stockThreshold').value = '';
            this.renderStockTable();
        };

        document.getElementById('btnStockPrint').onclick = () => this.printCurrentTab();
        document.getElementById('btnStockCSV').onclick = () => this.exportStockCSV();

        this.renderStockTable();
    },

    renderStockTable() {
        const search = document.getElementById('stockSearch').value.toLowerCase();
        const warehouseFilter = document.getElementById('stockWarehouse').value;
        const categoryFilter = document.getElementById('stockCategory').value;
        const brandFilter = document.getElementById('stockBrand').value;
        const thresholdFilter = document.getElementById('stockThreshold').value;

        let data = [];

        this.stock.forEach(s => {
            const product = this.products.find(p => p.id === s.productId);
            const warehouse = this.warehouses.find(w => w.id === s.warehouseId);
            if(!product || !warehouse) return;
            if(warehouseFilter && s.warehouseId != warehouseFilter) return;
            if(categoryFilter && product.category !== categoryFilter) return;
            if(brandFilter && product.brand !== brandFilter) return;
            if(search) {
                const searchableText = `${product.name} ${product.sku} ${product.barcode}`.toLowerCase();
                if(!searchableText.includes(search)) return;
            }
            const safetyStock = parseFloat(product.safetyStock) || 0;
            const isLow = s.quantity <= safetyStock;
            if(thresholdFilter === 'low' && !isLow) return;
            if(thresholdFilter === 'ok' && isLow) return;
            const baseCost = getBaseCost(product);
            const value = s.quantity * baseCost;
            data.push({ product: product.name, sku: product.sku || '—', warehouse: warehouse.name, category: product.category || '—', quantity: s.quantity, safetyStock, isLow, cost: baseCost, value });
        });

        const totalProducts = data.length;
        const totalUnits = data.reduce((sum, d) => sum + d.quantity, 0);
        const totalValue = data.reduce((sum, d) => sum + d.value, 0);
        const lowStock = data.filter(d => d.isLow).length;

        document.getElementById('stockTotalProducts').textContent = totalProducts;
        document.getElementById('stockTotalUnits').textContent = totalUnits;
        document.getElementById('stockTotalValue').textContent = totalValue.toFixed(2) + '€';
        document.getElementById('stockLowStock').textContent = lowStock;

        const tbody = document.getElementById('stockTableBody');
        if(data.length === 0) {
            tbody.innerHTML = '<tr><td colspan="9" class="tbl-empty">Aucun résultat</td></tr>';
            return;
        }

        tbody.innerHTML = data.map(d => `
            <tr>
                <td><strong>${d.product}</strong></td>
                <td>${d.sku}</td>
                <td>${d.warehouse}</td>
                <td>${d.category}</td>
                <td>${d.quantity}</td>
                <td>${d.safetyStock}</td>
                <td>${d.isLow
                    ? '<span class="badge" style="background:var(--red);color:#fff">⚠️ Stock bas</span>'
                    : '<span class="badge" style="background:var(--green);color:#fff">✓ OK</span>'}</td>
                <td>${d.cost.toFixed(2)}€</td>
                <td><strong>${d.value.toFixed(2)}€</strong></td>
            </tr>
        `).join('');
    },

    exportStockCSV() {
        const search = document.getElementById('stockSearch').value.toLowerCase();
        const warehouseFilter = document.getElementById('stockWarehouse').value;
        const categoryFilter = document.getElementById('stockCategory').value;
        const brandFilter = document.getElementById('stockBrand').value;
        const thresholdFilter = document.getElementById('stockThreshold').value;
        let data = [];
        this.stock.forEach(s => {
            const product = this.products.find(p => p.id === s.productId);
            const warehouse = this.warehouses.find(w => w.id === s.warehouseId);
            if(!product || !warehouse) return;
            if(warehouseFilter && s.warehouseId != warehouseFilter) return;
            if(categoryFilter && product.category !== categoryFilter) return;
            if(brandFilter && product.brand !== brandFilter) return;
            if(search) { if(!`${product.name} ${product.sku} ${product.barcode}`.toLowerCase().includes(search)) return; }
            const safetyStock = parseFloat(product.safetyStock) || 0;
            const isLow = s.quantity <= safetyStock;
            if(thresholdFilter === 'low' && !isLow) return;
            if(thresholdFilter === 'ok' && isLow) return;
            const baseCost = getBaseCost(product);
            data.push({ Produit: product.name, SKU: product.sku || '', 'Code-barres': product.barcode || '', Magasin: warehouse.name, Catégorie: product.category || '', Marque: product.brand || '', 'Stock actuel': s.quantity, 'Seuil minimum': safetyStock, Statut: isLow ? 'Stock bas' : 'OK', 'Coût unitaire': baseCost.toFixed(4), 'Valeur totale': (s.quantity * baseCost).toFixed(2) });
        });
        this.downloadCSV(data, 'rapport_stock');
    },

    // ================================================================
    // VALUE REPORT
    // ================================================================
    async loadValueReport() {
        document.getElementById('btnValuePrint').onclick = () => this.printCurrentTab();
        document.getElementById('btnValueCSV').onclick = () => this.exportValueCSV();
        this.renderValueTable();
    },

    renderValueTable() {
        const data = [];
        this.warehouses.forEach(wh => {
            const whStock = this.stock.filter(s => s.warehouseId === wh.id);
            const productCount = new Set(whStock.map(s => s.productId)).size;
            const totalUnits = whStock.reduce((sum, s) => sum + s.quantity, 0);
            let totalValue = 0;
            whStock.forEach(s => { const p = this.products.find(p => p.id === s.productId); if(p) totalValue += s.quantity * getBaseCost(p); });
            const avgValue = productCount > 0 ? totalValue / productCount : 0;
            data.push({ warehouse: wh.name, productCount, totalUnits, totalValue, avgValue });
        });
        const grandTotal = data.reduce((sum, d) => sum + d.totalValue, 0);
        const total = (this.valuation && typeof this.valuation.totalValue === 'number') ? this.valuation.totalValue : grandTotal;
        document.getElementById('valueTotalStock').textContent = total.toFixed(2) + '€';
        document.getElementById('valueWarehouseCount').textContent = data.length;
        const tbody = document.getElementById('valueTableBody');
        tbody.innerHTML = data.map(d => `
            <tr>
                <td><strong>${d.warehouse}</strong></td>
                <td>${d.productCount}</td>
                <td>${d.totalUnits}</td>
                <td><strong>${d.totalValue.toFixed(2)}€</strong></td>
                <td>${d.avgValue.toFixed(2)}€</td>
            </tr>
        `).join('');
    },

    exportValueCSV() {
        const data = [];
        this.warehouses.forEach(wh => {
            const whStock = this.stock.filter(s => s.warehouseId === wh.id);
            const productCount = new Set(whStock.map(s => s.productId)).size;
            const totalUnits = whStock.reduce((sum, s) => sum + s.quantity, 0);
            let totalValue = 0;
            whStock.forEach(s => { const p = this.products.find(p => p.id === s.productId); if(p) totalValue += s.quantity * getBaseCost(p); });
            data.push({ Magasin: wh.name, 'Nombre de produits': productCount, 'Unités totales': totalUnits, 'Valeur totale': totalValue.toFixed(2), 'Valeur moyenne/produit': (productCount > 0 ? totalValue / productCount : 0).toFixed(2) });
        });
        this.downloadCSV(data, 'rapport_valorisation');
    },

    // ================================================================
    // MOVEMENTS REPORT
    // ================================================================
    async loadMovementsReport() {
        const today = new Date();
        const from = new Date(today);
        from.setDate(from.getDate() - 30);
        document.getElementById('movementsDateFrom').value = from.toISOString().slice(0, 10);
        document.getElementById('movementsDateTo').value = today.toISOString().slice(0, 10);

        const whSelect = document.getElementById('movementsWarehouse');
        whSelect.innerHTML = '<option value="">Tous les magasins</option>' +
            this.warehouses.map(w => `<option value="${w.id}">${w.name}</option>`).join('');

        ['movementsDateFrom', 'movementsDateTo', 'movementsType', 'movementsWarehouse'].forEach(id => {
            document.getElementById(id).addEventListener('input', () => this.renderMovementsTable());
        });

        document.getElementById('btnMovementsReset').onclick = () => {
            document.getElementById('movementsDateFrom').value = from.toISOString().slice(0, 10);
            document.getElementById('movementsDateTo').value = today.toISOString().slice(0, 10);
            document.getElementById('movementsType').value = '';
            document.getElementById('movementsWarehouse').value = '';
            this.renderMovementsTable();
        };

        document.getElementById('btnMovementsPrint').onclick = () => this.printCurrentTab();
        document.getElementById('btnMovementsCSV').onclick = () => this.exportMovementsCSV();

        this.renderMovementsTable();
    },

    renderMovementsTable() {
        const dateFrom = document.getElementById('movementsDateFrom').value;
        const dateTo = document.getElementById('movementsDateTo').value;
        const typeFilter = document.getElementById('movementsType').value;
        const whFilter = document.getElementById('movementsWarehouse').value;

        let filtered = this.movements.filter(m => {
            if(dateFrom && m.date < dateFrom) return false;
            if(dateTo && m.date > dateTo + 'T23:59:59') return false;
            if(typeFilter && m.type !== typeFilter) return false;
            if(whFilter && m.warehouseId != whFilter) return false;
            return true;
        });

        const entries  = filtered.filter(m => m.type === 'entry' || m.type === 'add').length;
        const exits    = filtered.filter(m => m.type === 'remove').length;
        const transfers= filtered.filter(m => m.type === 'transfer').length;
        document.getElementById('movementsEntries').textContent  = entries;
        document.getElementById('movementsExits').textContent    = exits;
        document.getElementById('movementsTransfers').textContent= transfers;

        const tbody = document.getElementById('movementsTableBody');
        if(filtered.length === 0) {
            tbody.innerHTML = '<tr><td colspan="9" class="tbl-empty">Aucun mouvement</td></tr>';
            return;
        }

        // Labels et classes identiques à la page Mouvements
        const typeLabel = { add:'AJOUT', remove:'SORTIE', transfer:'TRANSFERT', entry:'ENTRÉE', inventory:'INVENTAIRE' };
        const typeCls   = { add:'success', remove:'danger', transfer:'info', entry:'success', inventory:'warning' };

        tbody.innerHTML = filtered.slice(0, 200).map(m => {
            const product   = this.products.find(p => p.id === m.productId);
            const warehouse = this.warehouses.find(w => w.id === m.warehouseId);
            const date = new Date(m.date).toLocaleString('fr-FR', {
                day:'2-digit', month:'2-digit', year:'numeric', hour:'2-digit', minute:'2-digit'
            });
            const qtySign  = m.type === 'remove' ? '-' : '+';
            const qtyCls   = m.type === 'remove' ? 'text-danger' : 'text-success';
            const reasonSite = [m.reason, m.site].filter(Boolean).join(' · ') || '—';
            const bcMatch = (m.reason || '').match(/\bBC-\d{8}-[A-Z0-9]+\b/);
            const docLabel = bcMatch ? bcMatch[0] : (m.deliveryNote || '—');
            return `
                <tr>
                    <td>${date}</td>
                    <td><span class="badge badge-${typeCls[m.type]||'secondary'}">${typeLabel[m.type]||m.type}</span></td>
                    <td><strong>${product?.name||'?'}</strong></td>
                    <td>${warehouse?.name||'?'}</td>
                    <td class="col-qty"><span class="${qtyCls}">${qtySign}${Math.abs(m.quantity)} ${m.unit||''}</span></td>
                    <td>${reasonSite}</td>
                    <td>${m.operator||m.user||'—'}</td>
                    <td>${m.note||'—'}</td>
                    <td>${docLabel}</td>
                </tr>
            `;
        }).join('');

        if(filtered.length > 200) {
            tbody.innerHTML += `<tr><td colspan="9" class="tbl-empty">… et ${filtered.length - 200} mouvements supplémentaires (exportez en CSV)</td></tr>`;
        }
    },

    exportMovementsCSV() {
        const dateFrom = document.getElementById('movementsDateFrom').value;
        const dateTo = document.getElementById('movementsDateTo').value;
        const typeFilter = document.getElementById('movementsType').value;
        const whFilter = document.getElementById('movementsWarehouse').value;
        const typeLabels = { entry: 'Entrée', add: 'Ajout', remove: 'Sortie', transfer: 'Transfert' };
        let filtered = this.movements.filter(m => {
            if(dateFrom && m.date < dateFrom) return false;
            if(dateTo && m.date > dateTo + 'T23:59:59') return false;
            if(typeFilter && m.type !== typeFilter) return false;
            if(whFilter && m.warehouseId != whFilter) return false;
            return true;
        });
        const typeLabels2 = { add:'Ajout', remove:'Sortie', transfer:'Transfert', entry:'Entrée', inventory:'Inventaire' };
        const data = filtered.map(m => {
            const product   = this.products.find(p => p.id === m.productId);
            const warehouse = this.warehouses.find(w => w.id === m.warehouseId);
            const bcMatch   = (m.reason||'').match(/\bBC-\d{8}-[A-Z0-9]+\b/);
            return {
                Date:        new Date(m.date).toLocaleString('fr-FR'),
                Type:        typeLabels2[m.type] || m.type,
                Produit:     product?.name || '',
                SKU:         product?.sku || '',
                Magasin:     warehouse?.name || '',
                Quantité:    (m.type==='remove'?'-':'+')+Math.abs(m.quantity),
                Unité:       m.unit || '',
                'Raison/Chantier': [m.reason, m.site].filter(Boolean).join(' · ') || '',
                Opérateur:   m.operator || m.user || '',
                Note:        m.note || '',
                Document:    bcMatch ? bcMatch[0] : (m.deliveryNote||'')
            };
        });
        this.downloadCSV(data, 'rapport_mouvements');
    },

    // ================================================================
    // ALERTS REPORT
    // ================================================================
    async loadAlertsReport() {
        document.getElementById('btnAlertsPrint').onclick = () => this.printCurrentTab();
        document.getElementById('btnAlertsCSV').onclick = () => this.exportAlertsCSV();
        this.renderAlertsTable();
    },

    renderAlertsTable() {
        const alerts = [];
        this.stock.forEach(s => {
            const product = this.products.find(p => p.id === s.productId);
            const warehouse = this.warehouses.find(w => w.id === s.warehouseId);
            if(!product || !warehouse) return;
            const safetyStock = parseFloat(product.safetyStock) || 0;
            if(s.quantity <= safetyStock) {
                const deficit = safetyStock - s.quantity;
                const priority = s.quantity === 0 ? 'critical' : (deficit > safetyStock * 0.5 ? 'high' : 'medium');
                alerts.push({ priority, product: product.name, sku: product.sku || '—', warehouse: warehouse.name, quantity: s.quantity, safetyStock, deficit, productId: product.id, warehouseId: warehouse.id });
            }
        });

        const priorityOrder = { critical: 0, high: 1, medium: 2 };
        alerts.sort((a, b) => priorityOrder[a.priority] - priorityOrder[b.priority]);

        const tbody = document.getElementById('alertsTableBody');
        if(alerts.length === 0) {
            tbody.innerHTML = '<tr><td colspan="8" class="tbl-empty">✅ Aucune alerte stock bas</td></tr>';
            return;
        }

        const priorityIcons = { critical: '🔴', high: '🟠', medium: '🟡' };
        const priorityLabels = { critical: 'CRITIQUE', high: 'ÉLEVÉE', medium: 'MOYENNE' };

        tbody.innerHTML = alerts.map(a => `
            <tr>
                <td><span class="badge" style="background:${a.priority === 'critical' ? 'var(--red)' : a.priority === 'high' ? 'var(--orange)' : 'var(--yellow)'};color:#fff">${priorityIcons[a.priority]} ${priorityLabels[a.priority]}</span></td>
                <td><strong>${a.product}</strong></td>
                <td>${a.sku}</td>
                <td>${a.warehouse}</td>
                <td>${a.quantity}</td>
                <td>${a.safetyStock}</td>
                <td><strong style="color:var(--red)">${a.deficit}</strong></td>
                <td><button class="btn btn-sm btn-primary" onclick="window.openMovementModal('entry', ${a.productId}, ${a.warehouseId})">📥 Approvisionner</button></td>
            </tr>
        `).join('');
    },

    exportAlertsCSV() {
        const alerts = [];
        this.stock.forEach(s => {
            const product = this.products.find(p => p.id === s.productId);
            const warehouse = this.warehouses.find(w => w.id === s.warehouseId);
            if(!product || !warehouse) return;
            const safetyStock = parseFloat(product.safetyStock) || 0;
            if(s.quantity <= safetyStock) {
                const deficit = safetyStock - s.quantity;
                const priority = s.quantity === 0 ? 'CRITIQUE' : (deficit > safetyStock * 0.5 ? 'ÉLEVÉE' : 'MOYENNE');
                alerts.push({ Priorité: priority, Produit: product.name, SKU: product.sku || '', Magasin: warehouse.name, 'Stock actuel': s.quantity, 'Seuil minimum': safetyStock, Déficit: deficit });
            }
        });
        this.downloadCSV(alerts, 'rapport_alertes');
    },

    // ================================================================
    // BRANDS REPORT
    // ================================================================
    async loadBrandsReport() {
        document.getElementById('btnBrandsPrint').onclick = () => this.printCurrentTab();
        document.getElementById('btnBrandsCSV').onclick = () => this.exportBrandsCSV();
        this.renderBrandsTable();
    },

    renderBrandsTable() {
        const brandData = {};
        this.products.forEach(p => {
            const brand = p.brand || 'Sans marque';
            if(!brandData[brand]) brandData[brand] = { productCount: 0, totalStock: 0, totalValue: 0, suppliers: new Set() };
            brandData[brand].productCount++;
            const productStock = this.stock.filter(s => s.productId === p.id);
            const totalQty = productStock.reduce((sum, s) => sum + s.quantity, 0);
            brandData[brand].totalStock += totalQty;
            brandData[brand].totalValue += totalQty * getBaseCost(p);
            if(p.supplier) { const sup = this.suppliers.find(s => s.id == p.supplier); if(sup) brandData[brand].suppliers.add(sup.name); }
        });

        const data = Object.entries(brandData).map(([brand, d]) => ({ brand, productCount: d.productCount, totalStock: d.totalStock, totalValue: d.totalValue, suppliers: Array.from(d.suppliers).join(', ') || '—' }));
        data.sort((a, b) => b.totalValue - a.totalValue);

        const tbody = document.getElementById('brandsTableBody');
        tbody.innerHTML = data.map(d => `
            <tr>
                <td><strong>${d.brand}</strong></td>
                <td>${d.productCount}</td>
                <td>${d.totalStock}</td>
                <td><strong>${d.totalValue.toFixed(2)}€</strong></td>
                <td>${d.suppliers}</td>
            </tr>
        `).join('');
    },

    exportBrandsCSV() {
        const brandData = {};
        this.products.forEach(p => {
            const brand = p.brand || 'Sans marque';
            if(!brandData[brand]) brandData[brand] = { productCount: 0, totalStock: 0, totalValue: 0, suppliers: new Set() };
            brandData[brand].productCount++;
            const productStock = this.stock.filter(s => s.productId === p.id);
            const totalQty = productStock.reduce((sum, s) => sum + s.quantity, 0);
            brandData[brand].totalStock += totalQty;
            brandData[brand].totalValue += totalQty * getBaseCost(p);
            if(p.supplier) { const sup = this.suppliers.find(s => s.id == p.supplier); if(sup) brandData[brand].suppliers.add(sup.name); }
        });
        const data = Object.entries(brandData).map(([brand, d]) => ({ Marque: brand, 'Nombre de produits': d.productCount, 'Stock total': d.totalStock, 'Valeur totale': d.totalValue.toFixed(2), Fournisseurs: Array.from(d.suppliers).join(', ') || '' }));
        this.downloadCSV(data, 'rapport_marques');
    },

    // ================================================================
    // GAP REPORT — Écarts inventaire
    // ================================================================
    async loadGapReport() {
        let inventories = [];
        try { inventories = await Api.get('api/inventories.php'); } catch(e) {}

        document.getElementById('btnGapPrint').onclick = () => this.printCurrentTab();
        document.getElementById('btnGapCSV').onclick = () => this.exportGapCSV(inventories);

        this.renderGapTable(inventories);
    },

    renderGapTable(inventories) {
        const tbody = document.getElementById('gapTableBody');
        if(!tbody) return;

        const latestMap = {};
        inventories.forEach(inv => {
            (inv.lines || []).forEach(l => {
                const key = `${l.productId}_${inv.warehouseId}`;
                if(!latestMap[key] || inv.date > latestMap[key].date) {
                    latestMap[key] = { date: inv.date, counted: l.counted, warehouseId: inv.warehouseId, productId: l.productId };
                }
            });
        });

        const rows = [];
        this.stock.forEach(s => {
            const product = this.products.find(p => p.id === s.productId);
            const warehouse = this.warehouses.find(w => w.id === s.warehouseId);
            if(!product || !warehouse) return;
            const key = `${s.productId}_${s.warehouseId}`;
            const inv = latestMap[key];
            if(!inv) return;
            const gap = s.quantity - inv.counted;
            const gapVal = gap * getBaseCost(product);
            rows.push({ product: product.name, sku: product.sku || '—', warehouse: warehouse.name, theoretical: s.quantity, counted: inv.counted, gap, gapVal, invDate: inv.date });
        });

        rows.sort((a, b) => Math.abs(b.gapVal) - Math.abs(a.gapVal));

        const totalGap = rows.reduce((s, r) => s + Math.abs(r.gapVal), 0);
        const linesWithGap = rows.filter(r => r.gap !== 0).length;
        if(document.getElementById('gapTotalLines')) document.getElementById('gapTotalLines').textContent = rows.length;
        if(document.getElementById('gapLinesWithGap')) document.getElementById('gapLinesWithGap').textContent = linesWithGap;
        if(document.getElementById('gapTotalValue')) document.getElementById('gapTotalValue').textContent = totalGap.toFixed(2) + '€';

        if(!rows.length) {
            tbody.innerHTML = '<tr><td colspan="8" class="tbl-empty">Aucun inventaire disponible pour comparaison</td></tr>';
            return;
        }

        tbody.innerHTML = rows.map(r => {
            const gapCls = r.gap === 0 ? 'color:var(--green)' : r.gap < 0 ? 'color:var(--red)' : 'color:var(--orange)';
            return `<tr>
                <td>${r.product}</td>
                <td>${r.sku}</td>
                <td>${r.warehouse}</td>
                <td>${r.theoretical}</td>
                <td>${r.counted}</td>
                <td style="${gapCls}"><strong>${r.gap > 0 ? '+' : ''}${r.gap}</strong></td>
                <td style="${gapCls}">${r.gap > 0 ? '+' : ''}${r.gapVal.toFixed(2)}€</td>
                <td>${formatDate(r.invDate)}</td>
            </tr>`;
        }).join('');
    },

    exportGapCSV(inventories) {
        const latestMap = {};
        inventories.forEach(inv => {
            (inv.lines || []).forEach(l => {
                const key = `${l.productId}_${inv.warehouseId}`;
                if(!latestMap[key] || inv.date > latestMap[key].date) {
                    latestMap[key] = { date: inv.date, counted: l.counted, warehouseId: inv.warehouseId, productId: l.productId };
                }
            });
        });
        const rows = [];
        this.stock.forEach(s => {
            const p = this.products.find(x => x.id === s.productId);
            const w = this.warehouses.find(x => x.id === s.warehouseId);
            if(!p || !w) return;
            const inv = latestMap[`${s.productId}_${s.warehouseId}`];
            if(!inv) return;
            const gap = s.quantity - inv.counted;
            rows.push({ Produit: p.name, SKU: p.sku || '', Magasin: w.name, 'Stock théorique': s.quantity, 'Stock compté': inv.counted, Écart: gap, 'Valeur écart': (gap * getBaseCost(p)).toFixed(2), 'Date inventaire': formatDate(inv.date) });
        });
        this.downloadCSV(rows, 'rapport_ecarts_inventaire');
    },

    // ================================================================
    // PRICES REPORT — Historique des prix d'achat
    // ================================================================
    async loadPricesReport() {
        let prices = [];
        try { prices = await Api.get('api/purchase_prices.php'); } catch(e) {}

        document.getElementById('btnPricesPrint').onclick = () => this.printCurrentTab();
        document.getElementById('btnPricesCSV').onclick = () => this.exportPricesCSV(prices);

        const prodSel = document.getElementById('pricesProductFilter');
        if(prodSel) {
            prodSel.innerHTML = '<option value="">Tous les produits</option>' +
                this.products.map(p => `<option value="${p.id}">${p.name}</option>`).join('');
            prodSel.addEventListener('change', () => this.renderPricesTable(prices));
        }

        document.getElementById('btnPricesReset')?.addEventListener('click', () => {
            if(prodSel) prodSel.value = '';
            this.renderPricesTable(prices);
        });

        this.renderPricesTable(prices);
    },

    renderPricesTable(prices) {
        const tbody = document.getElementById('pricesTableBody');
        if(!tbody) return;

        const prodFilter = document.getElementById('pricesProductFilter')?.value || '';
        let filtered = prices;
        if(prodFilter) filtered = filtered.filter(p => String(p.productId) === String(prodFilter));
        filtered = filtered.slice(0, 200);

        if(!filtered.length) {
            tbody.innerHTML = '<tr><td colspan="7" class="tbl-empty">Aucun historique de prix</td></tr>';
            return;
        }

        tbody.innerHTML = filtered.map(p => {
            const prod = this.products.find(x => x.id == p.productId);
            const supp = this.suppliers.find(s => s.id == p.supplier);
            return `<tr>
                <td>${formatDate(p.date)}</td>
                <td>${prod?.name || '?'}</td>
                <td>${prod?.sku || '—'}</td>
                <td>${p.quantity} ${p.unit || ''}</td>
                <td>${parseFloat(p.unitCost || 0).toFixed(4)}€</td>
                <td>${parseFloat(p.baseUnitCost || 0).toFixed(4)}€</td>
                <td>${supp?.name || p.supplier || '—'}</td>
            </tr>`;
        }).join('');
    },

    exportPricesCSV(prices) {
        const data = prices.map(p => {
            const prod = this.products.find(x => x.id == p.productId);
            const supp = this.suppliers.find(s => s.id == p.supplier);
            return { Date: formatDate(p.date), Produit: prod?.name || '', SKU: prod?.sku || '', Quantité: p.quantity, Unité: p.unit || '', 'Prix unitaire': parseFloat(p.unitCost || 0).toFixed(4), 'Prix base': parseFloat(p.baseUnitCost || 0).toFixed(4), Fournisseur: supp?.name || p.supplier || '' };
        });
        this.downloadCSV(data, 'historique_prix_achat');
    },

    // ================================================================
    // CSV EXPORT UTILITY
    // ================================================================
    downloadCSV(data, filename) {
        if(!data || data.length === 0) {
            toast('Aucune donnée à exporter', 'warning');
            return;
        }
        const headers = Object.keys(data[0]);
        const csvContent = [
            headers.join(';'),
            ...data.map(row => headers.map(h => {
                const value = row[h] ?? '';
                return String(value).includes(';') ? `"${value}"` : value;
            }).join(';'))
        ].join('\n');

        const blob = new Blob(['\ufeff' + csvContent], { type: 'text/csv;charset=utf-8;' });
        const link = document.createElement('a');
        link.href = URL.createObjectURL(blob);
        link.download = `${filename}_${new Date().toISOString().slice(0, 10)}.csv`;
        link.click();
        toast('CSV exporté', 'success');
    }
};
