// Central stage — cancer-vs-normal cell-line comparison driven by methylation gating.
// Roth et al., Nature 2026.

const { useState: useState_s, useEffect: useEffect_s, useMemo: useMemo_s, useRef: useRef_s } = React;

const GRID_COLS = 18;
const GRID_ROWS = 14;
const CELLS_PER_LINE = GRID_COLS * GRID_ROWS;
const SIM_DAYS = 90;

function Stage(props) {
  const { scenarioKey, targetIdx, variantKey, delivery, beta, running, setRunning, day, setDay, speed } = props;
  const scenario = SCENARIOS[scenarioKey];
  const target = scenario.targets[targetIdx];
  const cancerLine = CELL_LINES[scenario.cancer_line];
  const normalLine = CELL_LINES[scenario.normal_line];
  const variant = VARIANTS[variantKey];
  const tcKey = variantKey === 'CE' ? 'ce_thermocas9' : 'thermocas9';

  // Per-cell methylation states drawn from line β (with biological heterogeneity)
  const [cancerCells, setCancerCells] = useState_s(() => initCells(target.beta_cancer));
  const [normalCells, setNormalCells] = useState_s(() => initCells(target.beta_normal));
  const [history, setHistory] = useState_s(() => [{ day: 0, cancerEdit: 0, normalEdit: 0 }]);

  useEffect_s(() => {
    setCancerCells(initCells(target.beta_cancer));
    setNormalCells(initCells(target.beta_normal));
    setHistory([{ day: 0, cancerEdit: 0, normalEdit: 0 }]);
    setDay(0);
  }, [scenarioKey, targetIdx, variantKey, delivery]);

  useEffect_s(() => {
    if (!running) return;
    const delivEff = DELIVERY[delivery].efficiency;
    const variantScale = variant.activity_scale;
    const showsMethylation = variant.methylation_sensitive;

    const iv = setInterval(() => {
      setDay(d => {
        if (d >= SIM_DAYS) { setRunning(false); return d; }
        const nextDay = d + 1;

        const stepCells = (cells) => cells.map(c => {
          if (c.state === 'edited' || c.state === 'dead') {
            // edited cells decay to dead/cleared at a slow rate
            if (c.state === 'edited' && Math.random() < 0.04) return { ...c, state: 'dead' };
            return c;
          }
          // Cell methylation gates editability
          const effectiveBeta = showsMethylation ? c.methylation : 0;
          const editProb = delivEff * activityVsMethylation(tcKey, effectiveBeta) * variantScale * 0.18;
          if (Math.random() < editProb) return { ...c, state: 'edited' };
          return c;
        });

        const nextCancer = stepCells(cancerCells);
        const nextNormal = stepCells(normalCells);
        setCancerCells(nextCancer);
        setNormalCells(nextNormal);

        const cancerEdited = nextCancer.filter(c => c.state === 'edited' || c.state === 'dead').length;
        const normalEdited = nextNormal.filter(c => c.state === 'edited' || c.state === 'dead').length;
        setHistory(h => {
          const last = h[h.length - 1];
          if (last && last.day === nextDay) return h;
          return [...h, { day: nextDay, cancerEdit: cancerEdited / CELLS_PER_LINE, normalEdit: normalEdited / CELLS_PER_LINE }];
        });
        return nextDay;
      });
    }, Math.max(60, 400 / speed));
    return () => clearInterval(iv);
  }, [running, beta, delivery, targetIdx, variantKey, scenarioKey, speed, cancerCells, normalCells]);

  const cancerStats = countStates(cancerCells);
  const normalStats = countStates(normalCells);
  const cancerEditPct = (cancerStats.edited + cancerStats.dead) / CELLS_PER_LINE;
  const normalEditPct = (normalStats.edited + normalStats.dead) / CELLS_PER_LINE;
  const selectivity = normalEditPct > 0.005 ? cancerEditPct / normalEditPct : (cancerEditPct > 0.05 ? 999 : 1);

  return (
    <div className="stage">
      <div className="stage-header">
        <div className="stage-title-block">
          <h1>
            {scenario.name}{' '}
            <span style={{color:'var(--fg-mute)', fontFamily:'JetBrains Mono, monospace', fontSize: 14, fontWeight: 400, marginLeft: 8}}>
              · {target.gene} {target.site}
            </span>
          </h1>
          <div className="sub">
            ThermoCas9-{variant.abbr} / {DELIVERY[delivery].name} / PAM {target.pam}
          </div>
          <div className="blurb">{scenario.blurb}</div>
        </div>
        <div style={{textAlign:'right'}}>
          <div style={{fontFamily:'JetBrains Mono, monospace', fontSize: 10, letterSpacing: '0.1em', color:'var(--fg-mute)', textTransform:'uppercase'}}>
            Simulation day
          </div>
          <div className="tabular" style={{fontFamily:'JetBrains Mono, monospace', fontSize: 36, fontWeight: 300}}>
            {String(day).padStart(2, '0')}<span style={{color:'var(--fg-mute)', fontSize: 16}}> / {SIM_DAYS}</span>
          </div>
        </div>
      </div>

      <div className="stage-body">
        <div className="stage-cell">
          <div className="cell-title">
            Cell-line comparison <span className="hint">{CELLS_PER_LINE} cells per line</span>
          </div>
          <div className="dual-grid">
            <CellLineGrid cells={cancerCells} line={cancerLine} beta={target.beta_cancer} kind="cancer" />
            <CellLineGrid cells={normalCells} line={normalLine} beta={target.beta_normal} kind="normal" />
          </div>
          <SelectivityRow
            cancerStats={cancerStats} normalStats={normalStats}
            cancerEditPct={cancerEditPct} normalEditPct={normalEditPct}
            selectivity={selectivity}
          />
        </div>

        <div className="stage-cell">
          <div className="cell-title">
            Editing curves <span className="hint">cancer vs normal · % cells edited</span>
          </div>
          <ResponseChart history={history} cancerLine={cancerLine} normalLine={normalLine} />
          <EditFlow variant={variant} delivery={delivery} target={target} beta={beta} />
        </div>
      </div>
    </div>
  );
}

