/* ============================================================
   mobile-gestures.jsx
   Détecteur de gestes nommés pour smartphone.
   Chaque geste a un NOM SYSTÈME, et un composant de TEST.
   ============================================================ */

const { useState: uG, useRef: rG, useEffect: eG } = React;

/* ============================================================
   useGesture — hook bas niveau qui détecte les gestes
   Renvoie : { onTouchStart, onTouchMove, onTouchEnd } à attacher
   au composant qui doit recevoir les gestes.
   Callbacks supportés :
     onTap            tap simple (< 200ms, ne bouge pas)
     onDoubleTap      double-tap (deux tap rapides)
     onLongPress      long press (≥ 500ms sans bouger)
     onSwipeLeft      swipe vers la gauche
     onSwipeRight     swipe vers la droite
     onSwipeUp        swipe vers le haut
     onSwipeDown      swipe vers le bas
     onPanStart       début de glisser
     onPan            cours de glisser ({dx, dy})
     onPanEnd         fin de glisser
     onPinch          pincement ({scale, dx, dy})
   ============================================================ */
function useGesture(handlers = {}) {
  const state = rG({
    sx: 0, sy: 0, st: 0,
    lx: 0, ly: 0, lt: 0,
    moved: false, longPressTimer: null,
    lastTap: 0, lastTapPos: null,
    pinching: false, startDist: 0,
  });

  const reset = () => {
    if (state.current.longPressTimer) clearTimeout(state.current.longPressTimer);
  };

  const onTouchStart = (e) => {
    const t = e.touches[0];
    state.current.sx = t.clientX;
    state.current.sy = t.clientY;
    state.current.lx = t.clientX;
    state.current.ly = t.clientY;
    state.current.st = Date.now();
    state.current.lt = Date.now();
    state.current.moved = false;

    // Pinch detection
    if (e.touches.length === 2) {
      const dx = e.touches[1].clientX - t.clientX;
      const dy = e.touches[1].clientY - t.clientY;
      state.current.startDist = Math.hypot(dx, dy);
      state.current.pinching = true;
      return;
    }

    // Long press
    if (handlers.onLongPress) {
      state.current.longPressTimer = setTimeout(() => {
        if (!state.current.moved) {
          handlers.onLongPress({ x: t.clientX, y: t.clientY });
          state.current.moved = true; // empêche d'autres détections
        }
      }, 500);
    }
    handlers.onPanStart && handlers.onPanStart({ x: t.clientX, y: t.clientY });
  };

  const onTouchMove = (e) => {
    const t = e.touches[0];
    const dx = t.clientX - state.current.sx;
    const dy = t.clientY - state.current.sy;

    if (Math.abs(dx) > 10 || Math.abs(dy) > 10) {
      state.current.moved = true;
      reset();
    }

    if (state.current.pinching && e.touches.length === 2) {
      const px = e.touches[1].clientX - t.clientX;
      const py = e.touches[1].clientY - t.clientY;
      const dist = Math.hypot(px, py);
      const scale = dist / state.current.startDist;
      handlers.onPinch && handlers.onPinch({ scale, dx, dy });
      return;
    }

    handlers.onPan && handlers.onPan({ dx, dy, x: t.clientX, y: t.clientY });

    state.current.lx = t.clientX;
    state.current.ly = t.clientY;
    state.current.lt = Date.now();
  };

  const onTouchEnd = (e) => {
    reset();
    const dx = state.current.lx - state.current.sx;
    const dy = state.current.ly - state.current.sy;
    const dt = Date.now() - state.current.st;

    handlers.onPanEnd && handlers.onPanEnd({ dx, dy });

    if (state.current.pinching) {
      state.current.pinching = false;
      return;
    }

    if (state.current.moved && dt < 500) {
      const absX = Math.abs(dx), absY = Math.abs(dy);
      if (absX > 50 || absY > 50) {
        if (absX > absY) {
          if (dx > 0) handlers.onSwipeRight && handlers.onSwipeRight({ dx, dt });
          else        handlers.onSwipeLeft  && handlers.onSwipeLeft({ dx, dt });
        } else {
          if (dy > 0) handlers.onSwipeDown  && handlers.onSwipeDown({ dy, dt });
          else        handlers.onSwipeUp    && handlers.onSwipeUp({ dy, dt });
        }
      }
    } else if (!state.current.moved && dt < 200) {
      // Tap / DoubleTap
      const now = Date.now();
      const pos = { x: state.current.lx, y: state.current.ly };
      const lp  = state.current.lastTapPos;
      if (now - state.current.lastTap < 300 && lp && Math.hypot(pos.x - lp.x, pos.y - lp.y) < 30) {
        handlers.onDoubleTap && handlers.onDoubleTap(pos);
        state.current.lastTap = 0;
      } else {
        handlers.onTap && handlers.onTap(pos);
        state.current.lastTap = now;
        state.current.lastTapPos = pos;
      }
    }
  };

  return { onTouchStart, onTouchMove, onTouchEnd };
}

