/**
 * services/export-pdf.js
 * Génération de PDF par vue avec PDFKit (async/Promise)
 */
const PDFDocument = require('pdfkit');

// Palette RLA / McKinsey
const C = {
  primary: '#002D62',
  accent:  '#E31837',
  success: '#10b981',
  warning: '#f59e0b',
  danger:  '#ef4444',
  muted:   '#6b7280',
  light:   '#f8fafc',
  border:  '#e2e8f0',
  text:    '#1e293b',
  white:   '#ffffff',
};

function hex(h) {
  const s = h.replace('#', '');
  return [parseInt(s.slice(0,2),16), parseInt(s.slice(2,4),16), parseInt(s.slice(4,6),16)];
}
const fill   = (d, h) => d.fillColor(hex(h));
const stroke = (d, h) => d.strokeColor(hex(h));

// ─── Collect PDF to Buffer ────────────────────────────────────────────────────

function pdfToBuffer(doc, writeFn) {
  return new Promise((resolve, reject) => {
    const chunks = [];
    doc.on('data',  c => chunks.push(c));
    doc.on('end',   ()  => resolve(Buffer.concat(chunks)));
    doc.on('error', err => reject(err));
    try { writeFn(doc); doc.end(); } catch (e) { reject(e); }
  });
}

// ─── Header / Footer ─────────────────────────────────────────────────────────

function header(doc, title, subtitle) {
  fill(doc, C.primary);
  doc.rect(0, 0, doc.page.width, 68).fill();
  fill(doc, C.white);
  doc.fontSize(17).font('Helvetica-Bold').text(title || '', 40, 18, { width: 500 });
  if (subtitle) doc.fontSize(9).font('Helvetica').text(subtitle, 40, 42, { width: 500 });
  const now = new Date().toLocaleDateString('fr-FR', { day:'2-digit', month:'2-digit', year:'numeric' });
  doc.fontSize(8).text(`Édité le ${now}`, 0, 50, { align:'right', width: doc.page.width - 40 });
  doc.y = 88;
}

function footer(doc, n) {
  const y = doc.page.height - 38;
  fill(doc, C.border);
  doc.rect(0, y - 4, doc.page.width, 1).fill();
  fill(doc, C.muted);
  doc.fontSize(7.5).font('Helvetica')
    .text('RLA — Marchés Tunisie Telecom Zone Sud', 40, y)
    .text(`Page ${n}`, 0, y, { align:'right', width: doc.page.width - 40 });
}

// ─── KPI Box ─────────────────────────────────────────────────────────────────

function kpiBox(doc, x, y, w, h, label, value, color) {
  fill(doc, C.light);
  doc.rect(x, y, w, h).fill();
  fill(doc, color || C.primary);
  doc.rect(x, y, 4, h).fill();
  fill(doc, C.muted);
  doc.fontSize(7.5).font('Helvetica').text(label, x+10, y+7, { width: w-14 });
  fill(doc, C.text);
  doc.fontSize(16).font('Helvetica-Bold').text(String(value ?? '—'), x+10, y+20, { width: w-14 });
}

// ─── Table ────────────────────────────────────────────────────────────────────

