/* InverseDesign.jsx — the methodology demo
   Sliders = target outcome (premium reduction, capital efficiency, tail tolerance, regulatory headroom)
   Output = a recommended "boundary configuration" — coverage stack with constitutional scoring
*/

const COVERAGE_LINES = [
  { id: 'primary',  label: 'Primary retention',         color: 'var(--ink)' },
  { id: 'qs',       label: 'Quota-share treaty',        color: 'var(--navy)' },
  { id: 'xol',      label: 'Excess-of-loss layers',     color: 'var(--navy-soft)' },
  { id: 'cat',      label: 'Cat reinsurance',           color: 'var(--red)' },
  { id: 'param',    label: 'Parametric trigger',        color: 'var(--amber)' },
  { id: 'alt',      label: 'Alt-capital sidecar',       color: 'var(--green)' },
];

const CONSTRAINTS = [
  { id: 'rbnz',  label: 'RBNZ solvency margin', desc: 'Insurance (Prudential Supervision) Act 2010' },
  { id: 'ifrs',  label: 'IFRS 17 risk-adjustment confidence' },
  { id: 'xrb',   label: 'XRB climate disclosure' },
  { id: 'cap',   label: 'Treaty capacity ceiling' },
  { id: 'eth',   label: 'Constitutional ethics: no orphaning of cover' },
];

