/* PumpAbsorption.jsx — interactive pump-price chart
   Shows: spot crude shock vs the layered absorbers vs final pump price.
   Toggling layers off increases the pump-price line.
*/

const ABSORBERS = [
  { id: 'hedge',   label: 'Forward derivatives & FX hedges', sub: 'Singapore Mogas 95 / Gasoil swaps + NZD/USD forwards locked months ahead.', mag: 0.55, color: 'var(--navy)' },
  { id: 'cargo',   label: 'Marine cargo + war-risk insurance', sub: 'JWC zone surcharge spiked, but cover did not fail.', mag: 0.18, color: '#4d6a8a' },
  { id: 'credit',  label: 'Trade credit insurance', sub: 'Atradius / Coface / Euler — counterparty failure paid by insurer.', mag: 0.12, color: '#7d9bc1' },
  { id: 'bi',      label: 'Business-interruption (terminal)', sub: 'Tanker delay beyond deductible window covered at terminal level.', mag: 0.08, color: 'var(--amber)' },
  { id: 'buffer',  label: 'National reserve / strategic stock', sub: 'The buffer paid the bill in barrels rather than dollars.', mag: 0.07, color: 'var(--red)' },
];

function PumpAbsorption() {
  const tw = React.useContext(window.TweakCtx);
  const NS = tw.nodeScale, LS = tw.labelScale, AS = tw.axisLabelScale, LW = tw.lineWeight;
  const [on, setOn] = React.useState(Object.fromEntries(ABSORBERS.map(a => [a.id, true])));
  const [shock, setShock] = React.useState(0.65); // 0..1 severity of crude shock

  const toggle = (id) => setOn(s => ({ ...s, [id]: !s[id] }));

  // Simulate a 24-week timeline
  const W = 760, H = 360;
  const padL = 56, padR = 24, padT = 32, padB = 40;
  const iw = W - padL - padR, ih = H - padT - padB;
  const weeks = 24;

  // crude spot path: ramps up sharply then partly recovers
  const crudePts = Array.from({ length: weeks + 1 }, (_, i) => {
    const t = i / weeks;
    // shock spike around t=0.25..0.55
    const spike = Math.max(0, Math.exp(-Math.pow((t - 0.4) / 0.18, 2))) * 0.85;
    const tail = Math.max(0, (t - 0.5)) * 0.25;
    const v = 1 + (spike + tail) * shock;
    return v;
  });

  // pump price: crude minus enabled absorbers' damping
  const totalAbsorb = ABSORBERS.reduce((s, a) => s + (on[a.id] ? a.mag : 0), 0);
  const pumpPts = crudePts.map((c, i) => {
    // smoothing: pump lags crude (rolling-weighted methodology). We approximate by EMA + reduce shock above 1
    return 1 + (c - 1) * (1 - totalAbsorb);
  });
  // ema smoothing for pump (slower repricing)
  const ema = [];
  let prev = pumpPts[0];
  const alpha = 0.18;
  for (let i = 0; i < pumpPts.length; i++) {
    prev = alpha * pumpPts[i] + (1 - alpha) * prev;
    ema.push(prev);
  }

  const yMin = 0.95, yMax = 2.0;
  const xFor = (i) => padL + (i / weeks) * iw;
  const yFor = (v) => padT + (1 - (v - yMin) / (yMax - yMin)) * ih;

  const crudePath = smoothPath(crudePts.map((v, i) => ({ x: xFor(i), y: yFor(v) })));
  const pumpPath  = smoothPath(ema.map((v, i) => ({ x: xFor(i), y: yFor(v) })));

  // headline: peak pump multiplier
  const peakPump = Math.max(...ema);
  const peakCrude = Math.max(...crudePts);

  return (
    <section id="absorb">
      <div className="container">
        <SectionHeader
          num="02 / 06"
          tag="The pump-price anomaly"
          title="Where the shock actually went."
          lede="Crude spiked. Pump prices barely moved. Each layer below absorbs a slice of the shock invisibly. Toggle layers off to see what the consumer would have felt with naked exposure."
        />

        <div style={{ display: 'grid', gridTemplateColumns: '1fr 360px', gap: 32, alignItems: 'start' }}>
          {/* chart */}
          <div className="card flat" style={{ padding: '24px 28px' }}>
            <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', marginBottom: 8 }}>
              <div style={{ fontSize: 13, fontWeight: 600 }}>Crude spot vs pump price · 24 weeks · index 1.00 = pre-shock</div>
              <div className="flex-row" style={{ fontSize: 12 }}>
                <span style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
                  <span style={{ width: 14, height: 2, background: 'var(--red)' }} /> Crude spot
                </span>
                <span style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
                  <span style={{ width: 14, height: 2, background: 'var(--navy)' }} /> Pump price
                </span>
              </div>
            </div>

            <svg viewBox={`0 0 ${W} ${H}`} style={{ width: '100%', height: 'auto' }}>
              {/* gridlines */}
              {[1.0, 1.25, 1.5, 1.75, 2.0].map(v => (
                <g key={v}>
                  <line x1={padL} x2={W-padR} y1={yFor(v)} y2={yFor(v)}
                        stroke="#ece6d5" strokeWidth="1" strokeDasharray={v === 1 ? '0' : '2 4'} />
                  <text x={padL - 8} y={yFor(v) + 4} fontSize={10.5*AS} fill="#8a8a8a" textAnchor="end">
                    {v.toFixed(2)}
                  </text>
                </g>
              ))}
              {/* x labels */}
              {[0, 6, 12, 18, 24].map(w => (
                <g key={w}>
                  <line x1={xFor(w)} x2={xFor(w)} y1={H-padB} y2={H-padB+4} stroke="#cfcabb" />
                  <text x={xFor(w)} y={H-padB+18} fontSize={10.5*AS} fill="#8a8a8a" textAnchor="middle">
                    wk {w}
                  </text>
                </g>
              ))}

              {/* shock band */}
              <rect x={xFor(weeks*0.22)} y={padT}
                    width={xFor(weeks*0.55) - xFor(weeks*0.22)} height={ih}
                    fill="#f3e3e3" opacity="0.5" />
              <text x={(xFor(weeks*0.22) + xFor(weeks*0.55))/2} y={padT + 14}
                    fontSize={10.5*AS} fill="var(--red)" textAnchor="middle"
                    letterSpacing=".08em" fontWeight="600">HORMUZ DISRUPTION</text>

              {/* fill area between crude and pump (the absorbed delta) */}
              {(() => {
                const N = ema.length;
                let d = `M ${xFor(0)} ${yFor(crudePts[0])}`;
                for (let i = 1; i < N; i++) d += ` L ${xFor(i)} ${yFor(crudePts[i])}`;
                for (let i = N - 1; i >= 0; i--) d += ` L ${xFor(i)} ${yFor(ema[i])}`;
                d += ' Z';
                return <path d={d} fill="var(--tint)" opacity="0.7" />;
              })()}

              <path d={crudePath} fill="none" stroke="var(--red)" strokeWidth={2.25*LW} strokeLinecap="round" />
              <path d={pumpPath}  fill="none" stroke="var(--navy)" strokeWidth={2.5*LW} strokeLinecap="round" />

              {/* peak labels */}
              <g>
                {(() => {
                  const i = crudePts.indexOf(peakCrude);
                  return (
                    <text x={xFor(i)} y={yFor(peakCrude) - 10} fontSize={11*LS} fill="var(--red)"
                          textAnchor="middle" fontWeight="600">
                      {peakCrude.toFixed(2)}× crude
                    </text>
                  );
                })()}
                {(() => {
                  const i = ema.indexOf(peakPump);
                  return (
                    <text x={xFor(i)} y={yFor(peakPump) + 18} fontSize={11*LS} fill="var(--navy)"
                          textAnchor="middle" fontWeight="600">
                      {peakPump.toFixed(2)}× pump
                    </text>
                  );
                })()}
              </g>
            </svg>

            <div style={{ display: 'flex', justifyContent: 'space-between', marginTop: 8, fontSize: 12, color: 'var(--muted)' }}>
              <span>Shock severity: {(shock*100).toFixed(0)}%</span>
              <span>Total absorption capacity: {(totalAbsorb*100).toFixed(0)}%</span>
            </div>
            <input type="range" min="0" max="1" step="0.01" value={shock}
                   onChange={(e) => setShock(parseFloat(e.target.value))}
                   className="slider red" style={{ marginTop: 6 }} />
          </div>

          {/* layer toggles */}
          <div className="flex-col">
            <div style={{ fontSize: 11, letterSpacing: '.16em', textTransform: 'uppercase', color: 'var(--muted-2)', fontWeight: 600 }}>
              Risk-transfer layers
            </div>
            {ABSORBERS.map(a => (
              <div key={a.id} className="card flat" style={{
                padding: '14px 16px',
                cursor: 'pointer',
                borderColor: on[a.id] ? a.color : 'var(--rule)',
                background: on[a.id] ? 'var(--bg-card)' : 'rgba(0,0,0,0.02)',
                opacity: on[a.id] ? 1 : 0.55,
                transition: 'all .15s',
              }} onClick={() => toggle(a.id)}>
                <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', gap: 12 }}>
                  <div style={{ flex: 1 }}>
                    <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 4 }}>
                      <span style={{ width: 8, height: 8, borderRadius: '50%', background: a.color }} />
                      <span style={{ fontSize: 13, fontWeight: 600 }}>{a.label}</span>
                    </div>
                    <div style={{ fontSize: 11.5, color: 'var(--muted)', lineHeight: 1.45 }}>{a.sub}</div>
                  </div>
                  <div style={{ textAlign: 'right' }}>
                    <div className="mono" style={{ fontSize: 13, fontWeight: 600, color: a.color }}>
                      −{(a.mag*100).toFixed(0)}%
                    </div>
                    <div style={{ fontSize: 10, color: 'var(--muted-2)' }}>
                      {on[a.id] ? 'active' : 'off'}
                    </div>
                  </div>
                </div>
              </div>
            ))}

            <div className="aside" style={{ marginTop: 4 }}>
              The pump price is a rolling weighted average across multiple supply tranches — not the spot price of the marginal barrel.
            </div>
          </div>
        </div>
      </div>
    </section>
  );
}

window.PumpAbsorption = PumpAbsorption;
