const docx = require("docx");
const {
  Document, Packer, Paragraph, TextRun, Table, TableRow, TableCell,
  Header, Footer, AlignmentType, BorderStyle, WidthType, ShadingType,
  convertInchesToTwip, PageBreak
} = docx;

// ═══════════════════════════════════════════════════════════
// Palette exacte extraite du DOCX de référence (Doropo VF)
// ═══════════════════════════════════════════════════════════
const C = {
  // Texte / Headings
  NAVY:       "1B2A4A",  // H1, titre principal, fond headers tableaux
  BLUE:       "2E5090",  // H2, sous-titre zone, bordure header page
  ORANGE_H3:  "C45B28",  // H3, bordure séparateur titre
  // Sévérité — texte
  RED:        "C0392B",  // CRITIQUE, verdicts, classification, header page
  ORANGE:     "E67E22",  // ÉLEVÉ
  OLIVE:      "B7950B",  // MODÉRÉ
  GREEN:      "375623",  // FAIBLE (texte)
  // Sévérité — fonds de cellule
  BG_CRIT:    "FADBD8",  // fond CRITIQUE / Majeur
  BG_ELEV:    "FDEBD0",  // fond ÉLEVÉ / Significatif
  BG_MOD:     "FEF9E7",  // fond MODÉRÉ
  BG_LOW:     "E8F8F5",  // fond FAIBLE / Chronique / Positif
  // Neutres
  BLACK:      "000000",
  GREY_DARK:  "555555",  // source citations
  GREY:       "666666",  // sous-titre localisation
  GREY_MED:   "888888",  // footer, date, sources heading
  GREY_LIGHT: "D9D9D9",  // bordures cellules, bordure footer
  WHITE:      "FFFFFF",
};

const FONT = "Arial";

// Tailles en demi-points (half-points), exactes du DOCX de référence
const SZ = {
  TITLE:   36,  // 18pt — titre principal
  ZONE:    26,  // 13pt — sous-titre zone
  BODY:    20,  // 10pt — texte courant (défaut)
  H1:      28,  // 14pt — Heading 1
  H2:      24,  // 12pt — Heading 2
  H3:      22,  // 11pt — Heading 3
  TABLE:   18,  //  9pt — tout contenu de tableau, sources, légende, classification, date
  HEADER:  16,  //  8pt — en-tête page
  FOOTER:  14,  //  7pt — pied de page
};

// ═══════════════════════════════════════════════════════════
// Détection de sévérité
// ═══════════════════════════════════════════════════════════
function getSeverity(text) {
  const u = text.replace(/\*/g, "").toUpperCase().trim();
  if (u === "CRITIQUE")                        return { text: C.RED,    bg: C.BG_CRIT };
  if (u === "ÉLEVÉ" || u === "ELEVE")          return { text: C.ORANGE, bg: C.BG_ELEV };
  if (u === "MODÉRÉ" || u === "MODERE")        return { text: C.OLIVE,  bg: C.BG_MOD  };
  if (u === "FAIBLE")                          return { text: C.GREEN,  bg: C.BG_LOW  };
  return null;
}

function getImpactBg(text) {
  const u = text.replace(/\*/g, "").toUpperCase().trim();
  if (u === "MAJEUR" || u === "CRITIQUE")                           return C.BG_CRIT;
  if (u === "ÉLEVÉ" || u === "ELEVE" || u === "SIGNIFICATIF")       return C.BG_ELEV;
  if (u === "MODÉRÉ" || u === "MODERE")                             return C.BG_MOD;
  if (u === "FAIBLE" || u === "CHRONIQUE" || u === "POSITIF")       return C.BG_LOW;
  return null;
}

