// Bubbles — glassy bubble that peeks from the right edge of the waitlist form.
// Click to expand an info card. On mobile, card appears as a centred fixed overlay.

const PopEffect = ({ cx, cy }) => {
  const rings = [
    { delay: '0ms',   dur: '0.55s', size: 80,  color: 'rgba(127,179,201,0.55)' },
    { delay: '60ms',  dur: '0.65s', size: 110, color: 'rgba(159,198,214,0.38)' },
    { delay: '130ms', dur: '0.75s', size: 145, color: 'rgba(220,232,238,0.28)' },
  ];
  const dropAngles = [0, 45, 90, 135, 180, 225, 270, 315];
  const dropColors = [
    'rgba(127,179,201,0.9)', 'rgba(255,255,255,0.85)', 'rgba(159,198,214,0.9)',
    'rgba(220,232,238,0.85)', 'rgba(127,179,201,0.8)', 'rgba(255,255,255,0.9)',
    'rgba(180,215,230,0.85)', 'rgba(200,230,240,0.8)',
  ];
  return (
    <div style={{ position: 'absolute', left: cx, top: cy, pointerEvents: 'none' }}>
      {/* expanding rings */}
      {rings.map((r, i) => (
        <div key={i} style={{
          position: 'absolute',
          left: -r.size / 2, top: -r.size / 2,
          width: r.size, height: r.size,
          borderRadius: '50%',
          border: `1.5px solid ${r.color}`,
          animation: `popRing ${r.dur} ${r.delay} cubic-bezier(0.2,0.6,0.4,1) forwards`,
        }} />
      ))}
      {/* droplets */}
      {dropAngles.map((angle, i) => (
        <div key={i} style={{
          position: 'absolute', left: 0, top: 0,
          transform: `rotate(${angle}deg)`,
          transformOrigin: '0 0',
        }}>
          <div style={{ animation: `dropletFly 0.7s ${i * 18}ms ease-out forwards` }}>
            <div style={{
              position: 'absolute',
              left: -3, top: -26,
              width: i % 3 === 0 ? 7 : 5,
              height: i % 3 === 0 ? 7 : 5,
              borderRadius: '50%',
              background: dropColors[i],
              boxShadow: `0 0 4px ${dropColors[i]}`,
            }} />
          </div>
        </div>
      ))}
    </div>
  );
};

