// odd duck interactions — cursor companion + quack sound + click ripples
// Loaded last; mounts itself as a React tree on a dedicated div.

(function() {
  const { useState, useEffect, useRef } = React;

  // ---- Quack sound (synthesized so we don't need an audio file) ----
  let audioCtx = null;
  function quack() {
    try {
      if (!audioCtx) audioCtx = new (window.AudioContext || window.webkitAudioContext)();
      if (audioCtx.state === 'suspended') audioCtx.resume();
      const t0 = audioCtx.currentTime;

      // a "quack" is roughly: noisy formant that drops in pitch quickly, slight buzz
      const osc = audioCtx.createOscillator();
      const gain = audioCtx.createGain();
      const filter = audioCtx.createBiquadFilter();

      osc.type = 'sawtooth';
      osc.frequency.setValueAtTime(380, t0);
      osc.frequency.exponentialRampToValueAtTime(180, t0 + 0.16);

      filter.type = 'bandpass';
      filter.frequency.setValueAtTime(900, t0);
      filter.frequency.exponentialRampToValueAtTime(500, t0 + 0.16);
      filter.Q.value = 3.5;

      gain.gain.setValueAtTime(0.0001, t0);
      gain.gain.exponentialRampToValueAtTime(0.22, t0 + 0.02);
      gain.gain.exponentialRampToValueAtTime(0.0001, t0 + 0.22);

      osc.connect(filter);
      filter.connect(gain);
      gain.connect(audioCtx.destination);
      osc.start(t0);
      osc.stop(t0 + 0.25);
    } catch (e) {
      // ignore
    }
  }
  window.__quack = quack;

  // ---- Cursor companion duck ----
  // A tiny duck walks toward the cursor, lagging behind, and flips horizontally
  // based on direction. Click anywhere → quack + ripple.
  const CursorDuck = () => {
    const [enabled, setEnabled] = useState(false);
    const [pos, setPos] = useState({ x: -200, y: -200 });
    const [facing, setFacing] = useState(1); // 1 = right, -1 = left
    const [moving, setMoving] = useState(false);
    const target = useRef({ x: -200, y: -200 });
    const rafId = useRef(0);
    const lastX = useRef(0);
    const lastMoveTs = useRef(0);

    useEffect(() => {
      // Only show on devices that actually have a cursor
      const mq = window.matchMedia('(hover: hover) and (pointer: fine)');
      const update = () => setEnabled(mq.matches);
      update();
      mq.addEventListener?.('change', update);
      return () => mq.removeEventListener?.('change', update);
    }, []);

    useEffect(() => {
      if (!enabled) return;
      const onMove = (e) => {
        target.current = { x: e.clientX, y: e.clientY };
        lastMoveTs.current = performance.now();
      };
      window.addEventListener('mousemove', onMove, { passive: true });

      const tick = () => {
        setPos((prev) => {
          const tx = target.current.x;
          const ty = target.current.y;
          const dx = tx - prev.x;
          const dy = ty - prev.y;
          const dist = Math.hypot(dx, dy);
          // Stay ~70px behind the cursor; only move if far away
          const idleRadius = 70;
          if (dist < idleRadius) {
            setMoving(false);
            rafId.current = requestAnimationFrame(tick);
            return prev;
          }
          setMoving(true);
          const step = Math.min(dist - idleRadius, 6); // speed cap
          const nx = prev.x + (dx / dist) * step;
          const ny = prev.y + (dy / dist) * step;
          // facing direction
          if (Math.abs(nx - lastX.current) > 0.5) {
            setFacing(nx > lastX.current ? 1 : -1);
            lastX.current = nx;
          }
          rafId.current = requestAnimationFrame(tick);
          return { x: nx, y: ny };
        });
      };
      rafId.current = requestAnimationFrame(tick);
      return () => {
        window.removeEventListener('mousemove', onMove);
        cancelAnimationFrame(rafId.current);
      };
    }, [enabled]);

    if (!enabled) return null;

    return (
      <img
        src="assets/duck-walking.png"
        alt=""
        aria-hidden="true"
        className={"cursor-duck" + (moving ? " walking" : " idle")}
        style={{
          transform: `translate(${pos.x - 26}px, ${pos.y - 28}px) scaleX(${facing})`,
        }}
      />
    );
  };

  // ---- Click ripple + quack on duck images ----
  const useDuckClicks = () => {
    useEffect(() => {
      const onClick = (e) => {
        const el = e.target.closest('img[src*="duck"], .hero-duck-wrap, .contact-stamp, .nav-mark');
        if (!el) return;
        quack();
        // ripple
        const r = el.getBoundingClientRect();
        const ripple = document.createElement('span');
        ripple.className = 'duck-ripple';
        ripple.style.left = (r.left + r.width / 2) + 'px';
        ripple.style.top = (r.top + r.height / 2) + 'px';
        document.body.appendChild(ripple);
        setTimeout(() => ripple.remove(), 700);
        // little jump on the clicked element
        if (el.animate) {
          el.animate([
            { transform: el.style.transform + ' translateY(0)' },
            { transform: el.style.transform + ' translateY(-12px) rotate(-4deg)' },
            { transform: el.style.transform + ' translateY(0)' },
          ], { duration: 320, easing: 'cubic-bezier(.2,.7,.3,1.2)' });
        }
      };
      document.addEventListener('click', onClick);
      return () => document.removeEventListener('click', onClick);
    }, []);
  };

  const Interactions = () => {
    useDuckClicks();
    return null;
  };

  // mount
  const root = document.createElement('div');
  root.id = 'odd-duck-interactions';
  document.body.appendChild(root);
  ReactDOM.createRoot(root).render(<Interactions />);
})();
