/* RibbonVisual — "Aurora Bloom"
   A glass orb floating in an aurora field. The Method 8 ribbon lives suspended
   inside, slowly rotating in 3D. Cursor pushes the aurora; click pulses a shockwave;
   triple-click collapses everything into a singularity that re-blooms. */
const RibbonVisual = (function() {
  const { useState, useEffect, useRef } = React;

  function Ribbon({ onEgg, reduceMotion, accent }) {
    const wrapRef = useRef(null);
    const canvasRef = useRef(null);
    const mouseRef = useRef({ x: 0.5, y: 0.5, has: false });
    const stateRef = useRef({ pulse: 0, collapse: 0, time: 0 });
    const clickTimes = useRef([]);

    useEffect(() => {
      const canvas = canvasRef.current;
      const ctx = canvas.getContext("2d");
      const dpr = window.devicePixelRatio || 1;
      let W = 0, H = 0;

      const resize = () => {
        const r = wrapRef.current.getBoundingClientRect();
        W = r.width; H = r.height;
        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();
      const ro = new ResizeObserver(resize);
      ro.observe(wrapRef.current);

      // Aurora ribbons (3 layered curves)
      const ribbons = [
        { hue: 198, amp: 0.18, freq: 1.1, phase: 0, speed: 0.0006, alpha: 0.55 },
        { hue: 198, amp: 0.22, freq: 0.85, phase: 1.7, speed: 0.0004, alpha: 0.45 },
        { hue: 198, amp: 0.16, freq: 1.4, phase: 3.4, speed: 0.0008, alpha: 0.35 },
      ];

      // Orbiting particles
      const N = 80;
      const particles = Array.from({length: N}, (_, i) => ({
        a: (i / N) * Math.PI * 2,
        r: 130 + Math.random() * 90,
        speed: 0.0003 + Math.random() * 0.0008,
        size: 0.5 + Math.random() * 1.8,
        bright: 0.3 + Math.random() * 0.7,
        depth: Math.random(),
      }));

      let raf;
      const draw = (now) => {
        stateRef.current.time = now;
        const cx = W / 2, cy = H / 2;
        const collapse = stateRef.current.collapse; // 0..1 (1 = fully collapsed)

        // Background — deep cosmic gradient
        const bg = ctx.createRadialGradient(cx, cy, 0, cx, cy, Math.max(W, H));
        bg.addColorStop(0, "#1a2540");
        bg.addColorStop(0.5, "#0c111d");
        bg.addColorStop(1, "#050912");
        ctx.fillStyle = bg;
        ctx.fillRect(0, 0, W, H);

        // Cursor influence
        const mx = mouseRef.current.has ? (mouseRef.current.x - 0.5) : 0;
        const my = mouseRef.current.has ? (mouseRef.current.y - 0.5) : 0;

        // Aurora ribbons — sweeping wave field
        ctx.save();
        ctx.globalCompositeOperation = "screen";
        for (const rib of ribbons) {
          const y0 = cy + my * 60;
          ctx.beginPath();
          for (let x = 0; x <= W; x += 4) {
            const tx = x / W;
            const wave = Math.sin(tx * rib.freq * Math.PI * 2 + now * rib.speed + rib.phase) * H * rib.amp;
            const wave2 = Math.cos(tx * rib.freq * 1.7 + now * rib.speed * 1.3 + rib.phase) * H * 0.06;
            const y = y0 + wave + wave2;
            if (x === 0) ctx.moveTo(x, y);
            else ctx.lineTo(x, y);
          }
          // Vertical gradient stroke
          const grad = ctx.createLinearGradient(0, 0, W, 0);
          grad.addColorStop(0, `hsla(${rib.hue}, 90%, 65%, 0)`);
          grad.addColorStop(0.5, `hsla(${rib.hue}, 90%, 70%, ${rib.alpha * (1 - collapse)})`);
          grad.addColorStop(1, `hsla(${rib.hue}, 90%, 65%, 0)`);
          ctx.strokeStyle = grad;
          ctx.lineWidth = 80;
          ctx.filter = "blur(40px)";
          ctx.stroke();
        }
        ctx.filter = "none";
        ctx.restore();

        // Tighter aurora glow near center
        const glowR = 240 * (1 - collapse * 0.7);
        const glow = ctx.createRadialGradient(cx + mx * 30, cy + my * 30, 0, cx, cy, glowR);
        glow.addColorStop(0, accent + "55");
        glow.addColorStop(0.5, accent + "22");
        glow.addColorStop(1, accent + "00");
        ctx.fillStyle = glow;
        ctx.beginPath();
        ctx.arc(cx, cy, glowR, 0, Math.PI * 2);
        ctx.fill();

        // Pulse shockwave (on click)
        if (stateRef.current.pulse > 0) {
          const p = stateRef.current.pulse;
          ctx.save();
          ctx.strokeStyle = `rgba(255,255,255,${p * 0.4})`;
          ctx.lineWidth = 2 * p;
          ctx.beginPath();
          ctx.arc(cx, cy, 80 + (1 - p) * 220, 0, Math.PI * 2);
          ctx.stroke();
          ctx.strokeStyle = `${accent}${Math.round(p * 255).toString(16).padStart(2,'0')}`;
          ctx.lineWidth = 4 * p;
          ctx.beginPath();
          ctx.arc(cx, cy, 100 + (1 - p) * 180, 0, Math.PI * 2);
          ctx.stroke();
          ctx.restore();
          if (!reduceMotion) stateRef.current.pulse = Math.max(0, p - 0.018);
        }

        // Orbiting particles (3D-ish via depth) — DISABLED, replaced by ribbon centerpiece
        // ctx.save();
        // for (const p of particles) { ... }
        // ctx.restore();

        // Glass orb at center — DISABLED, ribbon stands alone
        const orbR = 0;

        // Singularity flare during collapse
        if (collapse > 0.4) {
          const flareR = 4 + (1 - collapse) * 60;
          const flare = ctx.createRadialGradient(cx, cy, 0, cx, cy, flareR * 6);
          flare.addColorStop(0, "rgba(255,255,255,1)");
          flare.addColorStop(0.2, accent + "ff");
          flare.addColorStop(1, accent + "00");
          ctx.fillStyle = flare;
          ctx.beginPath();
          ctx.arc(cx, cy, flareR * 6, 0, Math.PI * 2);
          ctx.fill();
        }

        // Update collapse state
        if (!reduceMotion) {
          if (stateRef.current.collapseTarget === 1) {
            stateRef.current.collapse = Math.min(1, stateRef.current.collapse + 0.03);
            if (stateRef.current.collapse >= 1) {
              setTimeout(() => { stateRef.current.collapseTarget = 0; }, 400);
            }
          } else {
            stateRef.current.collapse = Math.max(0, stateRef.current.collapse - 0.025);
          }
        }

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

      const onMove = (e) => {
        const r = wrapRef.current.getBoundingClientRect();
        mouseRef.current.x = (e.clientX - r.left) / r.width;
        mouseRef.current.y = (e.clientY - r.top) / r.height;
        mouseRef.current.has = true;
      };
      const onLeave = () => { mouseRef.current.has = false; };
      wrapRef.current.addEventListener("mousemove", onMove);
      wrapRef.current.addEventListener("mouseleave", onLeave);

      return () => {
        cancelAnimationFrame(raf);
        ro.disconnect();
        if (wrapRef.current) {
          wrapRef.current.removeEventListener("mousemove", onMove);
          wrapRef.current.removeEventListener("mouseleave", onLeave);
        }
      };
    }, [accent, reduceMotion]);

    const onClick = () => {
      stateRef.current.pulse = 1;
      const t = Date.now();
      clickTimes.current = [...clickTimes.current.filter((x) => t - x < 600), t];
      if (clickTimes.current.length >= 3) {
        clickTimes.current = [];
        stateRef.current.collapseTarget = 1;
        onEgg && onEgg("∞ — singularity");
      }
    };

    return (
      <div ref={wrapRef} className="layer" onClick={onClick} style={{cursor: 'pointer', overflow: 'hidden'}}>
        <canvas ref={canvasRef}/>
        {/* Floating M8 ribbon mark inside the orb */}
        <div className="m8-mark" style={{
          position:'absolute', left:'50%', top:'50%',
          transform:'translate(-50%,-50%)',
          width: 280, height: 280,
          pointerEvents:'none',
          filter: `drop-shadow(0 0 18px ${accent}aa) drop-shadow(0 0 48px ${accent}55)`,
          animation: 'm8breathe 6s ease-in-out infinite',
          opacity: 0.92,
        }}>
          <svg viewBox="0 0 32 32" width="280" height="280">
            {/* Three nested ribbons in brand sky-blue */}
            <path fill="none" stroke="#7CD4FD" strokeWidth="0.7" strokeLinecap="round" strokeLinejoin="round"
              opacity="0.95"
              d="M15.69 18.14 C17.42 20.60 20.14 23.28 23.38 22.44 C26.37 21.72 28.19 18.44 27.88 15.52
                 C27.66 12.55 25.66 9.79 22.51 10.02 C19.56 10.45 18.11 13.97 16.70 16.38
                 C15.08 19.17 13.33 23.09 9.64 23.49 C5.68 23.72 3.00 20.32 2.88 16.58
                 C2.44 11.06 8.46 6.24 13.24 10.10 C14.57 11.08 15.51 12.46 16.32 13.87
                 C14.94 11.94 13.23 10.07 10.87 9.52 C8.62 9.02 6.25 10.27 5.14 12.21
                 C2.98 15.52 4.24 21.27 8.50 21.96 C13.17 22.69 15.26 14.40 17.91 11.40
                 C19.51 9.09 22.35 7.69 25.07 9.01 C27.68 9.94 28.99 12.81 29.12 15.43
                 C29.37 18.88 27.05 22.57 23.55 23.20 C20.05 23.88 17.21 20.96 15.69 18.14 Z"/>
            <path fill="none" stroke="#7CD4FD" strokeWidth="0.8" strokeLinecap="round" strokeLinejoin="round"
              d="M15.89 17.76 C17.18 19.56 19.37 21.44 21.66 20.69 C23.80 20.08 25.04 17.66 24.76 15.54
                 C24.45 12.03 20.77 10.06 18.50 13.39 C16.69 15.80 15.81 19.02 13.33 20.99
                 C11.59 22.40 8.91 21.88 7.45 20.29 C5.67 18.18 5.51 15.03 6.99 12.79
                 C8.37 10.49 11.68 9.66 13.80 11.43 C14.80 12.16 15.53 13.17 16.11 14.24
                 C15.39 13.28 14.57 12.38 13.55 11.80 C10.30 9.69 6.74 13.04 7.24 16.46
                 C7.43 18.56 8.95 20.53 11.14 20.31 C12.03 20.20 12.85 19.52 13.50 18.61
                 C14.91 16.70 15.76 14.40 17.26 12.45 C20.26 8.10 25.82 10.56 25.99 15.43
                 C26.22 18.06 24.51 20.89 21.86 21.45 C19.23 22.06 17.00 19.92 15.89 17.76 Z"/>
            <path fill="none" stroke="#A6F4FF" strokeWidth="0.7" strokeLinecap="round" strokeLinejoin="round"
              opacity="0.85"
              d="M16.10 17.37 C17.01 18.46 18.52 19.58 19.95 18.91 C21.89 18.15 22.22 15.18 20.81 13.84
                 C17.95 11.73 16.90 16.86 15.40 18.49 C13.38 21.53 9.33 20.01 9.14 16.60
                 C8.72 13.82 11.81 10.97 14.33 12.77 C15.04 13.22 15.50 13.91 15.90 14.61
                 C14.99 13.53 13.49 12.40 12.06 13.07 C10.79 13.59 10.12 15.13 10.37 16.44
                 C10.56 17.73 11.47 18.79 12.78 18.63 C13.25 18.54 13.74 18.14 14.15 17.55
                 C15.31 15.95 15.93 13.83 17.57 12.49 C19.81 10.71 22.81 12.81 22.87 15.38
                 C23.14 19.78 18.15 21.54 16.10 17.37 Z"/>
          </svg>
        </div>
        <style>{`
          @keyframes m8breathe {
            0%, 100% { opacity: 0.88; transform: translate(-50%, -50%) scale(1); }
            50%      { opacity: 1.00; transform: translate(-50%, -50%) scale(1.03); }
          }
        `}</style>
      </div>
    );
  }

  return Ribbon;
})();

window.RibbonVisual = RibbonVisual;
