/* global React */
// Animated hero background — used as a fallback before the user supplies a video.
// Renders a flowing field of particles + soft accent-tinted blobs that loops
// indefinitely. Designed to be replaced by a <video> element.

window.HeroCanvas = function HeroCanvas({ paused = false }) {
  const ref = React.useRef(null);
  const rafRef = React.useRef(0);

  React.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;
    function resize() {
      const rect = canvas.getBoundingClientRect();
      w = rect.width; h = rect.height;
      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);
    ro.observe(canvas);

    // Read accent color from CSS at runtime so canvas adapts to palette swap
    function readAccent() {
      const cs = getComputedStyle(document.documentElement);
      return {
        accent: cs.getPropertyValue("--accent").trim() || "#c97a4a",
        bg: cs.getPropertyValue("--bg").trim() || "#0e0c0a",
        bgElev: cs.getPropertyValue("--bg-elev").trim() || "#16120e",
      };
    }

    // Particles — soft floating dots
    const N = 120;
    const parts = Array.from({ length: N }, () => ({
      x: Math.random(), y: Math.random(),
      vx: (Math.random() - 0.5) * 0.00015,
      vy: (Math.random() - 0.5) * 0.00015 - 0.00010,
      r: 0.5 + Math.random() * 1.6,
      a: 0.1 + Math.random() * 0.5,
    }));

    // Slow-moving blob centers
    const blobs = [
      { x: 0.2, y: 0.7, r: 0.45, t: 0 },
      { x: 0.75, y: 0.35, r: 0.55, t: 1.6 },
      { x: 0.55, y: 0.85, r: 0.40, t: 3.2 },
    ];

    let t0 = performance.now();
    let last = t0;

    function frame(now) {
      const dt = Math.min(now - last, 50);
      last = now;
      const elapsed = (now - t0) / 1000;
      const colors = readAccent();

      // Bg gradient
      const grd = ctx.createLinearGradient(0, 0, 0, h);
      grd.addColorStop(0, colors.bg);
      grd.addColorStop(1, colors.bgElev);
      ctx.fillStyle = grd;
      ctx.fillRect(0, 0, w, h);

      // Blobs (drawn as soft radial gradients)
      ctx.globalCompositeOperation = "lighter";
      blobs.forEach((b, i) => {
        const cx = (b.x + Math.sin(elapsed * 0.07 + b.t) * 0.12) * w;
        const cy = (b.y + Math.cos(elapsed * 0.09 + b.t * 0.7) * 0.10) * h;
        const rr = b.r * Math.max(w, h);
        const g = ctx.createRadialGradient(cx, cy, 0, cx, cy, rr);
        g.addColorStop(0, hexToRgba(colors.accent, 0.18));
        g.addColorStop(0.5, hexToRgba(colors.accent, 0.05));
        g.addColorStop(1, hexToRgba(colors.accent, 0));
        ctx.fillStyle = g;
        ctx.fillRect(0, 0, w, h);
      });
      ctx.globalCompositeOperation = "source-over";

      // Subtle horizontal scan band
      const band = ((elapsed * 18) % (h + 200)) - 100;
      const bandG = ctx.createLinearGradient(0, band - 80, 0, band + 80);
      bandG.addColorStop(0, hexToRgba(colors.accent, 0));
      bandG.addColorStop(0.5, hexToRgba(colors.accent, 0.025));
      bandG.addColorStop(1, hexToRgba(colors.accent, 0));
      ctx.fillStyle = bandG;
      ctx.fillRect(0, band - 80, w, 160);

      // Particles
      ctx.fillStyle = hexToRgba(colors.accent, 1);
      for (const p of parts) {
        p.x += p.vx * dt;
        p.y += p.vy * dt;
        if (p.x < -0.05) p.x = 1.05;
        if (p.x > 1.05) p.x = -0.05;
        if (p.y < -0.05) p.y = 1.05;
        if (p.y > 1.05) p.y = -0.05;
        ctx.globalAlpha = p.a;
        ctx.beginPath();
        ctx.arc(p.x * w, p.y * h, p.r, 0, Math.PI * 2);
        ctx.fill();
      }
      ctx.globalAlpha = 1;

      if (!paused) rafRef.current = requestAnimationFrame(frame);
    }

    rafRef.current = requestAnimationFrame(frame);
    return () => {
      cancelAnimationFrame(rafRef.current);
      ro.disconnect();
    };
  }, [paused]);

  return React.createElement("canvas", {
    ref,
    style: { width: "100%", height: "100%", display: "block" },
  });
};

// Helper — accept #rgb / #rrggbb / oklch / rgb() and return rgba string
function hexToRgba(input, a) {
  if (!input) return `rgba(201,122,74,${a})`;
  input = input.trim();
  if (input.startsWith("#")) {
    let hex = input.slice(1);
    if (hex.length === 3) hex = hex.split("").map(c => c + c).join("");
    const r = parseInt(hex.slice(0, 2), 16);
    const g = parseInt(hex.slice(2, 4), 16);
    const b = parseInt(hex.slice(4, 6), 16);
    return `rgba(${r},${g},${b},${a})`;
  }
  // For oklch() / rgb() / hsl(), wrap with color-mix fallback via canvas
  // Easiest: paint to a temp canvas to resolve.
  try {
    const tmp = document.createElement("canvas");
    tmp.width = tmp.height = 1;
    const tctx = tmp.getContext("2d");
    tctx.fillStyle = input;
    tctx.fillRect(0, 0, 1, 1);
    const [r, g, b] = tctx.getImageData(0, 0, 1, 1).data;
    return `rgba(${r},${g},${b},${a})`;
  } catch {
    return `rgba(201,122,74,${a})`;
  }
}