const Bubbles = () => {
  const [open, setOpen] = React.useState(false);
  const [popping, setPopping] = React.useState(false);
  const [popEvents, setPopEvents] = React.useState([]);
  const [tick, setTick] = React.useState(0);
  const tRef = React.useRef(0);
  const anchorRef = React.useRef({ x: 0, y: 0, formRight: 0 });

  const isMobile = window.innerWidth < 600 || window.matchMedia('(pointer: coarse)').matches;

  // close on click outside
  React.useEffect(() => {
    if (!open) return;
    const onDown = (e) => {
      if (e.target.closest('[data-popup="bubbles"]')) return;
      setOpen(false);
    };
    const id = setTimeout(() => document.addEventListener('mousedown', onDown), 0);
    return () => { clearTimeout(id); document.removeEventListener('mousedown', onDown); };
  }, [open]);

  // anchor to right edge of the waitlist form
  React.useEffect(() => {
    const update = () => {
      const form = document.querySelector('form');
      if (!form) return;
      const r = form.getBoundingClientRect();
      anchorRef.current = {
        x: r.right - 18,
        y: r.top + r.height / 2,
        formRight: r.right,
      };
      setTick(x => x + 1);
    };
    update();
    window.addEventListener('resize', update);
    const id = setInterval(update, 500);
    return () => { window.removeEventListener('resize', update); clearInterval(id); };
  }, []);

  // animation tick
  React.useEffect(() => {
    let raf;
    const start = performance.now();
    const loop = (now) => {
      tRef.current = (now - start) / 1000;
      setTick(x => (x + 1) % 1000000);
      raf = requestAnimationFrame(loop);
    };
    raf = requestAnimationFrame(loop);
    return () => cancelAnimationFrame(raf);
  }, []);

  const t = tRef.current;
  const { x: ax, y: ay, formRight } = anchorRef.current;

  const wob = Math.sin(t * 1.1) * 4;
  const rise = Math.sin(t * 0.7) * 3;
  const mainSize = isMobile ? 52 : 64;
  const mainCx = ax + 18 + wob;
  const mainCy = ay + rise;

  const tinies = [
    { size: isMobile ? 13 : 16, dx: 28, dy: -34, phase: 1.4, drift: 1.2 },
    { size: isMobile ? 10 : 12, dx: 8,  dy: 32,  phase: 2.7, drift: 1.5 },
  ];

  const handleClick = () => {
    const id = Date.now();
    setPopEvents(prev => [...prev, { id, cx: mainCx, cy: mainCy }]);
    setTimeout(() => setPopEvents(prev => prev.filter(e => e.id !== id)), 900);
    setPopping(true);
    setOpen(true);
    setTimeout(() => setPopping(false), 500);
  };

  // expanded card position — right of form on desktop, fixed centred on mobile
  const cardStyle = isMobile ? {
    position: 'fixed',
    left: '50%',
    top: '50%',
    transform: open
      ? 'translate(-50%, -50%) scale(1)'
      : 'translate(-50%, -50%) scale(0.88)',
    transformOrigin: '50% 50%',
    width: 'min(380px, calc(100vw - 32px))',
  } : {
    position: 'absolute',
    left: formRight + 32,
    top: ay - 220,
    transform: open ? 'scale(1) translateX(0)' : 'scale(0.3) translateX(-20px)',
    transformOrigin: '0% 50%',
    width: 520,
    maxWidth: 'calc(100vw - 60px)',
  };

  return (
    <div
      data-popup="bubbles"
      style={{ position: 'fixed', inset: 0, zIndex: 4, pointerEvents: 'none' }}
    >
      {/* rising column */}
      <svg width="80" height="160" style={{
        position: 'absolute',
        left: ax - 10,
        top: ay - 30,
        pointerEvents: 'none',
        opacity: open ? 0 : 0.55,
        transition: 'opacity 0.3s ease',
      }}>
        {[0,1,2,3].map(i => {
          const tt = (t * 0.4 + i * 0.7) % 1;
          const y = 160 - tt * 200;
          const x = 40 + Math.sin(tt * 6 + i) * 14;
          const r = 1.4 + (1 - tt) * 1.8;
          return <circle key={i} cx={x} cy={y} r={r} fill="rgba(255,255,255,0.55)" opacity={1 - tt} />;
        })}
      </svg>

      {/* companion bubbles */}
      {tinies.map((b, i) => {
        const w = Math.sin(t * 1.3 + b.phase) * 5 * b.drift;
        const r = Math.cos(t * 0.9 + b.phase) * 3 * b.drift;
        return (
          <BubbleBlob key={i} cx={mainCx + b.dx + w} cy={mainCy + b.dy + r}
            size={b.size} idx={`tiny-${i}`} t={t} hidden={open} />
        );
      })}

      {/* main bubble */}
      <div
        data-popup="bubbles"
        onClick={handleClick}
        style={{
          position: 'absolute',
          left: mainCx - mainSize / 2,
          top: mainCy - mainSize / 2,
          width: mainSize, height: mainSize,
          pointerEvents: open ? 'none' : 'auto',
          cursor: 'none',
          opacity: open ? 0 : 1,
          transition: 'opacity 0.35s ease',
          animation: popping ? 'bubblePop 0.42s ease-out forwards' : 'mainBubblePulse 3.4s ease-in-out infinite',
        }}
      >
        <BubbleBlob cx={mainSize / 2} cy={mainSize / 2} size={mainSize} idx="main" t={t} inline />
      </div>

      {/* hint label — right of bubble on desktop, below bubble on mobile */}
      {isMobile ? (
        <div style={{
          position: 'absolute',
          left: mainCx,
          top: mainCy + mainSize / 2 + 36,
          transform: 'translateX(-50%)',
          textAlign: 'center',
          pointerEvents: 'none',
          opacity: open ? 0 : 1,
          transition: 'opacity 0.12s ease',
          whiteSpace: 'nowrap',
        }}>
          <div style={{
            fontFamily: "'Instrument Sans', sans-serif",
            fontSize: 10, letterSpacing: '0.16em',
            textTransform: 'uppercase',
            color: 'var(--ink)', opacity: 0.6,
            marginBottom: 3,
          }}>pop me</div>
          <div style={{
            fontFamily: "'Fraunces', serif",
            fontSize: 12, fontStyle: 'italic',
            color: 'var(--ink)', opacity: 0.75,
            animation: 'hintBob 2.6s ease-in-out infinite',
          }}>
            what's tides?
          </div>
        </div>
      ) : (
        <div style={{
          position: 'absolute',
          left: mainCx + mainSize / 2 + 18,
          top: mainCy - 10,
          fontFamily: "'Instrument Sans', sans-serif",
          fontSize: 11,
          letterSpacing: '0.18em',
          textTransform: 'uppercase',
          color: 'var(--ink)',
          opacity: open ? 0 : 0.7,
          transition: 'opacity 0.12s ease',
          whiteSpace: 'nowrap',
          pointerEvents: 'none',
        }}>
          <span style={{ display: 'inline-block', animation: 'hintBob 2.6s ease-in-out infinite' }}>
            pop me
          </span>
          <div style={{
            fontFamily: "'Fraunces', serif",
            fontSize: 13, fontStyle: 'italic',
            letterSpacing: '0', textTransform: 'none',
            opacity: 0.7, marginTop: 2,
          }}>
            what's tides?
          </div>
        </div>
      )}

      {/* expanded card */}
      <div
        data-popup="bubbles"
        style={{
          ...cardStyle,
          pointerEvents: open ? 'auto' : 'none',
          opacity: open ? 1 : 0,
          transition: 'opacity 0.4s ease, transform 0.55s cubic-bezier(.2, 1.2, .3, 1.05)',
          zIndex: 60,
        }}
      >
        <div style={{
          position: 'relative',
          borderRadius: '44% 56% 42% 48% / 46% 48% 38% 42%',
          padding: isMobile ? '36px 26px 40px' : '52px 48px 64px',
          background: `
            radial-gradient(120% 100% at 30% 22%, rgba(255,255,255,0.88), rgba(255,255,255,0.2) 45%, rgba(255,255,255,0.06) 70%),
            linear-gradient(155deg, rgba(220,232,238,0.65), rgba(159,198,214,0.42) 60%, rgba(127,179,201,0.32))
          `,
          backdropFilter: 'blur(20px) saturate(1.2)',
          WebkitBackdropFilter: 'blur(20px) saturate(1.2)',
          border: '1px solid rgba(255,255,255,0.65)',
          boxShadow: `
            0 32px 64px -24px rgba(26,58,74,0.32),
            inset 0 2px 0 rgba(255,255,255,0.9),
            inset 0 -20px 40px -10px rgba(127,179,201,0.38),
            0 0 0 1px rgba(26,58,74,0.06)
          `,
          color: 'var(--ink)',
          animation: open ? 'bubbleBreathe 5s ease-in-out infinite' : 'none',
          overflow: 'hidden',
        }}>
          {/* highlight reflections */}
          <div style={{ position: 'absolute', top: 20, left: 32, width: 48, height: 28, borderRadius: '50%', background: 'radial-gradient(closest-side, rgba(255,255,255,0.92), transparent)', pointerEvents: 'none', transform: 'rotate(-20deg)' }} />
          <div style={{ position: 'absolute', top: 40, left: 64, width: 14, height: 14, borderRadius: '50%', background: 'rgba(255,255,255,0.88)', pointerEvents: 'none' }} />
          <div style={{ position: 'absolute', bottom: 32, right: 28, width: 20, height: 20, borderRadius: '50%', background: 'radial-gradient(closest-side, rgba(255,255,255,0.58), transparent)', pointerEvents: 'none' }} />

          {/* iridescent rim */}
          <div style={{
            position: 'absolute', inset: 0, borderRadius: 'inherit',
            background: 'conic-gradient(from 140deg, transparent, rgba(255,200,230,0.2), rgba(180,220,255,0.22), transparent 40%, transparent 60%, rgba(255,240,200,0.18), transparent)',
            mixBlendMode: 'screen', pointerEvents: 'none',
          }} />

          <button
            onClick={() => setOpen(false)}
            aria-label="Close"
            style={{
              position: 'absolute', top: 14, right: 18,
              width: 26, height: 26, borderRadius: '50%',
              background: 'rgba(255,255,255,0.35)', border: '1px solid rgba(255,255,255,0.5)',
              color: 'var(--ink)', opacity: 0.65,
              fontSize: 16, cursor: 'none', fontFamily: 'inherit', lineHeight: 1,
              zIndex: 2, display: 'flex', alignItems: 'center', justifyContent: 'center',
            }}
          >×</button>

          <div style={{ position: 'relative', zIndex: 1 }}>

            <div style={{
              fontFamily: "'Fraunces', serif",
              fontSize: isMobile ? 17 : 26,
              lineHeight: 1.22, letterSpacing: '-0.01em',
              marginBottom: 10,
              fontStyle: 'italic',
            }}>
              Discover live discounts at Melbourne's best activity venues.
            </div>

            <p style={{
              fontSize: isMobile ? 12 : 15.5,
              lineHeight: 1.55, margin: '0 0 10px', opacity: 0.85,
              textWrap: 'pretty',
            }}>
              Find something worth doing near you, tonight. Tides surfaces live deals up to 50% off from bowling and karting to escape rooms and mini golf, so you and your mates can actually lock something in. No vouchers, no pre-booking, just somewhere worth going. Join the waitlist and be first through the door when we launch.
            </p>

          </div>
        </div>
      </div>

      {/* pop effects */}
      {popEvents.map(e => <PopEffect key={e.id} cx={e.cx} cy={e.cy} />)}

      <style>{`
        @keyframes bubbleBreathe {
          0%,100% { border-radius: 44% 56% 42% 48% / 46% 48% 38% 42%; }
          50%      { border-radius: 50% 50% 46% 44% / 50% 50% 40% 38%; }
        }
        @keyframes bubblePop {
          0%   { transform: scale(1)    rotate(0deg);   opacity: 1; }
          12%  { transform: scale(0.78) rotate(-4deg);  opacity: 1; }
          40%  { transform: scale(1.55) rotate(3deg);   opacity: 0.85; }
          70%  { transform: scale(1.85) rotate(-1deg);  opacity: 0.35; }
          100% { transform: scale(2.1)  rotate(0deg);   opacity: 0; }
        }
        @keyframes mainBubblePulse {
          0%,100% { transform: scale(1); }
          50%     { transform: scale(1.06); }
        }
        @keyframes hintBob {
          0%,100% { transform: translateX(0); }
          50%     { transform: translateX(-4px); }
        }
        @keyframes popRing {
          0%   { transform: scale(0.2); opacity: 0.8; }
          100% { transform: scale(2.8); opacity: 0; }
        }
        @keyframes dropletFly {
          0%   { transform: translateY(-10px) scale(1);   opacity: 1; }
          60%  { opacity: 0.7; }
          100% { transform: translateY(-62px) scale(0.15); opacity: 0; }
        }
      `}</style>
    </div>
  );
};

