/* ============================================================
   mobile-sheets.jsx
   Types de fenêtres mobiles + composants spécifiques.
   Chaque type a un nom système ET un cas d'usage préconisé.
   ============================================================ */

const { useState: uS, useRef: rS, useEffect: eS } = React;

/* ============================================================
   BottomSheet — feuille modale qui monte du bas
   Nom système : BottomSheet
   Cas d'usage : action contextuelle, formulaire court, choix
                 dans une liste. À privilégier sur mobile à la
                 place d'une popup centrée (plus accessible au pouce).
   Gestes : swipe down pour fermer.
   ============================================================ */
function BottomSheet({ open, onClose, title, children, footer, height = 'auto' }) {
  const [dragY, setDragY] = uS(0);
  const [closing, setClosing] = uS(false);
  const startY = rS(0);

  eS(() => {
    if (open) { setDragY(0); setClosing(false); }
  }, [open]);

  if (!open && !closing) return null;

  const onStart = (e) => {
    startY.current = (e.touches ? e.touches[0].clientY : e.clientY);
  };
  const onMove = (e) => {
    const y = (e.touches ? e.touches[0].clientY : e.clientY);
    const d = Math.max(0, y - startY.current);
    setDragY(d);
  };
  const onEnd = () => {
    if (dragY > 80) {
      setClosing(true);
      setTimeout(() => { setClosing(false); setDragY(0); onClose(); }, 200);
    } else {
      setDragY(0);
    }
  };

  return (
    <div onClick={onClose} style={{
      position: 'absolute', inset: 0, zIndex: 200,
      background: `rgba(0,0,0,${closing ? 0 : 0.5 * (1 - dragY / 400)})`,
      transition: 'background .2s',
      display: 'flex', alignItems: 'flex-end',
    }}>
      <div onClick={(e) => e.stopPropagation()} style={{
        width: '100%',
        maxHeight: '85%',
        height: height === 'auto' ? 'auto' : height,
        background: 'var(--bg-2)',
        borderTop: '1px solid var(--border-2)',
        borderRadius: '20px 20px 0 0',
        boxShadow: '0 -8px 32px rgba(0,0,0,0.5)',
        transform: `translateY(${closing ? '100%' : dragY + 'px'})`,
        transition: closing ? 'transform .2s ease-in' : (dragY === 0 ? 'transform .3s cubic-bezier(.3,.7,.3,1.2)' : 'none'),
        display: 'flex', flexDirection: 'column',
        overflow: 'hidden',
      }}>
        {/* Drag handle */}
        <div onTouchStart={onStart} onTouchMove={onMove} onTouchEnd={onEnd}
             onMouseDown={onStart}
             style={{
               padding: '10px 0 6px',
               display: 'flex', justifyContent: 'center',
               cursor: 'grab', touchAction: 'none',
             }}>
          <div style={{
            width: 36, height: 5, borderRadius: 3,
            background: 'var(--ink-4)',
          }}/>
        </div>
        {title && (
          <div style={{
            padding: '0 18px 12px',
            display: 'flex', alignItems: 'center', gap: 8,
            borderBottom: '1px solid var(--border-1)',
          }}>
            <div style={{ flex: 1, fontSize: 17, fontWeight: 700 }}>{title}</div>
            <button onClick={onClose} style={{
              width: 30, height: 30, borderRadius: '50%',
              background: 'var(--bg-4)', border: 'none', color: 'var(--ink-2)',
              display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
              cursor: 'pointer', padding: 0,
              WebkitTapHighlightColor: 'transparent',
            }}><Icon name="close" size={12} /></button>
          </div>
        )}
        <div style={{ flex: 1, overflowY: 'auto', padding: 16 }}>{children}</div>
        {footer && (
          <div style={{
            padding: '12px 16px 22px',
            borderTop: '1px solid var(--border-1)',
            display: 'flex', gap: 8,
          }}>{footer}</div>
        )}
      </div>
    </div>
  );
}

/* ============================================================
   ActionSheet — menu d'actions style iOS
   Nom système : ActionSheet
   Cas d'usage : choix parmi 2-6 actions sur un élément
                 (équivalent menu contextuel desktop).
   ============================================================ */