// ═══════════════════════════════════════════════════════════
// Parsing inline markdown → TextRun[]
// ═══════════════════════════════════════════════════════════
function parseInline(text, defaults) {
  defaults = defaults || {};
  const sz = defaults.size || SZ.BODY;
  const clr = defaults.color || C.BLACK;
  const fnt = defaults.font || FONT;
  const runs = [];
  const parts = text.split(/(\*\*[^*]+\*\*|\*[^*]+\*)/g);

  for (let i = 0; i < parts.length; i++) {
    const part = parts[i];
    if (!part) continue;

    if (part.startsWith("**") && part.endsWith("**")) {
      const inner = part.slice(2, -2);
      const sev = getSeverity(inner);
      runs.push(new TextRun({
        text: inner,
        bold: true,
        color: sev ? sev.text : (defaults.boldColor || (defaults.bold ? clr : C.BLACK)),
        font: fnt, size: sz,
      }));
    } else if (part.startsWith("*") && part.endsWith("*")) {
      runs.push(new TextRun({
        text: part.slice(1, -1),
        italics: true,
        color: clr, font: fnt, size: sz,
      }));
    } else {
      // Flèches tendances
      const trendParts = part.split(/(↗\s*En hausse|→\s*Stable[^↘↗\n]*|↘\s*En baisse)/g);
      for (let j = 0; j < trendParts.length; j++) {
        const tp = trendParts[j];
        if (!tp) continue;
        let tc = clr, tb = defaults.bold || false;
        if (/^↗/.test(tp)) { tc = C.RED; tb = false; }
        else if (/^→/.test(tp)) { tc = C.OLIVE; tb = false; }
        else if (/^↘/.test(tp)) { tc = C.GREEN; tb = false; }
        runs.push(new TextRun({ text: tp, bold: tb, color: tc, font: fnt, size: sz }));
      }
    }
  }
  if (!runs.length) runs.push(new TextRun({ text: text, font: fnt, size: sz, color: clr, bold: defaults.bold || false }));
  return runs;
}

// ═══════════════════════════════════════════════════════════
// Bloc titre (4 lignes spéciales)
// ═══════════════════════════════════════════════════════════
function createTitleBlock(titleText, subtitleLines, formData) {
  const elements = [];
  const today = new Date().toLocaleDateString("fr-FR", { day: "numeric", month: "long", year: "numeric" });

  // Ligne 1 : titre principal — 18pt bold #1B2A4A centré
  elements.push(new Paragraph({
    alignment: AlignmentType.CENTER,
    spacing: { after: 40 },
    children: [new TextRun({
      text: titleText.replace(/\*/g, "").toUpperCase(),
      bold: true, color: C.NAVY, size: SZ.TITLE, font: FONT,
    })],
  }));

  // Classer les lignes de sous-titre capturées du markdown
  let zoneLine = "";
  let geoLine = "";
  let dateLine = "";

  if (subtitleLines && subtitleLines.length) {
    for (let k = 0; k < subtitleLines.length; k++) {
      const raw = subtitleLines[k];
      const clean = raw.replace(/\*\*/g, "").replace(/\*/g, "").trim();
      const upper = clean.toUpperCase();
      if (!zoneLine && (upper.startsWith("ZONE") || upper.includes("RÉGION") || upper.includes("REGION"))) {
        zoneLine = clean;
      } else if (!dateLine && (clean.toLowerCase().includes("période couverte") || clean.toLowerCase().includes("mise à jour"))) {
        dateLine = clean;
      } else if (!geoLine && clean.length > 0) {
        geoLine = clean;
      }
    }
  }

  // Fallbacks depuis formData si les lignes n'ont pas été capturées
  if (!zoneLine) zoneLine = "ZONE DE " + (formData.zone || "").toUpperCase();
  if (!geoLine) geoLine = formData.pays || "";
  if (!dateLine) dateLine = "Période couverte : " + (formData.periode || "") + " | Mise à jour : " + today;

  // Ligne 2 : zone + région — 13pt #2E5090 centré (PAS gras)
  elements.push(new Paragraph({
    alignment: AlignmentType.CENTER,
    spacing: { after: 40 },
    children: [new TextRun({
      text: zoneLine,
      color: C.BLUE, size: SZ.ZONE, font: FONT,
    })],
  }));

  // Ligne 3 : contexte géographique — 10pt #666666 centré
  elements.push(new Paragraph({
    alignment: AlignmentType.CENTER,
    spacing: { after: 40 },
    children: [new TextRun({
      text: geoLine,
      color: C.GREY, size: SZ.BODY, font: FONT,
    })],
  }));

  // Ligne 4 : période + mise à jour — 9pt #888888 centré + séparateur orange
  elements.push(new Paragraph({
    alignment: AlignmentType.CENTER,
    spacing: { after: 200 },
    border: { bottom: { style: BorderStyle.SINGLE, size: 6, color: C.ORANGE_H3, space: 8 } },
    children: [new TextRun({
      text: dateLine,
      color: C.GREY_MED, size: SZ.TABLE, font: FONT,
    })],
  }));

  return elements;
}