// ── single bubble SVG ──
const BubbleBlob = ({ cx, cy, size, idx, t, hidden, inline }) => {
  const r = size / 2;
  const wobX = 1 + Math.sin(t * 1.4 + (typeof idx === 'string' ? idx.length : idx)) * 0.06;
  const wobY = 1 + Math.cos(t * 1.4 + (typeof idx === 'string' ? idx.length * 0.7 : idx * 0.7)) * 0.06;

  const svg = (
    <svg width={size} height={size} viewBox={`0 0 ${size} ${size}`} style={{ overflow: 'visible' }}>
      <defs>
        <radialGradient id={`bg-${idx}`} cx="35%" cy="28%" r="70%">
          <stop offset="0%"   stopColor="rgba(255,255,255,0.9)" />
          <stop offset="35%"  stopColor="rgba(220,232,238,0.5)" />
          <stop offset="70%"  stopColor="rgba(159,198,214,0.3)" />
          <stop offset="100%" stopColor="rgba(127,179,201,0.22)" />
        </radialGradient>
      </defs>
      <circle cx={r} cy={r} r={r - 1} fill={`url(#bg-${idx})`} stroke="rgba(255,255,255,0.7)" strokeWidth="1" />
      <circle cx={r} cy={r} r={r - 3} fill="none" stroke="rgba(255,255,255,0.3)" strokeWidth="0.6" />
      <ellipse cx={r * 0.62} cy={r * 0.55} rx={r * 0.32} ry={r * 0.2} fill="rgba(255,255,255,0.85)" transform={`rotate(-25 ${r * 0.62} ${r * 0.55})`} />
      <circle cx={r * 0.82} cy={r * 0.78} r={r * 0.08} fill="rgba(255,255,255,0.7)" />
      <path d={`M ${r * 0.15} ${r * 1.15} A ${r - 2} ${r - 2} 0 0 0 ${r * 1.85} ${r * 1.15}`} fill="none" stroke="rgba(255,210,230,0.4)" strokeWidth="0.7" />
    </svg>
  );

  if (inline) return svg;

  return (
    <div style={{
      position: 'absolute',
      left: cx - r, top: cy - r,
      width: size, height: size,
      pointerEvents: 'none',
      opacity: hidden ? 0 : 1,
      transition: 'opacity 0.35s ease',
      transform: `scale(${wobX}, ${wobY})`,
    }}>
      {svg}
    </div>
  );
};

window.Bubbles = Bubbles;
