/**
 * Oveyo PWA — Composants partagés réutilisables
 * Style Vivinter : cards blanches + barre dégradée signature en bas
 */

// ============================================================
// GRADIENT BAR (signature Vivinter sous chaque card)
// ============================================================
const GradientBar = () => (
  <div
    className="h-[3px] w-full"
    style={{ background: 'linear-gradient(90deg, #102A43 0%, #F4632B 50%, #FFA45B 100%)' }}
  />
);

// ============================================================
// CARD avec gradient bar — pattern principal Vivinter
// ============================================================
const Card = ({ children, className = '', noBar = false, ...rest }) => (
  <div
    className={`bg-white rounded-2xl overflow-hidden ${className}`}
    style={{ boxShadow: '0 1px 0 rgba(16,42,67,0.04), 0 4px 20px rgba(16,42,67,0.05)' }}
    {...rest}
  >
    {children}
    {!noBar && <GradientBar />}
  </div>
);

// ============================================================
// ICON BUBBLE — bonbonnière gris-bleu derrière les icônes (Vivinter style)
// ============================================================
const IconBubble = ({ children, color = 'navy', size = 'md', className = '' }) => {
  const sizes = {
    sm: 'w-8 h-8 rounded-lg',
    md: 'w-10 h-10 rounded-xl',
    lg: 'w-12 h-12 rounded-xl',
    xl: 'w-14 h-14 rounded-2xl',
  };
  const colors = {
    navy: { bg: '#E8EBF0', icon: '#102A43' },
    orange: { bg: '#FEEEE3', icon: '#F4632B' },
    success: { bg: '#E8F5E9', icon: '#15803D' },
    slate: { bg: '#F1F4F9', icon: '#6B7891' },
  };
  const c = colors[color] || colors.navy;
  return (
    <div
      className={`${sizes[size]} flex items-center justify-center flex-shrink-0 ${className}`}
      style={{ background: c.bg }}
    >
      {React.cloneElement(children, { style: { color: c.icon, ...children.props.style } })}
    </div>
  );
};

// ============================================================
// FLASH TOAST (notification temporaire)
// ============================================================
const FlashContext = React.createContext(null);
const FlashProvider = ({ children }) => {
  const [flash, setFlash] = React.useState(null);
  const show = (type, message, duration = 3500) => {
    setFlash({ type, message });
    setTimeout(() => setFlash(null), duration);
  };
  return (
    <FlashContext.Provider value={{ show }}>
      {children}
      {flash && (
        <div
          className="fixed left-4 right-4 z-[10100] anim-slide rounded-2xl p-3.5 flex items-start gap-2.5 text-sm font-medium shadow-2xl"
          style={{
            top: 'calc(env(safe-area-inset-top, 20px) + 16px)',
            background:
              flash.type === 'success'
                ? '#15803D'
                : flash.type === 'error'
                ? '#DC2626'
                : flash.type === 'warning'
                ? '#F4632B'
                : '#102A43',
            color: 'white',
          }}
        >
          <div className="flex-1">{flash.message}</div>
          <button onClick={() => setFlash(null)} className="text-white/80 text-xl leading-none">
            ×
          </button>
        </div>
      )}
    </FlashContext.Provider>
  );
};
const useFlash = () => React.useContext(FlashContext);

// ============================================================
// SHEET / BOTTOM MODAL
// ============================================================
// V3.6 — corrections rigoureuses du scroll des sheets sur iOS Safari mobile :
//
//   PROBLÈME : `max-height: 92vh` se calcule contre le viewport **complet**
//   (y compris la zone occupée par la toolbar Safari), alors que
//   `position: fixed; bottom: 0` se positionne au-dessus de la toolbar.
//   Conséquence : le bas du sheet est masqué par la toolbar Safari, le
//   scroll natif n'a pas conscience de ces 80-100px cachés, et les
//   boutons "Envoyer" se retrouvent inaccessibles.
//
//   SOLUTION : on calcule la hauteur réellement visible via
//   `window.visualViewport.height` (la seule source de vérité quand la
//   toolbar Safari change d'état) et on l'applique en pixels. Recalculé
//   à chaque resize visualViewport (rotation, apparition/disparition
//   de la toolbar, clavier qui s'ouvre, etc.).
//
//   Compteur global pour ne pas réinitialiser body.overflow quand un
//   sheet se ferme alors qu'un autre est encore ouvert.
let _sheetOpenCount = 0;

