/* global window */
// ============================================================================
// MELR · Global Fund Grant Performance Framework export
// ----------------------------------------------------------------------------
// Generates a Global Fund Grant Performance Framework as a .docx file.
//
// The Global Fund to Fight AIDS, Tuberculosis and Malaria (GFATM) requires
// Principal Recipients (PRs) and Sub-Recipients (SRs) to produce a Grant
// Performance Framework (PF) for each grant cycle (typically 3 years). The
// PF aligns with the country's National Strategic Plan (NSP) and is
// structured by disease component : HIV, TB, Malaria, and RSSH (Resilient
// and Sustainable Systems for Health).
//
// Generated structure :
//   1. Cover Page (Global Fund branding)
//   2. National Disease Context (epidemiology, NSP alignment)
//   3. Grant Components (HIV / TB / Malaria / RSSH)
//   4. Performance Framework table (IPTT-style, 3 Y)
//   5. Indicator Narratives (per-indicator detail sheets)
//   6. Data Flow & Quality Assurance
//   7. M&E Arrangements
//   8. Risk Assessment
//
// Entry point :
//   await window.exportGlobalFundFramework({ projects, indicators, scope,
//                                            year, scopeLabel, orgName, lang })
//
// Uses shared helpers from window.melrDonor (reporting-donor-shared.jsx).
// ============================================================================