function table(doc, { title, headers, rows, colWidths }) {
  const pageW  = doc.page.width - 80;
  const totalW = colWidths.reduce((a, b) => a + b, 0);
  const scale  = pageW / totalW;
  const widths = colWidths.map(w => Math.round(w * scale));
  let y = doc.y;

  if (title) {
    fill(doc, C.text);
    doc.fontSize(10).font('Helvetica-Bold').text(title, 40, y);
    y += 16;
  }

  function drawHeader() {
    fill(doc, C.primary);
    doc.rect(40, y, pageW, 17).fill();
    fill(doc, C.white);
    doc.fontSize(7.5).font('Helvetica-Bold');
    let x = 40;
    for (let i = 0; i < headers.length; i++) {
      doc.text(headers[i], x + 3, y + 4, { width: widths[i] - 6, ellipsis: true });
      x += widths[i];
    }
    y += 17;
  }
  drawHeader();

  let alt = false;
  for (const row of rows) {
    if (y > doc.page.height - 75) {
      footer(doc, '—');
      doc.addPage();
      header(doc, '', '');
      y = doc.y;
      drawHeader();
      alt = false;
    }
    const rowH = 15;
    fill(doc, alt ? '#f1f5f9' : C.white);
    doc.rect(40, y, pageW, rowH).fill();
    fill(doc, C.text);
    doc.fontSize(7).font('Helvetica');
    let x = 40;
    for (let i = 0; i < row.length; i++) {
      doc.text(String(row[i] ?? '—'), x + 3, y + 4, { width: widths[i] - 6, ellipsis: true });
      x += widths[i];
    }
    stroke(doc, C.border);
    doc.moveTo(40, y + rowH).lineTo(40 + pageW, y + rowH).stroke();
    y += rowH;
    alt = !alt;
  }
  doc.y = y + 8;
}

const NL = n => ({ critique:'CRITIQUE', attention:'ATTENTION', élevé:'ÉLEVÉ', moyen:'MOYEN', faible:'FAIBLE', normal:'NORMAL', sous_avancement:'SOUS-AVT' }[n] || String(n||'').toUpperCase());

// ─── Vues ─────────────────────────────────────────────────────────────────────

function generateSynthese(data) {
  const doc = new PDFDocument({ margin:40, size:'A4' });
  return pdfToBuffer(doc, d => {
    header(d, 'Synthèse Globale — Marchés RLA', 'Tunisie Telecom Zone Sud');
    const kpis = [
      { l:'Total Marchés',    v: data.total,   c: C.primary },
      { l:'Actifs',           v: data.actifs,  c: C.success },
      { l:'Clôturés',         v: data.clotures,c: C.muted   },
      { l:'Alertes',          v: data.alertes_delais?.count||0, c: C.warning },
      { l:'Avt. Moy.(%)',     v:`${data.taux_avancement_moyen||0}%`, c: C.accent },
    ];
    let kx = 40;
    for (const k of kpis) { kpiBox(d, kx, d.y, 95, 48, k.l, k.v, k.c); kx += 101; }
    d.y += 58;

    if (data.budget) {
      fill(d, C.text); d.fontSize(10).font('Helvetica-Bold').text('Budget', 40, d.y); d.y += 12;
      for (const [l, v] of [['Total',data.budget.total],['Consommé',data.budget.consomme],['Restant',data.budget.restant]]) {
        fill(d, C.muted); d.fontSize(8.5).font('Helvetica').text(l+' :', 40, d.y, {width:110});
        fill(d, C.text);  d.fontSize(8.5).font('Helvetica-Bold').text(v, 155, d.y, {width:250}); d.y += 13;
      }
    }
    if (data.par_statut) {
      d.y += 6;
      table(d, { title:'Répartition par Statut', headers:['Statut','Nombre'], colWidths:[350,100],
        rows: Object.entries(data.par_statut).map(([s,n])=>[s,n]) });
    }
    if (data.alertes_delais?.items?.length) {
      const items = data.alertes_delais.items.slice(0,10);
      table(d, { title:`Top ${items.length} Alertes Délais`, headers:['Réf.','Projet','Région','Entrepreneur','J. Rest.','Niveau'],
        colWidths:[70,140,65,120,55,55], rows: items.map(a=>[a.ref,a.projet,a.region,a.entrepreneur,a.delai_restant,NL(a.niveau)]) });
    }
    footer(d, 1);
  });
}