// ═══════════════════════════════════════════════════════════
// Headings — valeurs exactes styles.xml du DOCX de référence
// ═══════════════════════════════════════════════════════════
function createH1(text) {
  return new Paragraph({
    spacing: { before: 300, after: 160 },
    children: parseInline(text.replace(/\*\*/g, ""), { size: SZ.H1, color: C.NAVY, bold: true }),
  });
}

function createH2(text) {
  return new Paragraph({
    spacing: { before: 240, after: 120 },
    children: parseInline(text.replace(/\*\*/g, ""), { size: SZ.H2, color: C.BLUE, bold: true }),
  });
}

function createH3(text) {
  return new Paragraph({
    spacing: { before: 200, after: 100 },
    children: parseInline(text.replace(/\*\*/g, ""), { size: SZ.H3, color: C.ORANGE_H3, bold: true }),
  });
}

function createH4(text) {
  return new Paragraph({
    spacing: { before: 160, after: 80 },
    children: [new TextRun({
      text: text.replace(/\*\*/g, ""),
      italics: true, color: "2E74B5", size: SZ.BODY, font: FONT,
    })],
  });
}

// ═══════════════════════════════════════════════════════════
// Paragraphes
// ═══════════════════════════════════════════════════════════
function createParagraph(text) {
  return new Paragraph({
    alignment: AlignmentType.JUSTIFIED,
    spacing: { after: 120 },
    children: parseInline(text, { size: SZ.BODY }),
  });
}

function createBullet(text) {
  return new Paragraph({
    spacing: { after: 80 },
    indent: { left: 720, hanging: 360 },
    children: [
      new TextRun({ text: "\u2022  ", font: FONT, size: SZ.BODY }),
      ...parseInline(text, { size: SZ.BODY }),
    ],
  });
}

function createNumberedItem(text, idx) {
  return new Paragraph({
    spacing: { after: 80 },
    indent: { left: 720, hanging: 360 },
    children: [
      new TextRun({ text: idx + ".  ", font: FONT, size: SZ.BODY }),
      ...parseInline(text, { size: SZ.BODY }),
    ],
  });
}

function createBlockquote(text) {
  return new Paragraph({
    spacing: { before: 80, after: 80 },
    indent: { left: 300 },
    border: { left: { style: BorderStyle.SINGLE, size: 6, color: C.NAVY, space: 8 } },
    shading: { fill: "F5F5F5", type: ShadingType.CLEAR, color: "auto" },
    children: parseInline(text, { size: SZ.BODY, color: "444444" }),
  });
}

// ═══════════════════════════════════════════════════════════
// Bordures et padding cellules — exactement DOCX de réf
// ═══════════════════════════════════════════════════════════
function cellBordersLight() {
  const b = { style: BorderStyle.SINGLE, size: 1, color: C.GREY_LIGHT };
  return { top: b, bottom: b, left: b, right: b };
}

function cellMargins() {
  return { top: 60, bottom: 60, left: 100, right: 100, marginUnitType: docx.WidthType.DXA };
}

// ═══════════════════════════════════════════════════════════
// Tableaux — reproduction exacte du DOCX de référence
// ═══════════════════════════════════════════════════════════

// Largeurs de colonnes selon le nombre de colonnes (en twips, total 9000)
function getColumnWidths(colCount) {
  if (colCount === 4) return [1200, 4000, 1800, 2000];   // Chronologie
  if (colCount === 5) return [2800, 1400, 1400, 1200, 2200]; // Matrice risques
  if (colCount === 3) return [2200, 1200, 5600];          // Évaluation
  // Fallback : répartition égale
  const w = Math.floor(9000 / colCount);
  return Array(colCount).fill(w);
}

// Détecte si une colonne est une colonne de sévérité (Niveau / Évaluation)
function isSeverityColumn(headerText) {
  const u = headerText.replace(/\*/g, "").toUpperCase().trim();
  return u === "NIVEAU" || u === "ÉVALUATION" || u === "EVALUATION";
}

// Détecte si une colonne est la colonne Impact
function isImpactColumn(headerText) {
  const u = headerText.replace(/\*/g, "").toUpperCase().trim();
  return u === "IMPACT";
}

