// CRA2 — Meridian Supply Co. simulator.
// Toggle each task between Human / Human + Agent / Agent (/ Eliminate)
// and watch capacity, throughput, and cost per order respond.

const MERIDIAN_TASKS = [
  {
    id: 'docs',
    name: 'Verify order documents',
    hours: 120,
    leak: true,
    canEliminate: false,
    recommended: 'Agent',
    notes: { Agent: 'Verification is pattern work. Agents do it in seconds, with an audit trail.' }
  },
  {
    id: 'entry',
    name: 'Re-enter data across 4 systems',
    hours: 90,
    leak: true,
    canEliminate: false,
    recommended: 'Agent',
    notes: { Agent: 'The same order was being typed in four times. Now it is typed zero times.' }
  },
  {
    id: 'credit',
    name: 'Credit and risk review',
    hours: 60,
    leak: false,
    canEliminate: false,
    recommended: 'Human + Agent',
    notes: { 'Human + Agent': 'Agents prepare the file. People make the judgment call.' },
    warns: { Agent: 'Flagged: high-risk judgment work. Fully delegating credit decisions gives up human oversight where it matters most. Tokaro would push back on this design.' }
  },
  {
    id: 'welcome',
    name: 'Customer welcome calls',
    hours: 50,
    leak: false,
    canEliminate: false,
    recommended: 'Human',
    notes: { Agent: 'Meridian kept this one human. Relationships are judgment work.' }
  },
  {
    id: 'status',
    name: 'Order status updates',
    hours: 40,
    leak: true,
    canEliminate: false,
    recommended: 'Agent',
    notes: {}
  },
  {
    id: 'dup',
    name: 'Duplicate compliance re-checks',
    hours: 30,
    leak: true,
    canEliminate: true,
    recommended: 'Eliminate',
    notes: { Eliminate: 'Two teams were checking the same thing. Nobody had ever seen it in one place.' }
  }
];

const MERIDIAN_FACTORS = { Human: 1, 'Human + Agent': 0.55, Agent: 0.15, Eliminate: 0 };
const MERIDIAN_RATE = 65;       // $/human-hour
const MERIDIAN_AGENT_RATE = 8;  // $/agent-run-hour equivalent
const MERIDIAN_BASE_THROUGHPUT = 240; // orders/week

function meridianTween(target, setter) {
  // smooth number tween
  return React.useEffect(() => {
    let raf, start;
    const from = setterCache.get(setter) ?? target;
    if (from === target) { setter(target); setterCache.set(setter, target); return; }
    const dur = 500;
    function tick(ts) {
      if (!start) start = ts;
      const t = Math.min(1, (ts - start) / dur);
      const eased = 1 - Math.pow(1 - t, 3);
      const v = from + (target - from) * eased;
      setter(v);
      if (t < 1) raf = requestAnimationFrame(tick);
      else setterCache.set(setter, target);
    }
    raf = requestAnimationFrame(tick);
    const settle = setTimeout(() => { setter(target); setterCache.set(setter, target); }, dur + 100);
    return () => { cancelAnimationFrame(raf); clearTimeout(settle); };
  }, [target]);
}
const setterCache = new WeakMap();