function generateAlertes(data) {
  const doc = new PDFDocument({ margin:40, size:'A4', layout:'landscape' });
  return pdfToBuffer(doc, d => {
    header(d, 'Alertes Délais — Marchés RLA', `${data.count||0} alerte(s) — dont ${data.critique||0} critique(s)`);
    if (data.items?.length) {
      table(d, { title:'Liste des Alertes', headers:['Réf.','Projet','Région','Entrepreneur','Taux Phy.','Date Fin','J. Rest.','Niveau'],
        colWidths:[70,155,65,125,55,65,55,55], rows: data.items.map(a=>[a.ref,a.projet,a.region,a.entrepreneur,a.taux_phy,a.date_fin,a.delai_restant,NL(a.niveau_alerte||a.niveau)]) });
    } else { fill(d, C.success); d.fontSize(14).font('Helvetica-Bold').text('Aucune alerte active.', {align:'center'}); }
    footer(d, 1);
  });
}

function generateEnService(data) {
  const doc = new PDFDocument({ margin:40, size:'A4', layout:'landscape' });
  return pdfToBuffer(doc, d => {
    header(d, 'Marchés en Service — RLA', `${data.count||0} marché(s) actif(s)`);
    table(d, { title:'Liste des Marchés en Service',
      headers:['Réf.','Projet','Région','Entrepreneur','Montant Max','Période','Avt. Phy.','Délai Rest.','Alerte'],
      colWidths:[65,140,65,110,90,90,55,55,60],
      rows: (data.items||[]).map(r=>[r.ref,r.projet,r.region,r.entrepreneur,r.montant,
        `${r.date_debut||'—'} → ${r.date_fin||'—'}`,r.taux_phy,r.delai_restant??'—',NL(r.niveau_alerte)]) });
    footer(d, 1);
  });
}

function generateEnCours(data) {
  const doc = new PDFDocument({ margin:40, size:'A4', layout:'landscape' });
  return pdfToBuffer(doc, d => {
    header(d, 'Marchés en Cours — RLA', `${data.count||0} marché(s) en cours`);
    table(d, { title:'Liste des Marchés en Cours',
      headers:['Réf.','Projet','Région','Entrepreneur','Montant Max','Période','Avt. Phy.','Niveau Avt.'],
      colWidths:[65,140,65,110,90,90,60,70],
      rows: (data.items||[]).map(r=>[r.ref,r.projet,r.region,r.entrepreneur,r.montant,
        `${r.date_debut||'—'} → ${r.date_fin||'—'}`,r.taux_phy,r.niveau_avancement||'—']) });
    footer(d, 1);
  });
}

function generateParRegion(data) {
  const doc = new PDFDocument({ margin:40, size:'A4' });
  return pdfToBuffer(doc, d => {
    header(d, 'Vue par Région — Marchés RLA', `${data.count||0} région(s)`);
    for (const reg of data.regions||[]) {
      if (d.y > d.page.height - 120) { footer(d, '—'); d.addPage(); header(d,'',''); }
      fill(d, C.primary); d.rect(40, d.y, d.page.width-80, 22).fill();
      fill(d, C.white); d.fontSize(11).font('Helvetica-Bold').text(reg.region, 52, d.y+5); d.y += 30;
      const kpis = [
        {l:'Actifs',v:reg.actifs},{l:'Clôturés',v:reg.clotures},
        {l:'Alertes',v:reg.alertes_count,c:C.warning},{l:'Critiques',v:reg.alertes_critique,c:C.danger},
        {l:'Taux moy.',v:`${reg.taux_moyen}%`},
      ];
      let kx=40; for(const k of kpis){kpiBox(d,kx,d.y,92,40,k.l,k.v,k.c||C.primary);kx+=98;}
      d.y+=50; d.moveDown(0.3);
    }
    footer(d, 1);
  });
}