function buildTable(rows) {
  const parsed = rows.map(function (row) {
    const parts = row.split("|");
    const cells = [];
    for (let i = 1; i < parts.length - 1; i++) cells.push(parts[i].trim());
    return cells;
  });

  if (!parsed.length || !parsed[0].length) return new Paragraph({ children: [] });

  const colCount = parsed[0].length;
  const colWidths = getColumnWidths(colCount);

  // Identifier les colonnes spéciales à partir du header
  const headers = parsed[0];
  const sevCols = headers.map(h => isSeverityColumn(h));
  const impCols = headers.map(h => isImpactColumn(h));

  const tableRows = parsed.map(function (cells, rowIdx) {
    const isHeader = rowIdx === 0;

    const tableCells = cells.map(function (cellText, colIdx) {
      const width = colWidths[colIdx] || Math.floor(9000 / colCount);
      const cleanText = cellText.replace(/\*/g, "").trim();

      // ── Cellule HEADER ──
      if (isHeader) {
        return new TableCell({
          children: [new Paragraph({
            alignment: AlignmentType.CENTER,
            children: [new TextRun({
              text: cleanText, bold: true, color: C.WHITE,
              size: SZ.TABLE, font: FONT,
            })],
          })],
          borders: cellBordersLight(),
          shading: { fill: C.NAVY, type: ShadingType.CLEAR, color: "auto" },
          margins: cellMargins(),
          verticalAlign: docx.VerticalAlign.CENTER,
          width: { size: width, type: WidthType.DXA },
        });
      }

      // ── Cellule SÉVÉRITÉ (Niveau / Évaluation) ──
      if (sevCols[colIdx]) {
        const sev = getSeverity(cellText);
        if (sev) {
          return new TableCell({
            children: [new Paragraph({
              alignment: AlignmentType.CENTER,
              children: [new TextRun({
                text: cleanText, bold: true, color: sev.text,
                size: SZ.TABLE, font: FONT,
              })],
            })],
            borders: cellBordersLight(),
            shading: { fill: sev.bg, type: ShadingType.CLEAR, color: "auto" },
            margins: cellMargins(),
            verticalAlign: docx.VerticalAlign.CENTER,
            width: { size: width, type: WidthType.DXA },
          });
        }
      }

      // ── Cellule IMPACT (fond coloré, texte noir) ──
      if (impCols[colIdx]) {
        const impBg = getImpactBg(cellText);
        if (impBg) {
          return new TableCell({
            children: [new Paragraph({
              alignment: AlignmentType.CENTER,
              children: [new TextRun({
                text: cleanText, color: C.BLACK,
                size: SZ.TABLE, font: FONT,
              })],
            })],
            borders: cellBordersLight(),
            shading: { fill: impBg, type: ShadingType.CLEAR, color: "auto" },
            margins: cellMargins(),
            verticalAlign: docx.VerticalAlign.CENTER,
            width: { size: width, type: WidthType.DXA },
          });
        }
      }

      // ── Cellule DATA standard ──
      const isCentered = colCount >= 4 && colIdx < colCount - 1 && colIdx !== 1;
      return new TableCell({
        children: [new Paragraph({
          alignment: isCentered ? AlignmentType.CENTER : AlignmentType.LEFT,
          children: parseInline(cellText, { size: SZ.TABLE }),
        })],
        borders: cellBordersLight(),
        margins: cellMargins(),
        verticalAlign: docx.VerticalAlign.CENTER,
        width: { size: width, type: WidthType.DXA },
      });
    });

    return new TableRow({ children: tableCells });
  });

  return new Table({
    rows: tableRows,
    width: { size: 9000, type: WidthType.DXA },
  });
}