function InverseDesign() {
  const [tgtPrem, setTgtPrem] = React.useState(15);   // % reduction
  const [tgtCap,  setTgtCap]  = React.useState(70);   // capital efficiency target
  const [tgtTail, setTgtTail] = React.useState(0.4);  // 1-in-X tail tolerance, 0..1
  const [tgtReg,  setTgtReg]  = React.useState(0.6);  // regulatory headroom
  const [iter, setIter] = React.useState(0);
  const [running, setRunning] = React.useState(false);

  // Committed targets — only update when the optimiser runs. The grade & stack
  // are derived from these, not from the live sliders.
  const [committed, setCommitted] = React.useState({
    tgtPrem: 15, tgtCap: 70, tgtTail: 0.4, tgtReg: 0.6, runId: 0,
  });
  const dirty = (tgtPrem !== committed.tgtPrem) || (tgtCap !== committed.tgtCap)
             || (tgtTail !== committed.tgtTail) || (tgtReg !== committed.tgtReg);

  // Deterministic "inverse design" — driven by COMMITTED targets only,
  // so the recommended stack and the grade reflect the last optimiser run.
  const alloc = React.useMemo(() => {
    const { tgtPrem, tgtCap, tgtTail, tgtReg } = committed;
    const primary = clamp(0.55 - tgtPrem * 0.018 + (1 - tgtTail) * 0.15, 0.05, 0.7);
    const qs      = clamp(0.18 + tgtPrem * 0.006 - tgtCap * 0.0015, 0.05, 0.4);
    const xol     = clamp(0.12 + tgtTail * 0.18 - tgtReg * 0.05, 0.04, 0.35);
    const cat     = clamp(0.06 + tgtTail * 0.22, 0.02, 0.35);
    const param   = clamp(0.04 + tgtPrem * 0.004 + (1 - tgtReg) * 0.06, 0.0, 0.25);
    const alt     = clamp(0.05 + (tgtCap / 100) * 0.18 - tgtTail * 0.05, 0.0, 0.30);
    const arr = { primary, qs, xol, cat, param, alt };
    const sum = Object.values(arr).reduce((a,b)=>a+b, 0);
    Object.keys(arr).forEach(k => arr[k] = arr[k] / sum);
    return arr;
  }, [committed]);

  // Constitutional scores — also from committed values only.
  const scores = React.useMemo(() => {
    const { tgtPrem, tgtCap, tgtTail, tgtReg } = committed;
    const premN = tgtPrem / 35;
    const capN  = (tgtCap - 40) / 55;
    return {
      rbnz: clamp(0.50 + alloc.cat * 1.6 + alloc.xol * 1.1 - premN * 0.35 + capN * 0.08, 0, 1),
      ifrs: clamp(0.45 + alloc.qs * 1.0 + alloc.xol * 0.7 + tgtReg * 0.30 - premN * 0.15, 0, 1),
      xrb:  clamp(0.40 + alloc.param * 1.8 + alloc.cat * 0.5 + tgtReg * 0.10, 0, 1),
      cap:  clamp(0.90 - alloc.qs * 0.7 - alloc.xol * 0.5 + alloc.alt * 0.6 - capN * 0.15, 0, 1),
      eth:  clamp(0.55 + alloc.primary * 0.6 + alloc.cat * 0.4 - alloc.alt * 0.5 - tgtTail * 0.10, 0, 1),
    };
  }, [alloc, committed]);

  const overallScore = Object.values(scores).reduce((a,b)=>a+b,0) / Object.keys(scores).length;
  const gradeColor = overallScore > 0.75 ? 'var(--green)' : overallScore > 0.55 ? 'var(--amber)' : 'var(--red)';
  const grade = overallScore > 0.85 ? 'A' : overallScore > 0.75 ? 'B+' : overallScore > 0.65 ? 'B' : overallScore > 0.55 ? 'C' : 'D';

  // pretend optimisation iterations — commits the live targets at the end
  const runOptimise = () => {
    setRunning(true);
    setIter(0);
    let n = 0;
    const id = setInterval(() => {
      n++; setIter(n);
      if (n >= 18) {
        clearInterval(id);
        setRunning(false);
        setCommitted({ tgtPrem, tgtCap, tgtTail, tgtReg, runId: committed.runId + 1 });
      }
    }, 80);
  };

  const Slider = ({ label, value, onChange, min, max, step, unit, hint }) => (
    <div style={{ marginBottom: 18 }}>
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', marginBottom: 6 }}>
        <div style={{ fontSize: 12.5, fontWeight: 500 }}>{label}</div>
        <div className="mono" style={{ fontSize: 13, fontWeight: 600, color: 'var(--red)' }}>
          {typeof value === 'number' && value < 1 ? value.toFixed(2) : value}{unit}
        </div>
      </div>
      <input type="range" min={min} max={max} step={step} value={value}
             onChange={(e) => onChange(parseFloat(e.target.value))}
             className="slider red" />
      <div style={{ fontSize: 11, color: 'var(--muted-2)', marginTop: 4 }}>{hint}</div>
    </div>
  );

  // bar segments
  let cumX = 0;
  const totalW = 100;
  const segs = COVERAGE_LINES.map(c => {
    const w = alloc[c.id] * totalW;
    const seg = { ...c, x: cumX, w };
    cumX += w;
    return seg;
  });

  return (
    <section id="inverse" style={{ background: '#0e0e0e', color: 'var(--bg)', borderTop: '1px solid #000' }}>
      <div className="container">
        <div className="section-tag" style={{ color: '#ff8a8a' }}>
          <span className="num" style={{ color: '#777' }}>04 / 06</span>
          <span>The methodology, applied</span>
          <span className="rule" style={{ background: '#333' }} />
        </div>
        <h2 style={{ color: '#fff', marginBottom: 18 }}>Forward modelling is commodity. Inverse design is rare.</h2>
        <p className="lede" style={{ color: 'rgba(255,255,255,0.65)', maxWidth: '64ch' }}>
          Verisk, RMS, Moody's, Milliman, Willis Re — given a portfolio and a hazard set, produce a loss
          distribution. Mature market. What almost nobody offers commercially is the inverse: given a
          desired outcome, find the boundary conditions that produce it.
        </p>

        {/* the equation */}
        <div style={{
          margin: '32px 0 40px',
          padding: '24px 32px',
          background: '#161616',
          border: '1px solid #2a2a2a',
          borderRadius: 4,
          fontFamily: 'Source Serif 4, Georgia, serif',
        }}>
          <div style={{ fontSize: 11, letterSpacing: '.18em', textTransform: 'uppercase', color: '#888', marginBottom: 8 }}>
            Inverse design equation
          </div>
          <div style={{ fontSize: 26, color: '#f5e7c0', letterSpacing: '-.01em', overflow: 'auto' }}>
            ∂* &nbsp;=&nbsp; argmin<sub style={{ fontSize: 14 }}>∂</sub> &nbsp;{'{'}&nbsp; ‖ ∫<sub style={{ fontSize: 14 }}>∂</sub> [Φ × λ × S] dA &nbsp;−&nbsp; B<sup style={{ fontSize: 14 }}>*</sup> ‖² &nbsp;+&nbsp; R(∂) &nbsp;{'}'}
          </div>
          <div style={{ fontSize: 12, color: '#aaa', marginTop: 10, lineHeight: 1.55, fontFamily: 'Inter' }}>
            Given a target B<sup>*</sup> (the desired risk profile), find the optimal boundary
            configuration ∂ — the coverage stack, mitigation portfolio, treaty allocation — subject to
            regularisation R(∂) capturing regulatory and physical constraints.
          </div>
        </div>

        <div style={{ display: 'grid', gridTemplateColumns: '320px 1fr', gap: 32, alignItems: 'start' }}>
          {/* targets */}
          <div style={{ background: '#161616', border: '1px solid #2a2a2a', padding: 24, borderRadius: 4 }}>
            <div style={{ fontSize: 11, letterSpacing: '.18em', textTransform: 'uppercase', color: '#888', fontWeight: 600, marginBottom: 16 }}>
              Target outcome B*
            </div>
            <Slider label="Premium reduction" value={tgtPrem} onChange={setTgtPrem}
                    min={0} max={35} step={1} unit="%"
                    hint="vs current cost-of-cover baseline" />
            <Slider label="Capital efficiency" value={tgtCap} onChange={setTgtCap}
                    min={40} max={95} step={1} unit=""
                    hint="ROCE on retained risk" />
            <Slider label="Tail-risk tolerance" value={tgtTail} onChange={setTgtTail}
                    min={0.05} max={0.95} step={0.01} unit=""
                    hint="0 = no appetite · 1 = retain everything" />
            <Slider label="Regulatory headroom" value={tgtReg} onChange={setTgtReg}
                    min={0.1} max={0.95} step={0.01} unit=""
                    hint="distance from RBNZ + IFRS 17 floors" />

            <button className="btn" onClick={runOptimise} disabled={running}
                    style={{ width: '100%', marginTop: 10,
                             background: dirty ? '#ff8a8a' : '#2a2a2a',
                             color: dirty ? '#000' : '#888',
                             borderColor: dirty ? '#ff8a8a' : '#3a3a3a' }}>
              {running ? `Optimising · iter ${iter}/18`
                : dirty ? 'Run optimiser →'
                : `Run optimiser · ${committed.runId === 0 ? 'initial' : 'last run #' + committed.runId}`}
            </button>
            {dirty && !running && (
              <div style={{ fontSize: 11, color: '#ff8a8a', marginTop: 6, textAlign: 'center', fontStyle: 'italic' }}>
                Targets changed — re-run optimiser to update boundary ∂* and grade.
              </div>
            )}
          </div>

          {/* output: stack + scores */}
          <div className="flex-col" style={{ gap: 20 }}>
            {/* stack */}
            <div style={{ background: '#161616', border: '1px solid #2a2a2a', padding: 24, borderRadius: 4 }}>
              <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', marginBottom: 12 }}>
                <div style={{ fontSize: 11, letterSpacing: '.18em', textTransform: 'uppercase', color: '#888', fontWeight: 600 }}>
                  Recommended boundary ∂*
                </div>
                <div style={{ fontSize: 11, color: '#666' }} className="mono">
                  iter {iter} · cost ‖.‖² = {(0.42 - iter*0.012).toFixed(3)}
                </div>
              </div>

              {/* stacked bar */}
              <div style={{ position: 'relative', height: 56, borderRadius: 3, overflow: 'hidden', border: '1px solid #2a2a2a' }}>
                {segs.map(s => (
                  <div key={s.id} style={{
                    position: 'absolute', left: `${s.x}%`, width: `${s.w}%`, height: '100%',
                    background: s.color,
                    transition: 'left .25s, width .25s',
                  }} />
                ))}
              </div>

              {/* legend rows */}
              <table style={{ width: '100%', marginTop: 16, fontSize: 13, borderCollapse: 'collapse' }}>
                <tbody>
                {COVERAGE_LINES.map(c => (
                  <tr key={c.id}>
                    <td style={{ padding: '6px 0', borderBottom: '1px solid #222', width: 18 }}>
                      <span style={{ display: 'inline-block', width: 10, height: 10, background: c.color, borderRadius: 2 }} />
                    </td>
                    <td style={{ padding: '6px 0', borderBottom: '1px solid #222', color: '#ddd' }}>{c.label}</td>
                    <td style={{ padding: '6px 0', borderBottom: '1px solid #222', textAlign: 'right', color: '#fff' }} className="mono">
                      {(alloc[c.id]*100).toFixed(1)}%
                    </td>
                  </tr>
                ))}
                </tbody>
              </table>
            </div>

            {/* constitutional score */}
            <div style={{ background: '#161616', border: '1px solid #2a2a2a', padding: 24, borderRadius: 4 }}>
              <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', marginBottom: 16 }}>
                <div>
                  <div style={{ fontSize: 11, letterSpacing: '.18em', textTransform: 'uppercase', color: '#888', fontWeight: 600 }}>
                    Constitutional scoring · R(∂)
                  </div>
                  <div style={{ fontSize: 12, color: '#999', marginTop: 4 }}>
                    Boundary configuration evaluated against five regularisation constraints.
                  </div>
                </div>
                <div style={{ textAlign: 'right' }}>
                  <div style={{ fontFamily: 'Source Serif 4', fontSize: 56, lineHeight: 1, letterSpacing: '-.03em', color: gradeColor }}>
                    {grade}
                  </div>
                  <div className="mono" style={{ fontSize: 11, color: '#999' }}>{(overallScore*100).toFixed(0)} / 100</div>
                </div>
              </div>

              <div style={{ display: 'grid', gridTemplateColumns: 'repeat(5, 1fr)', gap: 12 }}>
                {CONSTRAINTS.map(c => {
                  const v = scores[c.id];
                  const col = v > 0.75 ? 'var(--green)' : v > 0.55 ? 'var(--amber)' : 'var(--red)';
                  return (
                    <div key={c.id} style={{ background: '#0e0e0e', padding: 12, borderRadius: 3, border: '1px solid #222' }}>
                      <div style={{ fontSize: 10.5, color: '#aaa', minHeight: 28, lineHeight: 1.35, marginBottom: 8 }}>
                        {c.label}
                      </div>
                      <div style={{ height: 4, background: '#222', borderRadius: 2, overflow: 'hidden' }}>
                        <div style={{ width: `${v*100}%`, height: '100%', background: col, transition: 'width .25s' }} />
                      </div>
                      <div className="mono" style={{ fontSize: 12, fontWeight: 600, color: col, marginTop: 6 }}>
                        {(v*100).toFixed(0)}
                      </div>
                    </div>
                  );
                })}
              </div>

              <div style={{ marginTop: 14, fontSize: 11.5, fontStyle: 'italic', color: '#aaa', lineHeight: 1.5 }}>
                Audit trail: every iteration's configuration, score, and rejection reason is logged
                and signed. The output of inverse design is not a recommendation — it is a defensible analysis surface for the underwriter and the appointed actuary to interrogate.
              </div>
            </div>
          </div>
        </div>
      </div>
    </section>
  );
}

window.InverseDesign = InverseDesign;
