/* global React, Icon, Modal, window */
// ============================================================================
// MELR · Évaluations mi-parcours & finales — critères OCDE/CAD + cadre logique
// ----------------------------------------------------------------------------
// Phase 4c du module ÉVALUATIONS. Même squelette méthodologique que les
// politiques publiques (constantes partagées window.MELR_DAC), enrichi de :
//   - Cadre logique : lecture DIRECTE des indicateurs du projet MELR lié
//     (référence / cible / dernière valeur, taux d'atteinte calculé) ;
//   - Leçons apprises ;
//   - Réponse managériale (suivi des recommandations).
//
// Données : registre `evaluations` (type 'midterm_final', sous-type
// mi-parcours / finale dans le cadrage) + feuilles `evaluation_sheets`
// (framing / logframe / findings / lessons / conclusions / response).
// ============================================================================

(function () {
  const { useState, useEffect, useMemo } = React;

  const sec = (c, extra) => (window.MelrSection ? window.MelrSection.style(c, extra) : { marginBottom: 14, ...(extra || {}) });
  const secT = (c) => (window.MelrSection ? window.MelrSection.title(c) : { fontSize: 13, fontWeight: 700, marginBottom: 8 });
  const xbtn = (bg) => (window.MelrSection ? window.MelrSection.btn(bg) : {});
  const DAC = () => window.MELR_DAC || { CRITERIA: [], RATINGS: {}, RESPONSE_CHOICES: {}, RESPONSE_STATUSES: {} };

  const KINDS = {
    midterm: { fr: "Mi-parcours", en: "Mid-term", es: "Intermedia" },
    final:   { fr: "Finale",      en: "Final", es: "Final" },
  };

  // Teinte OKLCH distincte par onglet (.pd-tabs / .pd-tab, comme Projets / Ex-ante).
  const TABS = [
    { key: "overview",    fr: "Vue d'ensemble",                en: "Overview", es: "Visión general",                      hue: 230 },
    { key: "framing",     fr: "Cadrage",                       en: "Framing", es: "Encuadre",                       hue: 50 },
    { key: "logframe",    fr: "Cadre logique",                 en: "Logframe", es: "Marco lógico",                      hue: 200 },
    { key: "findings",    fr: "Constats par critère",          en: "Findings by criterion", es: "Constataciones por criterio",         hue: 150 },
    { key: "lessons",     fr: "Leçons apprises",               en: "Lessons learned", es: "Lecciones aprendidas",               hue: 25 },
    { key: "conclusions", fr: "Conclusions & recommandations", en: "Conclusions & recommendations", es: "Conclusiones y recomendaciones", hue: 285 },
    { key: "response",    fr: "Réponse managériale",           en: "Management response", es: "Respuesta directiva",           hue: 350 },
  ];

  const FRAMING_FIELDS = [
    { key: "object",    fr: "Objet et périmètre",        en: "Object and scope", es: "Objeto y alcance",
      hint_fr: "Projet/programme évalué, période couverte, zones et composantes incluses.",
      hint_en: "Project/programme evaluated, period covered, areas and components included." },
    { key: "purpose",   fr: "Finalité et utilisateurs",  en: "Purpose and users", es: "Finalidad y usuarios",
      hint_fr: "Mi-parcours : réorientation et pilotage. Finale : redevabilité, capitalisation, décision de suite.",
      hint_en: "Mid-term: steering and re-orientation. Final: accountability, capitalization, follow-on decision." },
    { key: "questions", fr: "Questions évaluatives",     en: "Evaluation questions", es: "Preguntas evaluativas",
      hint_fr: "Les grandes questions, rattachées aux critères CAD dans l'onglet Constats.",
      hint_en: "The main questions, linked to DAC criteria in the Findings tab." },
    { key: "methods",   fr: "Méthodologie",              en: "Methodology", es: "Metodología",
      hint_fr: "Revue documentaire, entretiens, visites de sites, méthodes mixtes, limites.",
      hint_en: "Desk review, interviews, site visits, mixed methods, limitations." },
    { key: "calendar",  fr: "Calendrier et gouvernance", en: "Timeline and governance", es: "Calendario y gobernanza",
      hint_fr: "Jalons, comité de pilotage, équipe d'évaluation.",
      hint_en: "Milestones, steering committee, evaluation team." },
  ];

  const nnum = (v) => {
    const n = Number(v);
    return v == null || v === "" || Number.isNaN(n) ? null : n;
  };

  // Dernière valeur d'un indicateur projet (lignes useIndicators :
  // indicator_values embarquées, non triées → on prend la plus récente).
  function latestValue(ind) {
    const vals = (ind.indicator_values || []).slice()
      .sort((a, b) => String(b.period_end || "").localeCompare(String(a.period_end || "")));
    return vals[0] || null;
  }
  // Taux d'atteinte : (dernier − référence) / (cible − référence).
  function achievementPct(ind) {
    const lv = latestValue(ind);
    const cur = lv ? nnum(lv.value) : null;
    const base = nnum(ind.baseline), target = nnum(ind.target);
    if (cur == null || target == null) return null;
    if (base != null && target !== base) return 100 * (cur - base) / (target - base);
    if (target) return 100 * cur / target;
    return null;
  }

  // ── Export Word / PDF ────────────────────────────────────────────────────
  function exportMidtermWord(lang, evaluation, sheets, projectIndicators) {
    const D = window.docx;
    if (!D) { window.alert(window.L("Bibliothèque Word indisponible.", "Word library unavailable.", "Biblioteca Word no disponible.")); return; }
    const L = (fr, en) => (lang === "fr" ? fr : en);
    const dac = DAC();
    const f = sheets.framing || {}, findings = sheets.findings || {}, lessons = sheets.lessons || {},
          conclusions = sheets.conclusions || {}, response = sheets.response || {}, logframe = sheets.logframe || {};
    const kind = KINDS[f.kind] || KINDS.midterm;
    const title = lang === "fr" ? (evaluation.title_fr || "Évaluation") : (evaluation.title_en || evaluation.title_fr || "Evaluation");
    const P = (text, o) => new D.Paragraph({
      children: [new D.TextRun({ text, size: (o && o.size) || 21, bold: !!(o && o.bold), color: (o && o.color) || "111827", font: "Arial", italics: !!(o && o.italics) })],
      spacing: { after: (o && o.after) != null ? o.after : 100 },
    });
    const H1 = (t) => P(t, { size: 25, bold: true, color: "0F2740", after: 130 });
    const H2 = (t) => P(t, { size: 21, bold: true, color: "1D4ED8", after: 80 });
    const block = (text) => ((text || "").trim() || L("(à compléter)", "(to be completed)")).split(/\n+/).map((line) => P(line));
    const border = { style: D.BorderStyle.DOTTED, size: 2, color: "94A3B8" };
    const borders = { top: border, bottom: border, left: border, right: border };
    const cell = (t, opts) => new D.TableCell({
      borders, margins: { top: 30, bottom: 30, left: 80, right: 80 },
      shading: opts && opts.head ? { type: D.ShadingType.CLEAR, fill: "1D4ED8" } : undefined,
      children: [new D.Paragraph({ children: [new D.TextRun({
        text: String(t), size: 17, font: "Arial",
        bold: !!(opts && (opts.head || opts.bold)), color: opts && opts.head ? "FFFFFF" : "111827",
      })] })],
    });
    const children = [
      P(L("RAPPORT D'ÉVALUATION ", "EVALUATION REPORT — ") + (lang === "fr" ? kind.fr.toUpperCase() : kind.en.toUpperCase()), { size: 27, bold: true, color: "0F2740", after: 80 }),
      P(title, { size: 24, bold: true, color: "1D4ED8", after: 60 }),
      P(L("Critères OCDE/CAD (2019) · Période : ", "OECD/DAC criteria (2019) · Period: ")
        + (evaluation.period_start || "—") + (evaluation.period_end ? " → " + evaluation.period_end : "")
        + (evaluation.projects ? L(" · Projet : ", " · Project: ") + evaluation.projects.code : ""),
        { size: 18, color: "64748B", after: 240 }),
      H1(L("1. Cadrage", "1. Framing")),
    ];
    FRAMING_FIELDS.forEach((ff) => { children.push(H2((lang === "es" ? (ff.es != null ? ff.es : ff.en) : lang === "fr" ? ff.fr : ff.en))); children.push(...block(f[ff.key])); });
    children.push(H1(L("2. Performance du cadre logique", "2. Logframe performance")));
    if ((projectIndicators || []).length > 0) {
      children.push(new D.Table({
        width: { size: 100, type: D.WidthType.PERCENTAGE },
        rows: [
          new D.TableRow({ tableHeader: true, children: [
            cell(L("Indicateur", "Indicator"), { head: true }),
            cell(L("Référence", "Baseline"), { head: true }),
            cell(L("Cible", "Target"), { head: true }),
            cell(L("Dernière valeur", "Latest value"), { head: true }),
            cell(L("Atteinte", "Achievement"), { head: true }),
          ]}),
          ...projectIndicators.map((ind) => {
            const lv = latestValue(ind);
            const pct = achievementPct(ind);
            return new D.TableRow({ children: [
              cell((ind.code ? ind.code + " · " : "") + ((lang === "es" ? (ind.name_es != null ? ind.name_es : ind.name_en || ind.name_fr) : lang === "fr" ? ind.name_fr : ind.name_en || ind.name_fr))),
              cell(ind.baseline_text || (ind.baseline == null ? "—" : ind.baseline)),
              cell(ind.target_text || (ind.target == null ? "—" : ind.target)),
              cell(lv ? (lv.value_text || (lv.value == null ? "—" : lv.value)) : "—"),
              cell(pct == null ? "—" : Math.round(pct) + " %", { bold: true }),
            ]});
          }),
        ],
      }));
      children.push(P("", { after: 120 }));
    }
    children.push(...block(logframe.narrative));
    children.push(H1(L("3. Constats par critère", "3. Findings by criterion")));
    dac.CRITERIA.forEach((c) => {
      const ff = (findings[c.key] || {});
      const r = dac.RATINGS[ff.rating];
      children.push(H2(((lang === "es" ? (c.es != null ? c.es : c.en) : lang === "fr" ? c.fr : c.en)) + (r ? L(" — Appréciation : ", " — Rating: ") + ((lang === "es" ? (r.es != null ? r.es : r.en) : lang === "fr" ? r.fr : r.en)) : "")));
      children.push(...block(ff.text));
    });
    children.push(H1(L("4. Leçons apprises", "4. Lessons learned")));
    ((lessons.rows || [])).forEach((row, i) => {
      children.push(P((i + 1) + ". " + (row.text || "—"), { size: 19, after: 50 }));
    });
    if (lessons.narrative) children.push(...block(lessons.narrative));
    children.push(H1(L("5. Conclusions", "5. Conclusions")));
    children.push(...block(conclusions.text));
    children.push(H1(L("6. Recommandations et réponse managériale", "6. Recommendations and management response")));
    const recs = conclusions.recommendations || [];
    if (recs.length === 0) children.push(...block(""));
    recs.forEach((rec, i) => {
      children.push(P("R" + (i + 1) + ". " + (rec.text || "—")
        + (rec.addressee ? L(" — Destinataire : ", " — Addressee: ") + rec.addressee : ""), { size: 20, bold: true, after: 40 }));
      const resp = (response.items || {})[String(i)] || {};
      const ch = dac.RESPONSE_CHOICES[resp.decision];
      if (ch || resp.comment) {
        children.push(P(L("Réponse : ", "Response: ")
          + (ch ? ((lang === "es" ? (ch.es != null ? ch.es : ch.en) : lang === "fr" ? ch.fr : ch.en)) : "—")
          + (resp.comment ? " — " + resp.comment : "")
          + (resp.responsible ? L(" · Responsable : ", " · Responsible: ") + resp.responsible : "")
          + (resp.due ? L(" · Échéance : ", " · Due: ") + resp.due : ""),
          { size: 18, italics: true, after: 80 }));
      }
    });
    const doc = new D.Document({ sections: [{ children }] });
    const fname = "Evaluation_" + (f.kind === "final" ? "finale" : "mi-parcours") + "_" + (evaluation.title_fr || "rapport").replace(/[^\wÀ-ſ-]+/g, "_") + ".docx";
    D.Packer.toBlob(doc).then((blob) => {
      const url = URL.createObjectURL(blob);
      const a = document.createElement("a");
      a.href = url; a.download = fname; a.click();
      setTimeout(() => URL.revokeObjectURL(url), 4000);
    });
  }

  function exportMidtermPdf(lang, evaluation, sheets, projectIndicators) {
    if (!window.jspdf || !window.jspdf.jsPDF) { window.alert(window.L("Bibliothèque PDF indisponible.", "PDF library unavailable.", "Biblioteca PDF no disponible.")); return; }
    const L = (fr, en) => (lang === "fr" ? fr : en);
    const dac = DAC();
    const { jsPDF } = window.jspdf;
    const doc = new jsPDF({ unit: "pt", format: "a4" });
    const W = 595, M = 48; let y = 56;
    const ensure = (h) => { if (y + h > 800) { doc.addPage(); y = 56; } };
    const text = (str, size, o) => {
      o = o || {};
      doc.setFont("helvetica", o.bold ? "bold" : (o.italics ? "italic" : "normal"));
      doc.setFontSize(size);
      const c = o.color || [17, 24, 39];
      doc.setTextColor(c[0], c[1], c[2]);
      doc.splitTextToSize(String(str || ""), W - 2 * M).forEach((line) => { ensure(size * 1.5); doc.text(line, M, y); y += size * 1.35; });
      y += o.after != null ? o.after : 5;
    };
    const H1 = (t) => text(t, 13, { bold: true, color: [15, 39, 64], after: 6 });
    const narrative = (t) => text((t || "").trim() || L("(à compléter)", "(to be completed)"), 10, { after: 8 });
    const f = sheets.framing || {}, findings = sheets.findings || {}, lessons = sheets.lessons || {},
          conclusions = sheets.conclusions || {}, response = sheets.response || {}, logframe = sheets.logframe || {};
    const kind = KINDS[f.kind] || KINDS.midterm;
    const title = lang === "fr" ? (evaluation.title_fr || "Évaluation") : (evaluation.title_en || evaluation.title_fr || "Evaluation");
    text(L("RAPPORT D'ÉVALUATION ", "EVALUATION REPORT — ") + (lang === "fr" ? kind.fr.toUpperCase() : kind.en.toUpperCase()), 14, { bold: true, color: [15, 39, 64], after: 3 });
    text(title, 12, { bold: true, color: [29, 78, 216], after: 3 });
    text(L("Critères OCDE/CAD · ", "OECD/DAC criteria · ") + (evaluation.period_start || "—") + (evaluation.period_end ? " → " + evaluation.period_end : "")
      + (evaluation.projects ? L(" · Projet ", " · Project ") + evaluation.projects.code : ""), 9, { color: [100, 116, 139], after: 12 });
    H1(L("1. Cadrage", "1. Framing"));
    FRAMING_FIELDS.forEach((ff) => { text((lang === "es" ? (ff.es != null ? ff.es : ff.en) : lang === "fr" ? ff.fr : ff.en), 10, { bold: true, color: [29, 78, 216], after: 2 }); narrative(f[ff.key]); });
    H1(L("2. Performance du cadre logique", "2. Logframe performance"));
    (projectIndicators || []).forEach((ind) => {
      const lv = latestValue(ind);
      const pct = achievementPct(ind);
      text("• " + (ind.code ? ind.code + " · " : "") + ((lang === "es" ? (ind.name_es != null ? ind.name_es : ind.name_en || ind.name_fr) : lang === "fr" ? ind.name_fr : ind.name_en || ind.name_fr))
        + L(" — réf. ", " — base ") + (ind.baseline_text || ind.baseline || "—")
        + L(" · cible ", " · target ") + (ind.target_text || ind.target || "—")
        + L(" · dernier ", " · latest ") + (lv ? (lv.value_text || lv.value || "—") : "—")
        + (pct == null ? "" : " · " + Math.round(pct) + " %"), 9, { after: 1 });
    });
    narrative(logframe.narrative);
    H1(L("3. Constats par critère", "3. Findings by criterion"));
    dac.CRITERIA.forEach((c) => {
      const ff = (findings[c.key] || {});
      const r = dac.RATINGS[ff.rating];
      text(((lang === "es" ? (c.es != null ? c.es : c.en) : lang === "fr" ? c.fr : c.en)) + (r ? L(" — ", " — ") + ((lang === "es" ? (r.es != null ? r.es : r.en) : lang === "fr" ? r.fr : r.en)) : ""), 10, { bold: true, color: [29, 78, 216], after: 2 });
      narrative(ff.text);
    });
    H1(L("4. Leçons apprises", "4. Lessons learned"));
    (lessons.rows || []).forEach((row, i) => text((i + 1) + ". " + (row.text || "—"), 10, { after: 1 }));
    if (lessons.narrative) narrative(lessons.narrative);
    H1(L("5. Conclusions", "5. Conclusions"));
    narrative(conclusions.text);
    H1(L("6. Recommandations et réponse managériale", "6. Recommendations and management response"));
    (conclusions.recommendations || []).forEach((rec, i) => {
      text("R" + (i + 1) + ". " + (rec.text || "—") + (rec.addressee ? L(" — ", " — ") + rec.addressee : ""), 10, { bold: true, after: 1 });
      const resp = (response.items || {})[String(i)] || {};
      const ch = dac.RESPONSE_CHOICES[resp.decision];
      if (ch || resp.comment) {
        text(L("Réponse : ", "Response: ") + (ch ? ((lang === "es" ? (ch.es != null ? ch.es : ch.en) : lang === "fr" ? ch.fr : ch.en)) : "—")
          + (resp.comment ? " — " + resp.comment : "")
          + (resp.responsible ? L(" · Resp. : ", " · Resp.: ") + resp.responsible : "")
          + (resp.due ? L(" · Échéance : ", " · Due: ") + resp.due : ""), 9, { italics: true, color: [75, 85, 99], after: 4 });
      }
    });
    doc.save("Evaluation_" + (f.kind === "final" ? "finale" : "mi-parcours") + "_" + (evaluation.title_fr || "rapport").replace(/[^\wÀ-ſ-]+/g, "_") + ".pdf");
  }

  // ── Modale de création ───────────────────────────────────────────────────
  function NewMidtermEvalModal({ lang, effectiveOrgId, onClose, onCreated }) {
    const { projects } = window.melr.useProjects ? window.melr.useProjects() : { projects: [] };
    const [kind, setKind] = useState("midterm");
    const [titleFr, setTitleFr] = useState("");
    const [titleEn, setTitleEn] = useState("");
    const [periodStart, setPeriodStart] = useState("");
    const [periodEnd, setPeriodEnd] = useState("");
    const [projectId, setProjectId] = useState("");
    const [busy, setBusy] = useState(false);
    const [err, setErr] = useState(null);
    const L = (fr, en) => (lang === "fr" ? fr : en);
    const lbl = { fontSize: 12, fontWeight: 600, display: "block", marginBottom: 4 };
    const submit = async (e) => {
      e.preventDefault();
      if (!titleFr.trim()) { setErr(L("Le titre (FR) est requis.", "Title (FR) is required.")); return; }
      setBusy(true); setErr(null);
      try {
        const ev = await window.melr.evaluationsCrud.create({
          organization_id: effectiveOrgId,
          type: "midterm_final",
          title_fr: titleFr.trim(),
          title_en: titleEn.trim() || titleFr.trim(),
          status: "planning",
          period_start: periodStart || null,
          period_end: periodEnd || null,
          project_id: projectId || null,
        });
        // Le sous-type (mi-parcours / finale) vit dans la feuille de cadrage.
        await window.melr.saveEvaluationSheet(ev.id, "framing", { kind });
        if (onCreated) onCreated(ev);
      } catch (ex) { setErr(ex.message); setBusy(false); }
    };
    return (
      <Modal title={L("Nouvelle évaluation mi-parcours / finale", "New mid-term / final evaluation")} onClose={onClose} onSubmit={submit}
        footer={(<>
          <button type="button" className="btn sm ghost" onClick={onClose}>{L("Annuler", "Cancel")}</button>
          <button type="submit" className="btn sm primary" disabled={busy}>{busy ? "…" : L("Créer", "Create")}</button>
        </>)}>
        <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 12, marginBottom: 12 }}>
          <div>
            <label style={lbl}>{L("Type *", "Type *")}</label>
            <select className="input" value={kind} onChange={(e) => setKind(e.target.value)} style={{ width: "100%" }}>
              <option value="midterm">{L("Mi-parcours", "Mid-term")}</option>
              <option value="final">{L("Finale", "Final")}</option>
            </select>
          </div>
          <div>
            <label style={lbl}>{L("Projet évalué *", "Evaluated project *")}</label>
            {/* useProjects() remappe : uuid = UUID (FK), id = CODE, nameFr/nameEn. */}
            <select className="input" value={projectId} onChange={(e) => setProjectId(e.target.value)} style={{ width: "100%" }}>
              <option value="">{L("— Aucun —", "— None —")}</option>
              {(projects || []).map((p) => (
                <option key={p.uuid} value={p.uuid}>{p.id} · {(lang === "es" ? (p.nameEs != null ? p.nameEs : p.nameEn || p.nameFr) : lang === "fr" ? p.nameFr : p.nameEn || p.nameFr)}</option>
              ))}
            </select>
          </div>
        </div>
        <div style={{ marginBottom: 12 }}>
          <label style={lbl}>{L("Titre (FR) *", "Title (FR) *")}</label>
          <input className="input" value={titleFr} onChange={(e) => setTitleFr(e.target.value)}
            placeholder={L("ex. Évaluation à mi-parcours du projet P-241", "e.g. Mid-term evaluation of project P-241")}
            style={{ width: "100%" }} />
        </div>
        <div style={{ marginBottom: 12 }}>
          <label style={lbl}>{L("Titre (EN)", "Title (EN)")}</label>
          <input className="input" value={titleEn} onChange={(e) => setTitleEn(e.target.value)} style={{ width: "100%" }} />
        </div>
        <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 12, marginBottom: 12 }}>
          <div>
            <label style={lbl}>{L("Début", "Start")}</label>
            <input type="date" className="input" value={periodStart} onChange={(e) => setPeriodStart(e.target.value)} style={{ width: "100%" }} />
          </div>
          <div>
            <label style={lbl}>{L("Fin", "End")}</label>
            <input type="date" className="input" value={periodEnd} onChange={(e) => setPeriodEnd(e.target.value)} style={{ width: "100%" }} />
          </div>
        </div>
        {err && <div style={{ color: "#b91c1c", fontSize: 12 }}>{err}</div>}
      </Modal>
    );
  }

  // ── Écran principal ──────────────────────────────────────────────────────
  function MidtermEvalScreen({ lang, effectiveOrgId, isSuperAdmin, hasPerm }) {
    const L = (fr, en) => (lang === "fr" ? fr : en);
    const dac = DAC();
    const { data: allEvals, refresh } = window.melr.useEvaluations
      ? window.melr.useEvaluations(effectiveOrgId)
      : { data: [], refresh: () => {} };
    const evals = useMemo(() => (allEvals || []).filter((e) => e.type === "midterm_final"), [allEvals]);

    const [tab, setTab] = useState("overview");
    const [selectedId, setSelectedId] = useState(() => {
      try { return localStorage.getItem("melr.midterm.selected") || null; } catch (_) { return null; }
    });
    const selected = useMemo(
      () => evals.find((e) => e.id === selectedId) || evals[0] || null,
      [evals, selectedId]
    );
    useEffect(() => {
      if (selected && selected.id !== selectedId) {
        setSelectedId(selected.id);
        try { localStorage.setItem("melr.midterm.selected", selected.id); } catch (_) {}
      }
    }, [selected, selectedId]);

    const canManage = isSuperAdmin
      || (typeof hasPerm === "function" && (hasPerm("users.manage") || hasPerm("evaluations.manage")));

    // Indicateurs du projet lié (cadre logique) — realtime via useIndicators.
    const { data: projectIndicators } = window.melr.useIndicators
      ? window.melr.useIndicators(selected ? selected.project_id : null)
      : { data: [] };
    const logframeInds = selected && selected.project_id ? (projectIndicators || []) : [];

    const SHEET_KEYS = ["framing", "logframe", "findings", "lessons", "conclusions", "response"];
    const [sheets, setSheets] = useState({});
    const [dirty, setDirty] = useState(false);
    const [busy, setBusy] = useState(false);
    const [msg, setMsg] = useState(null);
    useEffect(() => {
      let cancelled = false;
      setSheets({}); setDirty(false); setMsg(null);
      if (!selected) return;
      Promise.all(SHEET_KEYS.map((s) => window.melr.fetchEvaluationSheet(selected.id, s)))
        .then((rows) => {
          if (cancelled) return;
          const next = {};
          SHEET_KEYS.forEach((s, i) => { next[s] = (rows[i] && rows[i].data) || {}; });
          setSheets(next);
        })
        .catch((e) => { if (!cancelled) setMsg(e.message); });
      return () => { cancelled = true; };
    }, [selected && selected.id]);
    const patch = (sheet, data) => { setSheets({ ...sheets, [sheet]: data }); setDirty(true); };
    const saveAll = async () => {
      if (!selected) return;
      setBusy(true); setMsg(null);
      try {
        for (const s of SHEET_KEYS) await window.melr.saveEvaluationSheet(selected.id, s, sheets[s] || {});
        setDirty(false);
        setMsg(L("Évaluation enregistrée.", "Evaluation saved."));
      } catch (e) { setMsg(L("Erreur : ", "Error: ") + e.message); }
      finally { setBusy(false); }
    };

    const [newOpen, setNewOpen] = useState(false);
    const framing = sheets.framing || {};
    const findings = sheets.findings || {};
    const lessons = sheets.lessons || {};
    const conclusions = sheets.conclusions || {};
    const recommendations = conclusions.recommendations || [];
    const response = sheets.response || {};
    const kind = KINDS[framing.kind] || null;
    const STATUS_META = window.EVALUATION_STATUS_META || {};
    const RatingPillX = ({ rating }) => {
      const m = dac.RATINGS[rating];
      if (!m) return <span style={{ fontSize: 11, color: "var(--text-faint)" }}>—</span>;
      return <span style={{ fontSize: 10.5, fontWeight: 700, padding: "2px 8px", borderRadius: 999, background: m.fill, color: m.color }}>
        {(lang === "es" ? (m.es != null ? m.es : m.en) : lang === "fr" ? m.fr : m.en)}</span>;
    };

    return (
      <div className="page" data-screen-label="Mid-term / final evaluation">
        <div className="page-header">
          <div className="page-eyebrow">{L("ÉVALUATIONS · MI-PARCOURS & FINALE", "EVALUATIONS · MID-TERM & FINAL")}</div>
          <div className="page-header-row">
            <div>
              <h1 className="page-title">
                {L("Évaluations mi-parcours & finales", "Mid-term & final evaluations")}
                {selected && <span style={{ fontWeight: 500, color: "var(--text-faint)" }}>
                  {" — "}{(lang === "es" ? (selected.title_es != null ? selected.title_es : selected.title_en || selected.title_fr) : lang === "fr" ? selected.title_fr : selected.title_en || selected.title_fr)}
                  {kind && " (" + ((lang === "es" ? (kind.es != null ? kind.es : kind.en) : lang === "fr" ? kind.fr : kind.en)) + ")"}
                </span>}
              </h1>
              <div className="page-sub">
                {L("Critères OCDE/CAD + lecture directe du cadre logique du projet MELR lié (référence / cible / réalisé).",
                   "OECD/DAC criteria + direct read of the linked MELR project's logframe (baseline / target / actual).")}
              </div>
            </div>
            <div className="page-header-actions">
              {canManage && (
                <button className="btn sm primary" onClick={() => setNewOpen(true)}>
                  <Icon.plus /> {L("Nouvelle évaluation", "New evaluation")}
                </button>
              )}
            </div>
          </div>
        </div>

        {evals.length > 1 && (
          <div style={{ display: "flex", alignItems: "center", gap: 8, marginBottom: 10 }}>
            <span className="text-faint" style={{ fontSize: 11.5 }}>{L("Évaluation :", "Evaluation:")}</span>
            <select className="input" value={selected ? selected.id : ""}
              onChange={(e) => {
                setSelectedId(e.target.value);
                try { localStorage.setItem("melr.midterm.selected", e.target.value); } catch (_) {}
              }}>
              {evals.map((e) => <option key={e.id} value={e.id}>{(lang === "es" ? (e.title_es != null ? e.title_es : e.title_en || e.title_fr) : lang === "fr" ? e.title_fr : e.title_en || e.title_fr)}</option>)}
            </select>
          </div>
        )}
        <div className="pd-tabs" style={{ marginBottom: 16 }}>
          {TABS.map((tb) => (
            <button key={tb.key}
              className={"pd-tab" + (tab === tb.key ? " active" : "")}
              onClick={() => setTab(tb.key)}
              data-hue={tb.hue}
              style={{ "--tab-hue": tb.hue }}>
              {(lang === "es" ? (tb.es != null ? tb.es : tb.en) : lang === "fr" ? tb.fr : tb.en)}
            </button>
          ))}
        </div>

        {tab !== "overview" && selected && (
          <div style={{ display: "flex", alignItems: "center", gap: 10, marginBottom: 14, flexWrap: "wrap" }}>
            {canManage && (
              <button className="btn sm primary" disabled={busy || !dirty} onClick={saveAll}>
                {busy ? "…" : L("Enregistrer", "Save")}
              </button>
            )}
            <button style={xbtn("#2563eb")} onClick={() => exportMidtermWord(lang, selected, sheets, logframeInds)}>
              📄 {L("Rapport (Word)", "Report (Word)")}
            </button>
            <button style={xbtn("#dc2626")} onClick={() => exportMidtermPdf(lang, selected, sheets, logframeInds)}>
              📕 {L("Rapport (PDF)", "Report (PDF)")}
            </button>
            {dirty && <span style={{ fontSize: 11, color: "#b45309" }}>{L("Modifications non enregistrées", "Unsaved changes")}</span>}
            {msg && <span className="text-faint" style={{ fontSize: 11 }}>{msg}</span>}
          </div>
        )}
        {tab !== "overview" && !selected && (
          <div style={sec("green")}><div style={{ color: "var(--text-faint)", fontSize: 12.5 }}>
            {L("Créez d'abord une évaluation (bouton en haut à droite).", "Create an evaluation first (top-right button).")}
          </div></div>
        )}

        {/* ═ Vue d'ensemble ═ */}
        {tab === "overview" && (
          <div style={sec("green")}>
            <div>
              <table className="tbl" style={{ width: "100%" }}>
                <thead><tr>
                  <th>{L("Titre", "Title")}</th><th>{L("Type", "Type")}</th><th>{L("Période", "Period")}</th>
                  <th>{L("Projet", "Project")}</th><th>{L("Statut", "Status")}</th><th></th>
                </tr></thead>
                <tbody>
                  {evals.length === 0 && (
                    <tr><td colSpan={6} className="text-faint" style={{ padding: 16, fontSize: 12 }}>
                      {L("Aucune évaluation mi-parcours / finale pour le moment.", "No mid-term / final evaluation yet.")}
                    </td></tr>
                  )}
                  {evals.map((e) => {
                    const sm = STATUS_META[e.status] || { fr: e.status, en: e.status, color: "#6b7280", fill: "#f3f4f6" };
                    return (
                      <tr key={e.id} style={{ background: selected && selected.id === e.id ? "var(--bg-sunken)" : undefined }}>
                        <td style={{ fontWeight: 600, fontSize: 12.5 }}>{(lang === "es" ? (e.title_es != null ? e.title_es : e.title_en || e.title_fr) : lang === "fr" ? e.title_fr : e.title_en || e.title_fr)}</td>
                        <td style={{ fontSize: 12 }}>{selected && selected.id === e.id && kind ? ((lang === "es" ? (kind.es != null ? kind.es : kind.en) : lang === "fr" ? kind.fr : kind.en)) : "…"}</td>
                        <td style={{ fontSize: 12 }}>{(e.period_start || "—")}{e.period_end ? " → " + e.period_end : ""}</td>
                        <td style={{ fontSize: 12 }}>{e.projects ? e.projects.code : "—"}</td>
                        <td><span style={{ display: "inline-block", padding: "2px 8px", borderRadius: 10, background: sm.fill, color: sm.color, fontSize: 11, fontWeight: 600 }}>
                          {(lang === "es" ? (sm.es != null ? sm.es : sm.en) : lang === "fr" ? sm.fr : sm.en)}</span></td>
                        <td style={{ textAlign: "right", paddingRight: 12 }}>
                          <button className="btn xs ghost" onClick={() => {
                            setSelectedId(e.id);
                            try { localStorage.setItem("melr.midterm.selected", e.id); } catch (_) {}
                            setTab("framing");
                          }}>{L("Ouvrir", "Open")} →</button>
                        </td>
                      </tr>
                    );
                  })}
                </tbody>
              </table>
            </div>
          </div>
        )}

        {/* ═ Cadrage ═ */}
        {tab === "framing" && selected && (
          <div>
            <div style={sec("amber")}>
              <div style={{ display: "flex", gap: 18, alignItems: "center", flexWrap: "wrap" }}>
                <span style={{ fontSize: 12.5, fontWeight: 700 }}>{L("Type d'évaluation :", "Evaluation type:")}</span>
                <select className="input" disabled={!canManage} value={framing.kind || "midterm"}
                  onChange={(e) => patch("framing", { ...framing, kind: e.target.value })}
                  style={{ fontSize: 12 }}>
                  <option value="midterm">{L("Mi-parcours (réorientation)", "Mid-term (re-orientation)")}</option>
                  <option value="final">{L("Finale (redevabilité, capitalisation)", "Final (accountability, capitalization)")}</option>
                </select>
                {selected.projects && (
                  <span className="text-faint" style={{ fontSize: 11.5 }}>
                    {L("Projet lié : ", "Linked project: ")}{selected.projects.code} · {(lang === "es" ? (selected.projects.name_es != null ? selected.projects.name_es : selected.projects.name_en || selected.projects.name_fr) : lang === "fr" ? selected.projects.name_fr : selected.projects.name_en || selected.projects.name_fr)}
                  </span>
                )}
              </div>
            </div>
            {FRAMING_FIELDS.map((f) => (
              <div key={f.key} style={sec("green", { marginBottom: 12 })}>
                <div>
                  <div style={{ fontSize: 13, fontWeight: 700, marginBottom: 2 }}>{(lang === "es" ? (f.es != null ? f.es : f.en) : lang === "fr" ? f.fr : f.en)}</div>
                  <div className="text-faint" style={{ fontSize: 11.5, marginBottom: 8 }}>{(lang === "es" ? (f.hint_es != null ? f.hint_es : f.hint_en) : lang === "fr" ? f.hint_fr : f.hint_en)}</div>
                  <textarea className="input" rows={3} disabled={!canManage}
                    style={{ width: "100%", resize: "vertical", fontSize: 12.5 }}
                    value={framing[f.key] || ""}
                    onChange={(e) => patch("framing", { ...framing, [f.key]: e.target.value })} />
                </div>
              </div>
            ))}
          </div>
        )}

        {/* ═ Cadre logique ═ */}
        {tab === "logframe" && selected && (
          <div>
            <div style={sec("blue")}>
              <div>
                <div style={secT("blue")}>🎯 {L("Performance du cadre logique (lecture directe du projet MELR)", "Logframe performance (direct read from the MELR project)")}</div>
                {!selected.project_id && (
                  <div className="text-faint" style={{ fontSize: 12 }}>
                    {L("Aucun projet lié — liez un projet à l'évaluation pour charger ses indicateurs.",
                       "No linked project — link a project to the evaluation to load its indicators.")}
                  </div>
                )}
                {selected.project_id && (
                  <table className="tbl" style={{ width: "100%" }}>
                    <thead><tr>
                      <th>{L("Indicateur", "Indicator")}</th>
                      <th style={{ textAlign: "right" }}>{L("Référence", "Baseline")}</th>
                      <th style={{ textAlign: "right" }}>{L("Cible", "Target")}</th>
                      <th style={{ textAlign: "right" }}>{L("Dernière valeur", "Latest value")}</th>
                      <th style={{ textAlign: "right" }}>{L("Atteinte", "Achievement")}</th>
                    </tr></thead>
                    <tbody>
                      {logframeInds.length === 0 && (
                        <tr><td colSpan={5} className="text-faint" style={{ padding: 12, fontSize: 11.5 }}>
                          {L("Aucun indicateur sur ce projet.", "No indicator on this project.")}
                        </td></tr>
                      )}
                      {logframeInds.map((ind) => {
                        const lv = latestValue(ind);
                        const pct = achievementPct(ind);
                        return (
                          <tr key={ind.id}>
                            <td style={{ fontSize: 11.5 }}>
                              <span style={{ fontWeight: 700, marginRight: 6 }}>{ind.code}</span>
                              <span className="text-faint">{(lang === "es" ? (ind.name_es != null ? ind.name_es : ind.name_en || ind.name_fr) : lang === "fr" ? ind.name_fr : ind.name_en || ind.name_fr)}</span>
                            </td>
                            <td style={{ textAlign: "right", fontSize: 11.5 }}>{ind.baseline_text || (ind.baseline == null ? "—" : ind.baseline)}</td>
                            <td style={{ textAlign: "right", fontSize: 11.5 }}>{ind.target_text || (ind.target == null ? "—" : ind.target)}</td>
                            <td style={{ textAlign: "right", fontSize: 11.5 }}>{lv ? (lv.value_text || (lv.value == null ? "—" : lv.value)) : "—"}</td>
                            <td style={{ textAlign: "right", fontSize: 11.5, fontWeight: 800,
                              color: pct == null ? "var(--text-faint)" : pct >= 80 ? "#15803d" : pct >= 50 ? "#b45309" : "#b91c1c" }}>
                              {pct == null ? "—" : Math.round(pct) + " %"}
                            </td>
                          </tr>
                        );
                      })}
                    </tbody>
                  </table>
                )}
              </div>
            </div>
            <div style={sec("green")}>
              <div>
                <div style={{ fontSize: 13, fontWeight: 700, marginBottom: 8 }}>{L("Analyse de la performance", "Performance analysis")}</div>
                <textarea className="input" rows={5} disabled={!canManage}
                  placeholder={L("Écarts prévu/réalisé, causes, produits et effets en avance / en retard…", "Planned vs actual gaps, causes, outputs and outcomes ahead / behind…")}
                  style={{ width: "100%", resize: "vertical", fontSize: 12.5 }}
                  value={(sheets.logframe || {}).narrative || ""}
                  onChange={(e) => patch("logframe", { ...(sheets.logframe || {}), narrative: e.target.value })} />
              </div>
            </div>
          </div>
        )}

        {/* ═ Constats par critère ═ */}
        {tab === "findings" && selected && dac.CRITERIA.map((c) => {
          const f = findings[c.key] || {};
          return (
            <div key={c.key} style={sec("green", { marginBottom: 12 })}>
              <div>
                <div style={{ display: "flex", alignItems: "center", gap: 10, marginBottom: 2 }}>
                  <div style={{ fontSize: 13, fontWeight: 700 }}>{(lang === "es" ? (c.es != null ? c.es : c.en) : lang === "fr" ? c.fr : c.en)}</div>
                  <RatingPillX rating={f.rating} />
                  {canManage && (
                    <select className="input" value={f.rating || ""} style={{ fontSize: 11, marginLeft: "auto" }}
                      onChange={(e) => patch("findings", { ...findings, [c.key]: { ...f, rating: e.target.value || undefined } })}>
                      <option value="">{L("— Appréciation —", "— Rating —")}</option>
                      {Object.keys(dac.RATINGS).map((k) => (
                        <option key={k} value={k}>{(lang === "es" ? (dac.RATINGS[k].es != null ? dac.RATINGS[k].es : dac.RATINGS[k].en) : lang === "fr" ? dac.RATINGS[k].fr : dac.RATINGS[k].en)}</option>
                      ))}
                    </select>
                  )}
                </div>
                <div className="text-faint" style={{ fontSize: 11.5, marginBottom: 6 }}>{(lang === "es" ? (c.hint_es != null ? c.hint_es : c.hint_en) : lang === "fr" ? c.hint_fr : c.hint_en)}</div>
                <textarea className="input" rows={4} disabled={!canManage}
                  placeholder={L("Constats, données probantes, analyse…", "Findings, evidence, analysis…")}
                  style={{ width: "100%", resize: "vertical", fontSize: 12.5 }}
                  value={f.text || ""}
                  onChange={(e) => patch("findings", { ...findings, [c.key]: { ...f, text: e.target.value } })} />
              </div>
            </div>
          );
        })}

        {/* ═ Leçons apprises ═ */}
        {tab === "lessons" && selected && (
          <div style={sec("purple")}>
            <div>
              <div style={secT("purple")}>💡 {L("Leçons apprises", "Lessons learned")}</div>
              <div className="text-faint" style={{ fontSize: 11.5, marginBottom: 8 }}>
                {L("Enseignements transférables — utiles au-delà du projet (capitalisation, base d'évidence du module Apprentissage).",
                   "Transferable lessons — useful beyond the project (capitalization, Learning module evidence base).")}
              </div>
              {(lessons.rows || []).map((r, i) => (
                <div key={i} style={{ display: "grid", gridTemplateColumns: "36px 1fr auto", gap: 8, alignItems: "start", padding: "6px 0", borderTop: "1px dashed var(--line)" }}>
                  <span style={{ fontSize: 12, fontWeight: 700, paddingTop: 6 }}>L{i + 1}</span>
                  <textarea className="input" rows={2} disabled={!canManage} value={r.text || ""}
                    placeholder={L("Leçon apprise…", "Lesson learned…")}
                    onChange={(e) => patch("lessons", { ...lessons, rows: (lessons.rows || []).map((x, j) => (j === i ? { ...x, text: e.target.value } : x)) })}
                    style={{ width: "100%", fontSize: 12, resize: "vertical" }} />
                  {canManage && (
                    <button className="btn xs ghost" style={{ marginTop: 4 }}
                      onClick={() => patch("lessons", { ...lessons, rows: (lessons.rows || []).filter((_, j) => j !== i) })}>
                      <Icon.x />
                    </button>
                  )}
                </div>
              ))}
              {canManage && (
                <button className="btn xs ghost" style={{ marginTop: 8 }}
                  onClick={() => patch("lessons", { ...lessons, rows: [...(lessons.rows || []), {}] })}>
                  <Icon.plus /> {L("Ajouter une leçon", "Add a lesson")}
                </button>
              )}
            </div>
          </div>
        )}

        {/* ═ Conclusions & recommandations ═ */}
        {tab === "conclusions" && selected && (
          <div>
            <div style={sec("green", { marginBottom: 12 })}>
              <div>
                <div style={secT("green")}>{L("Conclusions", "Conclusions")}</div>
                <textarea className="input" rows={5} disabled={!canManage}
                  style={{ width: "100%", resize: "vertical", fontSize: 12.5 }}
                  value={conclusions.text || ""}
                  onChange={(e) => patch("conclusions", { ...conclusions, text: e.target.value })} />
              </div>
            </div>
            <div style={sec("amber")}>
              <div>
                <div style={secT("amber")}>{L("Recommandations", "Recommendations")}</div>
                {recommendations.map((rec, i) => (
                  <div key={i} style={{ display: "grid", gridTemplateColumns: "44px 1fr 200px auto", gap: 8, alignItems: "start", padding: "6px 0", borderTop: "1px dashed var(--line)" }}>
                    <span style={{ fontSize: 12, fontWeight: 700, paddingTop: 6 }}>R{i + 1}</span>
                    <textarea className="input" rows={2} disabled={!canManage} value={rec.text || ""}
                      placeholder={L("Recommandation…", "Recommendation…")}
                      onChange={(e) => {
                        const next = recommendations.map((r, j) => (j === i ? { ...r, text: e.target.value } : r));
                        patch("conclusions", { ...conclusions, recommendations: next });
                      }}
                      style={{ width: "100%", fontSize: 12, resize: "vertical" }} />
                    <input className="input" disabled={!canManage} value={rec.addressee || ""}
                      placeholder={L("Destinataire", "Addressee")}
                      onChange={(e) => {
                        const next = recommendations.map((r, j) => (j === i ? { ...r, addressee: e.target.value } : r));
                        patch("conclusions", { ...conclusions, recommendations: next });
                      }}
                      style={{ fontSize: 11.5 }} />
                    {canManage && (
                      <button className="btn xs ghost" style={{ marginTop: 4 }}
                        onClick={() => patch("conclusions", { ...conclusions, recommendations: recommendations.filter((_, j) => j !== i) })}>
                        <Icon.x />
                      </button>
                    )}
                  </div>
                ))}
                {canManage && (
                  <button className="btn xs ghost" style={{ marginTop: 8 }}
                    onClick={() => patch("conclusions", { ...conclusions, recommendations: [...recommendations, {}] })}>
                    <Icon.plus /> {L("Ajouter une recommandation", "Add a recommendation")}
                  </button>
                )}
              </div>
            </div>
          </div>
        )}

        {/* ═ Réponse managériale ═ */}
        {tab === "response" && selected && (
          <div style={sec("purple")}>
            <div>
              <div style={secT("purple")}>{L("Réponse managériale", "Management response")}</div>
              {recommendations.length === 0 && (
                <div className="text-faint" style={{ fontSize: 12 }}>
                  {L("Aucune recommandation définie pour le moment.", "No recommendation defined yet.")}
                </div>
              )}
              {recommendations.map((rec, i) => {
                const item = (response.items || {})[String(i)] || {};
                const setItem = (p) => patch("response", {
                  ...response, items: { ...(response.items || {}), [String(i)]: { ...item, ...p } },
                });
                return (
                  <div key={i} style={{ padding: "8px 0", borderTop: "1px dashed var(--line)" }}>
                    <div style={{ fontSize: 12, fontWeight: 700, marginBottom: 6 }}>R{i + 1}. {rec.text || "—"}</div>
                    <div style={{ display: "grid", gridTemplateColumns: "170px 1fr 160px 130px 130px", gap: 8 }}>
                      <select className="input" disabled={!canManage} value={item.decision || ""}
                        onChange={(e) => setItem({ decision: e.target.value || undefined })} style={{ fontSize: 11.5 }}>
                        <option value="">{L("— Décision —", "— Decision —")}</option>
                        {Object.keys(dac.RESPONSE_CHOICES).map((k) => (
                          <option key={k} value={k}>{(lang === "es" ? (dac.RESPONSE_CHOICES[k].es != null ? dac.RESPONSE_CHOICES[k].es : dac.RESPONSE_CHOICES[k].en) : lang === "fr" ? dac.RESPONSE_CHOICES[k].fr : dac.RESPONSE_CHOICES[k].en)}</option>
                        ))}
                      </select>
                      <input className="input" disabled={!canManage} value={item.comment || ""}
                        placeholder={L("Commentaire / mesures prévues", "Comment / planned measures")}
                        onChange={(e) => setItem({ comment: e.target.value })} style={{ fontSize: 11.5 }} />
                      <input className="input" disabled={!canManage} value={item.responsible || ""}
                        placeholder={L("Responsable", "Responsible")}
                        onChange={(e) => setItem({ responsible: e.target.value })} style={{ fontSize: 11.5 }} />
                      <input type="date" className="input" disabled={!canManage} value={item.due || ""}
                        onChange={(e) => setItem({ due: e.target.value })} style={{ fontSize: 11.5 }} />
                      <select className="input" disabled={!canManage} value={item.status || "todo"}
                        onChange={(e) => setItem({ status: e.target.value })} style={{ fontSize: 11.5 }}>
                        {Object.keys(dac.RESPONSE_STATUSES).map((k) => (
                          <option key={k} value={k}>{(lang === "es" ? (dac.RESPONSE_STATUSES[k].es != null ? dac.RESPONSE_STATUSES[k].es : dac.RESPONSE_STATUSES[k].en) : lang === "fr" ? dac.RESPONSE_STATUSES[k].fr : dac.RESPONSE_STATUSES[k].en)}</option>
                        ))}
                      </select>
                    </div>
                  </div>
                );
              })}
            </div>
          </div>
        )}

        {newOpen && (
          <NewMidtermEvalModal lang={lang} effectiveOrgId={effectiveOrgId}
            onClose={() => setNewOpen(false)}
            onCreated={(ev) => {
              setNewOpen(false);
              setSelectedId(ev.id);
              try { localStorage.setItem("melr.midterm.selected", ev.id); } catch (_) {}
              refresh && refresh();
              setTab("framing");
            }} />
        )}
      </div>
    );
  }

  window.MidtermEvalScreen = MidtermEvalScreen;
})();