const Sheet = ({ open, onClose, title, children, maxHeight = '92vh' }) => {
  // Hauteur dynamique en pixels, basée sur la vraie zone visible.
  const [computedMaxH, setComputedMaxH] = React.useState(maxHeight);

  React.useEffect(() => {
    if (!open) return;
    _sheetOpenCount += 1;
    document.body.style.overflow = 'hidden';
    // V4.1 — classe sur body pour permettre du CSS conditionnel
    // (notamment cacher la carte Leaflet derrière le sheet)
    document.body.classList.add('has-sheet-open');

    const recompute = () => {
      const vv = window.visualViewport;
      const h = vv ? vv.height : window.innerHeight;
      // V4.0 — On retire ~92px (offset bottom : tabbar 80px + ~12px de safe-area)
      // pour que la maxHeight reflète l'espace VRAIMENT disponible pour le sheet.
      // Avant : Math.floor(h * 0.92) → le sheet pouvait théoriquement dépasser
      // l'écran par le haut (titre coupé sur iPhone X+ avec encoche).
      const usableH = Math.max(280, h - 92);
      setComputedMaxH(`${Math.floor(usableH)}px`);
    };
    recompute();

    const vv = window.visualViewport;
    if (vv) {
      vv.addEventListener('resize', recompute);
      vv.addEventListener('scroll', recompute);
    }
    window.addEventListener('resize', recompute);

    return () => {
      _sheetOpenCount = Math.max(0, _sheetOpenCount - 1);
      if (_sheetOpenCount === 0) {
        document.body.style.overflow = '';
        document.body.classList.remove('has-sheet-open');
      }
      if (vv) {
        vv.removeEventListener('resize', recompute);
        vv.removeEventListener('scroll', recompute);
      }
      window.removeEventListener('resize', recompute);
    };
  }, [open, maxHeight]);

  if (!open) return null;

  return (
    <>
      <div
        className="fixed inset-0 z-[9999] anim-fade-in"
        style={{
          // V4.0 — Opacité montée à 75% (vs 55%) pour vraiment masquer
          // ce qui est derrière (la carte Leaflet de la page Carte
          // restait trop visible avec 55%).
          background: 'rgba(15,42,67,0.75)',
          backdropFilter: 'blur(4px)',
          touchAction: 'none',
          overscrollBehavior: 'none',
          transform: 'translateZ(0)',
          willChange: 'opacity',
        }}
        onClick={onClose}
      />
      {/* V3.8 P2 — refonte scroll :
          1) Le sheet s'arrête AU-DESSUS de la tabbar (bottom = hauteur tabbar)
             au lieu de bottom:0 (ce qui mettait le bas du contenu derrière
             la tabbar opaque).
          2) Layout flexbox interne : header sticky en haut + zone scrollable
             qui prend tout le reste avec `flex: 1; min-height: 0; overflow-y: auto`.
             C'est la SEULE manière fiable d'avoir un vrai scroll qui descend
             jusqu'en bas sur iOS Safari. */}
      <div
        className="fixed left-0 right-0 z-[10000] bg-white rounded-t-3xl anim-slide"
        style={{
          // V4.0 — Le sheet ne dépasse JAMAIS la safe-area du haut (encoche iPhone).
          // bottom : on s'arrête au-dessus de la tabbar (~80px + safe-area-bas).
          // top    : on respecte la status bar (44px sur iPhone X+).
          // maxHeight : recalculée dynamiquement plus bas via computedMaxH
          //             pour ne jamais excéder l'espace réellement disponible.
          bottom: 'calc(env(safe-area-inset-bottom, 0px) + 80px)',
          // Hauteur max = 92% de la zone visible MOINS l'offset bas (80px+safe)
          // MOINS la safe-area du haut (statusbar). On utilise un calc CSS robuste.
          maxHeight: `min(${computedMaxH}, calc(100dvh - 80px - env(safe-area-inset-top, 0px) - env(safe-area-inset-bottom, 0px) - 12px))`,
          animation: 'slide-up 0.3s ease-out',
          transform: 'translateZ(0)',
          willChange: 'transform',
          display: 'flex',
          flexDirection: 'column',
          // ombre légère au-dessus pour bien marquer la séparation avec la tabbar
          boxShadow: '0 -8px 24px -8px rgba(15,42,67,0.18)',
        }}
      >
        <div
          className="bg-white pt-3 pb-2 px-5 flex-shrink-0"
          style={{
            borderTopLeftRadius: '1.5rem',
            borderTopRightRadius: '1.5rem',
          }}
        >
          <div className="w-10 h-1 mx-auto rounded-full bg-bg-3 mb-3" />
          <div className="flex items-center justify-between">
            <h2 className="font-display font-bold text-xl text-ink">{title}</h2>
            <button
              onClick={onClose}
              className="w-9 h-9 rounded-full flex items-center justify-center text-slate"
              style={{ background: '#F1F4F9' }}
              aria-label="Fermer"
            >
              ×
            </button>
          </div>
        </div>
        {/* Zone scrollable : flex:1 + min-height:0 sont CRUCIAUX pour iOS */}
        <div
          className="px-5"
          style={{
            flex: '1 1 auto',
            minHeight: 0,
            overflowY: 'auto',
            overscrollBehavior: 'contain',
            WebkitOverflowScrolling: 'touch',
            touchAction: 'pan-y',
            paddingBottom: '24px',
          }}
        >
          {children}
        </div>
      </div>
    </>
  );
};

// ============================================================
// EMPTY STATE
// ============================================================
const EmptyState = ({ icon: Icon, title, subtitle, action }) => (
  <div className="text-center py-12 px-6">
    {Icon && (
      <div className="inline-flex w-14 h-14 rounded-2xl items-center justify-center mb-3" style={{ background: '#E8EBF0' }}>
        <Icon size={26} style={{ color: '#6B7891' }} strokeWidth={1.8} />
      </div>
    )}
    <h3 className="font-display font-bold text-base text-ink mb-1">{title}</h3>
    {subtitle && <p className="text-sm text-slate leading-relaxed">{subtitle}</p>}
    {action && <div className="mt-4">{action}</div>}
  </div>
);

// ============================================================
// LOADING SPINNER
// ============================================================
const Spinner = ({ size = 32 }) => (
  <div
    className="inline-block rounded-full animate-spin"
    style={{
      width: size,
      height: size,
      border: '3px solid #E8EBF0',
      borderTopColor: '#F4632B',
    }}
  />
);

// Export globaux
window.OveyoUI = {
  GradientBar,
  Card,
  IconBubble,
  FlashProvider,
  useFlash,
  Sheet,
  EmptyState,
  Spinner,
};
