/* ════════════════════════════════════════════════════════════
   P2-5 · Pull to Refresh — iOS style
   Wrap any scrollable container; pulls past 60px triggers refresh.
   ════════════════════════════════════════════════════════════ */

const { useState: p2r_s, useEffect: p2r_e, useRef: p2r_r } = React;

function PullToRefresh({ onRefresh, children, scrollRef }) {
  const [pull, setPull] = p2r_s(0);
  const [refreshing, setRefreshing] = p2r_s(false);
  const startY = p2r_r(0);
  const dragging = p2r_r(false);
  const wrapRef = p2r_r(null);
  const threshold = 64;
  const lastFired = p2r_r(false);

  p2r_e(() => {
    const el = scrollRef?.current || wrapRef.current;
    if (!el) return;
    const onDown = (e) => {
      if (el.scrollTop > 0) return;
      startY.current = e.clientY;
      dragging.current = true;
    };
    const onMove = (e) => {
      if (!dragging.current) return;
      const d = e.clientY - startY.current;
      if (d <= 0) return setPull(0);
      const damp = d > threshold ? threshold + (d - threshold) * 0.4 : d;
      setPull(damp);
      if (damp > threshold && !lastFired.current) { window.haptic?.medium(); lastFired.current = true; }
      else if (damp <= threshold && lastFired.current) { lastFired.current = false; }
    };
    const onUp = async () => {
      if (!dragging.current) return;
      dragging.current = false;
      if (pull > threshold && !refreshing) {
        setRefreshing(true);
        setPull(threshold);
        window.haptic?.success();
        try { await onRefresh?.(); } catch (e) {}
        setRefreshing(false);
        setPull(0);
      } else {
        setPull(0);
      }
      lastFired.current = false;
    };
    el.addEventListener('pointerdown', onDown);
    el.addEventListener('pointermove', onMove);
    el.addEventListener('pointerup',   onUp);
    el.addEventListener('pointercancel', onUp);
    return () => {
      el.removeEventListener('pointerdown', onDown);
      el.removeEventListener('pointermove', onMove);
      el.removeEventListener('pointerup',   onUp);
      el.removeEventListener('pointercancel', onUp);
    };
  }, [pull, refreshing]);

  const progress = Math.min(1, pull / threshold);
  return (
    <div ref={wrapRef} className="ptr-wrap" style={{ position: 'relative' }}>
      <div className="ptr-indicator" style={{
        height: pull,
        opacity: progress,
      }}>
        <div className={'ptr-spinner' + (refreshing ? ' on' : '')} style={{
          transform: `rotate(${progress * 360}deg) scale(${0.4 + progress * 0.6})`
        }}>
          <span/><span/><span/>
        </div>
      </div>
      <div style={{ transform: `translateY(${pull}px)`, transition: dragging.current ? 'none' : 'transform var(--dur-slow) var(--ease-spring-soft)' }}>
        {children}
      </div>
    </div>
  );
}
window.PullToRefresh = PullToRefresh;

/* ════════════════════════════════════════════════════════════
   P3-1 · Inline Reaction — tiny floater for likes/votes
   ════════════════════════════════════════════════════════════ */
function InlineReact({ value, onChange, icon = '♥', max = 99 }) {
  const [pop, setPop] = p2r_s(false);
  const v = value || 0;
  return (
    <button className={'inline-react' + (v ? ' on' : '') + (pop ? ' pop' : '')}
            onClick={() => { onChange?.(v ? 0 : 1); setPop(true); window.haptic?.light(); setTimeout(() => setPop(false), 260); }}>
      <span className="ir-icon">{icon}</span>
      {v > 0 && <span className="ir-count">{v > max ? `${max}+` : v}</span>}
    </button>
  );
}
window.InlineReact = InlineReact;

/* ════════════════════════════════════════════════════════════
   P11 · Live Region for ARIA announcements
   ════════════════════════════════════════════════════════════ */
(function () {
  let region;
  function ensure() {
    if (region) return region;
    region = document.createElement('div');
    region.setAttribute('aria-live', 'polite');
    region.setAttribute('aria-atomic', 'true');
    region.style.cssText = 'position:fixed;width:1px;height:1px;clip:rect(0 0 0 0);overflow:hidden;';
    document.body.appendChild(region);
    return region;
  }
  window.announce = function (msg) {
    const r = ensure();
    r.textContent = '';
    setTimeout(() => { r.textContent = msg; }, 50);
  };
})();
