/* global React, Icon, window */
// ============================================================================
// MELR · AVD / LIC-DSF — indicateur composite (CI) de capacité d'endettement
// ----------------------------------------------------------------------------
// Écran du moteur public/dsa-calc.jsx (window.DSA). Saisie des 5 variables du
// CI, calcul du CI, de sa décomposition, de la CLASSIFICATION (faible/moyenne/
// forte) et d'un simulateur de sensibilité (franchissement de seuil).
//
// Honnêteté du modèle (même retenue que l'écran STAR) : ce tableau de bord ne
// produit JAMAIS la notation officielle de risque de surendettement — celle-ci
// exige l'AVD complète (projections, tests de résistance, jugement) et reste
// publiée par le FMI/BM. C'est cette retenue qui le rend crédible.
// ============================================================================

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

  const sec = (c, extra) => (window.MelrSection && window.MelrSection.colors && window.MelrSection.colors[c] ? window.MelrSection.style(c, extra) : { marginBottom: 14, ...(extra || {}) });
  const secT = (c) => (window.MelrSection && window.MelrSection.colors && window.MelrSection.colors[c] ? window.MelrSection.title(c) : { fontSize: 13, fontWeight: 700, marginBottom: 8 });
  const fmt = (v, d) => (v == null || Number.isNaN(Number(v)) ? "—" : Number(v).toFixed(d == null ? 3 : d));

  const SUGGESTED = [
    { iso3: "SEN", fr: "Sénégal", en: "Senegal" },
    { iso3: "CIV", fr: "Côte d'Ivoire", en: "Côte d'Ivoire" },
    { iso3: "MLI", fr: "Mali", en: "Mali" },
    { iso3: "BFA", fr: "Burkina Faso", en: "Burkina Faso" },
    { iso3: "NER", fr: "Niger", en: "Niger" },
    { iso3: "BEN", fr: "Bénin", en: "Benin" },
    { iso3: "TGO", fr: "Togo", en: "Togo" },
    { iso3: "GHA", fr: "Ghana", en: "Ghana" },
  ];

  // Les 5 variables du CI + leurs unités (cf. dsa-calc.jsx).
  const FIELDS = [
    { key: "cpia",        fr: "CPIA (1–6)",                       en: "CPIA (1–6)",                    hintFr: "vide = CPIA BM", hintEn: "empty = WB CPIA", step: "0.1" },
    { key: "growth",      fr: "Croissance PIB (fraction)",        en: "GDP growth (fraction)",         hintFr: "0,05 = 5 % · moy. 10 ans", hintEn: "0.05 = 5% · 10-yr avg", step: "0.005" },
    { key: "importCov",   fr: "Couv. importations (réserves/imports)", en: "Import coverage (reserves/imports)", hintFr: "ex. 0,30 ≈ 3,6 mois", hintEn: "e.g. 0.30 ≈ 3.6 months", step: "0.01" },
    { key: "remit",       fr: "Envois de fonds (fraction PIB)",   en: "Remittances (fraction of GDP)", hintFr: "0,05 = 5 %", hintEn: "0.05 = 5%", step: "0.005" },
    { key: "worldGrowth", fr: "Croissance mondiale (fraction)",   en: "World growth (fraction)",       hintFr: "0,035 = 3,5 %", hintEn: "0.035 = 3.5%", step: "0.005" },
  ];

  // Décomposition (6 termes, dont le carré de la couverture d'importations).
  const CONTRIB = [
    { key: "cpia",        fr: "CPIA",                       en: "CPIA",                       c: "#2563eb" },
    { key: "growth",      fr: "Croissance PIB",             en: "GDP growth",                 c: "#16a34a" },
    { key: "importCov",   fr: "Couv. import. (linéaire)",   en: "Import coverage (linear)",   c: "#0891b2" },
    { key: "importCov2",  fr: "Couv. import. (carré, −)",   en: "Import coverage (square, −)", c: "#dc2626" },
    { key: "remit",       fr: "Envois de fonds",            en: "Remittances",                c: "#d97706" },
    { key: "worldGrowth", fr: "Croissance mondiale",        en: "World growth",               c: "#7c3aed" },
  ];

  const CLASS_COLORS = {
    weak:   { color: "#b45309", fill: "#fef3c7" },
    medium: { color: "#2563eb", fill: "#dbeafe" },
    strong: { color: "#15803d", fill: "#dcfce7" },
  };

  function Kpi({ label, value, hint, badge }) {
    return (
      <div style={{ background: "var(--bg-elev)", border: "1px solid var(--line)", borderRadius: 8, padding: "10px 14px", minWidth: 140, flex: 1 }}>
        <div style={{ fontSize: 10.5, textTransform: "uppercase", letterSpacing: ".4px", color: "var(--muted)", fontWeight: 600 }}>{label}</div>
        <div style={{ fontSize: 22, fontWeight: 800, marginTop: 2, color: badge ? badge.color : undefined }}>{value}</div>
        {hint && <div style={{ fontSize: 10, color: "var(--muted)", marginTop: 2 }}>{hint}</div>}
      </div>
    );
  }

  function NumIn({ label, hint, value, onChange, disabled, step }) {
    return (
      <div>
        <label style={{ fontSize: 10.5, fontWeight: 600, display: "block", marginBottom: 2 }}>{label}</label>
        <input type="number" className="input" disabled={disabled} step={step || "0.01"}
          value={value == null ? "" : value}
          onChange={(e) => onChange(e.target.value === "" ? null : Number(e.target.value))}
          style={{ width: 120, fontSize: 12, textAlign: "right" }} />
        {hint && <div style={{ fontSize: 9.5, color: "var(--muted)", marginTop: 1 }}>{hint}</div>}
      </div>
    );
  }

  function DsaScreen({ lang, effectiveOrgId, isSuperAdmin, hasPerm }) {
    const L = (fr, en) => (lang === "fr" ? fr : en);
    const D = window.DSA;
    const canManage = isSuperAdmin
      || (typeof hasPerm === "function" && (hasPerm("users.manage") || hasPerm("evaluations.manage")));

    const [iso3, setIso3] = useState(() => {
      try { return localStorage.getItem("melr.dsa.iso3") || "SEN"; } catch (_) { return "SEN"; }
    });
    useEffect(() => { try { localStorage.setItem("melr.dsa.iso3", iso3); } catch (_) {} }, [iso3]);
    const [model, setModel] = useState(D.DEFAULT_MODEL);

    const [profile, setProfile] = useState(null);
    const [dirty, setDirty] = useState(false);
    const [saveBusy, setSaveBusy] = useState(false);
    const [saveMsg, setSaveMsg] = useState(null);
    useEffect(() => {
      let cancelled = false;
      setProfile(null); setDirty(false); setSaveMsg(null);
      if (!effectiveOrgId || !iso3) return;
      window.melr.fetchDsaProfile(effectiveOrgId, iso3.trim().toUpperCase(), model)
        .then((p) => { if (!cancelled) setProfile(p || { inputs: {} }); })
        .catch(() => { if (!cancelled) setProfile({ inputs: {} }); });
      return () => { cancelled = true; };
    }, [effectiveOrgId, iso3, model]);
    const inputs = (profile && profile.inputs) || {};
    const patchInput = (k, v) => { setProfile({ ...(profile || {}), inputs: { ...inputs, [k]: v } }); setDirty(true); };

    // Référentiel CPIA UNIQUE : la CPIA globale (IRAI) provient du même lot
    // Banque mondiale que le STAR (star_wb_snapshots). Si aucune CPIA n'est
    // saisie ici, on utilise automatiquement la valeur BM — une seule source.
    // Hook appelé de façon INCONDITIONNELLE (règles React) : useStarWbSnapshots
    // est toujours exposé par melr-data (chargé avant cet écran).
    const wbSnap = window.melr.useStarWbSnapshots({ orgId: effectiveOrgId, iso3 });
    const snaps = wbSnap.data, refreshSnaps = wbSnap.refresh;
    const cpiaCode = (window.STAR && window.STAR.WB.cpiaOverall) ? window.STAR.WB.cpiaOverall.code : "IQ.CPA.IRAI.XQ";
    const wbCpiaRow = (snaps || []).find((r) => r.indicator_code === cpiaCode);
    const wbCpia = wbCpiaRow && wbCpiaRow.value != null ? Number(wbCpiaRow.value) : null;
    const [wbBusy, setWbBusy] = useState(false);
    const doRefreshWb = async () => {
      setWbBusy(true);
      try { await window.melr.refreshStarWorldBank(effectiveOrgId, iso3.trim().toUpperCase()); refreshSnaps && refreshSnaps(); }
      catch (_) {} finally { setWbBusy(false); }
    };
    const cpiaManual = inputs.cpia != null && inputs.cpia !== "";
    const effInputs = cpiaManual ? inputs : { ...inputs, cpia: wbCpia };

    const ciR = D.ci(effInputs, model);
    const classR = ciR ? D.classify(ciR.value, model) : null;
    const thr = (D.MODELS[model] || {}).thresholds || {};

    // Simulateur de sensibilité.
    const [simField, setSimField] = useState("cpia");
    const [simValue, setSimValue] = useState("");
    const sim = (simValue !== "" && ciR) ? D.sensitivity(effInputs, simField, Number(simValue), model) : null;

    const saveProfile = async () => {
      setSaveBusy(true); setSaveMsg(null);
      try {
        const country = (SUGGESTED.find((s) => s.iso3 === iso3) || {});
        await window.melr.saveDsaProfile(effectiveOrgId, iso3.trim().toUpperCase(), model, {
          country_name: profile.country_name || (lang === "fr" ? country.fr : country.en) || null,
          inputs: profile.inputs || {},
          notes: profile.notes || null,
        });
        setDirty(false);
        setSaveMsg(L("Profil enregistré.", "Profile saved."));
      } catch (e) { setSaveMsg(L("Erreur : ", "Error: ") + e.message); }
      finally { setSaveBusy(false); }
    };

    const classBadge = classR ? (CLASS_COLORS[classR.key] || {}) : {};

    return (
      <div className="page">
        <div className="page-header">
          <div className="page-eyebrow">{L("ÉVALUATIONS · VIABILITÉ DE LA DETTE", "EVALUATIONS · DEBT SUSTAINABILITY")}</div>
          <h1 className="page-title">{L("AVD / LIC-DSF — capacité d'endettement (CI)", "DSA / LIC-DSF — debt-carrying capacity (CI)")}</h1>
          <div className="page-sub">{L("Indicateur composite (CI) du Cadre de viabilité de la dette des pays à faible revenu (FMI/BM).", "Composite Indicator (CI) of the IMF/WB Low-Income Country Debt Sustainability Framework.")}</div>
        </div>

        {/* Pays / modèle */}
        <div style={sec("purple")}>
          <div style={{ display: "flex", gap: 12, flexWrap: "wrap", alignItems: "flex-end" }}>
            <div>
              <label style={{ fontSize: 10.5, fontWeight: 600, display: "block", marginBottom: 2 }}>{L("Pays (ISO3)", "Country (ISO3)")}</label>
              <input className="input" list="dsa-countries" value={iso3} disabled={!canManage}
                onChange={(e) => setIso3(e.target.value.toUpperCase())} style={{ width: 120, fontSize: 12 }} />
              <datalist id="dsa-countries">
                {SUGGESTED.map((s) => <option key={s.iso3} value={s.iso3}>{lang === "fr" ? s.fr : s.en}</option>)}
              </datalist>
            </div>
            <div>
              <label style={{ fontSize: 10.5, fontWeight: 600, display: "block", marginBottom: 2 }}>{L("Modèle", "Model")}</label>
              <select className="input" value={model} onChange={(e) => setModel(e.target.value)} style={{ fontSize: 12 }}>
                {Object.keys(D.MODELS).map((k) => <option key={k} value={k}>{D.MODELS[k].label || k}</option>)}
              </select>
            </div>
            {canManage && (
              <button className="btn sm primary" disabled={saveBusy || !dirty} onClick={saveProfile}>
                {saveBusy ? "…" : <><Icon.save /> {L("Enregistrer", "Save")}</>}
              </button>
            )}
            {saveMsg && <span className="text-faint" style={{ fontSize: 11.5 }}>{saveMsg}</span>}
          </div>
        </div>

        {/* Saisie des variables */}
        <div style={sec("amber")}>
          <div style={secT("amber")}>✍️ {L("Variables du CI (moyennes 10 ans, unités indiquées)", "CI variables (10-yr averages, units shown)")}</div>
          <div style={{ display: "flex", gap: 14, flexWrap: "wrap" }}>
            {FIELDS.map((f) => (
              <NumIn key={f.key} label={lang === "fr" ? f.fr : f.en} hint={lang === "fr" ? f.hintFr : f.hintEn}
                step={f.step} disabled={!canManage} value={inputs[f.key]} onChange={(v) => patchInput(f.key, v)} />
            ))}
          </div>
          <div className="text-faint" style={{ fontSize: 10.5, marginTop: 8 }}>
            {L("Unités selon le gabarit CI officiel du FMI. Croissances et envois en FRACTION (0,05 = 5 %), couverture des importations en ratio réserves/imports.",
               "Units per the official IMF CI worksheet. Growth and remittances as a FRACTION (0.05 = 5%), import coverage as reserves/imports ratio.")}
          </div>
          {(wbCpia != null || canManage) && (
            <div style={{ marginTop: 8, fontSize: 11, display: "flex", gap: 8, alignItems: "center", flexWrap: "wrap" }}>
              {wbCpia != null && (
                <span className="text-faint">
                  {L("CPIA globale (BM/IRAI) ", "Overall CPIA (WB/IRAI) ")}{iso3} : <b>{fmt(wbCpia, 1)}</b>{wbCpiaRow && wbCpiaRow.year ? " (" + wbCpiaRow.year + ")" : ""}
                  {" · "}{L("référentiel partagé avec le STAR", "shared reference with STAR")}
                  {!cpiaManual && <span> · <b style={{ color: "#15803d" }}>{L("utilisée", "used")}</b></span>}
                </span>
              )}
              {wbCpia != null && cpiaManual && canManage && (
                <button className="btn xs ghost" onClick={() => patchInput("cpia", wbCpia)}>{L("Utiliser cette CPIA", "Use this CPIA")}</button>
              )}
              {canManage && (
                <button className="btn xs ghost" disabled={wbBusy} onClick={doRefreshWb}>
                  {wbBusy ? "…" : <><Icon.refresh /> {L("Actualiser CPIA (BM)", "Refresh CPIA (WB)")}</>}
                </button>
              )}
            </div>
          )}
        </div>

        {/* CI + classification + décomposition */}
        <div style={sec("blue")}>
          <div style={secT("blue")}>📊 {L("CI, classification et décomposition", "CI, classification and decomposition")}</div>
          <div style={{ display: "flex", gap: 12, flexWrap: "wrap", marginBottom: 8 }}>
            <Kpi label="CI" value={ciR ? fmt(ciR.value, 3) : "—"} hint={model} />
            <Kpi label={L("Capacité d'endettement", "Debt-carrying capacity")}
              value={classR ? (lang === "fr" ? classR.fr : classR.en) : "—"} badge={classBadge}
              hint={L("faible < " + thr.weak + " ≤ moyenne ≤ " + thr.strong + " < forte", "weak < " + thr.weak + " ≤ medium ≤ " + thr.strong + " < strong")} />
          </div>
          {ciR && (
            <table style={{ width: "100%", maxWidth: 560, fontSize: 12, borderCollapse: "collapse" }}>
              <tbody>
                {CONTRIB.map((t) => (
                  <tr key={t.key} style={{ borderBottom: "1px solid var(--line-faint)" }}>
                    <td style={{ padding: "3px 6px" }}><span style={{ color: t.c, fontWeight: 700 }}>■</span> {lang === "fr" ? t.fr : t.en}</td>
                    <td className="mono" style={{ padding: "3px 6px", textAlign: "right", color: ciR.contrib[t.key] < 0 ? "#dc2626" : "var(--text)" }}>{fmt(ciR.contrib[t.key], 3)}</td>
                  </tr>
                ))}
                <tr style={{ fontWeight: 800 }}>
                  <td style={{ padding: "4px 6px" }}>CI = Σ</td>
                  <td className="mono" style={{ padding: "4px 6px", textAlign: "right" }}>{fmt(ciR.value, 3)}</td>
                </tr>
              </tbody>
            </table>
          )}
          {!ciR && <div className="text-faint" style={{ fontSize: 11.5 }}>{L("Saisir les 5 variables pour calculer le CI.", "Enter the 5 variables to compute the CI.")}</div>}
        </div>

        {/* Simulateur de sensibilité */}
        <div style={sec("green")}>
          <div style={secT("green")}>🎚️ {L("Sensibilité — franchissement de seuil", "Sensitivity — threshold crossing")}</div>
          <div style={{ display: "flex", gap: 10, flexWrap: "wrap", alignItems: "flex-end" }}>
            <div>
              <label style={{ fontSize: 10.5, fontWeight: 600, display: "block", marginBottom: 2 }}>{L("Variable", "Variable")}</label>
              <select className="input" value={simField} onChange={(e) => setSimField(e.target.value)} style={{ fontSize: 12 }}>
                {FIELDS.map((f) => <option key={f.key} value={f.key}>{lang === "fr" ? f.fr : f.en}</option>)}
              </select>
            </div>
            <div>
              <label style={{ fontSize: 10.5, fontWeight: 600, display: "block", marginBottom: 2 }}>{L("Nouvelle valeur", "New value")}</label>
              <input type="number" className="input" step="0.01" value={simValue}
                onChange={(e) => setSimValue(e.target.value)} style={{ width: 110, fontSize: 12, textAlign: "right" }} />
            </div>
          </div>
          {sim && (
            <div style={{ marginTop: 8, fontSize: 12.5 }}>
              {L("CI ", "CI ")}<b>{fmt(sim.before, 3)}</b> → <b>{fmt(sim.after, 3)}</b>
              {"  ·  ΔCI = "}<b style={{ color: sim.delta < 0 ? "#dc2626" : "#15803d" }}>{(sim.delta >= 0 ? "+" : "") + fmt(sim.delta, 3)}</b>
              {sim.classBefore && sim.classAfter && (
                <span style={{ marginLeft: 8 }}>
                  {lang === "fr" ? sim.classBefore.fr : sim.classBefore.en} → {lang === "fr" ? sim.classAfter.fr : sim.classAfter.en}
                  {sim.crossed && <span style={{ marginLeft: 6, fontWeight: 800, color: "#b45309" }}>⚠ {L("change de classe", "class changes")}</span>}
                </span>
              )}
            </div>
          )}
        </div>

        {/* Notes */}
        <div style={sec()}>
          <label style={{ fontSize: 10.5, fontWeight: 600, display: "block", marginBottom: 2 }}>{L("Notes", "Notes")}</label>
          <textarea className="input" disabled={!canManage} rows={2} style={{ width: "100%", fontSize: 12 }}
            value={(profile && profile.notes) || ""} onChange={(e) => { setProfile({ ...(profile || {}), notes: e.target.value }); setDirty(true); }} />
        </div>

        <div className="text-faint" style={{ fontSize: 10.5, marginTop: 4 }}>
          {L("Formule officielle du CI (LIC-DSF 2017/18). ⚠ Ce module calcule le CI, sa décomposition, la classification et la sensibilité — PAS la notation officielle de risque de surendettement (faible/modéré/élevé/en surendettement), qui exige l'AVD complète du FMI/BM. Révision du cadre en cours (2026) : coefficients et seuils sont paramétrés.",
             "Official CI formula (LIC-DSF 2017/18). ⚠ This module computes the CI, its decomposition, classification and sensitivity — NOT the official risk-of-debt-distress rating (low/moderate/high/in distress), which requires the full IMF/WB DSA. Framework under revision (2026): coefficients and thresholds are parameterized.")}
        </div>
      </div>
    );
  }

  window.DsaScreen = DsaScreen;
})();