function ActionSheet({ open, onClose, title, actions, cancelLabel = 'Annuler' }) {
  if (!open) return null;
  return (
    <div onClick={onClose} style={{
      position: 'absolute', inset: 0, zIndex: 200,
      background: 'rgba(0,0,0,0.5)',
      display: 'flex', alignItems: 'flex-end',
      padding: 10,
      animation: 'as-fade .2s',
    }}>
      <style>{`
        @keyframes as-fade { from { opacity: 0 } to { opacity: 1 } }
        @keyframes as-slide { from { transform: translateY(100%) } to { transform: translateY(0) } }
      `}</style>
      <div onClick={(e) => e.stopPropagation()} style={{
        width: '100%',
        display: 'flex', flexDirection: 'column', gap: 8,
        animation: 'as-slide .25s cubic-bezier(.3,.7,.3,1.2)',
      }}>
        <div style={{
          background: 'var(--bg-3)',
          border: '1px solid var(--border-2)',
          borderRadius: 14,
          overflow: 'hidden',
          boxShadow: 'var(--shadow-3)',
        }}>
          {title && (
            <div style={{
              padding: '12px 16px',
              fontSize: 12, color: 'var(--ink-3)',
              textAlign: 'center',
              borderBottom: '1px solid var(--border-1)',
            }}>{title}</div>
          )}
          {actions.map((a, i) => (
            <button key={i} onClick={() => { onClose(); a.onClick && a.onClick(); }}
              className="touch-press"
              style={{
                width: '100%', minHeight: 52,
                background: 'transparent', border: 'none',
                borderTop: i === 0 || (title && i === 0) ? 'none' : '1px solid var(--border-1)',
                color: a.danger ? 'var(--err)' : 'var(--accent)',
                fontFamily: 'var(--font-ui)', fontSize: 16, fontWeight: a.primary ? 700 : 500,
                cursor: 'pointer',
                display: 'inline-flex', alignItems: 'center', justifyContent: 'center', gap: 8,
                WebkitTapHighlightColor: 'transparent',
              }}>
              {a.icon && <Icon name={a.icon} size={16} />}
              {a.label}
            </button>
          ))}
        </div>
        <button onClick={onClose} className="touch-press" style={{
          width: '100%', minHeight: 52,
          background: 'var(--bg-3)',
          border: '1px solid var(--border-2)',
          borderRadius: 14,
          color: 'var(--accent)',
          fontFamily: 'var(--font-ui)', fontSize: 16, fontWeight: 700,
          cursor: 'pointer',
          boxShadow: 'var(--shadow-2)',
        }}>{cancelLabel}</button>
      </div>
    </div>
  );
}

/* ============================================================
   AlertDialog — alerte modale centrée
   Nom système : AlertDialog
   Cas d'usage : message critique, demande de confirmation
                 ferme (suppression, déconnexion).
   ============================================================ */
function AlertDialog({ open, onClose, icon, iconColor, title, message, actions }) {
  if (!open) return null;
  return (
    <div style={{
      position: 'absolute', inset: 0, zIndex: 200,
      background: 'rgba(0,0,0,0.55)',
      backdropFilter: 'blur(4px)',
      display: 'flex', alignItems: 'center', justifyContent: 'center',
      padding: 24,
      animation: 'as-fade .2s',
    }}>
      <div style={{
        width: '100%', maxWidth: 320,
        background: 'var(--bg-3)',
        border: '1px solid var(--border-2)',
        borderRadius: 18,
        overflow: 'hidden',
        boxShadow: 'var(--shadow-3)',
        animation: 'pop-in .25s cubic-bezier(.3,.7,.3,1.2)',
      }}>
        <style>{`@keyframes pop-in { from { opacity: 0; transform: scale(.92) } to { opacity: 1; transform: scale(1) } }`}</style>
        <div style={{
          padding: '22px 22px 18px',
          textAlign: 'center',
        }}>
          {icon && (
            <div style={{
              width: 48, height: 48, borderRadius: '50%',
              background: `color-mix(in oklch, ${iconColor || 'var(--accent)'} 18%, transparent)`,
              color: iconColor || 'var(--accent)',
              display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
              marginBottom: 12,
            }}>
              <Icon name={icon} size={24} />
            </div>
          )}
          <div style={{ fontSize: 17, fontWeight: 700, color: 'var(--ink-1)', marginBottom: 6 }}>{title}</div>
          {message && <div style={{ fontSize: 14, color: 'var(--ink-2)', lineHeight: 1.4 }}>{message}</div>}
        </div>
        <div style={{
          display: 'flex',
          borderTop: '1px solid var(--border-1)',
        }}>
          {actions.map((a, i) => (
            <button key={i} onClick={() => { onClose(); a.onClick && a.onClick(); }}
              className="touch-press"
              style={{
                flex: 1, minHeight: 46,
                background: 'transparent', border: 'none',
                borderLeft: i > 0 ? '1px solid var(--border-1)' : 'none',
                color: a.danger ? 'var(--err)' : 'var(--accent)',
                fontFamily: 'var(--font-ui)', fontSize: 15,
                fontWeight: a.primary ? 700 : 500,
                cursor: 'pointer',
                WebkitTapHighlightColor: 'transparent',
              }}>{a.label}</button>
          ))}
        </div>
      </div>
    </div>
  );
}

/* ============================================================
   Toast — notification éphémère en haut
   Nom système : Toast
   Cas d'usage : feedback succès/erreur après une action.
                 Disparaît automatiquement après 2.5s.
   ============================================================ */