function MeridianSim() {
  const [modes, setModes] = React.useState(() => Object.fromEntries(MERIDIAN_TASKS.map((t) => [t.id, 'Human'])));


  const totalBase = MERIDIAN_TASKS.reduce((s, t) => s + t.hours, 0);
  let humanHours = 0, agentCost = 0;
  MERIDIAN_TASKS.forEach((t) => {
    const m = modes[t.id];
    humanHours += t.hours * MERIDIAN_FACTORS[m];
    if (m === 'Agent') agentCost += t.hours * 0.1 * MERIDIAN_AGENT_RATE;
    if (m === 'Human + Agent') agentCost += t.hours * 0.05 * MERIDIAN_AGENT_RATE;
  });
  const freed = totalBase - humanHours;
  const freedShare = freed / totalBase;
  const throughput = MERIDIAN_BASE_THROUGHPUT * (1 + freedShare * 0.8);
  const weeklyCost = humanHours * MERIDIAN_RATE + agentCost;
  const costPerOrder = weeklyCost / throughput;
  const baselineCost = (totalBase * MERIDIAN_RATE) / MERIDIAN_BASE_THROUGHPUT;
  const changedCount = MERIDIAN_TASKS.filter((t) => modes[t.id] !== 'Human').length;
  const monthsAhead = Math.round((changedCount / MERIDIAN_TASKS.length) * 18);

  // tweened display values
  const [dFreed, setDFreed] = React.useState(freed);
  const [dThru, setDThru] = React.useState(throughput);
  const [dCost, setDCost] = React.useState(costPerOrder);
  meridianTween(freed, setDFreed);
  meridianTween(throughput, setDThru);
  meridianTween(costPerOrder, setDCost);

  function setMode(id, m) { setModes((prev) => ({ ...prev, [id]: m })); }
  function reset() { setModes(Object.fromEntries(MERIDIAN_TASKS.map((t) => [t.id, 'Human']))); }
  function recommend() {
    setModes(Object.fromEntries(MERIDIAN_TASKS.map((t) => [t.id, t.recommended])));
  }

  return (
    <div className="sim-frame">
      <div className="sim-head">
        <div className="sim-company">
          <span className="sim-company-name">Meridian Supply Co.</span>
          <span className="sim-company-desc">Mid-market distributor · order-to-cash workstream · illustrative numbers</span>
        </div>
        <div className="timeline">
          <span>Today</span>
          <span className="timeline-track"><span className="timeline-fill" style={{ width: (monthsAhead / 18 * 100) + '%' }}></span></span>
          <span className="timeline-now">{monthsAhead === 0 ? 'Today' : '+' + monthsAhead + ' months'}</span>
        </div>
      </div>

      <div className="sim-body">
        <div className="tasks">
          {MERIDIAN_TASKS.map((t) => {
            const m = modes[t.id];
            const note = t.notes[m];
            const warn = t.warns && t.warns[m];
            const opts = t.canEliminate
              ? ['Human', 'Human + Agent', 'Agent', 'Eliminate']
              : ['Human', 'Human + Agent', 'Agent'];
            return (
              <div className="task" key={t.id}>
                <div className="task-top">
                  <span className="task-name">{t.name}</span>
                  <span className="task-hours">
                    {Math.round(t.hours * MERIDIAN_FACTORS[m])} hrs/wk
                    {t.leak && m === 'Human' && <span className="task-leak"> · value leak</span>}
                  </span>
                </div>
                <div className="modes">
                  {opts.map((o) => (
                    <button
                      key={o}
                      className={'mode' + (m === o ? ' on' : '') + (o === 'Agent' ? ' mode-agent' : '') + (o === 'Eliminate' ? ' mode-gone' : '') + (t.warns && t.warns[o] && m === o ? ' warned' : '')}
                      onClick={() => setMode(t.id, o)}
                    >{o}</button>
                  ))}
                </div>
                {warn ? <div className="task-note warn">⚠ {warn}</div> : note ? <div className="task-note">{note}</div> : null}
              </div>
            );
          })}
        </div>

        <aside className="metrics">
          <div className="metrics-h">Meridian, redesigned</div>
          <div className="metric">
            <span className="metric-val"><span className="up">{Math.round(dFreed)}</span> hrs/wk</span>
            <span className="metric-label">capacity freed for higher-impact work</span>
            <div className="capacity-bar"><div className="capacity-fill" style={{ width: (freedShare * 100) + '%' }}></div></div>
          </div>
          <div className="metric">
            <span className="metric-val">{Math.round(dThru)} <span className="up">{throughput > MERIDIAN_BASE_THROUGHPUT ? '\u2191' : ''}</span></span>
            <span className="metric-label">orders shipped per week (was {MERIDIAN_BASE_THROUGHPUT})</span>
          </div>
          <div className="metric">
            <span className="metric-val"><span className="down">${dCost.toFixed(0)}</span></span>
            <span className="metric-label">cost per order (was ${baselineCost.toFixed(0)})</span>
          </div>
          <div className="metrics-actions">
            <button className="text-btn filled" onClick={recommend}>Apply Tokaro's recommended design</button>
            <button className="text-btn" onClick={reset}>Reset to today</button>
          </div>
          <div className="metrics-foot">Illustrative. Your numbers come from your own workgraph.</div>
        </aside>
      </div>
    </div>
  );
}

ReactDOM.createRoot(document.getElementById('sim-root')).render(<MeridianSim />);
