/**
 * routes/export.js
 * Exports PDF, PPTX, XLSX, DOCX par vue
 *
 * PDF  → tous les rôles authentifiés
 * PPTX / XLSX / DOCX → SuperAdmin uniquement (vérifié ici)
 */
const express = require('express');
const router  = express.Router();

const { getMarches } = require('../services/baserow');
const {
  isCloture, normalizeMarche, parseNum, formatMontant, selectVal,
  getDelaiRestant, niveauAlerte, niveauAvancement, niveauRisque,
  DELAI_CRITIQUE, DELAI_ATTENTION, SEUIL_STANDARD, SEUIL_CRITIQUE_PCT,
  buildRef,
} = require('../services/calc');

const pdfGen  = require('../services/export-pdf');
const { generateXlsx } = require('../services/export-xlsx');

// ─── Helpers ──────────────────────────────────────────────────────────────────

function applyFilters(rows, req) {
  const { region, entrepreneur, projet, nature, statut } = req.query;
  const regionFilter = req.regionFilter;
  let r = rows;
  if (regionFilter) r = r.filter(x => x.region === regionFilter);
  else if (region)  r = r.filter(x => x.region === region);
  if (entrepreneur) r = r.filter(x => String(x.entrepreneur || '').toLowerCase().includes(entrepreneur.toLowerCase()));
  if (projet)       r = r.filter(x => String(x.projet || '').toLowerCase().includes(projet.toLowerCase()));
  if (nature)       r = r.filter(x => String(x.nature || '').toLowerCase().includes(nature.toLowerCase()));
  if (statut)       r = r.filter(x => String(x.statut || '').toLowerCase().includes(statut.toLowerCase()));
  return r;
}

async function buildViewData(view, req) {
  const allRows = await getMarches();
  let rows = applyFilters(allRows, req);

  const actifs   = rows.filter(r => !isCloture(r));
  const clotures = rows.filter(r =>  isCloture(r));

  switch (view) {
    case 'synthese': {
      const tauxList   = actifs.map(r => parseNum(r.taux_phy ?? r.avt_phy)).filter(v => v > 0);
      const tauxMoyen  = tauxList.length ? Math.round(tauxList.reduce((a,b)=>a+b,0)/tauxList.length*10)/10 : 0;
      const totalBudget = actifs.reduce((s,r) => s+parseNum(r.tot_marche??r.totmarche??r.montant),0);
      const parStatut = {};
      for (const r of rows) { const s=selectVal(r.observation)||'Inconnu'; parStatut[s]=(parStatut[s]||0)+1; }
      const alertes = actifs
        .map(r=>({...r,_d:getDelaiRestant(r)}))
        .filter(r=>r._d!==null&&r._d<=DELAI_ATTENTION)
        .map(r=>({ref:buildRef(r),projet:r.projet||'',region:r.region||'',entrepreneur:r.entrepreneur||'',delai_restant:r._d,niveau:niveauAlerte(r._d)}))
        .sort((a,b)=>a.delai_restant-b.delai_restant);
      return {
        total: rows.length, actifs: actifs.length, clotures: clotures.length,
        taux_avancement_moyen: tauxMoyen, par_statut: parStatut,
        budget: { total: formatMontant(totalBudget), total_raw: totalBudget },
        alertes_delais: { count: alertes.length, critique: alertes.filter(a=>a.niveau==='critique').length, items: alertes },
      };
    }
    case 'alertes': {
      const items = actifs
        .map(r=>({...r,_d:getDelaiRestant(r)}))
        .filter(r=>r._d!==null&&r._d<=DELAI_ATTENTION)
        .map(r=>({...normalizeMarche(r),delai_restant:r._d,niveau:niveauAlerte(r._d),niveau_alerte:niveauAlerte(r._d)}))
        .sort((a,b)=>a.delai_restant-b.delai_restant);
      return { count: items.length, critique: items.filter(a=>a.niveau==='critique').length, items };
    }
    case 'en-service': {
      const enService = actifs.filter(r => selectVal(r.observation).toLowerCase().includes('en service'));
      return { count: enService.length, items: enService.map(normalizeMarche) };
    }
    case 'en-cours': {
      const enCours = actifs.filter(r=>parseNum(r.taux_phy??r.avt_phy)<100);
      return { count: enCours.length, items: enCours.map(normalizeMarche) };
    }
    case 'par-region': {
      const ALL_REGIONS = ['Gabes','Gafsa','Kebili','Medenine','Sfax','Tataouine','Tozeur'];
      const regions = ALL_REGIONS.map(reg => {
        const regActifs = actifs.filter(r=>(r.region||'')=== reg);
        const regTotal  = rows.filter(r=>(r.region||'')=== reg);
        const tauxList  = regActifs.map(r=>parseNum(r.taux_phy??r.avt_phy)).filter(v=>v>0);
        const tauxMoyen = tauxList.length ? Math.round(tauxList.reduce((a,b)=>a+b,0)/tauxList.length*10)/10 : 0;
        const budget    = regActifs.reduce((s,r)=>s+parseNum(r.tot_marche??r.totmarche??r.montant),0);
        const alertes   = regActifs
          .map(r=>({...r,_d:getDelaiRestant(r)}))
          .filter(r=>r._d!==null&&r._d<=DELAI_ATTENTION);
        return { region: reg, actifs: regActifs.length, clotures: regTotal.length-regActifs.length, total: regTotal.length,
          taux_moyen: tauxMoyen, budget: formatMontant(budget), alertes_count: alertes.length,
          alertes_critique: alertes.filter(r=>r._d<=DELAI_CRITIQUE).length };
      });
      return { count: regions.length, regions };
    }
    case 'clotures': {
      const totalBudget = clotures.reduce((s,r)=>s+parseNum(r.tot_marche??r.totmarche??r.montant),0);
      return { count: clotures.length, budget_total: formatMontant(totalBudget), items: clotures.map(normalizeMarche) };
    }
    case 'pilotage': {
      const items = actifs.map(r=>{
        const d = getDelaiRestant(r);
        return {...normalizeMarche(r), delai_restant:d, niveau_alerte:niveauAlerte(d), niveau_avancement:niveauAvancement(r.taux_phy??r.avt_phy,r.nature)};
      });
      const normal = items.filter(r=>r.niveau_avancement==='normal');
      const sous   = items.filter(r=>r.niveau_avancement==='sous_avancement');
      const dep    = items.filter(r=>r.niveau_avancement==='dépassé');
      return { resume:{total:items.length,normal:normal.length,sous_avancement:sous.length,depasse:dep.length},
        normal, sous_avancement:sous, depasse:dep, items };
    }
    case 'matrice-risque': {
      const items = actifs.map(r=>{
        const d=getDelaiRestant(r);
        return {...normalizeMarche(r),delai_restant:d,niveau_alerte:niveauAlerte(d),niveau_risque:niveauRisque(r),
          score_delai: d===null?1:d<=DELAI_CRITIQUE?3:d<=DELAI_ATTENTION?2:1,
          score_avancement: parseNum(r.taux_phy??r.avt_phy)>=SEUIL_CRITIQUE_PCT?3:parseNum(r.taux_phy??r.avt_phy)>=SEUIL_STANDARD?2:1,
        };
      });
      const pn={critique:0,élevé:0,moyen:0,faible:0};
      for(const i of items){ if(pn[i.niveau_risque]!==undefined) pn[i.niveau_risque]++; else pn[i.niveau_risque]=1; }
      return { total:items.length, par_niveau:pn, items };
    }
    default:
      return { items: actifs.map(normalizeMarche) };
  }
}

