/* global React, Icon, StatusChip, PageHeader, Banner, etb */
const { useState: useStateOR } = React;

/* ============================================================
   NBE Operational Risk — SMA · faithful copy of the NBE workbook
   Two-block sheet: (A) Interest-earning assets, (B) full P&L line items
   12–67 grouped ILDC / SC / FC, then the SMA computation.
   ETB millions · internal/synthetic. Stress = operational-loss uplift.
   ============================================================ */
const E = 2.71828;
const n = v => (v == null ? null : v);

// (A) Interest-earning assets — Balance Sheet, t / t-1 / t-2 (items 1–11)
const IEA = [
  { no: "1", label: "Placement with other banks", y: [11706.172, 2212.713, 920.694] },
  { no: "2", label: "Interest bearing investments*", y: [9181.559, 10629.808, 2787.185] },
  { no: "3", label: "Due from SOEs", y: [null, null, null] },
  { no: "4", label: "Due from banks", y: [null, null, null] },
  { no: "5", label: "Due from Corporate", y: [59722.492, 45022.007, 38435.221] },
  { no: "6", label: "Due from retail loans", y: [null, null, null] },
  { no: "7", label: "Due from residential mortgages", y: [null, null, null] },
  { no: "8", label: "Due from commercial mortgages", y: [null, null, null] },
  { no: "9", label: "Due to past due Exposures", y: [null, null, null] },
  { no: "10", label: "Lease assets measured at the end of each financial year", y: [null, null, null] },
  { no: "11", label: "Interest earning assets", y: [80610.223, 57864.528, 42143.1], tot: true },
];

// (B) P&L statement — items 12–67. t column populated per the NBE sheet; t-1/t-2 sparse.
const PL = [
  { sec: "Interest, Leases & Dividend Component (ILDC)" },
  { no: "12", label: "Interest income from loans and advances", t: 9145.062 },
  { no: "13", label: "Interest income from assets available for sale", t: null },
  { no: "14", label: "Interest income from assets held to maturity", t: 530.64 },
  { no: "15", label: "Interest income from trading assets", t: null },
  { no: "16", label: "Interests from financial and operational leases", t: null },
  { no: "17", label: "Interest income from hedge accounting derivatives", t: null },
  { no: "18", label: "Other interest income", t: 879.144 },
  { no: "19", label: "Profits from leased assets", t: null },
  { no: "20", label: "Total Interest income", t: 10554.846, tot: true },
  { no: "21", label: "Interest expenses from deposits", t: 3163.265 },
  { no: "22", label: "Interest expenses from debt securities issued", t: null },
  { no: "23", label: "Interest expenses from financial and operating leases", t: 13.035 },
  { no: "24", label: "Interest expenses from hedge accounting derivatives", t: null },
  { no: "25", label: "Other interest expenses", t: 43.829 },
  { no: "26", label: "Losses from leased assets", t: null },
  { no: "27", label: "Depreciation and impairment of operating leased assets", t: null },
  { no: "28", label: "Total Interest expense", t: 3220.128, tot: true },
  { no: "29", label: "Interest earning assets", t: 80610.223, tot: true },
  { no: "30", label: "Dividend income**", t: 60.855, tot: true },
  { sec: "Services Component (SC)" },
  { no: "32", label: "Bank retail services and transaction fees", t: 100 },
  { no: "33", label: "Fees income from safe box rentals", t: null },
  { no: "34", label: "Commission and fees income from foreign exchange transactions", t: 1765 },
  { no: "35", label: "Commission and fees income from clearing and settlements", t: null },
  { no: "36", label: "Commission and fees income from asset management", t: null },
  { no: "37", label: "Commission and fees income from custody services", t: null },
  { no: "38", label: "Commissions and fees from security issuance", t: null },
  { no: "39", label: "Fees income from loan commitments and guarantees given", t: 397 },
  { no: "40", label: "Other fees and commissions incomes", t: 438.153 },
  { no: "41", label: "Total fee and commission income", t: 2701, tot: true },
  { no: "42", label: "Commission and fees expense from foreign exchange transactions", t: null },
  { no: "43", label: "Commission and fees expense from clearing and settlements", t: null },
  { no: "44", label: "Commission and fees expense from custody services", t: null },
  { no: "45", label: "Fees expense from loan commitments and guarantees received", t: null },
  { no: "46", label: "Other fees and commissions expenses", t: 56 },
  { no: "47", label: "Total fee and commission expense", t: 56, tot: true },
  { no: "48", label: "Profit on sale of property and equipment", t: null },
  { no: "49", label: "Rental income from investment properties", t: null },
  { no: "50", label: "Other operating income not referred above***", t: 245.333 },
  { no: "51", label: "Total other operating income from ordinary activities", t: 245.333, tot: true },
  { no: "52", label: "Losses incurred as a consequence of operational****", t: null },
  { no: "53", label: "Losses from non-current assets and disposal groups", t: null },
  { no: "54", label: "Expenses related to establishing provisions", t: null },
  { no: "55", label: "Other operating expense not referred above", t: 88.7 },
  { no: "56", label: "Total other operating expense from ordinary activities", t: 88.7, tot: true },
  { sec: "Financial Component (FC)" },
  { no: "58", label: "Net profit/loss on trading assets and trading liabilities", t: null },
  { no: "59", label: "Net profit/loss from hedge accounting", t: null },
  { no: "60", label: "Net profit/loss from exchange differences", t: null },
  { no: "62", label: "Net profit (loss) on the trading book", t: 1480.768, tot: true },
  { no: "63", label: "Realised gains/losses on financial assets (AFS)*****", t: null },
  { no: "64", label: "Realised gains/losses on financial assets (amortised)******", t: null },
  { no: "67", label: "Net profit (loss) on the banking book", t: 612.4, tot: true },
];