(function () {
  if (typeof window === "undefined") return;

  // Global Fund brand red (their logo / report covers)
  const GF_COLOR = "E40043";

  function _shared() { return window.melrDonor; }
  function _ok() { return !!(_shared() && _shared().isReady && _shared().isReady()); }

  // ── Cover Page ──────────────────────────────────────────────────────────
  function buildCover({ orgName, scopeLabel, year, lang }) {
    const { Paragraph, TextRun, AlignmentType } = window.docx;
    const L = _shared().L;
    return [
      new Paragraph({ spacing: { before: 1200 }, children: [] }),
      new Paragraph({
        alignment: AlignmentType.CENTER,
        children: [new TextRun({ text: "The Global Fund", bold: true, size: 56, color: GF_COLOR })],
      }),
      new Paragraph({
        alignment: AlignmentType.CENTER,
        spacing: { after: 200 },
        children: [new TextRun({ text: L(lang, "to Fight AIDS, Tuberculosis and Malaria", "to Fight AIDS, Tuberculosis and Malaria"), italics: true, size: 22, color: _shared().COLORS.MUTED })],
      }),
      new Paragraph({
        alignment: AlignmentType.CENTER,
        spacing: { after: 600 },
        children: [new TextRun({ text: L(lang, "Cadre de performance de subvention", "Grant Performance Framework", "Marco de desempeño de subvención"), bold: true, size: 32, color: GF_COLOR })],
      }),
      new Paragraph({
        alignment: AlignmentType.CENTER,
        spacing: { after: 200 },
        children: [new TextRun({ text: scopeLabel || L(lang, "Subvention", "Grant", "Subvención"), bold: true, size: 28 })],
      }),
      new Paragraph({
        alignment: AlignmentType.CENTER,
        spacing: { after: 200 },
        children: [new TextRun({ text: orgName || L(lang, "Récipiendaire principal (PR)", "Principal Recipient (PR)", "Receptor Principal (PR)"), size: 24, color: _shared().COLORS.MUTED })],
      }),
      new Paragraph({
        alignment: AlignmentType.CENTER,
        spacing: { before: 800, after: 200 },
        children: [new TextRun({ text: L(lang, "Cycle de subvention", "Grant cycle", "Ciclo de subvención") + " : " + year + " — " + (parseInt(year, 10) + 2), size: 22 })],
      }),
      new Paragraph({
        alignment: AlignmentType.CENTER,
        spacing: { after: 1600 },
        children: [new TextRun({ text: L(lang, "Document généré le ", "Generated on ", "Documento generado el ") + new Date().toLocaleDateString(window.L("fr-FR", "en-US", "es-ES")), size: 20, color: _shared().COLORS.MUTED, italics: true })],
      }),
      new Paragraph({
        alignment: AlignmentType.CENTER,
        children: [new TextRun({ text: L(lang, "Généré automatiquement par MELR · REFT Africa", "Auto-generated by MELR · REFT Africa", "Generado automáticamente por MELR · REFT Africa"), size: 18, color: _shared().COLORS.MUTED })],
      }),
    ];
  }

  // ── National Disease Context ───────────────────────────────────────────
  function buildContext({ scopeLabel, lang }) {
    const s = _shared();
    const { H, P, PageBreak } = s;
    const out = [];
    out.push(H(1, s.L(lang, "1. Contexte épidémiologique national", "1. National Disease Context", "1. Contexto epidemiológico nacional"), { color: GF_COLOR }));
    out.push(P(s.L(lang,
      "Cette section présente la situation épidémiologique nationale des trois maladies prioritaires (VIH/SIDA, tuberculose, paludisme) et l'alignement de la subvention avec le Plan Stratégique National (PSN) de santé en vigueur.",
      "This section presents the national epidemiological situation of the three priority diseases (HIV/AIDS, tuberculosis, malaria) and the alignment of the grant with the National Strategic Plan (NSP) for health currently in force.", "Esta sección presenta la situación epidemiológica nacional de las tres enfermedades prioritarias (VIH/SIDA, tuberculosis, malaria) y la alineación de la subvención con el Plan Estratégico Nacional (PEN) de salud en vigor.")));

    out.push(H(2, s.L(lang, "VIH/SIDA", "HIV/AIDS", "VIH/SIDA"), { color: GF_COLOR }));
    out.push(P(s.L(lang,
      "Prévalence chez l'adulte 15-49 ans, incidence des nouvelles infections, couverture du traitement antirétroviral (TARV), suppression virale à 12 mois. Cibles 95-95-95 ONUSIDA.",
      "Adult HIV prevalence 15-49 yrs, incidence of new infections, antiretroviral therapy (ART) coverage, viral suppression at 12 months. UNAIDS 95-95-95 targets.", "Prevalencia en adultos de 15-49 años, incidencia de nuevas infecciones, cobertura del tratamiento antirretroviral (TAR), supresión viral a los 12 meses. Metas 95-95-95 de ONUSIDA.")));

    out.push(H(2, s.L(lang, "Tuberculose", "Tuberculosis", "Tuberculosis"), { color: GF_COLOR }));
    out.push(P(s.L(lang,
      "Incidence estimée par l'OMS, taux de notification, taux de succès thérapeutique, dépistage des cas TB-MR (multirésistant). Cibles End TB Strategy 2030.",
      "WHO-estimated incidence, notification rate, treatment success rate, MDR-TB (multi-drug resistant) case detection. End TB Strategy 2030 targets.", "Incidencia estimada por la OMS, tasa de notificación, tasa de éxito terapéutico, detección de casos de TB-MDR (multirresistente). Metas de la Estrategia Fin de la TB 2030.")));

    out.push(H(2, s.L(lang, "Paludisme", "Malaria", "Malaria"), { color: GF_COLOR }));
    out.push(P(s.L(lang,
      "Incidence et mortalité, couverture des moustiquaires imprégnées (LLIN), traitement préventif intermittent (TPI) pour les femmes enceintes, prise en charge des cas chez l'enfant.",
      "Incidence and mortality, long-lasting insecticidal nets (LLIN) coverage, intermittent preventive treatment (IPT) for pregnant women, case management for children.", "Incidencia y mortalidad, cobertura de mosquiteros tratados con insecticida de larga duración (LLIN), tratamiento preventivo intermitente (TPI) para mujeres embarazadas, manejo de casos en la infancia.")));

    out.push(H(2, s.L(lang, "RSSH — Systèmes de santé résilients & pérennes", "RSSH — Resilient & Sustainable Systems for Health", "RSSH — Sistemas de salud resilientes y sostenibles"), { color: GF_COLOR }));
    out.push(P(s.L(lang,
      "Renforcement du système d'information sanitaire (DHIS2), chaîne d'approvisionnement intégrée, ressources humaines en santé, surveillance des maladies, prestation de services au niveau communautaire.",
      "Health information system strengthening (DHIS2), integrated supply chain, health workforce, disease surveillance, community-level service delivery.", "Fortalecimiento del sistema de información sanitaria (DHIS2), cadena de suministro integrada, recursos humanos en salud, vigilancia de enfermedades, prestación de servicios a nivel comunitario.")));

    return out;
  }

  // ── Grant Components ───────────────────────────────────────────────────
  function buildGrantComponents({ projects, indicators, lang }) {
    const s = _shared();
    const { H, P, Cell, Row, Tbl, PageBreak } = s;
    const out = [];
    out.push(PageBreak());
    out.push(H(1, s.L(lang, "2. Modules de la subvention", "2. Grant Modules", "2. Módulos de la subvención"), { color: GF_COLOR }));
    out.push(P(s.L(lang,
      "Les indicateurs sont organisés par module Global Fund (HIV, TB, Malaria, RSSH). Cette classification reflète la structure modulaire du portail Global Fund Partner Portal.",
      "Indicators are organized by Global Fund module (HIV, TB, Malaria, RSSH). This classification reflects the modular structure of the Global Fund Partner Portal.", "Los indicadores se organizan por módulo del Global Fund (VIH, TB, Malaria, RSSH). Esta clasificación refleja la estructura modular del Global Fund Partner Portal.")));

    // Group indicators heuristically by sector keyword
    function moduleFor(ind) {
      const sec = (ind.sector || ind.sectorCode || "").toLowerCase();
      const name = ((ind.name_fr || ind.name_en || ind.name || "") + " " + (ind.code || "")).toLowerCase();
      if (sec.includes("vih") || sec.includes("hiv") || name.includes("vih") || name.includes("hiv") || name.includes("tarv") || name.includes("art")) return "HIV";
      if (sec.includes("tb") || name.includes("tuberculose") || name.includes("tuberculosis")) return "TB";
      if (sec.includes("palu") || name.includes("paludisme") || name.includes("malaria") || name.includes("moustiquaire")) return "Malaria";
      return "RSSH";
    }

    const modules = { HIV: [], TB: [], Malaria: [], RSSH: [] };
    (indicators || []).forEach((i) => {
      const m = moduleFor(i);
      modules[m].push(i);
    });

    const modLabels = {
      HIV:     { fr: "VIH/SIDA",                  en: "HIV/AIDS", es: "VIH/SIDA" },
      TB:      { fr: "Tuberculose",               en: "Tuberculosis", es: "Tuberculosis" },
      Malaria: { fr: "Paludisme",                 en: "Malaria", es: "Paludismo" },
      RSSH:    { fr: "RSSH (systèmes de santé)",  en: "RSSH (health systems)", es: "RSSH (sistemas de salud)" },
    };

    const hdr = { bold: true, color: "FFFFFF", fill: GF_COLOR };
    Object.keys(modules).forEach((mod) => {
      out.push(H(2, s.L(lang, modLabels[mod].fr, modLabels[mod].en), { color: GF_COLOR }));
      const arr = modules[mod];
      if (arr.length === 0) {
        out.push(P(s.L(lang, "Aucun indicateur attribué à ce module.", "No indicator assigned to this module.", "Ningún indicador asignado a este módulo."), { run: { italics: true, color: s.COLORS.MUTED } }));
        return;
      }
      const rows = [Row([
        Cell(s.L(lang, "Code", "Code"),         { ...hdr, width: 1000 }),
        Cell(s.L(lang, "Indicateur", "Indicator", "Indicador"), { ...hdr, width: 4000 }),
        Cell(s.L(lang, "Niveau", "Level", "Nivel"),      { ...hdr, width: 1400, align: window.docx.AlignmentType.CENTER }),
        Cell(s.L(lang, "Base", "Baseline", "Línea de base"),     { ...hdr, width: 1200, align: window.docx.AlignmentType.CENTER }),
        Cell(s.L(lang, "Cible", "Target", "Meta"),      { ...hdr, width: 1200, align: window.docx.AlignmentType.CENTER }),
        Cell(s.L(lang, "Réalisé", "Actual", "Realizado"),    { ...hdr, width: 560,  align: window.docx.AlignmentType.CENTER }),
      ])];
      arr.forEach((i) => {
        rows.push(Row([
          Cell(i.id || i.code || "—",                                              { width: 1000, size: 18 }),
          Cell(lang === "fr" ? (i.name_fr || i.name) : (i.name_en || i.name),     { width: 4000, size: 18 }),
          Cell(i.level || "Output",                                                 { width: 1400, size: 18, align: window.docx.AlignmentType.CENTER }),
          Cell(s.fmtNum(i.baseline, i.unit),                                        { width: 1200, size: 18, align: window.docx.AlignmentType.CENTER }),
          Cell(s.fmtNum(i.target, i.unit),                                          { width: 1200, size: 18, align: window.docx.AlignmentType.CENTER }),
          Cell(s.fmtNum(i.actual, i.unit),                                          { width: 560,  size: 18, align: window.docx.AlignmentType.CENTER }),
        ]));
      });
      out.push(Tbl(rows, { columnWidths: [1000, 4000, 1400, 1200, 1200, 560] }));
    });

    return out;
  }

  // ── Performance Framework (IPTT-style) ─────────────────────────────────
  function buildPerformanceFramework({ indicators, year, lang }) {
    const s = _shared();
    const { H, P, Cell, Row, Tbl, PageBreak } = s;
    const Y = 3;
    const out = [];
    out.push(PageBreak());
    out.push(H(1, s.L(lang, "3. Cadre de performance (Performance Framework)", "3. Performance Framework", "3. Marco de desempeño (Performance Framework)"), { color: GF_COLOR }));
    out.push(P(s.L(lang,
      "Le cadre de performance consolide indicateurs, cibles et réalisés sur les trois années du cycle de subvention. Le suivi est trimestriel ; les valeurs ci-dessous sont les cumuls annuels (PUDR — Progress Update / Disbursement Request).",
      "The performance framework consolidates indicators, targets, and actuals across the three years of the grant cycle. Monitoring is quarterly; values below are annual cumulative (PUDR — Progress Update / Disbursement Request).", "El marco de desempeño consolida indicadores, metas y valores reales a lo largo de los tres años del ciclo de subvención. El seguimiento es trimestral; los valores siguientes son los acumulados anuales (PUDR — Progress Update / Disbursement Request).")));

    const baseYear = parseInt(year, 10) || new Date().getFullYear();
    const yLabels = [];
    for (let i = 1; i <= Y; i++) yLabels.push("Y" + i + " (" + (baseYear - Y + i) + ")");

    const hdr = { bold: true, color: "FFFFFF", fill: GF_COLOR };
    const headerCells = [
      Cell(s.L(lang, "Code", "Code"),                  { ...hdr, width: 800 }),
      Cell(s.L(lang, "Indicateur", "Indicator", "Indicador"),       { ...hdr, width: 2600 }),
      Cell(s.L(lang, "Unité", "Unit", "Unidad"),                 { ...hdr, width: 600 }),
      Cell(s.L(lang, "Base", "Baseline", "Línea de base"),              { ...hdr, width: 800 }),
    ];
    yLabels.forEach((yl) => {
      headerCells.push(Cell(yl + " " + s.L(lang, "Cible", "Target", "Meta"),  { ...hdr, width: 800, align: window.docx.AlignmentType.CENTER }));
      headerCells.push(Cell(yl + " " + s.L(lang, "Réal.", "Actual", "Real."),  { ...hdr, width: 800, align: window.docx.AlignmentType.CENTER }));
      headerCells.push(Cell("%", { ...hdr, width: 520, align: window.docx.AlignmentType.CENTER }));
    });

    const rows = [Row(headerCells)];
    (indicators || []).forEach((ind) => {
      const perf = s.computePerformance(ind, baseYear, Y);
      rows.push(s.iptRow(ind, perf, lang, Y));
    });
    if ((indicators || []).length === 0) {
      rows.push(Row([Cell(s.L(lang, "Aucun indicateur dans le périmètre", "No indicators in scope", "Ningún indicador en el perímetro"),
        { colSpan: 4 + 3 * Y, color: s.COLORS.MUTED, align: window.docx.AlignmentType.CENTER })]));
    }

    const widths = [800, 2600, 600, 800];
    for (let i = 0; i < Y; i++) widths.push(800, 800, 520);
    out.push(Tbl(rows, { columnWidths: widths, width: widths.reduce((a, b) => a + b, 0) }));

    return out;
  }

  // ── Indicator Narratives ───────────────────────────────────────────────
  function buildIndicatorNarratives({ indicators, year, lang }) {
    const s = _shared();
    const { H, P, Cell, Row, Tbl, Spacer, PageBreak } = s;
    const out = [];
    out.push(PageBreak());
    out.push(H(1, s.L(lang, "4. Fiches narratives des indicateurs", "4. Indicator Narratives", "4. Fichas narrativas de los indicadores"), { color: GF_COLOR }));
    out.push(P(s.L(lang,
      "Chaque indicateur dispose d'une fiche détaillée précisant la définition, le numérateur, le dénominateur, les sources de données, la fréquence, et le commentaire de performance.",
      "Each indicator has a detail sheet specifying the definition, numerator, denominator, data sources, frequency, and performance commentary.", "Cada indicador dispone de una ficha detallada que precisa la definición, el numerador, el denominador, las fuentes de datos, la frecuencia y el comentario de desempeño.")));

    (indicators || []).forEach((ind, idx) => {
      if (idx > 0) out.push(Spacer(140));
      const name = lang === "fr" ? (ind.name_fr || ind.name) : (ind.name_en || ind.name);
      out.push(H(2, (ind.id || ind.code || "—") + " — " + name, { color: GF_COLOR }));

      const FILL = "F3F4F6";
      const rowsData = [
        [s.L(lang, "Définition", "Definition", "Definición"),                       lang === "fr" ? (ind.definition_fr || ind.definition || name) : (ind.definition_en || ind.definition || name)],
        [s.L(lang, "Numérateur", "Numerator", "Numerador"),                        s.L(lang, "Nombre d'individus/évènements correspondant à la définition.", "Number of individuals/events matching the definition.", "Número de individuos/eventos que corresponden a la definición.")],
        [s.L(lang, "Dénominateur", "Denominator", "Denominador"),                    s.L(lang, "Population éligible ou cible.", "Eligible or target population.", "Población elegible o destinataria.")],
        [s.L(lang, "Unité de mesure", "Unit of measure", "Unidad de medida"),              ind.unit || "—"],
        [s.L(lang, "Désagrégation", "Disaggregation", "Desagregación"),                ind.disaggregation_required ? s.L(lang, "Sexe, âge, géographie (voir grille de saisie)", "Sex, age, geography (see input grid)", "Sexo, edad, geografía (véase la cuadrícula de captura)") : s.L(lang, "Aucune", "None", "Ninguna")],
        [s.L(lang, "Source des données", "Data sources", "Fuente de los datos"),              s.L(lang, "DHIS2 + collecte terrain MELR (PWA mobile)", "DHIS2 + MELR field data (mobile PWA)", "DHIS2 + recopilación de campo MELR (PWA móvil)")],
        [s.L(lang, "Méthode de collecte", "Collection method", "Método de recopilación"),        s.L(lang, "Routine programmatique + supervisions formatives", "Routine programmatic + formative supervisions", "Rutina programática + supervisiones formativas")],
        [s.L(lang, "Fréquence de mesure", "Measurement frequency", "Frecuencia de medición"),    s.L(lang, "Trimestrielle (rapportée dans le PUDR)", "Quarterly (reported in the PUDR)", "Trimestral (reportada en el PUDR)")],
        [s.L(lang, "Niveau de désagrégation", "Disaggregation level", "Nivel de desagregación"), s.L(lang, "Site, district, région, national", "Site, district, region, national", "Sitio, distrito, región, nacional")],
        [s.L(lang, "Responsabilité", "Responsibility", "Responsabilidad"),                s.L(lang, "PR M&E unit (validation par le LFA Global Fund)", "PR M&E unit (validated by Global Fund LFA)", "Unidad de S&E del PR (validación por el LFA del Global Fund)")],
      ];

      const rows = rowsData.map(([k, v]) => Row([
        Cell(k, { width: 2800, bold: true, fill: FILL, color: GF_COLOR, size: 18 }),
        Cell(v, { width: 6560, size: 20 }),
      ]));
      out.push(Tbl(rows, { columnWidths: [2800, 6560] }));
    });

    if ((indicators || []).length === 0) {
      out.push(P(s.L(lang, "Aucun indicateur à détailler.", "No indicators to detail.", "Ningún indicador que detallar."), { run: { italics: true, color: s.COLORS.MUTED } }));
    }

    return out;
  }

  // ── Data Flow & Quality Assurance ──────────────────────────────────────
  function buildDataFlow({ lang }) {
    const s = _shared();
    const { H, P, PageBreak } = s;
    const out = [];
    out.push(PageBreak());
    out.push(H(1, s.L(lang, "5. Flux de données & assurance qualité", "5. Data Flow & Quality Assurance", "5. Flujo de datos y garantía de calidad"), { color: GF_COLOR }));
    out.push(P(s.L(lang,
      "Le flux standard Global Fund part du site de prestation (formation sanitaire, communauté) vers le niveau district, puis la coordination régionale et enfin l'unité M&E du PR pour consolidation et rapport au Local Fund Agent (LFA).",
      "The standard Global Fund flow runs from the service delivery site (health facility, community) up to the district level, then regional coordination, and finally the PR M&E unit for consolidation and reporting to the Local Fund Agent (LFA).", "El flujo estándar del Global Fund parte del sitio de prestación (establecimiento de salud, comunidad) hacia el nivel distrital, luego la coordinación regional y, finalmente, la unidad de S&E del PR para la consolidación y el reporte al Local Fund Agent (LFA).")));

    out.push(H(2, s.L(lang, "Niveaux du flux", "Flow levels", "Niveles del flujo"), { color: GF_COLOR }));
    out.push(P("• " + s.L(lang, "Site (formation sanitaire / communauté) — saisie quotidienne dans les outils Global Fund / MELR", "Site (health facility / community) — daily entry in Global Fund / MELR tools", "Sitio (establecimiento de salud / comunidad) — captura diaria en las herramientas Global Fund / MELR")));
    out.push(P("• " + s.L(lang, "District — agrégation hebdomadaire, validation par le District Health Management Team", "District — weekly aggregation, validation by the District Health Management Team", "Distrito — agregación semanal, validación por el District Health Management Team")));
    out.push(P("• " + s.L(lang, "Région — synthèse mensuelle, contrôle qualité", "Region — monthly summary, quality control", "Región — síntesis mensual, control de calidad")));
    out.push(P("• " + s.L(lang, "PR M&E unit — consolidation trimestrielle, soumission PUDR", "PR M&E unit — quarterly consolidation, PUDR submission", "Unidad de S&E del PR — consolidación trimestral, presentación del PUDR")));
    out.push(P("• " + s.L(lang, "Local Fund Agent (LFA) — vérification indépendante", "Local Fund Agent (LFA) — independent verification", "Local Fund Agent (LFA) — verificación independiente")));

    out.push(H(2, s.L(lang, "Audits internes (Spot-checks)", "Internal audits (Spot-checks)", "Auditorías internas (Spot-checks)"), { color: GF_COLOR }));
    out.push(P(s.L(lang,
      "10 % des sites tirés au sort chaque trimestre. Vérification croisée entre registres papier, DHIS2 et données MELR. Les écarts > 10 % déclenchent un plan d'action correctif.",
      "10 % of sites sampled each quarter. Cross-check between paper registers, DHIS2 and MELR data. Discrepancies > 10 % trigger a corrective action plan.", "10 % de los sitios seleccionados al azar cada trimestre. Verificación cruzada entre registros en papel, DHIS2 y datos MELR. Las discrepancias > 10 % activan un plan de acción correctivo.")));

    out.push(H(2, s.L(lang, "OSDV — On-Site Data Verification", "OSDV — On-Site Data Verification"), { color: GF_COLOR }));
    out.push(P(s.L(lang,
      "Le LFA conduit une OSDV annuelle sur un échantillon de sites. MELR met à disposition les modules SAT (Self-Assessment Tool) et DVT (Data Verification Tool) avec exports Word/Excel/PDF traçables.",
      "The LFA conducts an annual OSDV on a sample of sites. MELR provides the SAT (Self-Assessment Tool) and DVT (Data Verification Tool) modules with traceable Word/Excel/PDF exports.", "El LFA realiza una OSDV anual sobre una muestra de sitios. MELR pone a disposición los módulos SAT (Self-Assessment Tool) y DVT (Data Verification Tool) con exportaciones Word/Excel/PDF trazables.")));

    return out;
  }

  // ── M&E Arrangements ──────────────────────────────────────────────────
  function buildMEArrangements({ lang }) {
    const s = _shared();
    const { H, P, PageBreak } = s;
    const out = [];
    out.push(PageBreak());
    out.push(H(1, s.L(lang, "6. Dispositif de suivi-évaluation", "6. M&E Arrangements", "6. Dispositivo de seguimiento y evaluación"), { color: GF_COLOR }));

    out.push(H(2, s.L(lang, "Calendrier de rapport", "Reporting calendar", "Calendario de reporte"), { color: GF_COLOR }));
    out.push(P("• " + s.L(lang, "PUDR (Progress Update / Disbursement Request) — semestriel", "PUDR (Progress Update / Disbursement Request) — semi-annual", "PUDR (Progress Update / Disbursement Request) — semestral")));
    out.push(P("• " + s.L(lang, "Annual Funding Request — annuel", "Annual Funding Request — annual", "Annual Funding Request — anual")));
    out.push(P("• " + s.L(lang, "End of Grant Report — fin de cycle", "End of Grant Report — end of cycle", "End of Grant Report — fin de ciclo")));

    out.push(H(2, s.L(lang, "Réunions de suivi", "Monitoring meetings", "Reuniones de seguimiento"), { color: GF_COLOR }));
    out.push(P("• " + s.L(lang, "Réunion CCM (Country Coordinating Mechanism) — trimestrielle", "CCM (Country Coordinating Mechanism) meeting — quarterly", "Reunión del CCM (Country Coordinating Mechanism) — trimestral")));
    out.push(P("• " + s.L(lang, "Comité technique de suivi (CTS) — mensuel", "Technical Monitoring Committee — monthly", "Comité Técnico de Seguimiento (CTS) — mensual")));
    out.push(P("• " + s.L(lang, "Revue annuelle conjointe PR-LFA-Global Fund", "Joint PR-LFA-Global Fund annual review", "Revisión anual conjunta PR-LFA-Global Fund")));

    out.push(H(2, s.L(lang, "Évaluations externes", "External evaluations", "Evaluaciones externas"), { color: GF_COLOR }));
    out.push(P(s.L(lang,
      "Évaluation mi-parcours par un cabinet indépendant. Évaluation finale du cycle. Études d'impact des interventions phares (programmes communautaires, prise en charge décentralisée).",
      "Mid-term evaluation by an independent firm. End-of-cycle evaluation. Impact studies on flagship interventions (community programmes, decentralized care).", "Evaluación intermedia por una firma independiente. Evaluación final del ciclo. Estudios de impacto de las intervenciones emblemáticas (programas comunitarios, atención descentralizada).")));

    return out;
  }

  // ── Risk Assessment ───────────────────────────────────────────────────
  function buildRiskAssessment({ lang }) {
    const s = _shared();
    const { H, P, Cell, Row, Tbl, PageBreak } = s;
    const out = [];
    out.push(PageBreak());
    out.push(H(1, s.L(lang, "7. Évaluation des risques", "7. Risk Assessment", "7. Evaluación de riesgos"), { color: GF_COLOR }));
    out.push(P(s.L(lang,
      "Les risques majeurs identifiés conformément à la matrice Global Fund Integrated Risk Management (IRM).",
      "Major risks identified per the Global Fund Integrated Risk Management (IRM) matrix.", "Los riesgos principales identificados conforme a la matriz Global Fund Integrated Risk Management (IRM).")));

    const hdr = { bold: true, color: "FFFFFF", fill: GF_COLOR };
    const headerRow = Row([
      Cell(s.L(lang, "Catégorie", "Category", "Categoría"),         { ...hdr, width: 1800 }),
      Cell(s.L(lang, "Risque", "Risk", "Riesgo"),                { ...hdr, width: 2800 }),
      Cell(s.L(lang, "Sévérité", "Severity", "Severidad"),          { ...hdr, width: 1200, align: window.docx.AlignmentType.CENTER }),
      Cell(s.L(lang, "Mesure d'atténuation", "Mitigation", "Medida de mitigación"), { ...hdr, width: 3560 }),
    ]);

    const risks = [
      { cat_fr: "Gouvernance",     cat_en: "Governance", cat_es: "Gobernanza",
        r_fr: "Faiblesse de la CCM, retards de décision",  r_en: "Weak CCM, decision delays", r_es: "Debilidad del CCM, retrasos en la toma de decisiones",
        sev: s.L(lang, "Élevée", "High", "Alta"),
        m_fr: "Plan de renforcement CCM, suivi mensuel des engagements.",
        m_en: "CCM strengthening plan, monthly tracking of commitments.", m_es: "Plan de fortalecimiento del CCM, seguimiento mensual de los compromisos." },
      { cat_fr: "Mise en œuvre",   cat_en: "Implementation", cat_es: "Implementación",
        r_fr: "Retards d'approvisionnement médicaments traceurs", r_en: "Procurement delays of tracer commodities", r_es: "Retrasos de aprovisionamiento de medicamentos trazadores",
        sev: s.L(lang, "Modérée", "Moderate", "Moderada"),
        m_fr: "PSM (Procurement & Supply Management) plan glissant, stock de sécurité 6 mois.",
        m_en: "Rolling PSM (Procurement & Supply Management) plan, 6-month safety stock.", m_es: "Plan PSM (Procurement & Supply Management) rodante, stock de seguridad de 6 meses." },
      { cat_fr: "Qualité données", cat_en: "Data quality", cat_es: "Calidad de los datos",
        r_fr: "Sous-déclaration des cas TB chez les enfants",     r_en: "Under-reporting of pediatric TB cases", r_es: "Subnotificación de casos de TB en la población pediátrica",
        sev: s.L(lang, "Modérée", "Moderate", "Moderada"),
        m_fr: "Formation des cliniciens, supervision intégrée, audits DVT trimestriels.",
        m_en: "Clinician training, integrated supervision, quarterly DVT audits.", m_es: "Formación de los clínicos, supervisión integrada, auditorías DVT trimestrales." },
      { cat_fr: "Finance",         cat_en: "Finance",
        r_fr: "Sur-coûts des nouvelles directives traitement",     r_en: "Cost overruns of new treatment guidelines", r_es: "Sobrecostos de las nuevas directrices de tratamiento",
        sev: s.L(lang, "Élevée", "High", "Alta"),
        m_fr: "Re-priorisation budgétaire annuelle, plaidoyer auprès du Global Fund pour réallocation.",
        m_en: "Annual budget re-prioritization, advocacy with Global Fund for reallocation.", m_es: "Repriorización presupuestaria anual, incidencia ante el Global Fund para la reasignación." },
      { cat_fr: "Programmatique",  cat_en: "Programmatic", cat_es: "Programático",
        r_fr: "Résistance aux antipaludiques (ACT)",              r_en: "Antimalarial resistance (ACT)", r_es: "Resistencia a los antipalúdicos (ACT)",
        sev: s.L(lang, "Élevée", "High", "Alta"),
        m_fr: "Surveillance moléculaire, rotation des molécules, plans de réponse rapide.",
        m_en: "Molecular surveillance, drug rotation, rapid response plans.", m_es: "Vigilancia molecular, rotación de moléculas, planes de respuesta rápida." },
    ];

    const rows = [headerRow].concat(risks.map((r) => Row([
      Cell(s.L(lang, r.cat_fr, r.cat_en),    { width: 1800, size: 18 }),
      Cell(s.L(lang, r.r_fr, r.r_en),        { width: 2800, size: 18 }),
      Cell(r.sev,                            { width: 1200, size: 18, align: window.docx.AlignmentType.CENTER }),
      Cell(s.L(lang, r.m_fr, r.m_en),        { width: 3560, size: 18 }),
    ])));

    out.push(Tbl(rows, { columnWidths: [1800, 2800, 1200, 3560] }));

    return out;
  }

  // ── Master builder ─────────────────────────────────────────────────────
  function buildGfDoc({ projects, indicators, scope, year, scopeLabel, orgName, lang }) {
    if (!_ok()) throw new Error("melrDonor shared module not loaded");
    const { Document, Footer, PageNumber, TextRun, Paragraph, AlignmentType } = window.docx;
    const s = _shared();

    const children = [];
    children.push(...buildCover({ orgName, scopeLabel, year, lang }));
    children.push(s.PageBreak());
    children.push(...buildContext({ scopeLabel, lang }));
    children.push(...buildGrantComponents({ projects, indicators, lang }));
    children.push(...buildPerformanceFramework({ indicators, year, lang }));
    children.push(...buildIndicatorNarratives({ indicators, year, lang }));
    children.push(...buildDataFlow({ lang }));
    children.push(...buildMEArrangements({ lang }));
    children.push(...buildRiskAssessment({ lang }));

    return new Document({
      creator: "MELR",
      title: "Global Fund Grant PF — " + (scopeLabel || "Grant") + " — " + year,
      description: "Global Fund Grant Performance Framework auto-generated by MELR",
      styles: { default: { document: { run: { font: "Calibri", size: 22 } } } },
      sections: [{
        properties: {
          page: {
            margin: { top: 1200, right: 1200, bottom: 1200, left: 1200 },
            size: { width: 11906, height: 16838 }, // A4
          },
        },
        footers: {
          default: new Footer({
            children: [new Paragraph({
              alignment: AlignmentType.CENTER,
              children: [
                new TextRun({ text: "Global Fund Grant PF · " + (scopeLabel || "Grant") + " · " + year + " · ", color: s.COLORS.MUTED, size: 18 }),
                new TextRun({ children: [PageNumber.CURRENT], color: s.COLORS.MUTED, size: 18 }),
                new TextRun({ text: " / ", color: s.COLORS.MUTED, size: 18 }),
                new TextRun({ children: [PageNumber.TOTAL_PAGES], color: s.COLORS.MUTED, size: 18 }),
              ],
            })],
          }),
        },
        children,
      }],
    });
  }

  async function exportGlobalFundFramework(args) {
    args = args || {};
    if (!_ok()) {
      alert((args.lang || "fr") === "fr" ? "Module partagé indisponible." : "Shared module unavailable.");
      return;
    }
    const s = _shared();
    try {
      const doc = buildGfDoc({
        projects: args.projects || [],
        indicators: args.indicators || [],
        scope: args.scope || { mode: "all" },
        year: args.year || new Date().getFullYear(),
        scopeLabel: args.scopeLabel || s.L(args.lang, "Subvention", "Grant", "Subvención"),
        orgName: args.orgName || "",
        lang: args.lang || "fr",
      });
      await s.saveDocx(doc, (args.filename || ("GlobalFund-PF-" + (args.year || new Date().getFullYear()))), args.lang);
    } catch (e) {
      console.error("[Global Fund export]", e);
      alert(((args.lang || "fr") === "fr" ? "Erreur Global Fund : " : "Global Fund error: ") + e.message);
    }
  }

  window.exportGlobalFundFramework = exportGlobalFundFramework;
})();