/* ============================================================
   GestureZone — zone tactile de test
   Affiche le dernier geste détecté + un journal des gestes.
   Toutes les actions sont nommées explicitement.
   ============================================================ */
function GestureZone({ label, accept = [] }) {
  const [last, setLast] = uG(null);
  const [log, setLog] = uG([]);
  const [count, setCount] = uG({});
  const [trail, setTrail] = uG(null);

  const fire = (name, data) => {
    setLast({ name, data, time: Date.now() });
    setLog((l) => [{ name, t: new Date().toLocaleTimeString('fr-FR', { hour12: false }) }, ...l].slice(0, 5));
    setCount((c) => ({ ...c, [name]: (c[name] || 0) + 1 }));
  };

  const hAll = {
    onTap:        () => fire('Tap'),
    onDoubleTap:  () => fire('DoubleTap'),
    onLongPress:  () => fire('LongPress'),
    onSwipeLeft:  () => fire('SwipeLeft'),
    onSwipeRight: () => fire('SwipeRight'),
    onSwipeUp:    () => fire('SwipeUp'),
    onSwipeDown:  () => fire('SwipeDown'),
    onPan:        ({ dx, dy }) => setTrail({ dx, dy }),
    onPanEnd:     () => setTrail(null),
    onPinch:      ({ scale }) => fire('Pinch', { scale: scale.toFixed(2) }),
  };
  // Filtre uniquement les handlers demandés
  const h = accept.length === 0 ? hAll : Object.fromEntries(
    Object.entries(hAll).filter(([k]) => accept.some((n) => k.toLowerCase().includes(n.toLowerCase())))
  );
  const gesture = useGesture(h);

  return (
    <div style={{
      background: 'var(--bg-3)',
      border: '1px solid var(--border-2)',
      borderRadius: 12,
      overflow: 'hidden',
      boxShadow: 'var(--tile-3d)',
      marginBottom: 12,
    }}>
      {label && (
        <div style={{
          padding: '10px 14px',
          fontFamily: 'var(--font-mono)', fontSize: 11,
          letterSpacing: '0.08em', textTransform: 'uppercase',
          color: 'var(--ink-3)',
          background: 'var(--bg-2)',
          borderBottom: '1px solid var(--border-1)',
        }}>{label}</div>
      )}
      <div {...gesture}
           style={{
             height: 200,
             position: 'relative',
             background: `repeating-linear-gradient(45deg, var(--bg-3) 0 14px, var(--bg-4) 14px 15px)`,
             touchAction: 'none',
             userSelect: 'none',
             WebkitUserSelect: 'none',
             cursor: 'grab',
             display: 'flex', alignItems: 'center', justifyContent: 'center',
             overflow: 'hidden',
           }}>
        {/* indicateur central */}
        <div style={{
          fontFamily: 'var(--font-mono)', fontSize: 13,
          color: 'var(--ink-3)', textAlign: 'center',
          padding: 16, pointerEvents: 'none',
        }}>
          {last ? (
            <div style={{
              animation: 'gp-pop .3s cubic-bezier(.3,.7,.3,1.2)',
              fontSize: 22, fontWeight: 700, color: 'var(--accent)',
              fontFamily: 'var(--font-ui)',
            }}>
              {last.name}
              {last.data && (
                <div style={{ fontSize: 11, color: 'var(--ink-3)', fontFamily: 'var(--font-mono)', marginTop: 4 }}>
                  {Object.entries(last.data).map(([k, v]) => `${k}: ${v}`).join(' · ')}
                </div>
              )}
            </div>
          ) : (
            <span>essaie un geste ici</span>
          )}
          <style>{`@keyframes gp-pop { from { opacity: 0; transform: scale(.85) } to { opacity: 1; transform: scale(1) } }`}</style>
        </div>
        {/* trail visuel pendant le pan */}
        {trail && (
          <div style={{
            position: 'absolute',
            top: '50%', left: '50%',
            width: 14, height: 14,
            borderRadius: '50%',
            background: 'var(--accent)',
            boxShadow: '0 0 12px var(--accent-glow)',
            transform: `translate(calc(-50% + ${trail.dx}px), calc(-50% + ${trail.dy}px))`,
            pointerEvents: 'none',
          }} />
        )}
      </div>
      {/* Journal */}
      {log.length > 0 && (
        <div style={{
          padding: '8px 14px 10px',
          background: 'var(--bg-2)',
          borderTop: '1px solid var(--border-1)',
          fontFamily: 'var(--font-mono)', fontSize: 11,
          color: 'var(--ink-3)',
          display: 'flex', flexDirection: 'column', gap: 2,
        }}>
          <div style={{
            display: 'flex', justifyContent: 'space-between',
            fontSize: 9, letterSpacing: '0.08em', textTransform: 'uppercase',
            color: 'var(--ink-4)', marginBottom: 4,
          }}>
            <span>journal</span>
            <span>{log.length} dernier{log.length > 1 ? 's' : ''}</span>
          </div>
          {log.map((l, i) => (
            <div key={i} style={{ opacity: 1 - i * 0.15 }}>
              <span style={{ color: 'var(--ink-4)' }}>{l.t}</span>{' '}
              <span style={{ color: 'var(--accent)' }}>{l.name}</span>
            </div>
          ))}
        </div>
      )}
    </div>
  );
}