// --- SMA computation (uses averaged components; t shown, t-1/t-2 illustrative) ---
const avg3 = a => (a[0] + a[1] + a[2]) / 3;
const ILDC_IN = { ii: [10554.846, 8902.51, 7180.20], ie: [3220.128, 2698.44, 2204.10], iea: [80610.223, 57864.528, 42143.10], div: [60.855, 44.02, 31.18] };
const SC_IN = { feeI: [2701, 2204.6, 1748.3], feeE: [56, 48.3, 40.1], ooi: [245.333, 137.48, 92.43], ooe: [88.7, 64.2, 41.0] };
const FC_IN = { tb: [1480.768, 1704.902, 178.307], bb: [612.4, 705.1, 158.9] };
const ILDC = Math.min(Math.abs(avg3(ILDC_IN.ii) - avg3(ILDC_IN.ie)), 0.0225 * avg3(ILDC_IN.iea)) + avg3(ILDC_IN.div);
const SC = Math.max(avg3(SC_IN.feeI), avg3(SC_IN.feeE)) + Math.max(avg3(SC_IN.ooi), avg3(SC_IN.ooe));
const FC = avg3(FC_IN.tb) + avg3(FC_IN.bb);
const BI = ILDC + SC + FC;
const bicOf = bi => Math.min(bi, 3500) * 0.12 + Math.max(0, Math.min(bi, 35000) - 3500) * 0.15 + Math.max(0, bi - 35000) * 0.18;
const BIC = bicOf(BI);
const AVG_LOSS = 41.5, LC = 15 * AVG_LOSS;
const ilmOf = (lc, bic) => Math.log(E - 1 + Math.pow(lc / bic, 0.8));
const ILM = ilmOf(LC, BIC), CHARGE = BIC * ILM, OP_RWA = CHARGE * 9.1, OP_RWA_FALLBACK = BIC * 9.1;
const ORSEV = [{ name: "Mild", loss: 25 }, { name: "Moderate", loss: 60 }, { name: "Severe", loss: 130 }, { name: "Extreme", loss: 260 }];
const orAt = up => { const lc = LC * (1 + up / 100); const ilm = ilmOf(lc, BIC); const ch = BIC * ilm; return { lc, ilm, charge: ch, rwa: ch * 9.1 }; };

