// ArchViz — split-screen: intelligence lost (left, vortex) vs compounded (right, stacked layers)
const ARCH_STREAMS = ['Real users', 'Workflows', 'Prompts & logs', 'Expert corrections', 'Rejected outputs', 'Edge cases', 'Conversion signals'];
const ARCH_LAYERS  = ['Proprietary datasets', 'Eval sets', 'Model versions', 'Routing policies', 'Workflow memory', 'Runtime traces', 'Deployment control'];

const ArchViz = () => {
  const wrapRef = React.useRef(null);
  const canvasRef = React.useRef(null);

  React.useEffect(() => {
    const canvas = canvasRef.current, wrap = wrapRef.current;
    if (!canvas || !wrap) return;
    const ctx = canvas.getContext('2d');
    const reduced = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
    const TAU = 6.2831853;
    let W = 0, H = 0, DPR = 1, raf = 0, t0 = 0;
    const g = {};

    const layout = () => {
      g.cx = W * 0.5;
      g.vx = W * 0.31; g.vy = H * 0.52; g.vr = Math.min(W, H) * 0.085;
      g.gateX = W * 0.17;
      g.lanes = [];
      for (let i = 0; i < 7; i++) g.lanes.push(H * (0.24 + i * 0.58 / 6));
      const top = H * 0.18, bot = H * 0.86, span = bot - top, n = 7;
      g.lh = span / n * 0.6; g.gap = span / n * 0.4;
      g.sx = W * 0.79; g.lw = Math.min(W * 0.27, 250);
      g.layers = [];
      for (let i = 0; i < n; i++) g.layers.push(bot - (i + 1) * (g.lh + g.gap) + g.gap);
      g.smid = (g.layers[0] + g.lh + g.layers[6]) / 2;
      g.rx = g.lw * 0.6; g.ry = span * 0.42;
      g.absorb = g.lanes.map((y0) => {
        const x0 = W * 0.195;
        const ang0 = Math.atan2(y0 - g.vy, x0 - g.vx);
        const rimX = g.vx + Math.cos(ang0) * g.vr * 1.7, rimY = g.vy + Math.sin(ang0) * g.vr * 1.7;
        const cpx = (x0 + rimX) / 2, cpy = g.vy + (y0 - g.vy) * 0.28;
        const pts = [];
        for (let t = 0; t <= 1.0001; t += 0.1) {
          const mx = (1 - t) * (1 - t) * x0 + 2 * (1 - t) * t * cpx + t * t * rimX;
          const my = (1 - t) * (1 - t) * y0 + 2 * (1 - t) * t * cpy + t * t * rimY;
          pts.push([mx, my]);
        }
        let r = g.vr * 1.7, a = ang0;
        for (let s = 0; s < 15; s++) { a += 0.42; r *= 0.84; pts.push([g.vx + Math.cos(a) * r, g.vy + Math.sin(a) * r]); }
        return pts;
      });
    };

    const orbit = [];
    const rnd = Math.random;
    for (let i = 0; i < 5; i++) orbit.push({ t: i / 5 * TAU, s: 0.009 + rnd() * 0.005, px: 0, py: 0 });

    const rr = (x, y, w, h, r) => {
      ctx.beginPath();
      ctx.moveTo(x + r, y);
      ctx.arcTo(x + w, y, x + w, y + h, r);
      ctx.arcTo(x + w, y + h, x, y + h, r);
      ctx.arcTo(x, y + h, x, y, r);
      ctx.arcTo(x, y, x + w, y, r);
      ctx.closePath();
    };

    const drawDivider = () => {
      ctx.save();
      ctx.setLineDash([3, 7]); ctx.strokeStyle = 'rgba(255,255,255,0.05)'; ctx.lineWidth = 1;
      ctx.beginPath(); ctx.moveTo(g.cx, H * 0.10); ctx.lineTo(g.cx, H * 0.90); ctx.stroke();
      ctx.restore();
    };
    const drawGate = () => {
      const x = g.gateX, h = H * 0.5, y = g.vy - h / 2;
      ctx.strokeStyle = 'rgba(150,160,210,0.3)'; ctx.lineWidth = 1;
      ctx.fillStyle = 'rgba(255,255,255,0.015)';
      rr(x - 5, y, 10, h, 5); ctx.fill(); ctx.stroke();
    };
    const drawVortexArcs = (now) => {
      ctx.save(); ctx.translate(g.vx, g.vy); ctx.rotate(now * 0.0004);
      for (let i = 0; i < 4; i++) {
        const r = g.vr * (0.85 + i * 0.5);
        ctx.beginPath(); ctx.arc(0, 0, r, i * 0.6, i * 0.6 + 4.4);
        ctx.strokeStyle = `rgba(${135 - i * 8},115,205,${0.2 - i * 0.04})`;
        ctx.lineWidth = 1.2; ctx.stroke();
      }
      ctx.restore();
    };
    const drawVortexCore = () => {
      const grd = ctx.createRadialGradient(g.vx, g.vy, 0, g.vx, g.vy, g.vr * 1.6);
      grd.addColorStop(0, 'rgba(6,6,9,1)');
      grd.addColorStop(0.62, 'rgba(8,8,12,0.88)');
      grd.addColorStop(1, 'rgba(10,10,14,0)');
      ctx.fillStyle = grd;
      ctx.beginPath(); ctx.arc(g.vx, g.vy, g.vr * 1.6, 0, TAU); ctx.fill();
      ctx.beginPath(); ctx.arc(g.vx, g.vy, g.vr * 0.86, 0, TAU);
      ctx.strokeStyle = 'rgba(150,120,220,0.22)'; ctx.lineWidth = 1; ctx.stroke();
    };
    const drawStack = (now) => {
      const hi = ((now * 0.00018) % 1) * 7;
      const baseGlow = ctx.createRadialGradient(g.sx, g.layers[0] + g.lh, 0, g.sx, g.layers[0] + g.lh, g.lw);
      baseGlow.addColorStop(0, 'rgba(70,150,255,0.10)');
      baseGlow.addColorStop(1, 'rgba(70,150,255,0)');
      ctx.fillStyle = baseGlow;
      ctx.beginPath(); ctx.arc(g.sx, g.layers[0] + g.lh, g.lw, 0, TAU); ctx.fill();
      const x = g.sx - g.lw / 2;
      for (let i = 0; i < 7; i++) {
        const y = g.layers[i], estab = i / 6, near = Math.max(0, 1 - Math.abs(i - hi) * 0.7);
        ctx.fillStyle = `rgba(40,95,175,${0.10 + (1 - estab) * 0.05 + near * 0.10})`;
        rr(x, y, g.lw, g.lh, 4); ctx.fill();
        ctx.strokeStyle = `rgba(90,185,255,${0.26 + estab * 0.10 + near * 0.4})`;
        ctx.lineWidth = 1; ctx.stroke();
        ctx.font = '10px "JetBrains Mono", monospace';
        ctx.textAlign = 'left'; ctx.textBaseline = 'middle';
        ctx.fillStyle = `rgba(200,228,255,${0.55 + near * 0.4})`;
        ctx.fillText(ARCH_LAYERS[i], x + 11, y + g.lh / 2);
      }
    };
    const drawOrbitRing = () => {
      ctx.strokeStyle = 'rgba(110,180,255,0.07)'; ctx.lineWidth = 1;
      ctx.beginPath(); ctx.ellipse(g.sx, g.smid, g.rx, g.ry, 0, 0, TAU); ctx.stroke();
    };
    const drawStreamLabels = () => {
      ctx.font = '10px "JetBrains Mono", monospace';
      ctx.textAlign = 'left'; ctx.textBaseline = 'middle';
      ARCH_STREAMS.forEach((s, i) => {
        ctx.fillStyle = 'rgba(255,255,255,0.32)';
        ctx.fillText(s, 44, g.lanes[i]);
      });
    };

    const drawAbsorb = (now) => {
      for (const pts of g.absorb) {
        ctx.beginPath();
        ctx.moveTo(pts[0][0], pts[0][1]);
        for (let k = 1; k < pts.length; k++) ctx.lineTo(pts[k][0], pts[k][1]);
        ctx.setLineDash([]);
        ctx.strokeStyle = 'rgba(150,160,210,0.11)'; ctx.lineWidth = 1; ctx.stroke();
        ctx.save();
        ctx.setLineDash([5, 12]); ctx.lineDashOffset = -(now * 0.035);
        ctx.strokeStyle = 'rgba(178,188,232,0.22)'; ctx.lineWidth = 1; ctx.stroke();
        ctx.restore();
      }
      ctx.setLineDash([]);
    };

    const draw = (now) => {
      t0 = now;
      ctx.clearRect(0, 0, W, H);
      drawDivider();
      drawGate();
      drawVortexArcs(now);
      drawAbsorb(now);
      drawVortexCore();

      drawOrbitRing();
      drawStack(now);
      ctx.globalCompositeOperation = 'lighter';
      for (const o of orbit) {
        o.t += o.s;
        const x = g.sx + Math.cos(o.t) * g.rx, y = g.smid + Math.sin(o.t) * g.ry;
        ctx.strokeStyle = 'rgba(110,200,255,0.22)'; ctx.lineWidth = 1.4;
        ctx.beginPath(); ctx.moveTo(o.px || x, o.py || y); ctx.lineTo(x, y); ctx.stroke();
        ctx.beginPath(); ctx.arc(x, y, 1.9, 0, TAU);
        ctx.fillStyle = 'rgba(185,228,255,0.75)'; ctx.fill();
        o.px = x; o.py = y;
      }
      ctx.globalCompositeOperation = 'source-over';

      drawStreamLabels();
      raf = requestAnimationFrame(draw);
    };

    const drawStatic = () => {
      ctx.clearRect(0, 0, W, H);
      drawDivider(); drawGate(); drawVortexArcs(0); drawAbsorb(0);
      drawVortexCore(); drawOrbitRing(); drawStack(0);
      ctx.globalCompositeOperation = 'lighter';
      for (const o of orbit) {
        const x = g.sx + Math.cos(o.t) * g.rx, y = g.smid + Math.sin(o.t) * g.ry;
        ctx.beginPath(); ctx.arc(x, y, 1.9, 0, TAU);
        ctx.fillStyle = 'rgba(185,228,255,0.7)'; ctx.fill();
      }
      ctx.globalCompositeOperation = 'source-over';
      drawStreamLabels();
    };

    const resize = () => {
      const rect = wrap.getBoundingClientRect();
      W = rect.width; H = rect.height;
      DPR = Math.min(window.devicePixelRatio || 1, 2);
      canvas.width = Math.round(W * DPR); canvas.height = Math.round(H * DPR);
      canvas.style.width = W + 'px'; canvas.style.height = H + 'px';
      ctx.setTransform(DPR, 0, 0, DPR, 0, 0);
      layout();
      if (reduced) drawStatic();
    };

    const ro = new ResizeObserver(resize);
    ro.observe(wrap);
    resize();
    if (!reduced) raf = requestAnimationFrame(draw);
    return () => { cancelAnimationFrame(raf); ro.disconnect(); };
  }, []);

  return (
    <div className="archviz" ref={wrapRef}>
      <canvas ref={canvasRef} className="archviz-canvas" aria-hidden="true" />
      <div className="archviz-label archviz-label--l">AI App Today<span>intelligence lost</span></div>
      <div className="archviz-label archviz-label--r">Model OS<span>owned intelligence</span></div>
    </div>
  );
};

window.ArchViz = ArchViz;