// ═══════════════════════════════════════════════════════════
// Verdict — table mono-cellule exactement comme le DOCX réf
// ═══════════════════════════════════════════════════════════
function createVerdictBox(type, subtitleLines) {
  const configs = {
    "DÉFAVORABLE":  { bg: C.BG_CRIT, border: C.RED,   label: "AVIS DÉFAVORABLE" },
    "FAVORABLE":    { bg: "F0FFF4",  border: C.GREEN,  label: "AVIS FAVORABLE" },
    "CONDITIONNEL": { bg: C.BG_MOD,  border: C.OLIVE,  label: "AVIS CONDITIONNEL" },
  };
  const cfg = configs[type] || configs["DÉFAVORABLE"];

  const cellChildren = [
    new Paragraph({
      alignment: AlignmentType.CENTER,
      spacing: { after: 80 },
      children: [new TextRun({
        text: cfg.label,
        bold: true, color: cfg.border,
        size: SZ.H1, font: FONT,
      })],
    }),
  ];

  // Ajouter les lignes de sous-titre dans le verdict (gras → couleur du verdict)
  if (subtitleLines && subtitleLines.length) {
    subtitleLines.forEach(function (line) {
      cellChildren.push(new Paragraph({
        alignment: AlignmentType.CENTER,
        spacing: { after: 40 },
        children: parseInline(line, { size: SZ.BODY, boldColor: cfg.border }),
      }));
    });
  }

  return new Table({
    rows: [
      new TableRow({
        children: [
          new TableCell({
            children: cellChildren,
            borders: {
              top:    { style: BorderStyle.SINGLE, size: 6, color: cfg.border },
              bottom: { style: BorderStyle.SINGLE, size: 6, color: cfg.border },
              left:   { style: BorderStyle.SINGLE, size: 6, color: cfg.border },
              right:  { style: BorderStyle.SINGLE, size: 6, color: cfg.border },
            },
            shading: { fill: cfg.bg, type: ShadingType.CLEAR, color: "auto" },
            margins: { top: 120, bottom: 120, left: 200, right: 200, marginUnitType: WidthType.DXA },
            width: { size: 9000, type: WidthType.DXA },
          }),
        ],
      }),
    ],
    width: { size: 9000, type: WidthType.DXA },
  });
}

// ═══════════════════════════════════════════════════════════
// Sources
// ═══════════════════════════════════════════════════════════
function createSourcesHeading(text) {
  return new Paragraph({
    spacing: { before: 200, after: 60 },
    border: { top: { style: BorderStyle.SINGLE, size: 2, color: C.GREY_LIGHT, space: 6 } },
    children: [new TextRun({
      text: text.replace(/\*/g, ""),
      bold: true, color: C.GREY_MED,
      size: SZ.TABLE, font: FONT,
    })],
  });
}

function createSourceLine(text) {
  return new Paragraph({
    spacing: { after: 40 },
    children: [new TextRun({
      text: text.replace(/\*/g, ""),
      color: C.GREY_DARK, size: SZ.TABLE, font: FONT,
    })],
  });
}

// ═══════════════════════════════════════════════════════════
// Classification
// ═══════════════════════════════════════════════════════════
function createClassification() {
  return new Paragraph({
    spacing: { after: 40 },
    children: [new TextRun({
      text: "Classification : CONFIDENTIEL — Diffusion restreinte — Usage interne uniquement",
      bold: true, color: C.RED,
      size: SZ.TABLE, font: FONT,
    })],
  });
}

// ═══════════════════════════════════════════════════════════
// Légende sous tableau
// ═══════════════════════════════════════════════════════════
function createLegend(text) {
  return new Paragraph({
    spacing: { after: 200 },
    children: [new TextRun({
      text: text.replace(/\*/g, ""),
      color: C.GREY_DARK, size: SZ.TABLE, font: FONT,
    })],
  });
}

