/* Pressures.jsx — interactive immediacy × magnitude scatter */

const PRESSURES = [
  { id: 'xrb', label: 'Climate disclosure (XRB)', short: 'XRB', immediacy: 0.92, magnitude: 0.62,
    desc: 'Aotearoa NZ Climate Standards apply to large public-listed and financial entities for FY 2024 onwards. Many disclosures are vendor-derived and not fully understood internally.' },
  { id: 'ifrs', label: 'IFRS 17 transition', short: 'IFRS 17', immediacy: 0.78, magnitude: 0.55,
    desc: 'Insurers must define risk-adjustment methodology for confidence-level disclosure. Most NZ insurers transitioned 2023–24 using consultancy-supplied frameworks.' },
  { id: 'cyber', label: 'Cyber accumulation', short: 'Cyber', immediacy: 0.7, magnitude: 0.85,
    desc: 'Single cloud-service or supply-chain compromise hits hundreds of NZ firms simultaneously. Underwriters know they have correlated exposure but cannot quantify it well.' },
  { id: 'avf', label: 'Auckland Volcanic Field', short: 'AVF', immediacy: 0.32, magnitude: 0.96,
    desc: 'Insurers and reinsurers know the exposure exists. Defensible portfolio-level coverage modelling is rare. Cat models from Verisk and RMS exist but are general.' },
  { id: 'marsden', label: 'Marsden Point closure aftermath', short: 'Marsden Pt', immediacy: 0.55, magnitude: 0.7,
    desc: 'Three years of stranded fuel-import-terminal exposure. Reinsurers had to reprice. Some treaty wordings shifted materially.' },
  { id: 'cascade', label: 'Cascade-correlation in primary sector', short: 'Cascade', immediacy: 0.48, magnitude: 0.9,
    desc: 'Single MPI biosecurity event could simultaneously hit dairy, regional bank loan books, and rural insurance lines. Not in standard cat models.' },
];

