// shared.jsx — Common utilities for both designs
// - SALE_DATE (Saturday 23 May 2026, 1pm Melbourne)
// - useCountdown / useNow hooks
// - useConfetti (click anywhere to scatter hearts/stars)
// - WalkingLady (animated character: walks or follows cursor)
// - ChuggingTrain (bottom-of-page train on rails)
// - Palette presets

const SALE_DATE = new Date('2026-05-23T13:00:00+10:00'); // 1pm AEST Melbourne
const SALE_END  = new Date('2026-05-23T16:00:00+10:00'); // 4pm

const PALETTES = {
  crayon: {
    label: "Crayon",
    bg: '#FFF8F2', paper: '#FFFFFF', ink: '#1B1B1B',
    primary: '#FF2E8B', accent: '#E63946', pop: '#0BB07B', cool: '#1E88E5',
    yellow: '#FFC93C',
  },
  bubblegum: {
    label: 'Bubblegum Pop',
    bg: '#FFF0F8', paper: '#FFFFFF', ink: '#2D1B47',
    primary: '#FF5BA0', accent: '#7A5AE0', pop: '#FFD60A', cool: '#6BC1FF',
    yellow: '#FFD60A',
  },
  recess: {
    label: 'Recess',
    bg: '#FFFBEE', paper: '#FFFFFF', ink: '#1A1A1A',
    primary: '#FF6B35', accent: '#5856D6', pop: '#2A9D8F', cool: '#118AB2',
    yellow: '#FFD166',
  },
  sherbet: {
    label: 'Sherbet',
    bg: '#FFF4F0', paper: '#FFFFFF', ink: '#221A37',
    primary: '#FF9F1C', accent: '#E63946', pop: '#2EC4B6', cool: '#3D5A80',
    yellow: '#FFD60A',
  },
  lemonade: {
    label: 'Lemonade Stand',
    bg: '#FEFBE7', paper: '#FFFFFF', ink: '#1A1A1A',
    primary: '#06A77D', accent: '#F26430', pop: '#2274A5', cool: '#7A5AE0',
    yellow: '#FFD60A',
  },
};

function applyPaletteVars(rootEl, p) {
  if (!rootEl) return;
  const s = rootEl.style;
  s.setProperty('--bg', p.bg);
  s.setProperty('--paper', p.paper);
  s.setProperty('--ink', p.ink);
  s.setProperty('--primary', p.primary);
  s.setProperty('--accent', p.accent);
  s.setProperty('--pop', p.pop);
  s.setProperty('--cool', p.cool);
  s.setProperty('--yellow', p.yellow);
}

// ── countdown ──────────────────────────────────────────────────────────
function useCountdown(target) {
  const [now, setNow] = React.useState(() => new Date());
  React.useEffect(() => {
    const t = setInterval(() => setNow(new Date()), 1000);
    return () => clearInterval(t);
  }, []);
  let diff = target - now;
  const past = diff <= 0;
  diff = Math.max(0, diff);
  const days = Math.floor(diff / 86400000);
  const hours = Math.floor(diff / 3600000) % 24;
  const mins = Math.floor(diff / 60000) % 60;
  const secs = Math.floor(diff / 1000) % 60;
  return { days, hours, mins, secs, past };
}

// ── confetti ───────────────────────────────────────────────────────────
// Attaches a click handler to the given element. Each click scatters
// hearts + stars from the click point. Designed to layer over anything.
function useConfetti(rootRef, opts={}) {
  const colorsRef = React.useRef(opts.colors);
  colorsRef.current = opts.colors;
  React.useEffect(() => {
    const root = rootRef.current;
    if (!root) return;
    function onClick(e) {
      // Skip if the user clicked a real interactive control
      if (e.target.closest('button, a, input, select, textarea, label, .no-confetti')) return;
      const rect = root.getBoundingClientRect();
      // Divide by current CSS scale: on narrow viewports the canvas is
      // visually scaled down, so clientX is in screen pixels but the
      // confetti bits inherit the canvas's internal coord system.
      const scale = root.offsetWidth ? rect.width / root.offsetWidth : 1;
      const x = (e.clientX - rect.left) / (scale || 1);
      const y = (e.clientY - rect.top) / (scale || 1);
      const colors = colorsRef.current || ['#FF2E8B','#FFD60A','#06A77D','#1E88E5','#E63946','#7A5AE0'];
      const N = 16;
      for (let i = 0; i < N; i++) {
        const el = document.createElement('div');
        el.className = 'confetti-bit';
        const shape = i % 2 === 0 ? 'heart' : 'star';
        el.dataset.shape = shape;
        const c = colors[i % colors.length];
        if (shape === 'heart') {
          el.innerHTML = `<svg viewBox="0 0 24 24" width="22" height="22"><path d="M12 21s-7-4.5-9.5-9C.5 8 3 4 7 4c2 0 3.5 1 5 3 1.5-2 3-3 5-3 4 0 6.5 4 4.5 8C19 16.5 12 21 12 21z" fill="${c}" stroke="#1a1a1a" stroke-width="1.5"/></svg>`;
        } else {
          el.innerHTML = `<svg viewBox="0 0 24 24" width="22" height="22"><path d="M12 2l2.6 6.6 7 .6-5.3 4.6 1.6 6.8L12 17l-5.9 3.6 1.6-6.8L2.4 9.2l7-.6L12 2z" fill="${c}" stroke="#1a1a1a" stroke-width="1.5" stroke-linejoin="round"/></svg>`;
        }
        el.style.left = x + 'px';
        el.style.top = y + 'px';
        const angle = (Math.PI * 2 * i) / N + (Math.random() - 0.5) * 0.4;
        const dist = 60 + Math.random() * 140;
        el.style.setProperty('--dx', Math.cos(angle) * dist + 'px');
        el.style.setProperty('--dy', Math.sin(angle) * dist - 40 + 'px');
        el.style.setProperty('--rot', (Math.random() * 720 - 360) + 'deg');
        el.style.setProperty('--dur', (700 + Math.random() * 600) + 'ms');
        root.appendChild(el);
        setTimeout(() => el.remove(), 1400);
      }
    }
    root.addEventListener('click', onClick);
    return () => root.removeEventListener('click', onClick);
  }, [rootRef]);
}