// ═══════════════════════════════════════════════════════════
// Parsing Markdown → éléments DOCX
// ═══════════════════════════════════════════════════════════
function parseMarkdownToDocx(md, formData) {
  const lines = md.split("\n");
  const children = [];
  let i = 0;
  let numCounter = 0;
  let titleDone = false;
  let inSourcesSection = false;

  while (i < lines.length) {
    const tr = lines[i].trim();

    // Lignes vides
    if (tr === "") { i++; continue; }

    // Séparateurs de tableau
    if (/^\|[\s\-|:]+\|$/.test(tr)) { i++; continue; }

    // ── TABLEAU ──
    if (tr.startsWith("|") && tr.endsWith("|")) {
      const tableLines = [];
      while (i < lines.length) {
        const tl = lines[i].trim();
        if (!tl.startsWith("|") || !tl.endsWith("|")) break;
        if (!/^\|[\s\-|:]+\|$/.test(tl)) tableLines.push(tl);
        i++;
      }
      if (tableLines.length > 0) children.push(buildTable(tableLines));
      continue;
    }

    // Règle horizontale
    if (tr === "---" || tr === "***" || tr === "___") { i++; continue; }

    // ── TITRE PRINCIPAL (# NOTE DE SÉCURITÉ...) ──
    if (tr.startsWith("# ") && !titleDone) {
      titleDone = true;
      const titleText = tr.slice(2);
      i++;
      // Sauter les éventuelles lignes vides entre le titre et les sous-titres
      while (i < lines.length && lines[i].trim() === "") i++;
      // Capturer les lignes de sous-titre par pattern matching (max 3)
      // Gère les cas avec ou sans lignes vides entre les sous-titres
      const subtitleLines = [];
      while (i < lines.length && subtitleLines.length < 3) {
        const next = lines[i].trim();
        if (next.startsWith("#") || next.startsWith("|")) break;
        if (next === "") { i++; continue; }
        // Vérifier que la ligne ressemble à un sous-titre (pas du contenu)
        const clean = next.replace(/\*\*/g, "").replace(/\*/g, "").trim();
        const upper = clean.toUpperCase();
        const isSubtitle =
          upper.startsWith("ZONE") || upper.includes("RÉGION") || upper.includes("REGION") ||
          clean.toLowerCase().includes("période couverte") || clean.toLowerCase().includes("mise à jour") ||
          (clean.includes("—") && clean.length < 120);
        if (isSubtitle) {
          subtitleLines.push(next);
          i++;
        } else {
          break; // Pas un sous-titre → arrêter la capture
        }
      }
      const titleElements = createTitleBlock(titleText, subtitleLines, formData);
      titleElements.forEach(el => children.push(el));
      continue;
    }

    // ── HEADERS ──
    if (tr.startsWith("#### ")) {
      children.push(createH4(tr.slice(5)));
      i++; continue;
    }
    if (tr.startsWith("### ")) {
      const h3Text = tr.slice(4);
      // Détection section sources
      if (h3Text.toUpperCase().includes("SOURCE")) {
        inSourcesSection = true;
        children.push(createSourcesHeading(h3Text));
        i++; continue;
      }
      inSourcesSection = false;
      children.push(createH3(h3Text));
      i++; continue;
    }
    if (tr.startsWith("## ")) {
      const h2Text = tr.slice(3);
      if (h2Text.toUpperCase().includes("SOURCE")) {
        inSourcesSection = true;
        children.push(createSourcesHeading(h2Text));
        i++; continue;
      }
      inSourcesSection = false;
      children.push(createH2(h2Text));
      i++; continue;
    }
    if (tr.startsWith("# ")) {
      // H1 subséquent (pas le titre)
      const h1Text = tr.slice(2);
      if (h1Text.toUpperCase().includes("SOURCE")) {
        inSourcesSection = true;
        children.push(createSourcesHeading(h1Text));
        i++; continue;
      }
      inSourcesSection = false;
      children.push(createH1(h1Text));
      i++; continue;
    }

    // ── LISTES À PUCES ──
    if (/^[-*] /.test(tr)) {
      while (i < lines.length && /^[-*] /.test(lines[i].trim())) {
        children.push(createBullet(lines[i].trim().slice(2)));
        i++;
      }
      continue;
    }

    // ── LISTES NUMÉROTÉES ──
    if (/^\d+\. /.test(tr)) {
      numCounter = 0;
      while (i < lines.length && /^\d+\. /.test(lines[i].trim())) {
        numCounter++;
        children.push(createNumberedItem(lines[i].trim().replace(/^\d+\. /, ""), numCounter));
        i++;
      }
      continue;
    }

    // ── BLOCKQUOTE ──
    if (tr.startsWith("> ")) {
      const bqLines = [];
      while (i < lines.length && lines[i].trim().startsWith("> ")) {
        bqLines.push(lines[i].trim().slice(2));
        i++;
      }
      children.push(createBlockquote(bqLines.join(" ")));
      continue;
    }

    // ── CAS SPÉCIAUX ──
    const upper = tr.toUpperCase();

    // Verdict DÉFAVORABLE
    if (upper.includes("AVIS DÉFAVORABLE") || upper.includes("AVIS DEFAVORABLE")) {
      i++;
      // Capturer les lignes de sous-titre du verdict
      const subLines = [];
      while (i < lines.length && lines[i].trim() !== "" && !lines[i].trim().startsWith("#") && !lines[i].trim().startsWith("**Justification") && !lines[i].trim().startsWith("Justification")) {
        subLines.push(lines[i].trim());
        i++;
      }
      children.push(createVerdictBox("DÉFAVORABLE", subLines));
      continue;
    }
    if (upper.includes("AVIS CONDITIONNEL")) {
      i++;
      const subLines = [];
      while (i < lines.length && lines[i].trim() !== "" && !lines[i].trim().startsWith("#") && !lines[i].trim().startsWith("**Justification") && !lines[i].trim().startsWith("Justification")) {
        subLines.push(lines[i].trim());
        i++;
      }
      children.push(createVerdictBox("CONDITIONNEL", subLines));
      continue;
    }
    if (upper.includes("AVIS FAVORABLE") && !upper.includes("DÉFAVORABLE") && !upper.includes("CONDITIONNEL")) {
      i++;
      const subLines = [];
      while (i < lines.length && lines[i].trim() !== "" && !lines[i].trim().startsWith("#") && !lines[i].trim().startsWith("**Justification") && !lines[i].trim().startsWith("Justification")) {
        subLines.push(lines[i].trim());
        i++;
      }
      children.push(createVerdictBox("FAVORABLE", subLines));
      continue;
    }

    // Classification
    if (upper.includes("CONFIDENTIEL") && tr.toLowerCase().includes("classification")) {
      children.push(createClassification());
      i++; continue;
    }

    // Légende tableau
    if (tr.toLowerCase().startsWith("légende") || tr.toLowerCase().startsWith("legende")) {
      children.push(createLegend(tr));
      i++; continue;
    }

    // Ligne de sources (dans la section sources)
    if (inSourcesSection) {
      children.push(createSourceLine(tr));
      i++; continue;
    }

    // Ligne de source avant un tableau (italic, petite)
    if (tr.toLowerCase().startsWith("sources :") || tr.toLowerCase().startsWith("source :")) {
      children.push(new Paragraph({
        spacing: { after: 100 },
        children: [new TextRun({
          text: tr.replace(/\*/g, ""),
          color: C.GREY_DARK, size: SZ.TABLE, font: FONT,
        })],
      }));
      i++; continue;
    }

    // ── PARAGRAPHE STANDARD ──
    children.push(createParagraph(tr));
    i++;
  }

  return children;
}