const OR_HELP = {
  title: "Operational Risk · SMA",
  purpose: "A faithful copy of the NBE SMA workbook: interest-earning assets, the full P&L line items (12–67) grouped into ILDC / SC / FC, then BI → BIC → ILM → capital charge and RWA (×9.1, i.e. the 11% floor).",
  first: "The sheet mirrors the NBE template line-for-line. The SMA computation block at the foot derives the charge; Stress raises the Loss Component.",
  terms: [["BI", "Business Indicator = ILDC + SC + FC."], ["BIC", "BI × marginal coefficients (12/15/18%)."], ["LC", "15 × average annual operational loss."], ["ILM", "ln{e − 1 + (LC/BIC)^0.8}."]],
  next: ["Click Stress test to raise the Loss Component and watch ILM, charge & RWA respond.", "Tune the loss uplift; the Custom column recomputes live.", "A large charge hands off to Recovery."],
  connections: ["P&L lines reconcile to the audited income statement.", "RWA-equivalent feeds total RWA in the Capital return.", "Loss data must meet NBE quality thresholds."],
  guardrail: "Internal SMA workpaper. Loss data is provisional/synthetic; stress is analysis-only.",
};

function OpRiskSheet({ go, info }) {
  const [stress, setStress] = useStateOR(false);
  const [mode, setMode] = useStateOR("Custom");
  const [lossUp, setLossUp] = useStateOR(130);
  const [calcOpen, setCalcOpen] = useStateOR(false);
  const live = orAt(lossUp);
  const f = (v, dp = 1) => v == null ? "" : etb(+v.toFixed(dp), dp);
  const span = stress ? 9 : 5;

  // result row: single value spanning the 3 year columns, optional stress
  const ResRow = (label, base, kind, stOf) => (
    <tr className={kind === "tot" ? "xl-orange" : "xl-sub"}>
      <td className="xl-no"></td><td className="xl-label">{label}</td>
      <td className="xl-amt tnum" colSpan={3}>{base}</td>
      {stress && <React.Fragment>{ORSEV.map((s, j) => <td key={j} className={"xl-amt xl-stress tnum" + (lossUp === s.loss ? " on" : "")} style={{ color: stOf ? "var(--indigo)" : "var(--ink-3)" }}>{stOf ? stOf(s.loss) : "—"}</td>)}<td className="xl-amt tnum" style={{ borderLeft: "2px solid var(--indigo)", background: "rgba(79,77,208,.05)", color: stOf ? "var(--indigo)" : "var(--ink-3)", fontWeight: 600 }}>{stOf ? stOf(lossUp) : "—"}</td></React.Fragment>}
    </tr>
  );
  const blanks = () => stress ? <React.Fragment>{ORSEV.map((s, j) => <td key={j} className={"xl-amt xl-stress" + (lossUp === s.loss ? " on" : "")} />)}<td className="xl-amt" style={{ borderLeft: "2px solid var(--indigo)", background: "rgba(79,77,208,.05)" }} /></React.Fragment> : null;

  return (
    <div className="main-inner">
      <PageHeader eyebrow="Prudential Risk" title="Operational Risk · SMA" onInfo={() => info(OR_HELP)}
        right={<button className={"btn btn-sm " + (stress ? "btn-dark" : "btn-ghost")} onClick={() => setStress(!stress)}><Icon name="flask" size={15} /> {stress ? "Stress on" : "Stress test"}</button>} />

      <div style={{ marginBottom: 14 }}><Banner kind="amber" icon="alert">Faithful NBE SMA workbook. Loss data is provisional (synthetic seed) and must meet NBE quality thresholds before official use.</Banner></div>

      {stress && <div className="banner banner-indigo mb12" style={{ alignItems: "center", padding: "11px 15px" }}>
        <Icon name="flask" size={18} className="ic" /><div className="grow"><b>Operational-loss overlay</b> · raises the Loss Component → ILM → capital charge · analysis-only</div><span className="chip chip-indigo">SMA · ×9.1</span>
      </div>}

      <div style={{ display: "flex", gap: 16, alignItems: "flex-start" }}>
        <div className="grow" style={{ minWidth: 0 }}>
          <div className="xl-wrap">
            <table className={"xl" + (stress ? " xl-scroll" : "")}>
              <colgroup>
                <col style={{ width: 40 }} /><col style={{ width: stress ? 320 : "100%" }} />
                <col style={{ width: 116 }} /><col style={{ width: 116 }} /><col style={{ width: 116 }} />
                {stress ? ORSEV.map(s => <col key={s.name} style={{ width: 82 }} />) : null}
                {stress ? <col style={{ width: 90 }} /> : null}
              </colgroup>
              <thead><tr>
                <th className="xl-no"></th>
                <th style={{ textAlign: "left" }}>Minimum Capital Requirement for Operational Risk (SMA) · ETB millions</th>
                <th className="xl-amt">FY 2025 (t)</th><th className="xl-amt">FY 2024 (t-1)</th><th className="xl-amt">FY 2023 (t-2)</th>
                {stress && <React.Fragment>{ORSEV.map(s => <th key={s.name} className={"xl-amt xl-stress" + (lossUp === s.loss ? " on" : "")} style={{ cursor: "pointer" }} onClick={() => setLossUp(s.loss)}>{s.name}</th>)}<th className="xl-amt" style={{ background: "var(--indigo)", color: "#fff", borderLeft: "2px solid var(--indigo)" }}>Custom</th></React.Fragment>}
              </tr></thead>
              <tbody>
                <tr className="xl-green"><td className="xl-no"></td><td colSpan={span}>Calculation of Interest-earning Assets (for the ILDC) · Balance Sheet</td></tr>
                {IEA.map(r => (
                  <tr key={"iea" + r.no} className={r.tot ? "xl-sub" : "xl-item"}>
                    <td className="xl-no">{r.no}</td><td className="xl-label">{r.label}</td>
                    {r.y.map((v, i) => <td key={i} className="xl-amt tnum">{v == null ? <span style={{ opacity: .3 }}>–</span> : etb(+v.toFixed(1), 1)}</td>)}
                    {blanks()}
                  </tr>
                ))}
                <tr className="xl-green"><td className="xl-no"></td><td colSpan={span}>P&amp;L Statement &amp; additional required information</td></tr>
                {PL.map((r, i) => {
                  if (r.sec) return <tr key={"s" + i} className="xl-sub"><td className="xl-no"></td><td className="xl-label" colSpan={span} style={{ fontStyle: "italic", fontWeight: 700 }}>{r.label || r.sec}</td></tr>;
                  return (
                    <tr key={r.no} className={r.tot ? "xl-sub" : "xl-item"}>
                      <td className="xl-no">{r.no}</td><td className="xl-label">{r.label}</td>
                      <td className="xl-amt tnum" style={{ fontWeight: r.tot ? 700 : 400 }}>{r.t == null ? <span style={{ opacity: .3 }}>–</span> : etb(+r.t.toFixed(1), 1)}</td>
                      <td className="xl-amt tnum"><span style={{ opacity: .3 }}>–</span></td><td className="xl-amt tnum"><span style={{ opacity: .3 }}>–</span></td>
                      {blanks()}
                    </tr>
                  );
                })}
                <tr className="xl-green"><td className="xl-no"></td><td colSpan={span}>Business Indicator &amp; SMA Capital Charge</td></tr>
                {ResRow("ILDC = min(|ĪI − ĪE|, 2.25%·ĪEA) + D̄iv", f(ILDC), "sub")}
                {ResRow("SC = max(F̄ee Inc, F̄ee Exp) + max(ŌOI, ŌOE)", f(SC), "sub")}
                {ResRow("FC = |N̄et P&L Trading| + |N̄et P&L Banking|", f(FC), "sub")}
                {ResRow("Business Indicator (BI = ILDC + SC + FC)", f(BI), "tot")}
                {ResRow("Business Indicator Component (BIC · 12/15/18%)", f(BIC), "tot")}
                {ResRow("Loss Component (LC = 15 × avg annual loss)", f(LC), "sub", u => f(orAt(u).lc))}
                {ResRow("Internal Loss Multiplier · ILM = ln{e−1+(LC/BIC)^0.8}", ILM.toFixed(3) + "×", "sub", u => orAt(u).ilm.toFixed(3) + "×")}
                {ResRow("Operational risk capital charge (BIC × ILM)", <span className="cell-evi" onClick={(e) => { e.stopPropagation(); setCalcOpen(true); }}>{f(CHARGE)}</span>, "tot", u => f(orAt(u).charge))}
                {ResRow("Operational RWA-equivalent (charge × 9.1)", f(OP_RWA, 0), "tot", u => f(orAt(u).rwa, 0))}
                {ResRow("NBE fallback if ILM is not applicable (BIC × 9.1)", f(OP_RWA_FALLBACK, 0), "tot")}
              </tbody>
            </table>
          </div>
          {stress && <div className="mt12"><Banner kind="indigo" icon="flask">The loss overlay raises the <b>Loss Component</b>, flowing through the <b>ILM</b> into the charge and RWA — BI &amp; BIC (income-based) are unchanged, exactly as the SMA prescribes.</Banner></div>}
        </div>

        {stress && <aside className="stress-dock">
          <div className="between mb12"><span className="center gap8"><Icon name="sliders" size={15} style={{ color: "var(--indigo)" }} /><b style={{ fontSize: 14, whiteSpace: "nowrap" }}>Loss-event controls</b></span><span className="chip chip-indigo">Analysis-only</span></div>
          <div className="seg-ctl" style={{ width: "100%", marginBottom: 14 }}>{[["Presets", "Presets"], ["Custom", "Custom"]].map(([l, k]) => <button key={k} className={mode === k ? "on" : ""} style={{ flex: 1 }} onClick={() => setMode(k)}>{l}</button>)}</div>
          {mode === "Presets" && <div><div className="dock-label">Scenario severity</div><div className="seg-ctl" style={{ width: "100%" }}>{ORSEV.map((s, i) => <button key={s.name} className={lossUp === s.loss ? "on" : ""} style={{ flex: 1, padding: "6px 2px" }} onClick={() => setLossUp(s.loss)}>{s.name === "Moderate" ? "Mod" : s.name}</button>)}</div><div className="muted" style={{ fontSize: 11.5, marginTop: 8 }}>Raises the Loss Component to NBE's named severity bands.</div></div>}
          {mode === "Custom" && <div><div className="between" style={{ marginBottom: 5 }}><span style={{ fontSize: 12, fontWeight: 600 }}>Operational-loss uplift</span><span className="chip chip-indigo" style={{ fontSize: 10.5 }}>+{lossUp}%</span></div><input type="range" className="lev-slider" min={0} max={400} step={10} value={lossUp} onChange={e => setLossUp(+e.target.value)} /><div className="muted" style={{ fontSize: 10.5, marginTop: 3 }}>raises the Loss Component (LC)</div></div>}
          <hr className="hr" style={{ margin: "16px 0" }} />
          <div className="dock-label">Live capital charge</div>
          <div className="big-num tnum" style={{ fontSize: 28, color: "var(--indigo)", marginTop: 2 }}>{f(live.charge)}</div>
          <div className="muted" style={{ fontSize: 11.5, marginTop: 4 }}>vs base {f(CHARGE)} · ILM {live.ilm.toFixed(3)}× · RWA-equiv {f(live.rwa, 0)}</div>
          <button className="btn btn-dark btn-sm" style={{ width: "100%", marginTop: 12 }} onClick={() => go("recovery")}>Send to Recovery <Icon name="arrowR" size={13} /></button>
          <button className="btn btn-ghost btn-sm" style={{ width: "100%", marginTop: 8 }} onClick={() => setLossUp(0)}><Icon name="refresh" size={13} /> Clear stress · restore baseline</button>
        </aside>}
      </div>
      <CalcDrawer open={calcOpen} onClose={() => setCalcOpen(false)} go={go} />
    </div>
  );
}
window.OpRiskSheet = OpRiskSheet;

/* ---------- calculation drilldown (the SMA engine, on demand) ---------- */
function CalcDrawer({ open, onClose, go }) {
  const row = (l, v, b) => <div className="between" style={{ padding: "7px 0", borderBottom: "1px solid var(--border)", fontWeight: b ? 700 : 400 }}><span style={{ fontSize: 12.5, color: b ? "var(--ink)" : "var(--ink-2)" }}>{l}</span><span className="tnum" style={{ fontSize: 12.5 }}>{v}</span></div>;
  const f = (v, dp = 2) => etb(+v.toFixed(dp), dp);
  return (
    <Drawer open={open} onClose={onClose} wide>
      <DrawerHead title="Business Indicator calculation" sub="How the operational capital charge is derived · SMA engine"
        chip={<StatusChip s="EVIDENCE_NEEDED" />} onClose={onClose} />
      <div className="drawer-body">
        <Banner kind="indigo" icon="info">This is the derivation behind the charge cell — the same working as the NBE workbook's calculation block. The official figures use <b>ILM = 1</b> (see fallback below); Stress lets you explore a higher ILM as analysis-only.</Banner>

        <div className="section-label mt20 mb8">Step 1 · Business Indicator (BI)</div>
        <table className="tbl" style={{ fontSize: 12.5 }}>
          <thead><tr><th>Component</th><th className="num">Term A</th><th className="num">Term B</th><th className="num">Result</th></tr></thead>
          <tbody>
            <tr><td><b>ILDC</b><div className="muted" style={{ fontSize: 11 }}>min(A, B) + dividends</div></td><td className="num tnum">5,859.6<div className="muted" style={{ fontSize: 10 }}>|ĪI−ĪE|</div></td><td className="num tnum" style={{ color: "var(--green-ink)", fontWeight: 700 }}>1,354.6 ✓<div className="muted" style={{ fontSize: 10 }}>2.25%·ĪEA</div></td><td className="num tnum" style={{ fontWeight: 700 }}>{f(ILDC)}</td></tr>
            <tr><td><b>SC</b><div className="muted" style={{ fontSize: 11 }}>max(fee) + max(other op)</div></td><td className="num tnum">158.4<div className="muted" style={{ fontSize: 10 }}>OOI/OOE</div></td><td className="num tnum">1,844.9<div className="muted" style={{ fontSize: 10 }}>fee inc/exp</div></td><td className="num tnum" style={{ fontWeight: 700 }}>{f(SC)}</td></tr>
            <tr><td><b>FC</b><div className="muted" style={{ fontSize: 11 }}>|trading| + |banking|</div></td><td className="num tnum">{f(avg3(FC_IN.tb))}</td><td className="num tnum">{f(avg3(FC_IN.bb))}</td><td className="num tnum" style={{ fontWeight: 700 }}>{f(FC)}</td></tr>
          </tbody>
        </table>
        <div style={{ marginTop: 10 }}>{row("Business Indicator (BI = ILDC + SC + FC)", f(BI), true)}</div>

        <div className="section-label mt20 mb8">Step 2 · Business Indicator Component (BIC)</div>
        <table className="tbl" style={{ fontSize: 12.5 }}>
          <thead><tr><th>BI band</th><th className="num">Coefficient</th><th className="num">Charge</th></tr></thead>
          <tbody>
            <tr><td>First 3,500</td><td className="num">12%</td><td className="num tnum">{f(Math.min(BI, 3500) * 0.12)}</td></tr>
            <tr><td>Excess to BI ({f(Math.max(0, BI - 3500), 1)})</td><td className="num">15%</td><td className="num tnum">{f(Math.max(0, Math.min(BI, 35000) - 3500) * 0.15)}</td></tr>
            <tr className="sel"><td><b>Business Indicator Component</b></td><td></td><td className="num tnum" style={{ fontWeight: 800 }}>{f(BIC)}</td></tr>
          </tbody>
        </table>

        <div className="section-label mt20 mb8">Step 3 · Internal Loss Multiplier &amp; charge</div>
        {row("Loss Component (LC = 15 × avg annual loss)", f(LC))}
        {row("Business Indicator Component (BIC)", f(BIC))}
        {row("ILM = ln{e − 1 + (LC/BIC)^0.8}", ILM.toFixed(3) + "×", true)}
        {row("Operational capital charge (BIC × ILM)", f(CHARGE), true)}
        {row("Operational RWA-equivalent (charge × 9.1)", f(OP_RWA, 0), true)}

        <div className="mt16"><Banner kind="amber" icon="lock"><b>NBE fallback rule.</b> The directive requires quality loss data for 10 years (minimum 5). If unavailable, the Bank shall use <b>ILM = 1</b> — so the official charge equals the BIC until an approved loss history is attached.</Banner></div>
      </div>
      <div className="drawer-foot">
        <span className="muted center gap6" style={{ fontSize: 12 }}><Icon name="hash" size={14} /> Derivation · cites P&amp;L lines 12–67</span>
        <button className="btn btn-dark" style={{ marginLeft: "auto" }} onClick={() => go("evidence")}>Attach loss evidence <Icon name="arrowR" size={14} /></button>
      </div>
    </Drawer>
  );
}
