/**
 * services/export-xlsx.js
 * Génération XLSX comprehensive — Situation des Marchés RLA Zone Sud
 */
const ExcelJS  = require('exceljs');
const { buildRef } = require('./calc');

const C = {
  NAVY:    'FF002D62',
  WHITE:   'FFFFFFFF',
  ACCENT:  'FF00D4FF',
  GREEN:   'FF16A34A',
  ORANGE:  'FFEA580C',
  RED:     'FFDC2626',
  YELLOW:  'FFEAB308',
  GRAY:    'FF64748B',
  ALT:     'FFF1F5F9',
  LIGHT:   'FFE2E8F0',
  CAPEX:   'FFD1FAE5',
  OPEX:    'FFFEF3C7',
  TOTAL:   'FFDBEAFE',
  HEADER:  'FF0F172A',
};

function fill(argb) { return { type: 'pattern', pattern: 'solid', fgColor: { argb } }; }
function font(argb, bold = false, size = 10) { return { color: { argb }, bold, size }; }
function border(color = C.LIGHT) {
  const s = { style: 'thin', color: { argb: color } };
  return { top: s, bottom: s, left: s, right: s };
}

const ALL_REGIONS = ['Gabes', 'Gafsa', 'Kebili', 'Medenine', 'Sfax', 'Tataouine', 'Tozeur'];

function parseNum(v) {
  if (v === null || v === undefined || v === '') return 0;
  if (typeof v === 'object') return 0;
  const n = parseFloat(String(v).replace(/\s/g, '').replace(',', '.'));
  return isNaN(n) ? 0 : n;
}

function selectVal(v) {
  if (!v) return '';
  if (typeof v === 'object' && v.value !== undefined) return String(v.value);
  if (Array.isArray(v)) return v.map(x => x.value !== undefined ? x.value : x).join(', ');
  return String(v);
}

