// Models & Metrics — uses SITE.models

// Draws the actual mathematical function for each model on a canvas
const FormulaGraph = ({ model }) => {
  const canvasRef = React.useRef(null);
  const key = model.id;

  React.useEffect(() => {
    const canvas = canvasRef.current;
    if (!canvas) return;
    const dpr = window.devicePixelRatio || 1;
    const W = canvas.parentElement.clientWidth;
    const H = 220;
    canvas.width = W * dpr;
    canvas.height = H * dpr;
    canvas.style.width = W + 'px';
    canvas.style.height = H + 'px';
    const ctx = canvas.getContext('2d');
    ctx.scale(dpr, dpr);

    const css = (v) => getComputedStyle(document.documentElement).getPropertyValue(v).trim();
    const ink = css('--ink');
    const ink3 = css('--ink-3');
    const ink4 = css('--ink-4');
    const accent = css('--accent');
    const hairline = css('--hairline');
    const isDark = document.documentElement.dataset.theme === 'dark';

    const padL = 48, padR = 20, padT = 18, padB = 32;
    const gW = W - padL - padR;
    const gH = H - padT - padB;

    ctx.clearRect(0, 0, W, H);

    // Grid
    ctx.strokeStyle = hairline;
    ctx.lineWidth = 1;
    for (let i = 0; i <= 4; i++) {
      const y = padT + (i / 4) * gH;
      ctx.beginPath(); ctx.moveTo(padL, y); ctx.lineTo(padL + gW, y); ctx.stroke();
    }
    for (let i = 0; i <= 5; i++) {
      const x = padL + (i / 5) * gW;
      ctx.beginPath(); ctx.moveTo(x, padT); ctx.lineTo(x, padT + gH); ctx.stroke();
    }

    // Function definitions per model
    let fn, xLabel, yLabel, xRange, yRange, markerX, paramLabel;

    if (key === 'pin') {
      // PIN = αμ / (αμ + noise) where noise = ε_b + ε_s varies
      const alpha = 0.382, mu = 284;
      const aM = alpha * mu;
      xRange = [0, 1400]; yRange = [0, 1];
      fn = (noise) => aM / (aM + noise);
      xLabel = 'uninformed flow  ε_b + ε_s';
      yLabel = 'PIN';
      markerX = 568; // ε_b+ε_s ≈ 568 gives PIN=0.214
      paramLabel = `PIN = ${0.214}`;
    } else if (key === 'bkelly') {
      // f* as function of n_eff, b=2, p̄=0.541, κ=10
      const pBar = 0.541, b = 2, kappa = 10;
      const rawF = pBar - (1 - pBar) / b;
      xRange = [0, 800]; yRange = [0, rawF * 1.05];
      fn = (n) => rawF * n / (n + kappa);
      xLabel = 'effective sample size  n_eff';
      yLabel = 'f*';
      markerX = 412;
      paramLabel = `f* = 0.182`;
    } else if (key === 'ddr') {
      // f*(d) = κd/(1−α), d = 0..0.3
      const kappa = 0.71, alpha = 0.18;
      xRange = [0, 0.30]; yRange = [0, 0.71 * 0.30 / (1 - 0.18) * 1.1];
      fn = (d) => kappa * d / (1 - alpha);
      xLabel = 'log-distance to barrier  d';
      yLabel = 'f*(d)';
      markerX = 0.142;
      paramLabel = `f* = ${(kappa * 0.142 / (1 - alpha)).toFixed(3)}`;
    } else {
      // Square-root impact: ΔP = σ·sqrt(Q/V), σ=0.184, β=0.62
      const sigma = 0.184;
      xRange = [0, 0.30]; yRange = [0, sigma * Math.pow(0.30, 0.62) * 1.1];
      fn = (qv) => sigma * Math.pow(Math.max(qv, 0.0001), 0.62);
      xLabel = 'participation rate  Q / V';
      yLabel = 'ΔP';
      markerX = 0.084;
      paramLabel = `ΔP = ${(sigma * Math.pow(0.084, 0.62)).toFixed(4)}`;
    }

    const toX = (v) => padL + ((v - xRange[0]) / (xRange[1] - xRange[0])) * gW;
    const toY = (v) => padT + gH - ((v - yRange[0]) / (yRange[1] - yRange[0])) * gH;

    // Area fill under curve
    const steps = 200;
    const pts = [];
    for (let i = 0; i <= steps; i++) {
      const xv = xRange[0] + (i / steps) * (xRange[1] - xRange[0]);
      pts.push([toX(xv), toY(fn(xv))]);
    }

    const grad = ctx.createLinearGradient(0, padT, 0, padT + gH);
    grad.addColorStop(0, isDark ? 'rgba(217,105,79,0.22)' : 'rgba(139,42,31,0.14)');
    // Use accent color directly from CSS var
    grad.addColorStop(1, 'rgba(0,0,0,0)');

    // Re-read accent and build gradient from it properly
    ctx.fillStyle = grad;
    ctx.beginPath();
    ctx.moveTo(pts[0][0], padT + gH);
    pts.forEach(([x, y]) => ctx.lineTo(x, y));
    ctx.lineTo(pts[pts.length - 1][0], padT + gH);
    ctx.closePath();
    ctx.fill();

    // Curve line
    ctx.strokeStyle = accent;
    ctx.lineWidth = 1.8;
    ctx.lineJoin = 'round';
    ctx.beginPath();
    pts.forEach(([x, y], i) => i === 0 ? ctx.moveTo(x, y) : ctx.lineTo(x, y));
    ctx.stroke();

    // Marker — dashed crosshairs at measured parameter value
    const mx = toX(markerX);
    const my = toY(fn(markerX));
    ctx.strokeStyle = accent;
    ctx.lineWidth = 1;
    ctx.setLineDash([3, 4]);
    ctx.beginPath(); ctx.moveTo(mx, padT); ctx.lineTo(mx, my); ctx.stroke();
    ctx.beginPath(); ctx.moveTo(padL, my); ctx.lineTo(mx, my); ctx.stroke();
    ctx.setLineDash([]);

    // Marker dot
    ctx.fillStyle = accent;
    ctx.beginPath(); ctx.arc(mx, my, 4, 0, Math.PI * 2); ctx.fill();

    // Marker label
    ctx.fillStyle = accent;
    ctx.font = `500 10px JetBrains Mono, monospace`;
    ctx.textAlign = 'left';
    ctx.fillText(paramLabel, mx + 7, my - 4);

    // Axes labels
    ctx.fillStyle = ink3;
    ctx.font = '10px JetBrains Mono, monospace';
    ctx.textAlign = 'center';
    ctx.fillText(xLabel, padL + gW / 2, H - 4);

    ctx.save();
    ctx.translate(11, padT + gH / 2);
    ctx.rotate(-Math.PI / 2);
    ctx.textAlign = 'center';
    ctx.fillText(yLabel, 0, 0);
    ctx.restore();

    // Y-axis ticks
    ctx.textAlign = 'right';
    for (let i = 0; i <= 4; i++) {
      const yv = yRange[0] + (i / 4) * (yRange[1] - yRange[0]);
      const y = toY(yv);
      ctx.fillText(yv.toFixed(yRange[1] < 1 ? 2 : 0), padL - 6, y + 3);
    }

  }, [key]);

  return <canvas ref={canvasRef} style={{ display: 'block', width: '100%' }} />;
};

