/* global React */
/* ============================================================
   Sterrenstof — feeërieke "toverstaf"-zwaai bij het laden van de
   homepage (thema: Sprookjes en verhalen). Decoratief en eenmalig:
   pointer-events:none, ruimt zichzelf op, en doet niets als de
   bezoeker bewegingsreductie heeft ingesteld.
   ============================================================ */
function Stardust() {
  const canvasRef = React.useRef(null);
  const [done, setDone] = React.useState(false);

  React.useEffect(() => {
    if (window.matchMedia && window.matchMedia("(prefers-reduced-motion: reduce)").matches) { setDone(true); return; }
    const canvas = canvasRef.current;
    if (!canvas) return;
    const ctx = canvas.getContext("2d");
    const dpr = Math.min(window.devicePixelRatio || 1, 2);
    let W = 0, H = 0;
    const resize = () => {
      W = window.innerWidth; H = window.innerHeight;
      canvas.width = W * dpr; canvas.height = H * dpr;
      canvas.style.width = W + "px"; canvas.style.height = H + "px";
      ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
    };
    resize();
    window.addEventListener("resize", resize);

    const COLORS = ["#D4A24A", "#E8C57A", "#F3DFA8", "#FFF7E6", "#7FBBA9"]; // goud/amber/warmwit + zacht teal
    const BRIGHT = ["#FFF7E6", "#F3DFA8", "#E8C57A"];                       // lichtere tinten voor de zwaai
    const rnd = (a, b) => a + Math.random() * (b - a);
    const particles = [];
    const MAX = 190;

    function spawn(x, y, opts) {
      if (particles.length >= MAX) return;
      opts = opts || {};
      const pal = opts.bright ? BRIGHT : COLORS;
      particles.push({
        x, y,
        vx: rnd(-0.5, 0.5) + (opts.vx || 0),
        vy: rnd(0.1, 0.8) + (opts.vy || 0),
        size: rnd(1.4, 3.4) * (opts.size || 1),
        color: pal[(Math.random() * pal.length) | 0],
        rot: rnd(0, Math.PI),
        vrot: rnd(-0.05, 0.05),
        life: 0,
        ttl: rnd(150, 300),         // langer leven -> langer fonkelen
        twk: rnd(0.07, 0.18),       // twinkel-snelheid
        twp: rnd(0, Math.PI * 2),
      });
    }

    // verspreide sterrenstof over de hele pagina ("net neergedaald")
    for (let i = 0; i < 38; i++) spawn(rnd(0, W), rnd(0, H * 0.9), { vy: rnd(-0.2, 0.35), size: rnd(0.8, 1.2) });

    function star(px, py, r, rot, alpha, color) {
      ctx.save();
      ctx.translate(px, py);
      ctx.rotate(rot);
      ctx.globalAlpha = alpha;
      ctx.shadowColor = color;
      ctx.shadowBlur = r * 2.4;
      ctx.fillStyle = color;
      ctx.beginPath();
      for (let i = 0; i < 4; i++) {                 // 4-puntige fonkel ✦
        const a = (Math.PI / 2) * i;
        ctx.lineTo(Math.cos(a) * r, Math.sin(a) * r);
        ctx.lineTo(Math.cos(a + Math.PI / 4) * r * 0.34, Math.sin(a + Math.PI / 4) * r * 0.34);
      }
      ctx.closePath();
      ctx.fill();
      ctx.restore();
    }

    const SWEEP = 46;        // frames (~0,8s): de zwaai
    const TRAIL_FADE = 24;   // frames waarin de sliert daarna uitdooft
    const trail = [];
    let frame = 0, raf;

    function tick() {
      ctx.clearRect(0, 0, W, H);

      // staf-positie, gloeiende sliert en heldere punt (tijdens + kort na de zwaai)
      if (frame < SWEEP + TRAIL_FADE) {
        const t = Math.min(1, frame / SWEEP);
        const sx = W * (0.07 + 0.86 * t);
        const sy = H * (0.17 + 0.13 * Math.sin(t * Math.PI));
        const tipFade = frame < SWEEP ? 1 : 1 - (frame - SWEEP) / TRAIL_FADE;

        if (frame < SWEEP) {
          trail.push({ x: sx, y: sy });
          if (trail.length > 18) trail.shift();
          for (let i = 0; i < 4; i++) spawn(sx + rnd(-15, 15), sy + rnd(-15, 15), { vx: rnd(-0.7, 0.7), vy: rnd(-0.15, 0.7), size: rnd(1.1, 1.8), bright: true });
        }

        // gloeiende sliert achter de staf
        ctx.save();
        ctx.lineCap = "round";
        ctx.shadowColor = "#FFE6A0";
        ctx.shadowBlur = 22;
        ctx.strokeStyle = "#FBE6A6";
        for (let i = 1; i < trail.length; i++) {
          const a = i / trail.length;               // recenter = helderder/breder
          ctx.globalAlpha = 0.42 * a * tipFade;
          ctx.lineWidth = 7 * a;
          ctx.beginPath();
          ctx.moveTo(trail[i - 1].x, trail[i - 1].y);
          ctx.lineTo(trail[i].x, trail[i].y);
          ctx.stroke();
        }
        ctx.restore();

        // heldere staf-punt: kern + zachte halo
        if (frame < SWEEP) {
          ctx.save();
          ctx.shadowColor = "#FFF1C9"; ctx.shadowBlur = 48;
          ctx.fillStyle = "#FFFBEF";
          ctx.globalAlpha = 0.97;
          ctx.beginPath(); ctx.arc(sx, sy, 6, 0, Math.PI * 2); ctx.fill();
          ctx.globalAlpha = 0.5;
          ctx.beginPath(); ctx.arc(sx, sy, 13, 0, Math.PI * 2); ctx.fill();
          ctx.restore();
        }
      }

      for (let i = particles.length - 1; i >= 0; i--) {
        const p = particles[i];
        p.life++;
        if (p.life >= p.ttl) { particles.splice(i, 1); continue; }
        p.x += p.vx; p.y += p.vy; p.vy += 0.0032; p.vx *= 0.993; p.rot += p.vrot;
        const lr = p.life / p.ttl;
        const fade = lr < 0.12 ? lr / 0.12 : 1 - (lr - 0.12) / 0.88;
        const twinkle = 0.5 + 0.5 * Math.sin(p.life * p.twk + p.twp);
        star(p.x, p.y, p.size, p.rot, Math.max(0, fade) * twinkle, p.color);
      }

      frame++;
      if (particles.length > 0 || frame < SWEEP) raf = requestAnimationFrame(tick);
      else setDone(true);
    }
    raf = requestAnimationFrame(tick);

    return () => { cancelAnimationFrame(raf); window.removeEventListener("resize", resize); };
  }, []);

  if (done) return null;
  return (
    <canvas ref={canvasRef} aria-hidden="true"
      style={{ position: "fixed", inset: 0, width: "100%", height: "100%", pointerEvents: "none", zIndex: 9999 }} />
  );
}

Object.assign(window, { Stardust });
