/* global React */
const { useEffect, useRef } = React;

/* Isometric "compounding infrastructure" diagram.
   Three stacked layers on an iso grid: Baseline (wide) → Build (mid) → Outcome (a single ember cube on top).
   Gentle rotation hinting. Vectory palette only. */

function IsometricInfra({ speed = 1, density = 1 }) {
  const ref = useRef(null);
  useEffect(() => {
    const canvas = ref.current;
    if (!canvas) return;
    const ctx = canvas.getContext('2d');
    const dpr = Math.min(window.devicePixelRatio || 1, 2);
    let W=0, H=0;
    const resize = () => {
      const parent = canvas.parentElement;
      const r = parent.getBoundingClientRect();
      W = Math.max(1, r.width); H = Math.max(1, r.height);
      canvas.style.width = W + 'px';
      canvas.style.height = H + 'px';
      canvas.width = Math.floor(W*dpr); canvas.height = Math.floor(H*dpr);
      ctx.setTransform(dpr,0,0,dpr,0,0);
    };
    resize();
    const ro = new ResizeObserver(resize); if (canvas.parentElement) ro.observe(canvas.parentElement);

    const ink = '#0E1014';
    const paper = '#FAFAF7';
    const line = '#B8BCC6';
    const lineSoft = '#DCDEE4';
    const signal = '#D9541A';

    const iso = (x, y, z) => ({
      x: (x - y) * Math.cos(Math.PI/6),
      y: (x + y) * Math.sin(Math.PI/6) - z,
    });

    let raf=0, t0=performance.now();

    const drawFace = (pts, fill, stroke, lw=1) => {
      ctx.beginPath();
      pts.forEach((p, i) => i===0 ? ctx.moveTo(p.x, p.y) : ctx.lineTo(p.x, p.y));
      ctx.closePath();
      if (fill) { ctx.fillStyle = fill; ctx.fill(); }
      if (stroke) { ctx.strokeStyle = stroke; ctx.lineWidth = lw; ctx.stroke(); }
    };

    const cube = (cx, cy, sx, sy, sz, opts) => {
      const o = opts || {};
      const top    = [iso(0,0,sz), iso(sx,0,sz), iso(sx,sy,sz), iso(0,sy,sz)];
      const front  = [iso(0,sy,0), iso(sx,sy,0), iso(sx,sy,sz), iso(0,sy,sz)];
      const right  = [iso(sx,0,0), iso(sx,sy,0), iso(sx,sy,sz), iso(sx,0,sz)];
      const shift = pts => pts.map(p => ({x: p.x + cx, y: p.y + cy}));
      drawFace(shift(front), o.front || paper, o.stroke || ink, o.lw || 1);
      drawFace(shift(right), o.right || '#F0EFE8', o.stroke || ink, o.lw || 1);
      drawFace(shift(top),   o.top   || '#FFFFFF', o.stroke || ink, o.lw || 1);
    };

    const draw = (now) => {
      const t = ((now - t0)/1000) * speed;
      ctx.clearRect(0,0,W,H);

      const originX = W*0.5;
      const originY = H*0.82;
      const U = Math.min(W, H) * 0.045; // iso unit

      // Iso grid floor
      ctx.strokeStyle = lineSoft;
      ctx.lineWidth = 1;
      ctx.globalAlpha = 0.7;
      const GRID = 10;
      for (let i = -GRID; i <= GRID; i++) {
        const a = iso(i, -GRID, 0), b = iso(i, GRID, 0);
        ctx.beginPath(); ctx.moveTo(originX + a.x*U, originY + a.y*U); ctx.lineTo(originX + b.x*U, originY + b.y*U); ctx.stroke();
        const c = iso(-GRID, i, 0), d = iso(GRID, i, 0);
        ctx.beginPath(); ctx.moveTo(originX + c.x*U, originY + c.y*U); ctx.lineTo(originX + d.x*U, originY + d.y*U); ctx.stroke();
      }
      ctx.globalAlpha = 1;

      // Phase labels positions
      const lvlY = t * 0.2; // subtle bob

      // ---- Layer 1: Baseline — 4x4 slab of small cubes
      const L1z = 0 + Math.sin(lvlY)*0.1;
      for (let x=-2; x<2; x++) {
        for (let y=-2; y<2; y++) {
          const p = iso(x, y, L1z);
          cube(originX + p.x*U, originY + p.y*U, U, U, U*0.6, { front: '#F5F5F2', right: '#ECEDF1', top: '#FFFFFF', stroke: ink, lw: 1 });
        }
      }

      // ---- Layer 2: Build — 2x2 slab offset
      const L2base = 0.6;
      const L2z = L2base + Math.sin(lvlY + 1)*0.1;
      for (let x=-1; x<1; x++) {
        for (let y=-1; y<1; y++) {
          const p = iso(x, y, L2z);
          cube(originX + p.x*U, originY + p.y*U, U, U, U*0.7, { front: '#DCDEE4', right: '#B8BCC6', top: '#ECEDF1', stroke: ink, lw: 1 });
        }
      }

      // ---- Layer 3: Outcome — single ember cube, floating slightly
      const L3base = 1.3;
      const L3z = L3base + Math.sin(lvlY + 2)*0.15 + 0.2;
      const p3 = iso(-0.5, -0.5, L3z);
      cube(originX + p3.x*U, originY + p3.y*U, U, U, U*0.9, {
        front: signal, right: '#B0400F', top: '#E87240', stroke: ink, lw: 1.2
      });

      // Arrow rising from top — ember
      const arrowBase = iso(0, 0, L3z + 0.9);
      const arrowTip  = iso(0, 0, L3z + 1.6 + Math.sin(t*1.5)*0.05);
      ctx.strokeStyle = signal;
      ctx.lineWidth = 2;
      ctx.beginPath();
      ctx.moveTo(originX + arrowBase.x*U, originY + arrowBase.y*U);
      ctx.lineTo(originX + arrowTip.x*U, originY + arrowTip.y*U);
      ctx.stroke();
      // arrowhead
      const tipX = originX + arrowTip.x*U, tipY = originY + arrowTip.y*U;
      ctx.beginPath();
      ctx.moveTo(tipX - 4, tipY + 8);
      ctx.lineTo(tipX, tipY);
      ctx.lineTo(tipX + 4, tipY + 8);
      ctx.stroke();

      // Connection lines between stacked centers — dashed hairline
      ctx.setLineDash([3, 4]);
      ctx.strokeStyle = line;
      ctx.lineWidth = 1;
      ctx.globalAlpha = 0.6;
      const c1 = iso(0, 0, L1z + 0.6);
      const c2 = iso(0, 0, L2z + 0.7);
      const c3 = iso(0, 0, L3z);
      ctx.beginPath();
      ctx.moveTo(originX + c1.x*U, originY + c1.y*U);
      ctx.lineTo(originX + c2.x*U, originY + c2.y*U);
      ctx.lineTo(originX + c3.x*U, originY + c3.y*U);
      ctx.stroke();
      ctx.setLineDash([]);
      ctx.globalAlpha = 1;

      // Corner markers (ember squares) — like the reference
      const mk = (gx, gy, gz) => {
        const p = iso(gx, gy, gz);
        ctx.fillStyle = signal;
        ctx.fillRect(originX + p.x*U - 4, originY + p.y*U - 4, 8, 8);
      };
      mk(-3.2, -3.2, 0);
      mk(3.2, 3.2, 0);
      mk(3.2, -3.2, 0);
      mk(-3.2, 3.2, 0);

      // Phase labels — mono text
      ctx.fillStyle = '#5A6070';
      ctx.font = '500 10px "JetBrains Mono", monospace';
      const label = (gx, gy, gz, text) => {
        const p = iso(gx, gy, gz);
        ctx.fillText(text, originX + p.x*U + 8, originY + p.y*U + 4);
      };
      label(2.2, -2.2, L1z + 0.6, '01 · BASELINE');
      label(1.2, -1.2, L2z + 0.7, '03 · BUILD');
      label(0.6, -0.6, L3z + 0.9, '05 · OUTCOME');

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

    return () => { cancelAnimationFrame(raf); ro.disconnect(); };
  }, [speed, density]);

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

window.IsometricInfra = IsometricInfra;