// ── walking lady character ─────────────────────────────────────────────
// Mode 'walk': bobs across from left to right repeatedly.
// Mode 'follow': follows the cursor with a soft lag.
function WalkingLady({ mode = 'walk', containerRef, size = 220, bottomOffset = 0 }) {
  const ref = React.useRef(null);
  const posRef = React.useRef({ x: -size, y: 0, facing: 1 });
  React.useEffect(() => {
    const el = ref.current;
    const root = containerRef?.current;
    if (!el || !root) return;
    let raf;
    let last = performance.now();
    let target = { x: 0, y: 0 };
    const speed = 0.09; // px per ms when walking
    let walkX = -size;

    function onMove(e) {
      const r = root.getBoundingClientRect();
      target.x = e.clientX - r.left;
      target.y = e.clientY - r.top;
    }
    if (mode === 'follow') root.addEventListener('pointermove', onMove);

    function frame(t) {
      const dt = Math.min(64, t - last); last = t;
      const W = root.clientWidth;
      const H = root.clientHeight;
      if (mode === 'walk') {
        walkX += speed * dt;
        if (walkX > W + size) walkX = -size - Math.random() * 400;
        posRef.current.x = walkX;
        posRef.current.y = H - size * 0.95 - bottomOffset;
        posRef.current.facing = 1;
      } else {
        // follow cursor with lag, offset so lady is below+behind cursor
        const desiredX = target.x - size * 0.45;
        const desiredY = target.y - size * 0.55;
        const k = 0.08;
        posRef.current.x += (desiredX - posRef.current.x) * k;
        posRef.current.y += (desiredY - posRef.current.y) * k;
        // facing: depends on cursor direction
        posRef.current.facing = target.x > posRef.current.x + size * 0.4 ? 1 : -1;
      }
      const bob = Math.sin(t / 140) * 4;
      el.style.transform =
        `translate(${posRef.current.x}px, ${posRef.current.y + bob}px) ` +
        `scaleX(${posRef.current.facing})`;
      raf = requestAnimationFrame(frame);
    }
    raf = requestAnimationFrame(frame);
    return () => {
      cancelAnimationFrame(raf);
      if (mode === 'follow') root.removeEventListener('pointermove', onMove);
    };
  }, [mode, containerRef, size, bottomOffset]);

  return (
    <div ref={ref} className="walking-lady" style={{
      position: 'absolute', left: 0, top: 0,
      width: size, height: size * 1.1,
      pointerEvents: 'none', zIndex: 8,
      willChange: 'transform',
      transform: `translate(-${size + 100}px, 0)`,
    }}>
      <img src="sprites/lady.png" alt="" draggable="false"
           style={{ width: '100%', height: '100%', objectFit: 'contain',
                    animation: 'lady-step 0.6s steps(2) infinite',
                    transformOrigin: 'bottom center' }} />
    </div>
  );
}

// ── chugging train (bottom rail) ───────────────────────────────────────
// The train + track are baked into one PNG, so we
// loop the image horizontally for a continuous run.
function ChuggingTrain({ containerRef, height = 200, speed = 0.07 }) {
  const ref = React.useRef(null);
  React.useEffect(() => {
    const root = containerRef?.current;
    const el = ref.current;
    if (!root || !el) return;
    let raf, last = performance.now();
    // train width relative to container; start mostly offscreen-right
    let x = root.clientWidth - el.clientWidth * 0.45;
    function frame(t) {
      const dt = Math.min(64, t - last); last = t;
      const W = root.clientWidth;
      x -= speed * dt;
      // when the train fully exits to the left, snap back
      if (x < -el.clientWidth - 100) x = W - el.clientWidth * 0.4;
      const bob = Math.sin(t / 110) * 1.5;
      el.style.transform = `translate(${x}px, ${bob}px)`;
      raf = requestAnimationFrame(frame);
    }
    raf = requestAnimationFrame(frame);
    return () => cancelAnimationFrame(raf);
  }, [containerRef, speed]);

  return (
    <div className="train-track">
      <div ref={ref} className="train-car" style={{ height }}>
        <img src="sprites/v2-train.png" alt="" draggable="false"
             style={{ height: '100%', display: 'block' }} />
      </div>
    </div>
  );
}

Object.assign(window, {
  SALE_DATE, SALE_END, PALETTES, applyPaletteVars,
  useCountdown, useConfetti, WalkingLady, ChuggingTrain,
});