// ─── Route PDF ────────────────────────────────────────────────────────────────

router.get('/pdf', async (req, res) => {
  try {
    const view = req.query.view || 'synthese';
    const data = await buildViewData(view, req);

    let buf;
    switch (view) {
      case 'synthese':       buf = await pdfGen.generateSynthese(data);       break;
      case 'alertes':        buf = await pdfGen.generateAlertes(data);        break;
      case 'en-service':     buf = await pdfGen.generateEnService(data);      break;
      case 'en-cours':       buf = await pdfGen.generateEnCours(data);        break;
      case 'par-region':     buf = await pdfGen.generateParRegion(data);      break;
      case 'clotures':       buf = await pdfGen.generateClotures(data);       break;
      case 'pilotage':       buf = await pdfGen.generatePilotage(data);       break;
      case 'matrice-risque': buf = await pdfGen.generateMatriceRisque(data);  break;
      default:               buf = await pdfGen.generateGeneric(view, data);  break;
    }

    const filename = `RLA_${view}_${new Date().toISOString().slice(0,10)}.pdf`;
    res.set({
      'Content-Type':        'application/pdf',
      'Content-Disposition': `attachment; filename="${filename}"`,
      'Content-Length':      buf.length,
    });
    res.end(buf);
  } catch (err) {
    res.status(502).json({ error: 'Erreur génération PDF', detail: err.message });
  }
});

// ─── Route XLSX (SuperAdmin) ──────────────────────────────────────────────────

router.get('/xlsx', async (req, res) => {
  if (req.user?.role !== 'superadmin') {
    return res.status(403).json({ error: 'Accès réservé au SuperAdmin' });
  }
  try {
    const allRows  = await getMarches();
    const filtered = applyFilters(allRows, req);
    const actifs   = filtered.filter(r => !isCloture(r));
    const buf      = await generateXlsx('all', {}, actifs);
    const filename = `Marches_RLA_Zone_Sud_${new Date().toISOString().slice(0,10)}.xlsx`;
    res.set({
      'Content-Type':        'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
      'Content-Disposition': `attachment; filename="${filename}"`,
    });
    res.end(buf);
  } catch (err) {
    res.status(502).json({ error: 'Erreur génération XLSX', detail: err.message });
  }
});

// ─── Route PPTX (SuperAdmin) ──────────────────────────────────────────────────