function initCells(meanBeta) {
  // Each cell gets its own PAM-cytosine methylation state: Normal(meanBeta, 0.12) clamped.
  const arr = new Array(CELLS_PER_LINE);
  for (let i = 0; i < CELLS_PER_LINE; i++) {
    const u1 = Math.random(), u2 = Math.random();
    const z = Math.sqrt(-2 * Math.log(u1 || 1e-9)) * Math.cos(2 * Math.PI * u2);
    let m = meanBeta + z * 0.12;
    if (m < 0) m = 0;
    if (m > 1) m = 1;
    arr[i] = { methylation: m, state: 'cell' };
  }
  return arr;
}

function countStates(cells) {
  let edited = 0, dead = 0, intact = 0;
  for (const c of cells) {
    if (c.state === 'edited') edited++;
    else if (c.state === 'dead') dead++;
    else intact++;
  }
  return { edited, dead, intact };
}

function CellLineGrid({ cells, line, beta, kind }) {
  return (
    <div className="line-panel">
      <div className="line-panel-head">
        <div>
          <div className="ln-name">{line.name} <span className="ln-tag" data-kind={kind}>{line.type}</span></div>
          <div className="ln-sub">{line.long}</div>
        </div>
        <div className="ln-beta tabular">β <b>{beta.toFixed(2)}</b></div>
      </div>
      <div className="tumor-grid" style={{gridTemplateColumns: `repeat(${GRID_COLS}, 1fr)`, gridTemplateRows: `repeat(${GRID_ROWS}, 1fr)`}}>
        {cells.map((c, i) => (
          <div
            key={i}
            className="tumor-cell"
            data-state={c.state === 'cell' ? cellMethylationClass(c.methylation) : c.state}
            title={`PAM β = ${c.methylation.toFixed(2)}`}
          />
        ))}
      </div>
    </div>
  );
}

function cellMethylationClass(b) {
  if (b < 0.20) return 'cell-hypo';
  if (b < 0.50) return 'cell-mid';
  if (b < 0.80) return 'cell-mhi';
  return 'cell-hyper';
}

function SelectivityRow({ cancerStats, normalStats, cancerEditPct, normalEditPct, selectivity }) {
  return (
    <div className="stats-row">
      <div className="stat">
        <div className="label">Cancer line edited</div>
        <div className="value good tabular">{(cancerEditPct * 100).toFixed(0)}<span style={{fontSize: 12, color:'var(--fg-mute)'}}>%</span></div>
        <div className="delta">{cancerStats.edited + cancerStats.dead} / {CELLS_PER_LINE} cells</div>
      </div>
      <div className="stat">
        <div className="label">Normal line edited</div>
        <div className="value warn tabular">{(normalEditPct * 100).toFixed(0)}<span style={{fontSize: 12, color:'var(--fg-mute)'}}>%</span></div>
        <div className="delta">{normalStats.edited + normalStats.dead} / {CELLS_PER_LINE} cells</div>
      </div>
      <div className="stat">
        <div className="label">Selectivity ratio</div>
        <div className="value accent tabular">
          {selectivity > 999 ? '∞' : selectivity.toFixed(1)}<span style={{fontSize: 12, color:'var(--fg-mute)'}}>×</span>
        </div>
        <div className="delta">cancer / normal</div>
      </div>
      <div className="stat">
        <div className="label">DSB events</div>
        <div className="value tabular" style={{color: 'var(--fg-dim)'}}>{cancerStats.edited + cancerStats.dead + normalStats.edited + normalStats.dead}</div>
        <div className="delta">total cleavages</div>
      </div>
    </div>
  );
}