const Models = () => {
  const list = SITE.models;
  const [active, setActive] = React.useState(list[0].id);
  const m = list.find(x => x.id === active) || list[0];

  return (
    <section id="models" className="section" data-screen-label="Models">
      <div className="shell">
        <div className="reveal"><SectionHead idx="III" eyebrow="Models & Metrics"
          title="The mathematical objects we maintain, calibrate, and trust." numeral="III" /></div>

        <div style={{
          display: 'flex', gap: 0,
          borderTop: '1px solid var(--hairline)',
          borderBottom: '1px solid var(--hairline)',
          flexWrap: 'wrap',
        }}>
          {list.map((mm) => (
            <button key={mm.id} onClick={() => setActive(mm.id)}
              style={{
                flex: '1 1 200px',
                background: active === mm.id ? 'color-mix(in oklab, var(--accent) 6%, transparent)' : 'transparent',
                border: 'none',
                borderRight: '1px solid var(--hairline)',
                padding: '20px 22px', textAlign: 'left',
                position: 'relative', cursor: 'pointer',
              }}>
              <div className="mono" style={{
                fontSize: 10, color: active === mm.id ? 'var(--accent)' : 'var(--ink-3)',
                letterSpacing: '0.16em', textTransform: 'uppercase',
              }}>{mm.type}</div>
              <div style={{
                marginTop: 10, fontSize: 22, fontWeight: 460, letterSpacing: '-0.02em',
                color: 'var(--ink)',
              }}>{mm.name}</div>
              {active === mm.id && (
                <div style={{ position: 'absolute', top: -1, left: 0, right: 0, height: 1, background: 'var(--accent)' }} />
              )}
            </button>
          ))}
        </div>

        <div style={{
          display: 'grid', gridTemplateColumns: 'minmax(0, 1fr) minmax(0, 1.3fr)', gap: 0,
        }} className="model-detail">
          <div style={{ padding: '40px 40px 40px 0', borderRight: '1px solid var(--hairline)' }} key={active + '-l'}>
            <div className="fade-up">
              <div className="mono" style={{
                fontSize: 13, color: 'var(--ink)', letterSpacing: '0.02em', marginBottom: 20,
                padding: '12px 16px', background: 'var(--bg-elev)', borderRadius: 6,
                border: '1px solid var(--hairline)', display: 'inline-block',
              }}>{m.formula}</div>
              <p className="serif" style={{ margin: 0, fontSize: 18, lineHeight: 1.6, color: 'var(--ink-2)' }}>
                {m.description}
              </p>

              <div style={{
                marginTop: 36, display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 0,
                border: '1px solid var(--hairline)', borderRadius: 8, overflow: 'hidden',
              }}>
                {m.metrics.map(([k, v], i) => (
                  <div key={i} style={{
                    padding: '18px 20px',
                    borderRight: i % 2 === 0 ? '1px solid var(--hairline)' : 'none',
                    borderBottom: i < 2 ? '1px solid var(--hairline)' : 'none',
                  }}>
                    <div className="mono" style={{ fontSize: 10, color: 'var(--ink-3)', letterSpacing: '0.1em', textTransform: 'uppercase' }}>{k}</div>
                    <div className="tabular display" style={{ marginTop: 6, fontSize: 28, fontWeight: 460, letterSpacing: '-0.03em' }}>{v}</div>
                  </div>
                ))}
              </div>
            </div>
          </div>

          <div style={{ padding: '40px 0 40px 40px' }} key={active + '-r'}>
            <div className="fade-up">
              <div style={{ marginBottom: 20 }}>
                <span className="eyebrow">Function graph · {m.formula}</span>
              </div>
              <FormulaGraph model={m} />
              <div className="serif" style={{
                marginTop: 32, fontSize: 17, lineHeight: 1.6, color: 'var(--ink-2)',
                fontStyle: 'italic', paddingLeft: 18, borderLeft: '2px solid var(--accent)',
              }}>
                {active === 'pin' && "Adverse selection decays with uninformed volume. The marked point is our current calibration."}
                {active === 'bkelly' && "Bayesian shrinkage collapses position size toward zero under estimation risk. Asymptotes to the plug-in Kelly as samples accumulate."}
                {active === 'ddr' && "Leverage grows linearly with distance from the drawdown barrier. At the barrier, position is fully closed."}
                {active === 'impact' && "Square-root impact: execution cost grows sub-linearly with participation rate. The concavity is why large orders must be sliced."}
              </div>
            </div>
          </div>
        </div>
      </div>
    </section>
  );
};

window.Models = Models;
