// HeroBackground — animated, movement-y background washes for the hero.
//
// Effects (chosen via `effect` prop):
//   "off"     — nothing rendered
//   "mesh"    — Stripe-style multi-blob mesh gradient, recolored to our palette,
//               painted on a low-FPS canvas with heavy blur
//   "aurora"  — pure-CSS aurora: giant blurred radial blobs translating on
//               long ease-in-out keyframes
//   "cord"    — a vertical "umbilical cord": soft gradient band of color, with
//               small saffron / terracotta / kelp pulses streaming down through
//               it like payment data flowing
//
// `inverse` flips the palette for the cacao-on-cacao hero.
//
// Always pointer-events:none, position:absolute, fills its parent — drop it
// inside a `position: relative` hero section as the first child.

function HeroBackground({ effect = "off", inverse = false }) {
  if (effect === "off") return null;
  const Comp =
    effect === "mesh"   ? MeshBg :
    effect === "aurora" ? AuroraBg :
    effect === "cord"   ? CordBg :
    null;
  if (!Comp) return null;
  return (
    <div
      aria-hidden="true"
      style={{
        position: "absolute",
        inset: 0,
        width: "100%",
        height: "100%",
        minHeight: "100%",
        overflow: "hidden",
        pointerEvents: "none",
        zIndex: 0,
      }}
    >
      <Comp inverse={inverse} />
    </div>
  );
}