router.get('/pptx', async (req, res) => {
  if (req.user?.role !== 'superadmin') {
    return res.status(403).json({ error: 'Accès réservé au SuperAdmin' });
  }
  try {
    const PptxGenJS = require('pptxgenjs');
    const allRows   = await getMarches();
    const filtered  = applyFilters(allRows, req);
    const actifs    = filtered.filter(r => !isCloture(r));
    const clotures  = filtered.filter(r =>  isCloture(r));
    const today     = new Date().toLocaleDateString('fr-FR');
    const ALL_REGIONS = ['Gabes','Gafsa','Kebili','Medenine','Sfax','Tataouine','Tozeur'];

    const parseN  = v => { const n = parseFloat(String(v||'').replace(/\s/g,'').replace(',','.')); return isNaN(n)?0:n; };
    const fmtPct  = v => { const n = parseN(v); return n===0?'0%':`${n.toFixed(0)}%`; };
    const fmtMDT  = v => { const n = parseN(v); if(!n) return '—'; if(n>=1e6) return `${(n/1e6).toFixed(1)} MDT`; return `${(n/1e3).toFixed(0)} kDT`; };
    const selVal  = v => { if(!v) return ''; if(typeof v==='object'&&v.value!==undefined) return String(v.value); return String(v); };

    const totalBudget = actifs.reduce((s,r)=>s+parseN(r.tot_marche||r.totmarche||r.montant),0);
    const phyList     = actifs.map(r=>parseN(r.taux_phy||r.avt_phy)).filter(v=>v>0);
    const avgPhy      = phyList.length ? phyList.reduce((a,b)=>a+b,0)/phyList.length : 0;
    const alerteItems = actifs
      .map(r=>({...r,_d: (() => { const v=parseInt(String(r.delai_restant||''),10); return !isNaN(v)?v:null; })()}))
      .filter(r=>r._d!==null&&r._d<=DELAI_ATTENTION)
      .sort((a,b)=>a._d-b._d);

    const SEUIL_STD = parseFloat(process.env.SEUIL_STANDARD||70);
    const SEUIL_MOD = parseFloat(process.env.SEUIL_MODERNISATION||50);
    const classify  = r => {
      const t = parseN(r.taux_phy||r.avt_phy);
      const s = String(selVal(r.nature)||'').toLowerCase().includes('modern') ? SEUIL_MOD : SEUIL_STD;
      if(!t) return 'Non déterminé';
      if(t>=SEUIL_CRITIQUE_PCT) return 'Dépassement';
      if(t>=s) return 'Normal';
      return 'Sous Avancement';
    };
    const normal = actifs.filter(r=>classify(r)==='Normal');
    const sous   = actifs.filter(r=>classify(r)==='Sous Avancement');
    const dep    = actifs.filter(r=>classify(r)==='Dépassement');

    const pptx = new PptxGenJS();
    pptx.layout  = 'LAYOUT_WIDE';
    pptx.author  = 'RLA API';
    pptx.company = 'Tunisie Telecom Zone Sud';
    pptx.subject = 'Marchés RLA Zone Sud';

    const addFooter = slide => {
      slide.addText(`Tunisie Telecom  •  Zone Sud  •  ${today}`, {
        x: 0, y: 5.3, w: '100%', h: 0.25,
        fontSize: 8, color: '64748B', align: 'center',
      });
    };

    // ── Slide 1: Couverture
    const s1 = pptx.addSlide();
    s1.background = { color: '002D62' };
    s1.addShape(pptx.ShapeType.rect, { x: 0, y: 0, w: '100%', h: 0.08, fill: { color: '00D4FF' } });
    s1.addText('TUNISIE TELECOM', { x: 0.5, y: 0.4, w: '90%', h: 0.5, fontSize: 14, color: '94A3B8', align: 'center' });
    s1.addText('RAPPORT DE SUIVI DES MARCHÉS RLA', { x: 0.5, y: 1.1, w: '90%', h: 1.0, fontSize: 30, bold: true, color: 'FFFFFF', align: 'center' });
    s1.addText('Zone Sud — Situation Actuelle & Pilotage Proactif', { x: 0.5, y: 2.2, w: '90%', h: 0.5, fontSize: 16, color: '00D4FF', align: 'center' });
    s1.addShape(pptx.ShapeType.rect, { x: 3.5, y: 3.0, w: 6.5, h: 0.05, fill: { color: '00D4FF' }, line: { color: '00D4FF' } });
    s1.addText(`📅 ${today}`, { x: 0.5, y: 3.2, w: '90%', h: 0.4, fontSize: 12, color: 'CBD5E1', align: 'center' });
    s1.addText(`📋 ${actifs.length} marchés actifs  │  💰 ${fmtMDT(totalBudget)}`, { x: 0.5, y: 3.7, w: '90%', h: 0.4, fontSize: 11, color: '94A3B8', align: 'center' });
    s1.addShape(pptx.ShapeType.rect, { x: 0, y: 5.47, w: '100%', h: 0.08, fill: { color: '00D4FF' } });

    // ── Slide 2: Synthèse globale
    const s2 = pptx.addSlide();
    s2.background = { color: '0F172A' };
    s2.addText('SYNTHÈSE GLOBALE', { x: 0.3, y: 0.15, w: '90%', h: 0.45, fontSize: 18, bold: true, color: '00D4FF' });
    s2.addShape(pptx.ShapeType.rect, { x: 0.3, y: 0.6, w: 9.4, h: 0.04, fill: { color: '002D62' } });

    const kpis = [
      { label: 'Total Marchés', val: String(actifs.length), color: '00D4FF' },
      { label: 'Budget Total',  val: fmtMDT(totalBudget),   color: '10B981' },
      { label: 'Avt. Phy Moy',  val: fmtPct(avgPhy),        color: '10B981' },
      { label: 'Alertes',       val: String(alerteItems.filter(r=>r._d<=DELAI_CRITIQUE).length), color: 'EF4444' },
    ];
    kpis.forEach((k, i) => {
      const x = 0.3 + i * 2.5;
      s2.addShape(pptx.ShapeType.roundRect, { x, y: 0.75, w: 2.3, h: 1.3, fill: { color: '1E3A5F' }, line: { color: '002D62' } });
      s2.addText(k.val,   { x, y: 0.85, w: 2.3, h: 0.7, fontSize: 26, bold: true, color: k.color, align: 'center' });
      s2.addText(k.label, { x, y: 1.6,  w: 2.3, h: 0.35, fontSize: 9, color: '94A3B8', align: 'center' });
    });

    // Par statut
    const parStatut = {};
    for (const r of filtered) {
      const s = selVal(r.observation) || 'Inconnu';
      parStatut[s] = (parStatut[s] || 0) + 1;
    }
    const statRows = Object.entries(parStatut).slice(0, 8).map(([s, n]) => [
      { text: s,      options: { color: 'CBD5E1', fontSize: 9 } },
      { text: String(n), options: { color: '00D4FF', bold: true, fontSize: 9, align: 'right' } },
    ]);
    if (statRows.length) {
      s2.addText('Répartition par Statut', { x: 0.3, y: 2.2, w: 4, h: 0.3, fontSize: 11, bold: true, color: 'FFFFFF' });
      s2.addTable([
        [{ text: 'Statut', options: { bold: true, color: 'FFFFFF', fill: '002D62', fontSize: 9 } },
         { text: 'Nb',     options: { bold: true, color: 'FFFFFF', fill: '002D62', fontSize: 9 } }],
        ...statRows,
      ], { x: 0.3, y: 2.55, w: 4, fontSize: 9, border: { type: 'solid', color: '1E3A5F' }, colW: [3.2, 0.8] });
    }

    // Par région
    const regData = ['Gabes','Gafsa','Kebili','Medenine','Sfax','Tataouine','Tozeur'].map(reg => {
      const ra = actifs.filter(r=>(r.region||'')===reg);
      const pl = ra.map(r=>parseN(r.taux_phy||r.avt_phy)).filter(v=>v>0);
      const pm = pl.length ? pl.reduce((a,b)=>a+b,0)/pl.length : 0;
      return [
        { text: reg,             options: { color: 'CBD5E1', fontSize: 9 } },
        { text: String(ra.length),  options: { color: '00D4FF', bold: true, fontSize: 9, align: 'center' } },
        { text: fmtPct(pm),      options: { color: pm>=70?'10B981':'EF4444', bold: true, fontSize: 9, align: 'center' } },
      ];
    });
    s2.addText('Par Région', { x: 5.2, y: 2.2, w: 4.5, h: 0.3, fontSize: 11, bold: true, color: 'FFFFFF' });
    s2.addTable([
      [{ text: 'Région', options: { bold: true, color: 'FFFFFF', fill: '002D62', fontSize: 9 } },
       { text: 'Marchés', options: { bold: true, color: 'FFFFFF', fill: '002D62', fontSize: 9 } },
       { text: 'Phy %', options: { bold: true, color: 'FFFFFF', fill: '002D62', fontSize: 9 } }],
      ...regData,
    ], { x: 5.2, y: 2.55, w: 4.5, fontSize: 9, border: { type: 'solid', color: '1E3A5F' }, colW: [2.5, 1.0, 1.0] });
    addFooter(s2);

    // ── Slide 3: Alertes
    const s3 = pptx.addSlide();
    s3.background = { color: '0F172A' };
    s3.addText('ALERTES DÉLAIS', { x: 0.3, y: 0.15, w: '90%', h: 0.45, fontSize: 18, bold: true, color: 'EF4444' });
    s3.addShape(pptx.ShapeType.rect, { x: 0.3, y: 0.6, w: 9.4, h: 0.04, fill: { color: 'EF4444' } });
    s3.addText(`${alerteItems.filter(r=>r._d<=DELAI_CRITIQUE).length} critique(s)  •  ${alerteItems.length} total`, {
      x: 0.3, y: 0.7, w: 9.4, h: 0.3, fontSize: 10, color: '94A3B8',
    });
    if (alerteItems.length) {
      const alertRows = alerteItems.slice(0, 18).map(r => {
        const alColor = r._d <= DELAI_CRITIQUE ? 'EF4444' : 'EA580C';
        return [
          { text: buildRef(r), options: { fontSize: 8, color: 'CBD5E1' } },
          { text: r.projet||'',                  options: { fontSize: 8, color: 'CBD5E1' } },
          { text: r.region||'',                  options: { fontSize: 8, color: 'CBD5E1' } },
          { text: r.entrepreneur||'',            options: { fontSize: 8, color: 'CBD5E1' } },
          { text: String(r._d||'—'),             options: { fontSize: 8, bold: true, color: alColor, align: 'center' } },
        ];
      });
      s3.addTable([
        ['Référence','Projet','Région','Entrepreneur','Délai (j)'].map(t => ({
          text: t, options: { bold: true, color: 'FFFFFF', fill: '7F1D1D', fontSize: 8 },
        })),
        ...alertRows,
      ], { x: 0.3, y: 1.1, w: 9.4, fontSize: 8, border: { type: 'solid', color: '1E3A5F' }, colW: [2.0, 2.5, 1.2, 2.5, 1.2] });
    }
    addFooter(s3);

    // ── Slide 4: Pilotage proactif
    const s4 = pptx.addSlide();
    s4.background = { color: '0F172A' };
    s4.addText('PILOTAGE PROACTIF', { x: 0.3, y: 0.15, w: '90%', h: 0.45, fontSize: 18, bold: true, color: '00D4FF' });
    s4.addShape(pptx.ShapeType.rect, { x: 0.3, y: 0.6, w: 9.4, h: 0.04, fill: { color: '002D62' } });

    const pilotKpis = [
      { label: 'Normal',          val: String(normal.length),  color: '10B981' },
      { label: 'Sous Avancement', val: String(sous.length),    color: 'EF4444' },
      { label: 'Dépassement',     val: String(dep.length),     color: 'EA580C' },
    ];
    pilotKpis.forEach((k, i) => {
      const x = 0.5 + i * 3.3;
      s4.addShape(pptx.ShapeType.roundRect, { x, y: 0.75, w: 3.0, h: 1.0, fill: { color: '1E3A5F' }, line: { color: '002D62' } });
      s4.addText(k.val,   { x, y: 0.8,  w: 3.0, h: 0.55, fontSize: 28, bold: true, color: k.color, align: 'center' });
      s4.addText(k.label, { x, y: 1.4,  w: 3.0, h: 0.25, fontSize: 9,  color: '94A3B8', align: 'center' });
    });

    const pilotItems = [...sous, ...dep].slice(0, 18);
    if (pilotItems.length) {
      const pilRows = pilotItems.map((r, i) => {
        const t = parseN(r.taux_phy||r.avt_phy);
        const res = classify(r);
        return [
          { text: buildRef(r),  options: { fontSize: 8, color: 'CBD5E1' } },
          { text: r.projet||'',                   options: { fontSize: 8, color: 'CBD5E1' } },
          { text: r.region||'',                   options: { fontSize: 8, color: 'CBD5E1' } },
          { text: r.entrepreneur||'',             options: { fontSize: 8, color: 'CBD5E1' } },
          { text: fmtPct(t),                      options: { fontSize: 8, bold: true, color: t>=SEUIL_CRITIQUE_PCT?'EA580C':'EF4444', align: 'center' } },
          { text: res,                            options: { fontSize: 8, bold: true, color: res==='Dépassement'?'EA580C':'EF4444', align: 'center' } },
        ];
      });
      s4.addText('Marchés Sous Avancement & Dépassement', { x: 0.3, y: 1.9, w: 9.4, h: 0.3, fontSize: 10, bold: true, color: 'FFFFFF' });
      s4.addTable([
        ['Référence','Projet','Région','Entrepreneur','Phy %','Résultat'].map(t => ({
          text: t, options: { bold: true, color: 'FFFFFF', fill: '002D62', fontSize: 8 },
        })),
        ...pilRows,
      ], { x: 0.3, y: 2.25, w: 9.4, fontSize: 8, border: { type: 'solid', color: '1E3A5F' }, colW: [2.0, 2.3, 1.0, 2.0, 0.9, 1.2] });
    }
    addFooter(s4);

    // ── Slide 5: Par région
    const s5 = pptx.addSlide();
    s5.background = { color: '0F172A' };
    s5.addText('SYNTHÈSE PAR RÉGION', { x: 0.3, y: 0.15, w: '90%', h: 0.45, fontSize: 18, bold: true, color: '00D4FF' });
    s5.addShape(pptx.ShapeType.rect, { x: 0.3, y: 0.6, w: 9.4, h: 0.04, fill: { color: '002D62' } });

    const regTableData = ALL_REGIONS.map(reg => {
      const ra  = actifs.filter(r=>(r.region||'')===reg);
      const rc  = filtered.filter(r=>(r.region||'')===reg&&isCloture(r));
      const bud = ra.reduce((s,r)=>s+parseN(r.tot_marche||r.totmarche||r.montant),0);
      const pl  = ra.map(r=>parseN(r.taux_phy||r.avt_phy)).filter(v=>v>0);
      const pm  = pl.length ? pl.reduce((a,b)=>a+b,0)/pl.length : 0;
      const al  = ra.map(r=>({_d:parseInt(String(r.delai_restant||''),10)||null})).filter(r=>r._d!==null&&r._d<=DELAI_ATTENTION);
      return [
        { text: reg,              options: { color: '00D4FF', bold: true, fontSize: 9 } },
        { text: String(ra.length), options: { color: 'CBD5E1', fontSize: 9, align: 'center' } },
        { text: String(rc.length), options: { color: '64748B', fontSize: 9, align: 'center' } },
        { text: fmtMDT(bud),      options: { color: 'CBD5E1', fontSize: 9, align: 'right' } },
        { text: fmtPct(pm),       options: { color: pm>=70?'10B981':'EF4444', bold: true, fontSize: 9, align: 'center' } },
        { text: String(al.length), options: { color: al.length>0?'EF4444':'10B981', bold: true, fontSize: 9, align: 'center' } },
      ];
    });
    s5.addTable([
      ['Région','Actifs','Clôturés','Budget','Phy Moy','Alertes'].map(t => ({
        text: t, options: { bold: true, color: 'FFFFFF', fill: '002D62', fontSize: 9 },
      })),
      ...regTableData,
    ], { x: 0.3, y: 0.75, w: 9.4, fontSize: 9, border: { type: 'solid', color: '1E3A5F' }, colW: [2.0, 1.2, 1.2, 1.8, 1.5, 1.7] });
    addFooter(s5);

    const filename = `Marches_RLA_Zone_Sud_${new Date().toISOString().slice(0,10)}.pptx`;
    const buf = await pptx.write({ outputType: 'nodebuffer' });
    res.set({
      'Content-Type':        'application/vnd.openxmlformats-officedocument.presentationml.presentation',
      'Content-Disposition': `attachment; filename="${filename}"`,
    });
    res.end(buf);
  } catch (err) {
    res.status(502).json({ error: 'Erreur génération PPTX', detail: err.message });
  }
});