function Pressures() {
  const tw = React.useContext(window.TweakCtx);
  const NS = tw.nodeScale, LS = tw.labelScale, AS = tw.axisLabelScale;
  const [sel, setSel] = React.useState('cyber');
  const [drag, setDrag] = React.useState(null);
  const [pts, setPts] = React.useState(PRESSURES);
  const W = 720, H = 460;
  const padL = 56, padR = 32, padT = 24, padB = 56;
  const iw = W - padL - padR, ih = H - padT - padB;

  const xFor = (v) => padL + v * iw;
  const yFor = (v) => padT + (1 - v) * ih;

  const onMove = (e) => {
    if (!drag) return;
    const svg = e.currentTarget;
    const rect = svg.getBoundingClientRect();
    const x = ((e.clientX - rect.left) / rect.width) * W;
    const y = ((e.clientY - rect.top) / rect.height) * H;
    const im = clamp((x - padL) / iw, 0, 1);
    const mg = clamp(1 - (y - padT) / ih, 0, 1);
    setPts(arr => arr.map(p => p.id === drag ? { ...p, immediacy: im, magnitude: mg } : p));
  };

  const cur = pts.find(p => p.id === sel);

  // priority score = immediacy × magnitude, ranked
  const ranked = [...pts].sort((a,b) => (b.immediacy*b.magnitude) - (a.immediacy*a.magnitude));

  return (
    <section id="pressures" className="tight" style={{ background: 'var(--tint)' }}>
      <div className="container">
        <SectionHeader
          num="03 / 06"
          tag="Pressures the market is currently under"
          title="Six structural pressures, in roughly decreasing order of immediacy."
          lede="Each is a decision under deep uncertainty about a high-dimensional risk surface, currently navigated with vendor tools designed for global generic portfolios. Drag the dots if your read disagrees with the placement."
        />

        <div style={{ display: 'grid', gridTemplateColumns: '1fr 360px', gap: 32, alignItems: 'start' }}>
          <div className="card flat" style={{ padding: '20px 24px', background: 'var(--bg-card)' }}>
            <svg viewBox={`0 0 ${W} ${H}`} style={{ width: '100%', height: 'auto', userSelect: 'none' }}
                 onMouseMove={onMove}
                 onMouseUp={() => setDrag(null)}
                 onMouseLeave={() => setDrag(null)}>
              {/* axes */}
              <line x1={padL} y1={H-padB} x2={W-padR} y2={H-padB} stroke="#cfcabb" />
              <line x1={padL} y1={padT} x2={padL} y2={H-padB} stroke="#cfcabb" />

              {/* quadrant tinting */}
              <rect x={padL + iw/2} y={padT} width={iw/2} height={ih/2} fill="rgba(139,26,26,0.04)" />

              {/* gridlines */}
              {[0.25, 0.5, 0.75].map(v => (
                <g key={v}>
                  <line x1={padL + v*iw} y1={padT} x2={padL + v*iw} y2={H-padB} stroke="#ece6d5" strokeDasharray="2 4" />
                  <line x1={padL} y1={padT + v*ih} x2={W-padR} y2={padT + v*ih} stroke="#ece6d5" strokeDasharray="2 4" />
                </g>
              ))}

              {/* axis labels */}
              <text x={padL} y={H-padB+18} fontSize={10.5*AS} fill="#8a8a8a">slow</text>
              <text x={W-padR} y={H-padB+18} fontSize={10.5*AS} fill="#8a8a8a" textAnchor="end">acute</text>
              <text x={(padL+W-padR)/2} y={H-padB+38} fontSize={11*AS} fontWeight="600" fill="var(--ink)" textAnchor="middle"
                    letterSpacing=".08em">IMMEDIACY →</text>

              <text x={padL-12} y={H-padB} fontSize={10.5*AS} fill="#8a8a8a" textAnchor="end">low</text>
              <text x={padL-12} y={padT+8} fontSize={10.5*AS} fill="#8a8a8a" textAnchor="end">high</text>
              <text x={padL-32} y={(padT+H-padB)/2} fontSize={11*AS} fontWeight="600" fill="var(--ink)" textAnchor="middle"
                    letterSpacing=".08em" transform={`rotate(-90 ${padL-32} ${(padT+H-padB)/2})`}>
                MAGNITUDE →
              </text>

              {/* "do these first" callout */}
              <text x={W-padR-12} y={padT + 18} fontSize={10.5*AS} fill="var(--red)"
                    textAnchor="end" letterSpacing=".08em" fontWeight="600">PRIORITY ZONE</text>

              {pts.map(p => {
                const cx = xFor(p.immediacy), cy = yFor(p.magnitude);
                const isSel = sel === p.id;
                const r = (isSel ? 13 : 10) * NS;
                return (
                  <g key={p.id} style={{ cursor: 'grab' }}
                     onMouseDown={() => setDrag(p.id)}
                     onClick={() => setSel(p.id)}>
                    <circle cx={cx} cy={cy} r={r + 6} fill="var(--red)" opacity={isSel ? 0.12 : 0} />
                    <circle cx={cx} cy={cy} r={r}
                            fill={isSel ? 'var(--red)' : 'var(--bg-card)'}
                            stroke={isSel ? 'var(--red)' : 'var(--ink)'}
                            strokeWidth="1.5" />
                    <text x={cx} y={cy + 4} fontSize={10*LS} fontWeight="600"
                          fill={isSel ? '#fff' : 'var(--ink)'}
                          textAnchor="middle">
                      {p.id === 'cyber' || p.id === 'avf' ? p.short.charAt(0) : p.id.charAt(0).toUpperCase()}
                    </text>
                    <text x={cx + r + 6} y={cy + 4} fontSize={11.5*LS}
                          fill={isSel ? 'var(--red)' : 'var(--ink-soft)'}
                          fontWeight={isSel ? 600 : 500}>
                      {p.short}
                    </text>
                  </g>
                );
              })}
            </svg>
          </div>

          <div className="flex-col">
            <div className="card flat card-pad-sm">
              <div style={{ fontSize: 11, letterSpacing: '.16em', textTransform: 'uppercase', color: 'var(--muted-2)', fontWeight: 600, marginBottom: 4 }}>
                Selected pressure
              </div>
              <div style={{ fontFamily: 'Source Serif 4', fontSize: 22, letterSpacing: '-.015em', marginBottom: 10 }}>
                {cur.label}
              </div>
              <div style={{ display: 'flex', gap: 16, marginBottom: 10 }}>
                <div>
                  <div style={{ fontSize: 10, color: 'var(--muted-2)', textTransform: 'uppercase', letterSpacing: '.08em' }}>Immediacy</div>
                  <div className="mono" style={{ fontSize: 18, fontWeight: 600 }}>{(cur.immediacy*100).toFixed(0)}</div>
                </div>
                <div>
                  <div style={{ fontSize: 10, color: 'var(--muted-2)', textTransform: 'uppercase', letterSpacing: '.08em' }}>Magnitude</div>
                  <div className="mono" style={{ fontSize: 18, fontWeight: 600 }}>{(cur.magnitude*100).toFixed(0)}</div>
                </div>
                <div>
                  <div style={{ fontSize: 10, color: 'var(--muted-2)', textTransform: 'uppercase', letterSpacing: '.08em' }}>Priority</div>
                  <div className="mono" style={{ fontSize: 18, fontWeight: 600, color: 'var(--red)' }}>
                    {(cur.immediacy*cur.magnitude*100).toFixed(0)}
                  </div>
                </div>
              </div>
              <div style={{ fontSize: 12.5, color: 'var(--ink-soft)', lineHeight: 1.5 }}>
                {cur.desc}
              </div>
            </div>

            <div className="card flat card-pad-sm">
              <div style={{ fontSize: 11, letterSpacing: '.16em', textTransform: 'uppercase', color: 'var(--muted-2)', fontWeight: 600, marginBottom: 8 }}>
                Live priority ranking
              </div>
              {ranked.map((p, i) => (
                <div key={p.id} style={{
                  display: 'flex', alignItems: 'center', gap: 10,
                  padding: '6px 0',
                  borderBottom: i < ranked.length - 1 ? '1px solid var(--rule)' : 'none',
                  cursor: 'pointer',
                }} onClick={() => setSel(p.id)}>
                  <div className="mono" style={{ width: 22, color: 'var(--muted-2)', fontSize: 12 }}>{i+1}</div>
                  <div style={{ flex: 1, fontSize: 13, fontWeight: sel===p.id ? 600 : 500,
                                color: sel===p.id ? 'var(--red)' : 'var(--ink)' }}>
                    {p.short}
                  </div>
                  <div style={{ width: 80, height: 4, background: 'var(--rule)', borderRadius: 2, overflow: 'hidden' }}>
                    <div style={{ width: `${p.immediacy*p.magnitude*100}%`, height: '100%', background: 'var(--red)' }} />
                  </div>
                </div>
              ))}
            </div>
          </div>
        </div>
      </div>
    </section>
  );
}

window.Pressures = Pressures;
