/* RainCanvas — canvas-based rain with subtle ground splashes.
 *
 * Sits between the backdrop image and the vignette overlay.
 * Respects prefers-reduced-motion (renders nothing).
 *
 * Props:
 *   density   — drops per 1000px of viewport width (default 60)
 *   angle     — degrees from vertical, positive = wind to the right (default 14)
 *   speed     — multiplier on fall speed (default 1)
 *   color     — drop color (default soft blue-white)
 */
function RainCanvas({
  density = 60,
  angle = 14,
  speed = 1,
  color = "rgba(200, 215, 235, 0.55)",
} = {}) {
  const canvasRef = React.useRef(null);
  const rafRef = React.useRef(0);
  const stateRef = React.useRef({ drops: [], splashes: [], w: 0, h: 0, dpr: 1 });

  React.useEffect(() => {
    const reduced =
      typeof window !== "undefined" &&
      window.matchMedia &&
      window.matchMedia("(prefers-reduced-motion: reduce)").matches;
    if (reduced) return;

    const canvas = canvasRef.current;
    if (!canvas) return;
    const ctx = canvas.getContext("2d");
    const s = stateRef.current;

    const rad = (angle * Math.PI) / 180;
    const sin = Math.sin(rad);
    const cos = Math.cos(rad);

    function resize() {
      const dpr = Math.min(window.devicePixelRatio || 1, 2);
      const w = canvas.clientWidth;
      const h = canvas.clientHeight;
      canvas.width = Math.floor(w * dpr);
      canvas.height = Math.floor(h * dpr);
      ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
      s.w = w;
      s.h = h;
      s.dpr = dpr;
      seed();
    }

    function seed() {
      const count = Math.max(40, Math.floor((s.w / 1000) * density * 4));
      s.drops = new Array(count).fill(0).map(() => makeDrop(true));
    }

    function makeDrop(initial) {
      // length & speed correlate so far drops look slower/thinner
      const z = Math.random(); // depth 0..1
      const length = 10 + z * 22; // 10–32px
      const baseSpeed = 7 + z * 11; // 7–18 px/frame at 60fps
      return {
        x: Math.random() * (s.w + Math.abs(sin) * s.h) - Math.abs(sin) * s.h * 0.5,
        y: initial ? Math.random() * s.h : -20 - Math.random() * 40,
        len: length,
        vy: baseSpeed * speed,
        alpha: 0.25 + z * 0.55,
        z,
      };
    }

    function spawnSplash(x, y) {
      s.splashes.push({
        x,
        y,
        r: 0,
        maxR: 3 + Math.random() * 3,
        life: 0,
        ttl: 22 + Math.random() * 10,
      });
    }

    let last = performance.now();
    function tick(now) {
      const dt = Math.min(2, (now - last) / 16.67); // normalize to ~60fps frames
      last = now;

      ctx.clearRect(0, 0, s.w, s.h);

      // --- drops ---
      ctx.lineCap = "round";
      for (let i = 0; i < s.drops.length; i++) {
        const d = s.drops[i];
        const vx = d.vy * sin * 0.8;
        const vy = d.vy * cos;
        d.x += vx * dt;
        d.y += vy * dt;

        // tail endpoints
        const x2 = d.x - sin * d.len;
        const y2 = d.y - cos * d.len;

        ctx.strokeStyle = color.replace(
          /rgba\(([^)]+),\s*[\d.]+\)/,
          `rgba($1, ${d.alpha.toFixed(3)})`
        );
        ctx.lineWidth = 0.6 + d.z * 0.9;
        ctx.beginPath();
        ctx.moveTo(d.x, d.y);
        ctx.lineTo(x2, y2);
        ctx.stroke();

        if (d.y > s.h) {
          // splash on "ground" — only some of the time, biased toward closer drops
          if (Math.random() < 0.35 + d.z * 0.4) {
            spawnSplash(d.x, s.h - 1);
          }
          Object.assign(d, makeDrop(false));
        } else if (d.x > s.w + 40 || d.x < -40) {
          Object.assign(d, makeDrop(false));
        }
      }

      // --- splashes ---
      for (let i = s.splashes.length - 1; i >= 0; i--) {
        const sp = s.splashes[i];
        sp.life += dt;
        sp.r = (sp.life / sp.ttl) * sp.maxR;
        const a = Math.max(0, 1 - sp.life / sp.ttl) * 0.5;
        ctx.strokeStyle = `rgba(210, 220, 235, ${a.toFixed(3)})`;
        ctx.lineWidth = 1;
        // half-ellipse to suggest puddle ring
        ctx.beginPath();
        ctx.ellipse(sp.x, sp.y, sp.r, sp.r * 0.35, 0, Math.PI, 2 * Math.PI);
        ctx.stroke();
        if (sp.life >= sp.ttl) s.splashes.splice(i, 1);
      }

      rafRef.current = requestAnimationFrame(tick);
    }

    resize();
    rafRef.current = requestAnimationFrame(tick);
    window.addEventListener("resize", resize);

    return () => {
      cancelAnimationFrame(rafRef.current);
      window.removeEventListener("resize", resize);
    };
  }, [density, angle, speed, color]);

  return (
    <canvas
      ref={canvasRef}
      aria-hidden="true"
      style={{
        position: "absolute",
        inset: 0,
        width: "100%",
        height: "100%",
        pointerEvents: "none",
        mixBlendMode: "screen",
      }}
    />
  );
}

window.RainCanvas = RainCanvas;