// ─── Route DOCX (SuperAdmin) ──────────────────────────────────────────────────

router.get('/docx', async (req, res) => {
  if (req.user?.role !== 'superadmin') {
    return res.status(403).json({ error: 'Accès réservé au SuperAdmin' });
  }
  try {
    const {
      Document, Packer, Paragraph, Table, TableRow, TableCell,
      TextRun, HeadingLevel, AlignmentType, WidthType, PageBreak,
      Header, Footer, ImageRun,
    } = require('docx');

    const allRows  = await getMarches();
    const filtered = applyFilters(allRows, req);
    const actifs   = filtered.filter(r => !isCloture(r));
    const clotures = filtered.filter(r =>  isCloture(r));
    const today    = new Date().toLocaleDateString('fr-FR');
    const ALL_REGIONS = ['Gabes','Gafsa','Kebili','Medenine','Sfax','Tataouine','Tozeur'];

    const parseN  = v => { const n = parseFloat(String(v||'').replace(/\s/g,'').replace(',','.')); return isNaN(n)?0:n; };
    const fmtPct  = v => { const n = parseN(v); return n===0?'0 %':`${n.toFixed(0)} %`; };
    const fmtMDT  = v => { const n = parseN(v); if(!n) return '—'; if(n>=1e6) return `${(n/1e6).toFixed(1)} MDT`; return `${(n/1e3).toFixed(0)} kDT`; };
    const selVal  = v => { if(!v) return ''; if(typeof v==='object'&&v.value!==undefined) return String(v.value); return String(v); };
    const parseDt = d => { if(!d) return null; const p=String(d).split(/[\/\-]/); if(p.length===3){const[a,b,c]=p; if(a.length===4) return new Date(`${a}-${b}-${c}`); if(c.length===4) return new Date(`${c}-${b}-${a}`);} const dt=new Date(d); return isNaN(dt.getTime())?null:dt; };
    const fmtDate = d => { const dt=parseDt(d); if(!dt) return '—'; return dt.toLocaleDateString('fr-FR',{day:'2-digit',month:'2-digit',year:'numeric'}); };

    const totalBudget = actifs.reduce((s,r)=>s+parseN(r.tot_marche||r.totmarche||r.montant),0);
    const phyList     = actifs.map(r=>parseN(r.taux_phy||r.avt_phy)).filter(v=>v>0);
    const avgPhy      = phyList.length ? phyList.reduce((a,b)=>a+b,0)/phyList.length : 0;

    const SEUIL_STD = parseFloat(process.env.SEUIL_STANDARD||70);
    const SEUIL_MOD = parseFloat(process.env.SEUIL_MODERNISATION||50);
    const classify  = r => {
      const t = parseN(r.taux_phy||r.avt_phy);
      const s = String(selVal(r.nature)||'').toLowerCase().includes('modern') ? SEUIL_MOD : SEUIL_STD;
      if(!t) return 'Non déterminé';
      if(t>=SEUIL_CRITIQUE_PCT) return 'Dépassement';
      if(t>=s) return 'Normal';
      return 'Sous Avancement';
    };

    // Helpers
    const navyFill = { fill: '002D62' };
    const altFill  = { fill: 'F1F5F9' };
    const hdr = (texts, opts={}) => new Paragraph({ children: texts, ...opts });
    const tr = (cells, isHeader=false) => new TableRow({
      tableHeader: isHeader,
      children: cells.map(([text, width, shade]) => new TableCell({
        children: [new Paragraph({
          children: [new TextRun({ text: String(text??'—'), bold: isHeader, color: isHeader?'FFFFFF':'1E293B', size: 18 })],
          alignment: AlignmentType.LEFT,
        })],
        width: { size: width||1000, type: WidthType.DXA },
        shading: shade || (isHeader ? navyFill : undefined),
      })),
    });
    const h1 = text => new Paragraph({
      children: [new TextRun({ text, bold: true, color: '002D62', size: 32 })],
      spacing: { before: 300, after: 150 },
      border: { bottom: { style: 'single', size: 8, color: '00D4FF' } },
    });
    const h2 = text => new Paragraph({
      children: [new TextRun({ text, bold: true, color: '0F172A', size: 24 })],
      spacing: { before: 200, after: 100 },
    });
    const spacer = () => new Paragraph({ text: '', spacing: { before: 80, after: 80 } });

    const children = [];

    // ── Page de couverture
    children.push(new Paragraph({ children: [new TextRun({ text: '', break: 4 })] }));
    children.push(new Paragraph({
      children: [new TextRun({ text: 'TUNISIE TELECOM', bold: true, color: '002D62', size: 36, allCaps: true })],
      alignment: AlignmentType.CENTER,
      spacing: { before: 100, after: 50 },
    }));
    children.push(new Paragraph({
      children: [new TextRun({ text: 'Direction Centrale', color: '64748B', size: 24 })],
      alignment: AlignmentType.CENTER,
    }));
    children.push(new Paragraph({
      children: [new TextRun({ text: 'Zone Sud', color: '64748B', size: 24 })],
      alignment: AlignmentType.CENTER,
      spacing: { after: 200 },
    }));
    children.push(new Paragraph({
      children: [new TextRun({ text: 'Rapport de Suivi des Marchés RLA', bold: true, color: '002D62', size: 44 })],
      alignment: AlignmentType.CENTER,
      spacing: { before: 100, after: 80 },
    }));
    children.push(new Paragraph({
      children: [new TextRun({ text: 'Situation Actuelle & Analyse Prospective', color: '0F172A', size: 26 })],
      alignment: AlignmentType.CENTER,
      spacing: { after: 200 },
    }));
    children.push(new Paragraph({
      children: [new TextRun({ text: `📅  ${today}      📋  ${actifs.length} marchés      💰  Budget total : ${fmtMDT(totalBudget)}`, color: '475569', size: 20 })],
      alignment: AlignmentType.CENTER,
      spacing: { after: 100 },
    }));
    children.push(new Paragraph({ children: [new PageBreak()] }));

    // ── Sommaire exécutif
    children.push(h1('Sommaire Exécutif'));
    children.push(new Paragraph({
      children: [new TextRun({ text: `Ce rapport présente la situation au ${today} des ${actifs.length} marchés actifs de la Zone Sud de Tunisie Telecom. Budget global engagé : ${fmtMDT(totalBudget)}. Avancement physique moyen : ${fmtPct(avgPhy)}.`, size: 20, color: '374151' })],
      spacing: { after: 120 },
    }));

    // KPI table
    const normal = actifs.filter(r=>classify(r)==='Normal').length;
    const sous   = actifs.filter(r=>classify(r)==='Sous Avancement').length;
    const dep    = actifs.filter(r=>classify(r)==='Dépassement').length;
    const nd     = actifs.filter(r=>classify(r)==='Non déterminé').length;

    children.push(new Paragraph({ children: [new TextRun({ text: 'Indicateurs Clés', bold: true, size: 22, color: '002D62' })], spacing: { before: 150, after: 80 } }));
    children.push(new Table({
      width: { size: 100, type: WidthType.PERCENTAGE },
      rows: [
        tr([['Indicateur',2500,navyFill],['Valeur',2000,navyFill]], true),
        tr([['Total marchés actifs', 2500], [String(actifs.length), 2000]]),
        tr([['Marchés clôturés',     2500], [String(clotures.length), 2000]], false),
        tr([['Budget total',         2500], [fmtMDT(totalBudget), 2000]], false),
        tr([['Avancement physique moyen', 2500], [fmtPct(avgPhy), 2000]], false),
        tr([['Normal',               2500], [String(normal), 2000]], false),
        tr([['Sous Avancement',      2500], [String(sous),   2000]], false),
        tr([['Dépassement',          2500], [String(dep),    2000]], false),
      ],
    }));
    children.push(new Paragraph({ children: [new PageBreak()] }));

    // ── Alertes
    children.push(h1('Alertes Délais'));
    const alerteItems = actifs
      .map(r => ({ ...r, _d: (() => { const v=parseInt(String(r.delai_restant||''),10); return !isNaN(v)?v:null; })() }))
      .filter(r => r._d !== null && r._d <= DELAI_ATTENTION)
      .sort((a, b) => a._d - b._d);

    children.push(new Paragraph({
      children: [new TextRun({ text: `${alerteItems.filter(r=>r._d<=DELAI_CRITIQUE).length} marché(s) en alerte critique (< ${DELAI_CRITIQUE}j)  •  ${alerteItems.length} total (< ${DELAI_ATTENTION}j)`, size: 20, color: 'EF4444', bold: true })],
      spacing: { after: 100 },
    }));
    if (alerteItems.length) {
      children.push(new Table({
        width: { size: 100, type: WidthType.PERCENTAGE },
        rows: [
          tr([['Référence',2500,navyFill],['Projet',3000,navyFill],['Région',1200,navyFill],['Délai (j)',1200,navyFill]], true),
          ...alerteItems.slice(0,20).map((r, i) => tr([
            [buildRef(r), 2500, i%2===1?altFill:undefined],
            [r.projet||'',                  3000, i%2===1?altFill:undefined],
            [r.region||'',                  1200, i%2===1?altFill:undefined],
            [String(r._d||'—'),             1200, i%2===1?altFill:undefined],
          ])),
        ],
      }));
    }
    children.push(new Paragraph({ children: [new PageBreak()] }));

    // ── Synthèse par région
    children.push(h1('Synthèse par Région'));
    for (const region of ALL_REGIONS) {
      const regActifs = actifs.filter(r => (r.region||'') === region);
      if (!regActifs.length) continue;
      children.push(h2(`📍 ${region}`));
      const bud = regActifs.reduce((s,r)=>s+parseN(r.tot_marche||r.totmarche||r.montant),0);
      const pl  = regActifs.map(r=>parseN(r.taux_phy||r.avt_phy)).filter(v=>v>0);
      const pm  = pl.length ? pl.reduce((a,b)=>a+b,0)/pl.length : 0;
      children.push(new Paragraph({
        children: [new TextRun({ text: `${regActifs.length} marchés  •  Budget : ${fmtMDT(bud)}  •  Phy moy : ${fmtPct(pm)}`, size: 18, color: '64748B' })],
        spacing: { after: 80 },
      }));
      children.push(new Table({
        width: { size: 100, type: WidthType.PERCENTAGE },
        rows: [
          tr([['Référence',2500,navyFill],['Projet',2800,navyFill],['Entrepreneur',2000,navyFill],['Phy %',700,navyFill],['Statut',1000,navyFill]], true),
          ...regActifs.map((r, i) => {
            const phy = parseN(r.taux_phy||r.avt_phy);
            return tr([
              [buildRef(r), 2500, i%2===1?altFill:undefined],
              [r.projet||'',                  2800, i%2===1?altFill:undefined],
              [r.entrepreneur||'',            2000, i%2===1?altFill:undefined],
              [fmtPct(phy),                   700,  i%2===1?altFill:undefined],
              [selVal(r.observation)||'—',    1000, i%2===1?altFill:undefined],
            ]);
          }),
        ],
      }));
      children.push(spacer());
    }
    children.push(new Paragraph({ children: [new PageBreak()] }));

    // ── Pilotage proactif
    children.push(h1('Pilotage Proactif'));
    children.push(new Paragraph({
      children: [new TextRun({ text: `Normal: ${normal}  •  Sous Avancement: ${sous}  •  Dépassement: ${dep}  •  Non déterminé: ${nd}`, size: 20, color: '374151' })],
      spacing: { after: 100 },
    }));
    const pilotItems = actifs.map(r => ({ r, res: classify(r), phy: parseN(r.taux_phy||r.avt_phy) }))
      .sort((a,b) => a.phy - b.phy);
    children.push(new Table({
      width: { size: 100, type: WidthType.PERCENTAGE },
      rows: [
        tr([['Référence',2200,navyFill],['Projet',2500,navyFill],['Région',1000,navyFill],['Entrepreneur',1800,navyFill],['Phy %',700,navyFill],['Résultat',1300,navyFill]], true),
        ...pilotItems.map(({ r, res, phy }, i) => tr([
          [buildRef(r), 2200, i%2===1?altFill:undefined],
          [r.projet||'',                  2500, i%2===1?altFill:undefined],
          [r.region||'',                  1000, i%2===1?altFill:undefined],
          [r.entrepreneur||'',            1800, i%2===1?altFill:undefined],
          [fmtPct(phy),                   700,  i%2===1?altFill:undefined],
          [res,                           1300, i%2===1?altFill:undefined],
        ])),
      ],
    }));

    const doc = new Document({
      creator: 'RLA API',
      description: 'Rapport Marchés Tunisie Telecom Zone Sud',
      title: 'Rapport RLA Zone Sud',
      sections: [{ children }],
    });
    const buf = await Packer.toBuffer(doc);
    const filename = `Rapport_RLA_Zone_Sud_${new Date().toISOString().slice(0,10)}.docx`;
    res.set({
      'Content-Type':        'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
      'Content-Disposition': `attachment; filename="${filename}"`,
    });
    res.end(buf);
  } catch (err) {
    res.status(502).json({ error: 'Erreur génération DOCX', detail: err.message });
  }
});

module.exports = router;