function ResponseChart({ history, cancerLine, normalLine }) {
  const W = 600, H = 280;
  const PAD_L = 36, PAD_R = 12, PAD_T = 12, PAD_B = 28;
  const plotW = W - PAD_L - PAD_R;
  const plotH = H - PAD_T - PAD_B;
  const xMax = SIM_DAYS, yMax = 1.0;
  const toX = (d) => PAD_L + (d / xMax) * plotW;
  const toY = (v) => PAD_T + plotH - (v / yMax) * plotH;

  const cancerPath = history.map((p, i) => `${i === 0 ? 'M' : 'L'}${toX(p.day).toFixed(1)},${toY(p.cancerEdit).toFixed(1)}`).join(' ');
  const normalPath = history.map((p, i) => `${i === 0 ? 'M' : 'L'}${toX(p.day).toFixed(1)},${toY(p.normalEdit).toFixed(1)}`).join(' ');

  const gridLines = [0, 0.25, 0.5, 0.75, 1].map(f => f * yMax);
  const xTicks = [0, 15, 30, 45, 60, 75, 90];

  return (
    <div className="chart-wrap">
      <svg viewBox={`0 0 ${W} ${H}`} preserveAspectRatio="none">
        {gridLines.map((v, i) => (
          <line key={i} x1={PAD_L} x2={W - PAD_R} y1={toY(v)} y2={toY(v)} className="grid-line-soft" />
        ))}
        <line x1={PAD_L} x2={W - PAD_R} y1={toY(0)} y2={toY(0)} className="grid-line" />
        <line x1={PAD_L} x2={PAD_L} y1={PAD_T} y2={H - PAD_B} className="grid-line" />
        {gridLines.map((v, i) => (
          <text key={i} x={PAD_L - 6} y={toY(v) + 3} textAnchor="end" className="axis-label">
            {Math.round((v / yMax) * 100)}%
          </text>
        ))}
        {xTicks.map(t => (
          <text key={t} x={toX(t)} y={H - 10} textAnchor="middle" className="axis-label">d{t}</text>
        ))}
        <path d={cancerPath} className="line-tumor" style={{stroke: 'var(--good)'}} />
        <path d={normalPath} className="line-edited" style={{stroke: 'var(--warn)', strokeDasharray: '3 3'}} />

        {history.length > 0 && (() => {
          const last = history[history.length - 1];
          return (
            <g>
              <circle cx={toX(last.day)} cy={toY(last.cancerEdit)} r="3" fill="var(--good)" />
              <circle cx={toX(last.day)} cy={toY(last.normalEdit)} r="3" fill="var(--warn)" />
            </g>
          );
        })()}

        <g transform={`translate(${PAD_L + 8}, ${PAD_T + 8})`} fontFamily="JetBrains Mono, monospace" fontSize="10">
          <rect x="-4" y="-10" width="220" height="38" fill="var(--bg-2)" opacity="0.9" stroke="var(--line)" />
          <line x1="0" x2="14" y1="0" y2="0" stroke="var(--good)" strokeWidth="2" />
          <text x="20" y="3" fill="var(--fg-dim)">Cancer line: {cancerLine.name} edited</text>
          <line x1="0" x2="14" y1="14" y2="14" stroke="var(--warn)" strokeWidth="1.5" strokeDasharray="3 3" />
          <text x="20" y="17" fill="var(--fg-dim)">Normal line: {normalLine.name} edited</text>
        </g>
      </svg>
    </div>
  );
}

function EditFlow({ variant, delivery, target, beta }) {
  return (
    <div className="flow">
      <div className="node active">{DELIVERY[delivery].short}</div>
      <div className="arr">→</div>
      <div className="node active">PAM {target.pam}</div>
      <div className="arr">→</div>
      <div className={`node ${variant.methylation_sensitive ? 'active' : ''}`}>5mC gate</div>
      <div className="arr">→</div>
      <div className="node active">{variant.abbr} @ {target.gene}</div>
    </div>
  );
}

Object.assign(window, {
  Stage, CellLineGrid, ResponseChart, SelectivityRow, EditFlow,
  SIM_DAYS, CELLS_PER_LINE, GRID_COLS, GRID_ROWS,
});