function Toast({ open, onClose, icon, message, variant = 'ok', duration = 2500 }) {
  eS(() => {
    if (open) {
      const t = setTimeout(onClose, duration);
      return () => clearTimeout(t);
    }
  }, [open, duration, onClose]);
  if (!open) return null;
  const colors = {
    ok:   { bg: 'var(--ok)',   fg: 'var(--bg-1)', icon: 'play' },
    warn: { bg: 'var(--warn)', fg: 'var(--bg-1)', icon: 'alert' },
    err:  { bg: 'var(--err)',  fg: '#fff',        icon: 'close' },
    info: { bg: 'var(--info)', fg: 'var(--bg-1)', icon: 'bell' },
  }[variant];
  return (
    <div style={{
      position: 'absolute', top: 50, left: 16, right: 16, zIndex: 300,
      padding: '12px 16px',
      background: colors.bg,
      color: colors.fg,
      borderRadius: 12,
      display: 'flex', alignItems: 'center', gap: 10,
      boxShadow: '0 8px 24px rgba(0,0,0,0.4)',
      animation: 'toast-in .3s cubic-bezier(.3,.7,.3,1.2)',
      fontFamily: 'var(--font-ui)', fontSize: 14, fontWeight: 600,
    }}>
      <style>{`@keyframes toast-in { from { opacity: 0; transform: translateY(-12px) } to { opacity: 1; transform: translateY(0) } }`}</style>
      <Icon name={icon || colors.icon} size={18} />
      <span style={{ flex: 1 }}>{message}</span>
    </div>
  );
}

/* ============================================================
   FAB — Floating Action Button (Android Material)
   Nom système : FAB
   Cas d'usage : action principale unique sur un écran
                 (créer, ajouter). Toujours en bas à droite.
   ============================================================ */
function FAB({ icon, label, onClick }) {
  return (
    <button onClick={onClick} className="touch-press" style={{
      position: 'absolute', bottom: 90, right: 18,
      width: 56, height: 56, borderRadius: '50%',
      background: 'var(--accent)',
      color: 'var(--bg-1)',
      border: 'none',
      display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
      cursor: 'pointer',
      boxShadow: '0 6px 18px var(--accent-glow), inset 0 1px 0 rgba(255,255,255,0.25), 0 2px 6px rgba(0,0,0,0.4)',
      zIndex: 50,
      WebkitTapHighlightColor: 'transparent',
    }} aria-label={label}>
      <Icon name={icon} size={22} />
    </button>
  );
}

/* ============================================================
   PullToRefresh — wrapper pour rafraîchir au pull-down
   Nom système : PullToRefresh
   Geste associé : swipe down depuis le haut du contenu.
   ============================================================ */
function PullToRefresh({ onRefresh, children }) {
  const [pull, setPull] = uS(0);
  const [refreshing, setRefreshing] = uS(false);
  const startY = rS(0);
  const wrap = rS();

  const onStart = (e) => {
    if (wrap.current && wrap.current.scrollTop === 0) {
      startY.current = e.touches[0].clientY;
    } else {
      startY.current = null;
    }
  };
  const onMove = (e) => {
    if (startY.current == null) return;
    const d = e.touches[0].clientY - startY.current;
    if (d > 0) setPull(Math.min(d, 100));
  };
  const onEnd = async () => {
    if (pull > 60 && !refreshing) {
      setRefreshing(true);
      setPull(60);
      try { await Promise.resolve(onRefresh && onRefresh()); }
      finally {
        await new Promise((r) => setTimeout(r, 600));
        setRefreshing(false);
        setPull(0);
      }
    } else {
      setPull(0);
    }
    startY.current = null;
  };

  return (
    <div ref={wrap}
         onTouchStart={onStart} onTouchMove={onMove} onTouchEnd={onEnd}
         style={{ position: 'relative', overflowY: 'auto', height: '100%', WebkitOverflowScrolling: 'touch' }}>
      {/* indicateur */}
      <div style={{
        position: 'absolute', top: -20 + pull, left: 0, right: 0,
        display: 'flex', justifyContent: 'center',
        transition: pull === 0 || pull === 60 ? 'top .2s ease-out' : 'none',
        pointerEvents: 'none',
        zIndex: 10,
      }}>
        <div style={{
          width: 32, height: 32, borderRadius: '50%',
          background: 'var(--bg-3)',
          border: '1px solid var(--border-2)',
          display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
          color: 'var(--accent)',
          boxShadow: 'var(--shadow-2)',
        }}>
          <Icon name="refresh" size={14} style={{
            transform: `rotate(${pull * 4}deg)`,
            animation: refreshing ? 'spin 1s linear infinite' : 'none',
            transition: refreshing ? 'none' : 'transform .1s linear',
          }} />
          <style>{`@keyframes spin { to { transform: rotate(360deg) } }`}</style>
        </div>
      </div>
      <div style={{
        transform: `translateY(${pull}px)`,
        transition: pull === 0 || pull === 60 ? 'transform .2s ease-out' : 'none',
      }}>{children}</div>
    </div>
  );
}

Object.assign(window, {
  BottomSheet, ActionSheet, AlertDialog, Toast, FAB, PullToRefresh,
});