function parseDateFR(d) {
  if (!d) return null;
  const parts = String(d).split(/[\/\-]/);
  if (parts.length === 3) {
    const [a, b, c] = parts;
    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;
}

function fmtDate(d) {
  const dt = parseDateFR(d);
  if (!dt) return '-';
  return dt.toLocaleDateString('fr-FR', { day: '2-digit', month: '2-digit', year: 'numeric' });
}

function fmtMDT(val) {
  const n = parseNum(val);
  if (n === 0) return '0';
  if (n >= 1000000) return `${(n / 1000000).toFixed(1)} MDT`;
  if (n >= 1000)    return `${(n / 1000).toFixed(0)} kDT`;
  return `${n.toFixed(0)} DT`;
}

function isCloture(r) {
  const obs = selectVal(r.observation).toLowerCase();
  return obs.includes('clôtur') || obs.includes('clotur') || !!r.date_cloture;
}

function getDelai(r) {
  const dField = r.delai_restant;
  if (dField !== null && dField !== undefined && dField !== '') {
    const v = parseInt(String(dField), 10);
    if (!isNaN(v)) return v;
  }
  const fin = r.date_fin || r.date_fin_marche || r.datefin;
  const dt  = parseDateFR(fin);
  if (!dt) return '-';
  return Math.ceil((dt - new Date()) / 86400000);
}

async function generateXlsx(view, data, allRows) {
  const wb = new ExcelJS.Workbook();
  wb.creator  = 'RLA API';
  wb.company  = 'Tunisie Telecom Zone Sud';
  wb.created  = new Date();

  const rows   = allRows || data.items || data.regions || [];
  const actifs = allRows ? rows.filter(r => !isCloture(r)) : rows;

  await buildSheet1(wb, actifs);
  await buildSheet2(wb, actifs);

  return wb.xlsx.writeBuffer();
}

async function buildSheet1(wb, actifs) {
  const ws = wb.addWorksheet('Situation des Marchés');
  ws.views = [{ state: 'frozen', ySplit: 9 }];

  // Column widths
  const cols = [
    { width: 40 }, { width: 20 }, { width: 22 }, { width: 12 },
    { width: 16 }, { width: 14 }, { width: 8  }, { width: 14 },
    { width: 8  }, { width: 14 }, { width: 14 }, { width: 8  }, { width: 22 },
  ];
  ws.columns = cols.map((c, i) => ({ key: String.fromCharCode(65 + i), width: c.width }));

  const today    = new Date().toLocaleDateString('fr-FR');
  const capex    = actifs.filter(r => String(selectVal(r.nature)).toUpperCase().includes('CAPEX') ||
                                     !String(selectVal(r.nature)).toUpperCase().includes('OPEX'));
  const opex     = actifs.filter(r => String(selectVal(r.nature)).toUpperCase().includes('OPEX'));
  const totalBudget = actifs.reduce((s, r) => s + parseNum(r.tot_marche || r.totmarche || r.montant), 0);

  const avgPhy = (() => {
    const vals = actifs.map(r => parseNum(r.taux_phy || r.avt_phy)).filter(v => v > 0);
    return vals.length ? vals.reduce((a, b) => a + b, 0) / vals.length : 0;
  })();

  // Row 1: Title
  const r1 = ws.addRow(['📊  SITUATION DES MARCHÉS RLA — ZONE SUD', ...Array(12).fill('')]);
  r1.height = 30;
  ws.mergeCells('A1:M1');
  const c1 = r1.getCell(1);
  c1.fill  = fill(C.NAVY);
  c1.font  = { color: { argb: C.WHITE }, bold: true, size: 16 };
  c1.alignment = { horizontal: 'center', vertical: 'middle' };

  // Row 2: Subtitle
  const r2 = ws.addRow([`Tunisie Telecom  •  Direction Centrale Achats  •  Zone Sud`, ...Array(12).fill('')]);
  r2.height = 18;
  ws.mergeCells('A2:M2');
  r2.getCell(1).fill = fill('FF0F172A');
  r2.getCell(1).font = font('FFCBD5E1', false, 11);
  r2.getCell(1).alignment = { horizontal: 'center', vertical: 'middle' };

  // Row 3: Stats bar
  const r3 = ws.addRow([
    `📅 ${today}   │   📋 ${actifs.length} marchés   │   💰 ${fmtMDT(totalBudget)}   │   📈 Phy moy: ${avgPhy.toFixed(0)}%`,
    ...Array(12).fill(''),
  ]);
  r3.height = 16;
  ws.mergeCells('A3:M3');
  r3.getCell(1).fill = fill('FF1E3A5F');
  r3.getCell(1).font = font('FF94A3B8', false, 10);
  r3.getCell(1).alignment = { horizontal: 'center', vertical: 'middle' };

  // Row 4: empty
  ws.addRow([]);

  // Row 5: KPI headers
  const r5 = ws.addRow(['📊  GLOBAL', '', '', '', '', '🟢  CAPEX', '', '', '', '', '🟠  OPEX', '', '']);
  r5.height = 22;
  ws.mergeCells('A5:E5'); ws.mergeCells('F5:J5'); ws.mergeCells('K5:M5');
  const kpiHdrStyle = (cell, argb) => {
    cell.fill = fill(argb);
    cell.font = { color: { argb: C.WHITE }, bold: true, size: 11 };
    cell.alignment = { horizontal: 'center', vertical: 'middle' };
  };
  kpiHdrStyle(r5.getCell(1), C.NAVY);
  kpiHdrStyle(r5.getCell(6), 'FF16A34A');
  kpiHdrStyle(r5.getCell(11), C.ORANGE);

  const capexBudget = capex.reduce((s, r) => s + parseNum(r.tot_marche || r.totmarche || r.montant), 0);
  const opexBudget  = opex.reduce((s, r) => s + parseNum(r.tot_marche || r.totmarche || r.montant), 0);
  const capexPhy    = (() => { const v = capex.map(r => parseNum(r.taux_phy || r.avt_phy)).filter(x => x > 0); return v.length ? v.reduce((a,b)=>a+b,0)/v.length : 0; })();
  const opexPhy     = (() => { const v = opex.map(r => parseNum(r.taux_phy || r.avt_phy)).filter(x => x > 0); return v.length ? v.reduce((a,b)=>a+b,0)/v.length : 0; })();

  // Row 6: KPI values
  const r6 = ws.addRow([`${actifs.length} marchés`, '', '', '', '',
    `${capex.length} marchés`, '', '', '', '', `${opex.length} marchés`, '', '']);
  r6.height = 18;
  ws.mergeCells('A6:E6'); ws.mergeCells('F6:J6'); ws.mergeCells('K6:M6');
  [1, 6, 11].forEach(col => {
    r6.getCell(col).font = { bold: true, size: 14, color: { argb: C.NAVY } };
    r6.getCell(col).alignment = { horizontal: 'center', vertical: 'middle' };
  });

  // Row 7: KPI details
  const r7 = ws.addRow([
    `Budget: ${fmtMDT(totalBudget)}  •  Phy moy: ${avgPhy.toFixed(0)}%`, '', '', '', '',
    `Budget: ${fmtMDT(capexBudget)}  •  Phy: ${capexPhy.toFixed(0)}%`, '', '', '', '',
    `Budget: ${fmtMDT(opexBudget)}  •  Phy: ${opexPhy.toFixed(0)}%`, '', '',
  ]);
  r7.height = 16;
  ws.mergeCells('A7:E7'); ws.mergeCells('F7:J7'); ws.mergeCells('K7:M7');
  [1, 6, 11].forEach(col => {
    r7.getCell(col).font = { size: 9, color: { argb: C.GRAY } };
    r7.getCell(col).alignment = { horizontal: 'center', vertical: 'middle' };
  });

  // Row 8: empty
  ws.addRow([]);

  // Row 9: Column headers
  const HEADERS = ['Référence', 'Projet', 'Entrepreneur', 'Nature',
    'Montant Marché', 'Av. Phy (DT)', 'Phy %', 'Av. Fin (DT)', 'Fin %',
    'Début', 'Fin', 'Délai', 'Observation'];
  const r9 = ws.addRow(HEADERS);
  r9.height = 22;
  r9.eachCell(cell => {
    cell.fill = fill(C.HEADER);
    cell.font = { color: { argb: C.WHITE }, bold: true, size: 10 };
    cell.alignment = { horizontal: 'center', vertical: 'middle', wrapText: true };
    cell.border = border(C.NAVY);
  });

  // Per-region data
  for (const region of ALL_REGIONS) {
    const regRows = actifs.filter(r => (r.region || '') === region);
    if (!regRows.length) continue;

    // Region header row
    const rh = ws.addRow([`📍  ${region}  —  ${regRows.length} marchés`, ...Array(12).fill('')]);
    rh.height = 18;
    ws.mergeCells(`A${rh.number}:M${rh.number}`);
    rh.getCell(1).fill = fill('FF1E3A5F');
    rh.getCell(1).font = { bold: true, size: 11, color: { argb: C.ACCENT } };
    rh.getCell(1).alignment = { horizontal: 'left', vertical: 'middle', indent: 1 };

    let subtotalBudget = 0, subtotalPhy = 0, subtotalFin = 0, phyCount = 0;

    for (let i = 0; i < regRows.length; i++) {
      const r    = regRows[i];
      const nat  = selectVal(r.nature);
      const isCapex = nat.toUpperCase().includes('CAPEX');
      const budget  = parseNum(r.tot_marche || r.totmarche || r.montant);
      const phyDT   = parseNum(r.avt_phy);
      const phyPct  = parseNum(r.taux_phy || r.avt_phy);
      const finDT   = parseNum(r.avt_fin);
      const finPct  = parseNum(r.taux_fin);
      const delai   = getDelai(r);

      subtotalBudget += budget;
      if (phyPct > 0) { subtotalPhy += phyPct; phyCount++; }
      subtotalFin += finDT;

      const rd = ws.addRow([
        buildRef(r),
        r.projet || '',
        r.entrepreneur || '',
        nat,
        budget || '',
        phyDT || '',
        phyPct > 0 ? phyPct / 100 : '',
        finDT || '',
        finPct > 0 ? finPct / 100 : '',
        fmtDate(r.date_debut || r.debut_marche),
        fmtDate(r.date_fin   || r.date_fin_marche),
        delai,
        selectVal(r.observation),
      ]);
      rd.height = 15;

      const altFill = i % 2 === 1 ? fill(C.ALT) : undefined;
      const natFill = isCapex ? fill(C.CAPEX) : fill(C.OPEX);

      rd.eachCell((cell, col) => {
        if (altFill) cell.fill = altFill;
        if (col === 4) cell.fill = natFill;
        cell.border = { bottom: { style: 'thin', color: { argb: C.LIGHT } } };
        cell.alignment = { vertical: 'middle' };
        if ([5, 6, 8].includes(col)) cell.numFmt = '#,##0';
        if ([7, 9].includes(col)) cell.numFmt = '0%';
        if ([12].includes(col)) cell.alignment = { horizontal: 'center', vertical: 'middle' };
      });
    }

    // Subtotal row
    const avgPct = phyCount > 0 ? subtotalPhy / phyCount : 0;
    const rst = ws.addRow([
      `Sous-total ${region}  (${regRows.length})`, '', '',
      '', subtotalBudget, '', avgPct / 100, '', '',
      '', '', '', '',
    ]);
    rst.height = 16;
    ws.mergeCells(`A${rst.number}:D${rst.number}`);
    rst.eachCell(cell => {
      cell.fill = fill('FF1E3A5F');
      cell.font = { bold: true, size: 9, color: { argb: C.WHITE } };
      cell.border = { top: { style: 'medium', color: { argb: C.NAVY } }, bottom: { style: 'medium', color: { argb: C.NAVY } } };
    });
    rst.getCell(5).numFmt = '#,##0';
    rst.getCell(7).numFmt = '0%';
    rst.getCell(1).alignment = { horizontal: 'right', vertical: 'middle' };

    ws.addRow([]); // spacer
  }

  // Grand total row
  const gt = ws.addRow([
    `TOTAL ZONE SUD  (${actifs.length} marchés)`, '', '', '',
    actifs.reduce((s, r) => s + parseNum(r.tot_marche || r.totmarche || r.montant), 0),
    '', avgPhy / 100, '', '', '', '', '', '',
  ]);
  ws.mergeCells(`A${gt.number}:D${gt.number}`);
  gt.height = 22;
  gt.eachCell(cell => {
    cell.fill = fill(C.NAVY);
    cell.font = { bold: true, size: 11, color: { argb: C.WHITE } };
    cell.border = { top: { style: 'medium', color: { argb: C.ACCENT } } };
  });
  gt.getCell(5).numFmt  = '#,##0';
  gt.getCell(7).numFmt  = '0%';
  gt.getCell(1).alignment = { horizontal: 'right', vertical: 'middle' };
}

async function buildSheet2(wb, actifs) {
  const ws = wb.addWorksheet('Pilotage Proactif');
  ws.views = [{ state: 'frozen', ySplit: 9 }];

  ws.columns = [
    { width: 40 }, { width: 20 }, { width: 22 }, { width: 16 },
    { width: 10 }, { width: 10 }, { width: 12 }, { width: 12 }, { width: 18 },
  ];

  const today = new Date().toLocaleDateString('fr-FR');

  // Title
  const r1 = ws.addRow(['📈  PILOTAGE PROACTIF — ZONE SUD', ...Array(8).fill('')]);
  r1.height = 30;
  ws.mergeCells('A1:I1');
  r1.getCell(1).fill = fill(C.NAVY);
  r1.getCell(1).font = { color: { argb: C.WHITE }, bold: true, size: 16 };
  r1.getCell(1).alignment = { horizontal: 'center', vertical: 'middle' };

  const r2 = ws.addRow([`Tunisie Telecom  •  Direction Centrale Achats  •  Zone Sud`, ...Array(8).fill('')]);
  r2.height = 18;
  ws.mergeCells('A2:I2');
  r2.getCell(1).fill = fill('FF0F172A');
  r2.getCell(1).font = font('FFCBD5E1', false, 11);
  r2.getCell(1).alignment = { horizontal: 'center', vertical: 'middle' };

  const r3 = ws.addRow([`📅 ${today}   │   📋 ${actifs.length} marchés actifs`, ...Array(8).fill('')]);
  r3.height = 16;
  ws.mergeCells('A3:I3');
  r3.getCell(1).fill = fill('FF1E3A5F');
  r3.getCell(1).font = font('FF94A3B8', false, 10);
  r3.getCell(1).alignment = { horizontal: 'center', vertical: 'middle' };

  ws.addRow([]);

  // KPIs
  const SEUIL_STD  = parseFloat(process.env.SEUIL_STANDARD || 70);
  const SEUIL_CRIT = parseFloat(process.env.SEUIL_CRITIQUE_PCT || 90);
  const SEUIL_MOD  = parseFloat(process.env.SEUIL_MODERNISATION || 50);

  const classify = r => {
    const taux = parseNum(r.taux_phy || r.avt_phy);
    const nat  = String(selectVal(r.nature) || '').toLowerCase();
    const seuil = nat.includes('modern') ? SEUIL_MOD : SEUIL_STD;
    if (taux === 0)             return 'Non déterminé';
    if (taux >= SEUIL_CRIT)    return 'Dépassement';
    if (taux >= seuil)         return 'Normal';
    return 'Sous Avancement';
  };

  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;

  const r5 = ws.addRow(['✅  NORMAL', '', '❌  SOUS AVANCEMENT', '', '⚡  DÉPASSEMENT', '', '❓  NON DÉTERMINÉ', '', '📊  TOTAL']);
  r5.height = 22;
  ws.mergeCells('A5:B5'); ws.mergeCells('C5:D5'); ws.mergeCells('E5:F5'); ws.mergeCells('G5:H5');
  [[1,C.GREEN],[3,'FFDC2626'],[5,C.ORANGE],[7,C.GRAY],[9,C.NAVY]].forEach(([col, argb]) => {
    r5.getCell(col).fill = fill(argb);
    r5.getCell(col).font = { color: { argb: C.WHITE }, bold: true, size: 10 };
    r5.getCell(col).alignment = { horizontal: 'center', vertical: 'middle' };
  });

  const r6 = ws.addRow([normal, '', sous, '', dep, '', nd, '', actifs.length]);
  r6.height = 20;
  ws.mergeCells('A6:B6'); ws.mergeCells('C6:D6'); ws.mergeCells('E6:F6'); ws.mergeCells('G6:H6');
  [1, 3, 5, 7, 9].forEach(col => {
    r6.getCell(col).font = { bold: true, size: 18 };
    r6.getCell(col).alignment = { horizontal: 'center', vertical: 'middle' };
  });

  ws.addRow([]);
  ws.addRow([]);

  // Column headers
  const HEADERS2 = ['Référence', 'Projet', 'Entrepreneur', 'Région',
    'Phy %', 'Fin %', 'Délai', 'Alerte', 'Résultat'];
  const r9 = ws.addRow(HEADERS2);
  r9.height = 22;
  r9.eachCell(cell => {
    cell.fill = fill(C.HEADER);
    cell.font = { color: { argb: C.WHITE }, bold: true, size: 10 };
    cell.alignment = { horizontal: 'center', vertical: 'middle', wrapText: true };
    cell.border = border(C.NAVY);
  });

  const ALERTE_COLOR = { 'critique': 'FFDC2626', 'attention': 'FFEA580C', 'normal': C.GREEN, 'indéterminé': C.GRAY };
  const RESULT_COLOR = { 'Normal': C.GREEN, 'Sous Avancement': 'FFDC2626', 'Dépassement': C.ORANGE, 'Non déterminé': C.GRAY };

  const DELAI_CRIT = parseInt(process.env.DELAI_CRITIQUE || 45);
  const DELAI_ATT  = parseInt(process.env.DELAI_ATTENTION || 90);
  const niveauAlerte = d => d === null ? 'indéterminé' : d <= DELAI_CRIT ? 'critique' : d <= DELAI_ATT ? 'attention' : 'normal';

  const sorted = [...actifs].sort((a, b) => {
    const ta = parseNum(a.taux_phy || a.avt_phy);
    const tb = parseNum(b.taux_phy || b.avt_phy);
    return ta - tb;
  });

  for (let i = 0; i < sorted.length; i++) {
    const r     = sorted[i];
    const phyPct = parseNum(r.taux_phy || r.avt_phy);
    const finPct = parseNum(r.taux_fin);
    const delai  = getDelai(r);
    const alerte = niveauAlerte(typeof delai === 'number' ? delai : null);
    const result = classify(r);

    const rd = ws.addRow([
      buildRef(r),
      r.projet || '',
      r.entrepreneur || '',
      r.region || '',
      phyPct / 100,
      finPct / 100,
      typeof delai === 'number' ? delai : '-',
      alerte,
      result,
    ]);
    rd.height = 15;

    if (i % 2 === 1) rd.eachCell(cell => { cell.fill = fill(C.ALT); });

    rd.getCell(5).numFmt = '0%';
    rd.getCell(6).numFmt = '0%';
    rd.getCell(8).font = { color: { argb: ALERTE_COLOR[alerte] || C.GRAY }, bold: true };
    rd.getCell(9).font = { color: { argb: RESULT_COLOR[result]  || C.GRAY }, bold: true };
    rd.eachCell(cell => {
      cell.border = { bottom: { style: 'thin', color: { argb: C.LIGHT } } };
      cell.alignment = { vertical: 'middle' };
    });
  }
}

module.exports = { generateXlsx };