// ═══════════════════════════════════════════════════════════
// Construction du document DOCX complet
// ═══════════════════════════════════════════════════════════
function buildDocx(markdown, formData) {
  const monthYear = new Date().toLocaleDateString("fr-FR", { month: "long", year: "numeric" });
  const children = parseMarkdownToDocx(markdown, formData);

  return new Document({
    creator: "Analyste Sécuritaire IA",
    title: "Note de Sécurité — " + (formData.zone || ""),
    description: "Note sécuritaire générée par Analyste Sécuritaire",
    styles: {
      default: {
        document: {
          run: { font: FONT, size: SZ.BODY, color: C.BLACK },
        },
      },
    },
    sections: [
      {
        properties: {
          page: {
            margin: { top: 1134, bottom: 1134, left: 1134, right: 1134 },
            size: { width: 11906, height: 16838 },  // A4 exact
          },
        },
        headers: {
          default: new Header({
            children: [
              new Paragraph({
                alignment: AlignmentType.RIGHT,
                border: { bottom: { style: BorderStyle.SINGLE, size: 4, color: C.BLUE, space: 4 } },
                children: [new TextRun({
                  text: "CONFIDENTIEL — DIFFUSION RESTREINTE",
                  bold: true, color: C.RED,
                  size: SZ.HEADER, font: FONT,
                })],
              }),
            ],
          }),
        },
        footers: {
          default: new Footer({
            children: [
              new Paragraph({
                alignment: AlignmentType.CENTER,
                border: { top: { style: BorderStyle.SINGLE, size: 2, color: C.GREY_LIGHT, space: 4 } },
                children: [new TextRun({
                  text: "Note sécuritaire — " + (formData.zone || "Zone") + " — " + monthYear,
                  color: C.GREY_MED,
                  size: SZ.FOOTER, font: FONT,
                })],
              }),
            ],
          }),
        },
        children: children,
      },
    ],
  });
}

// ═══════════════════════════════════════════════════════════
// Export
// ═══════════════════════════════════════════════════════════
async function generateDocxBuffer(markdown, formData) {
  const doc = buildDocx(markdown, formData);
  return await Packer.toBuffer(doc);
}

module.exports = { generateDocxBuffer };