function generateClotures(data) {
  const doc = new PDFDocument({ margin:40, size:'A4', layout:'landscape' });
  return pdfToBuffer(doc, d => {
    header(d, 'Marchés Clôturés — RLA', `${data.count||0} marché(s) — Budget : ${data.budget_total||'—'}`);
    table(d, { title:'Liste des Marchés Clôturés',
      headers:['Réf.','Projet','Région','Entrepreneur','Montant','Taux Phy.','Date Clôture'],
      colWidths:[70,155,65,130,100,60,75],
      rows: (data.items||[]).map(r=>[r.ref,r.projet,r.region,r.entrepreneur,r.montant,r.taux_phy,r.date_cloture]) });
    footer(d, 1);
  });
}

function generatePilotage(data) {
  const doc = new PDFDocument({ margin:40, size:'A4' });
  return pdfToBuffer(doc, d => {
    const r = data.resume||{};
    header(d, 'Pilotage Proactif — Marchés RLA', `Total actifs : ${r.total||0}`);
    const kpis = [
      {l:'Dans les normes',v:r.normal||0,c:C.success},
      {l:'Sous avancement',v:r.sous_avancement||0,c:C.warning},
      {l:'Dépassé',v:r.depasse||0,c:C.danger},
    ];
    let kx=40; for(const k of kpis){kpiBox(d,kx,d.y,148,50,k.l,k.v,k.c);kx+=156;}
    d.y+=62;
    const problematic = [...(data.depasse||[]),...(data.sous_avancement||[])];
    if (problematic.length) {
      table(d, { title:'Marchés à surveiller', headers:['Réf.','Projet','Région','Entrepreneur','Taux Phy.','Niveau'],
        colWidths:[70,155,65,130,60,75], rows: problematic.map(r=>[r.ref,r.projet,r.region,r.entrepreneur,r.taux_phy,r.niveau_avancement]) });
    }
    footer(d, 1);
  });
}

function generateMatriceRisque(data) {
  const doc = new PDFDocument({ margin:40, size:'A4' });
  return pdfToBuffer(doc, d => {
    const pn = data.par_niveau||{};
    header(d, 'Matrice de Risque — Marchés RLA', `${data.total||0} marchés analysés`);
    const kpis = [
      {l:'Critique',v:pn.critique||0,c:C.danger},
      {l:'Élevé',v:pn['élevé']||0,c:C.warning},
      {l:'Moyen',v:pn.moyen||0,c:'#6366f1'},
      {l:'Faible',v:pn.faible||0,c:C.success},
    ];
    let kx=40; for(const k of kpis){kpiBox(d,kx,d.y,110,50,k.l,k.v,k.c);kx+=118;}
    d.y+=62;
    if (data.items?.length) {
      const sorted = [...data.items].sort((a,b)=>(b.score_delai+b.score_avancement)-(a.score_delai+a.score_avancement));
      table(d, { title:'Marchés classés par niveau de risque', headers:['Réf.','Projet','Région','Entrepreneur','Taux Phy.','J. Rest.','Risque'],
        colWidths:[70,145,65,125,55,50,55], rows: sorted.map(r=>[r.ref,r.projet,r.region,r.entrepreneur,r.taux_phy,r.delai_restant??'—',NL(r.niveau_risque)]) });
    }
    footer(d, 1);
  });
}

function generateGeneric(title, data) {
  const doc = new PDFDocument({ margin:40, size:'A4', layout:'landscape' });
  return pdfToBuffer(doc, d => {
    header(d, title, '');
    const items = data.items||[];
    if (items.length) {
      const keys = Object.keys(items[0]).filter(k=>!k.endsWith('_raw')&&k!=='id'&&typeof items[0][k]!=='object').slice(0,8);
      table(d, { headers:keys, colWidths:keys.map(()=>Math.floor(700/keys.length)),
        rows: items.slice(0,100).map(r=>keys.map(k=>r[k])) });
    }
    footer(d, 1);
  });
}

module.exports = {
  generateSynthese, generateAlertes, generateEnService, generateEnCours,
  generateParRegion, generateClotures, generatePilotage, generateMatriceRisque, generateGeneric,
};