/* Catalogue des gestes — utile pour affichage + onglet d'aide */
const GESTURE_CATALOG = [
  { name: 'Tap',        icon: 'play',      desc: 'Pression rapide sur l\'écran.',  usage: 'Action principale (équiv. clic).' },
  { name: 'DoubleTap',  icon: 'plus',      desc: 'Deux Tap rapprochés (<300 ms).', usage: 'Zoomer une image, liker (style Instagram).' },
  { name: 'LongPress',  icon: 'clock',     desc: 'Pression maintenue ≥ 500 ms.',   usage: 'Ouvrir un menu contextuel, sélectionner.' },
  { name: 'SwipeLeft',  icon: 'chevL',     desc: 'Glisser le doigt vers la gauche.', usage: 'Naviguer à l\'écran suivant, supprimer une ligne.' },
  { name: 'SwipeRight', icon: 'chevR',     desc: 'Glisser le doigt vers la droite.', usage: 'Retour à l\'écran précédent, archiver.' },
  { name: 'SwipeUp',    icon: 'chevU',     desc: 'Glisser vers le haut.',           usage: 'Voir plus de détails, fermer une popup.' },
  { name: 'SwipeDown',  icon: 'chevD',     desc: 'Glisser vers le bas.',            usage: 'Rafraîchir (PullToRefresh), fermer une BottomSheet.' },
  { name: 'Pan',        icon: 'grid',      desc: 'Glisser en continu (drag).',      usage: 'Déplacer un élément, scroll horizontal.' },
  { name: 'Pinch',      icon: 'search',    desc: 'Écarter / rapprocher 2 doigts.',  usage: 'Zoomer une carte, une image.' },
];

Object.assign(window, { useGesture, GestureZone, GESTURE_CATALOG });