// ── MESH (Stripe-style) ─────────────────────────────────────────
function MeshBg({ inverse }) {
  const ref = React.useRef(null);

  React.useEffect(() => {
    const canvas = ref.current;
    if (!canvas) return;
    const ctx = canvas.getContext("2d");
    let raf = 0;
    let running = true;

    const palette = inverse
      ? [
          { c: "#D89B2C", a: 0.42 },
          { c: "#B0392E", a: 0.34 },
          { c: "#6E8A7E", a: 0.30 },
          { c: "#341800", a: 0.0  },
        ]
      : [
          { c: "#D89B2C", a: 0.32 },
          { c: "#F2C772", a: 0.28 },
          { c: "#B0392E", a: 0.18 },
          { c: "#6E8A7E", a: 0.18 },
        ];

    const resize = () => {
      const dpr = Math.min(window.devicePixelRatio || 1, 2);
      const w = canvas.clientWidth;
      const h = canvas.clientHeight;
      canvas.width = Math.max(1, Math.floor(w * dpr));
      canvas.height = Math.max(1, Math.floor(h * dpr));
      ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
    };
    resize();
    const ro = new ResizeObserver(resize);
    ro.observe(canvas);

    const start = performance.now();
    const draw = () => {
      if (!running) return;
      const w = canvas.clientWidth;
      const h = canvas.clientHeight;
      const t = (performance.now() - start) / 1000;
      ctx.clearRect(0, 0, w, h);

      palette.forEach((p, i) => {
        if (p.a === 0) return;
        const phase = i * 1.7;
        const px = w * (0.5 + 0.42 * Math.sin(t * 0.13 + phase));
        const py = h * (0.5 + 0.55 * Math.cos(t * 0.11 + phase * 1.3));
        const r  = Math.max(w, h) * (0.55 + 0.12 * Math.sin(t * 0.07 + phase));
        const grd = ctx.createRadialGradient(px, py, 0, px, py, r);
        grd.addColorStop(0, hexA(p.c, p.a));
        grd.addColorStop(1, hexA(p.c, 0));
        ctx.fillStyle = grd;
        ctx.fillRect(0, 0, w, h);
      });

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

    return () => {
      running = false;
      cancelAnimationFrame(raf);
      ro.disconnect();
    };
  }, [inverse]);

  return (
    <canvas
      ref={ref}
      style={{
        position: "absolute",
        inset: 0,
        width: "100%",
        height: "100%",
        filter: "blur(48px) saturate(1.05)",
        opacity: inverse ? 0.95 : 0.7,
      }}
    />
  );
}

// hex + alpha → rgba string
function hexA(hex, a) {
  const n = hex.replace("#", "");
  const r = parseInt(n.slice(0, 2), 16);
  const g = parseInt(n.slice(2, 4), 16);
  const b = parseInt(n.slice(4, 6), 16);
  return `rgba(${r},${g},${b},${a})`;
}

// ── AURORA (pure CSS) ────────────────────────────────────────────
function AuroraBg({ inverse }) {
  // Extra low / large blobs so tall viewports (mobile) never show a flat band of base
  // canvas below the glow — reads as one continuous field, not a "hero card".
  const blobs = inverse
    ? [
        { c: "rgba(216,155,44,0.55)",  size: 1100, x: -10, y: -20, anim: "amosAurora1 22s ease-in-out infinite" },
        { c: "rgba(176,57,46,0.40)",   size: 1300, x: 110, y: 30,  anim: "amosAurora2 28s ease-in-out infinite" },
        { c: "rgba(110,138,126,0.35)", size: 1000, x: 45,  y: 110, anim: "amosAurora3 32s ease-in-out infinite" },
        { c: "rgba(216,155,44,0.22)",  size: 1800, x: 70,  y: 88,  anim: "amosAurora2 28s ease-in-out infinite reverse" },
        { c: "rgba(239,227,209,0.08)", size: 2200, x: 20,  y: 118, anim: "amosAurora1 26s ease-in-out infinite" },
      ]
    : [
        { c: "rgba(216,155,44,0.45)",  size: 1100, x: -10, y: -10, anim: "amosAurora1 22s ease-in-out infinite" },
        { c: "rgba(242,199,114,0.55)", size: 1200, x: 90,  y: 20,  anim: "amosAurora2 26s ease-in-out infinite" },
        { c: "rgba(176,57,46,0.22)",   size: 900,  y: 90,  x: 30,  anim: "amosAurora3 30s ease-in-out infinite" },
        { c: "rgba(216,155,44,0.20)",  size: 1700, x: 55,  y: 92,  anim: "amosAurora3 34s ease-in-out infinite reverse" },
        { c: "rgba(110,138,126,0.12)", size: 2000, x: -15, y: 108, anim: "amosAurora1 30s ease-in-out infinite" },
      ];
  return (
    <React.Fragment>
      <style>{`
        @keyframes amosAurora1 {
          0%,100% { transform: translate3d(-12%, -8%, 0) scale(1); }
          50%     { transform: translate3d(8%,   6%,  0) scale(1.08); }
        }
        @keyframes amosAurora2 {
          0%,100% { transform: translate3d(8%,  4%, 0) scale(1.05); }
          50%     { transform: translate3d(-6%, -8%, 0) scale(1); }
        }
        @keyframes amosAurora3 {
          0%,100% { transform: translate3d(-4%, 6%, 0) scale(1); }
          50%     { transform: translate3d(6%, -4%, 0) scale(1.1); }
        }
      `}</style>
      {blobs.map((b, i) => (
        <div
          key={i}
          style={{
            position: "absolute",
            top: `${b.y}%`,
            left: `${b.x}%`,
            width: b.size,
            height: b.size,
            borderRadius: "50%",
            background: `radial-gradient(circle at center, ${b.c} 0%, transparent 60%)`,
            filter: "blur(32px)",
            animation: b.anim,
            mixBlendMode: inverse ? "screen" : "multiply",
          }}
        />
      ))}
    </React.Fragment>
  );
}

// ── CORD — umbilical with streaming payment pulses ───────────────
// A soft vertical band (the "cord") sits center-screen, ever so slightly
// undulating (drawn on canvas as a sinusoidal ribbon). Inside, small colored
// pulses stream downward at varying speeds — they're like packets of payment
// data flowing through the stack.
//
// Muted by default: the cord itself is barely there, the pulses give it life.
function CordBg({ inverse }) {
  const ref = React.useRef(null);

  React.useEffect(() => {
    const canvas = ref.current;
    if (!canvas) return;
    const ctx = canvas.getContext("2d");
    let raf = 0;
    let running = true;
    let pulses = [];

    // Pulse colors — three brand accents, muted alpha
    const pulseColors = inverse
      ? ["#D89B2C", "#F2C772", "#B0392E", "#6E8A7E"]
      : ["#D89B2C", "#B0392E", "#6E8A7E", "#B5811F"];

    // Cord band gradient stops (rendered every frame as the cord pulses)
    const cordEdge = inverse ? "rgba(216,155,44,0.0)" : "rgba(52,24,0,0.0)";
    const cordCore = inverse ? "rgba(216,155,44,0.18)" : "rgba(52,24,0,0.10)";
    const cordHalo = inverse ? "rgba(239,227,209,0.06)" : "rgba(176,57,46,0.05)";

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

    const spawn = (h, anywhere) => {
      const speed = 0.6 + Math.random() * 1.8; // px/frame at 60fps
      return {
        // Position along cord — relative offset from cord centerline (-1..1)
        u: (Math.random() - 0.5) * 0.7,   // not too far from center
        y: anywhere ? Math.random() * h : -20 - Math.random() * 200,
        r: 1.6 + Math.random() * 2.2,     // pulse radius
        a: 0.5 + Math.random() * 0.4,
        c: pulseColors[Math.floor(Math.random() * pulseColors.length)],
        v: speed,
        // Phase offsets for cord undulation (each pulse rides a slightly
        // different phase so they don't move in lockstep)
        ph: Math.random() * Math.PI * 2,
        wob: Math.random() * 0.6 + 0.4,
      };
    };

    const seedPulses = () => {
      const h = canvas.clientHeight;
      const target = Math.max(28, Math.floor(h / 18));
      pulses = Array.from({ length: target }, () => spawn(h, true));
    };

    resize();
    const ro = new ResizeObserver(resize);
    ro.observe(canvas);

    const start = performance.now();
    const draw = () => {
      if (!running) return;
      const w = canvas.clientWidth;
      const h = canvas.clientHeight;
      const t = (performance.now() - start) / 1000;
      ctx.clearRect(0, 0, w, h);

      // Cord centerline x — gently undulates left/right
      const cx = (y) => w / 2 + Math.sin(t * 0.4 + y * 0.004) * (w * 0.02);

      // Draw the cord as a soft vertical band (multi-pass for halo + core)
      // Outer halo
      drawBand(ctx, w, h, cx, /*halfWidth*/ 130, [
        [0, "rgba(0,0,0,0)"],
        [0.25, cordHalo],
        [0.75, cordHalo],
        [1, "rgba(0,0,0,0)"],
      ]);
      // Inner core (slightly tinted)
      drawBand(ctx, w, h, cx, /*halfWidth*/ 56, [
        [0, "rgba(0,0,0,0)"],
        [0.2, cordEdge],
        [0.5, cordCore],
        [0.8, cordEdge],
        [1, "rgba(0,0,0,0)"],
      ]);

      // Draw pulses
      ctx.globalCompositeOperation = inverse ? "lighter" : "source-over";
      pulses.forEach((p) => {
        // Move
        p.y += p.v;
        if (p.y > h + 30) {
          Object.assign(p, spawn(h, false));
        }
        // x based on cord centerline + per-pulse wobble
        const x = cx(p.y) + Math.sin(t * 1.2 + p.ph) * 22 * p.wob + p.u * 70;

        // Glow halo
        const halo = ctx.createRadialGradient(x, p.y, 0, x, p.y, p.r * 6);
        halo.addColorStop(0, hexA(p.c, p.a * 0.55));
        halo.addColorStop(1, hexA(p.c, 0));
        ctx.fillStyle = halo;
        ctx.beginPath();
        ctx.arc(x, p.y, p.r * 6, 0, Math.PI * 2);
        ctx.fill();

        // Core dot
        ctx.fillStyle = hexA(p.c, p.a);
        ctx.beginPath();
        ctx.arc(x, p.y, p.r, 0, Math.PI * 2);
        ctx.fill();

        // Trail — thin tapered streak above the pulse
        const trail = ctx.createLinearGradient(x, p.y - p.r * 12, x, p.y);
        trail.addColorStop(0, hexA(p.c, 0));
        trail.addColorStop(1, hexA(p.c, p.a * 0.7));
        ctx.strokeStyle = trail;
        ctx.lineWidth = p.r * 0.8;
        ctx.beginPath();
        ctx.moveTo(x, p.y - p.r * 12);
        ctx.lineTo(x, p.y);
        ctx.stroke();
      });
      ctx.globalCompositeOperation = "source-over";

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

    return () => {
      running = false;
      cancelAnimationFrame(raf);
      ro.disconnect();
    };
  }, [inverse]);

  return (
    <canvas
      ref={ref}
      style={{
        position: "absolute",
        inset: 0,
        width: "100%",
        height: "100%",
        filter: "blur(0.6px)",
        opacity: 1,
      }}
    />
  );
}

// Helper — paints a vertical band of horizontal gradients, sampled along Y.
// `cx(y)` returns the band's centerline x at row y. `halfWidth` is the band's
// half-thickness. `stops` is an array of [t, color] pairs across [0..1] horiz.
function drawBand(ctx, w, h, cx, halfWidth, stops) {
  // Step in 6px rows for performance
  const step = 6;
  for (let y = 0; y < h; y += step) {
    const x = cx(y);
    const grd = ctx.createLinearGradient(x - halfWidth, y, x + halfWidth, y);
    stops.forEach(([t, c]) => grd.addColorStop(t, c));
    ctx.fillStyle = grd;
    ctx.fillRect(x - halfWidth, y, halfWidth * 2, step + 1);
  }
}

window.HeroBackground = HeroBackground;
