/* ============================================================
   mobile-forms.jsx
   Composants de saisie mobile avec contrôle du clavier virtuel.
   Tous nommés et exposés sur window.
   ============================================================ */

const { useState: uMF, useRef: rMF } = React;

/* ============================================================
   FormField — wrapper standard pour un champ
   Nom système : FormField
   Affiche : label · description · le champ · message d'erreur/hint
   ============================================================ */
function FormField({ label, hint, error, required, children }) {
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 6, marginBottom: 14 }}>
      {label && (
        <label style={{
          fontFamily: 'var(--font-mono)', fontSize: 11,
          letterSpacing: '0.08em', textTransform: 'uppercase',
          color: 'var(--ink-3)',
        }}>
          {label}{required && <span style={{ color: 'var(--accent)', marginLeft: 4 }}>*</span>}
        </label>
      )}
      {children}
      {(error || hint) && (
        <div style={{
          fontSize: 12,
          color: error ? 'var(--err)' : 'var(--ink-4)',
          lineHeight: 1.4,
        }}>{error || hint}</div>
      )}
    </div>
  );
}

/* ============================================================
   TextInput — champ texte avec contrôle complet du clavier virtuel
   Nom système : TextInput
   Props clavier virtuel (mobile uniquement) :
     keyboard: 'text' | 'numeric' | 'tel' | 'email' | 'url' | 'search' | 'decimal' | 'none'
     autocomplete: 'name'|'email'|'tel'|'address-line1'|'postal-code'|'country'|
                   'given-name'|'family-name'|'current-password'|'new-password'|
                   'one-time-code'|'off'…  (Web Authentication API)
     autocapitalize: 'sentences' | 'words' | 'characters' | 'off'
     spellCheck: bool
     enterHint: 'send'|'search'|'go'|'done'|'next'|'previous'  (texte de la touche Entrée)
     pattern: regex de validation
   ============================================================ */
function TextInput({
  value, onChange, placeholder, type = 'text', icon, trailing,
  keyboard, autocomplete = 'off', autocapitalize = 'sentences',
  spellCheck = false, enterHint, pattern, maxLength, multiline, rows = 4,
  error,
}) {
  const C = multiline ? 'textarea' : 'input';
  const inputProps = {
    value, onChange: (e) => onChange(e.target.value),
    placeholder,
    inputMode: keyboard,
    autoComplete: autocomplete,
    autoCapitalize: autocapitalize,
    spellCheck,
    enterKeyHint: enterHint,
    pattern, maxLength,
    rows: multiline ? rows : undefined,
    type: !multiline ? type : undefined,
    style: {
      flex: 1, minWidth: 0,
      background: 'transparent', border: 'none', outline: 'none',
      color: 'var(--ink-1)',
      fontFamily: type === 'password' ? 'var(--font-mono)' : 'var(--font-ui)',
      fontSize: 15,
      padding: multiline ? '4px 0' : 0,
      resize: multiline ? 'vertical' : undefined,
      minHeight: multiline ? rows * 22 : undefined,
    },
  };
  return (
    <div style={{
      display: 'flex', alignItems: multiline ? 'flex-start' : 'center', gap: 10,
      padding: '12px 14px',
      background: 'var(--bg-1)',
      border: `1px solid ${error ? 'var(--err)' : 'var(--border-2)'}`,
      borderRadius: 10,
      boxShadow: 'inset 0 1px 2px rgba(0,0,0,0.25)',
    }}>
      {icon && <Icon name={icon} size={16} style={{ color: 'var(--ink-3)', flex: '0 0 auto', marginTop: multiline ? 4 : 0 }} />}
      <C {...inputProps} />
      {trailing}
    </div>
  );
}

/* ============================================================
   DateInput — date picker natif mobile
   Nom système : DateInput
   ============================================================ */
function DateInput({ value, onChange, mode = 'date' }) {
  // mode : 'date' | 'datetime-local' | 'time' | 'month' | 'week'
  const icons = { date: 'clock', 'datetime-local': 'clock', time: 'clock', month: 'clock', week: 'clock' };
  return (
    <div style={{
      display: 'flex', alignItems: 'center', gap: 10,
      padding: '12px 14px',
      background: 'var(--bg-1)',
      border: '1px solid var(--border-2)',
      borderRadius: 10,
      boxShadow: 'inset 0 1px 2px rgba(0,0,0,0.25)',
    }}>
      <Icon name={icons[mode]} size={16} style={{ color: 'var(--accent)' }} />
      <input
        type={mode}
        value={value}
        onChange={(e) => onChange(e.target.value)}
        style={{
          flex: 1, minWidth: 0,
          background: 'transparent', border: 'none', outline: 'none',
          color: 'var(--ink-1)',
          fontFamily: 'var(--font-mono)', fontSize: 15,
          colorScheme: 'dark',
        }}
      />
    </div>
  );
}

/* ============================================================
   Dropdown — select natif stylisé
   Nom système : Dropdown
   ============================================================ */
function Dropdown({ value, onChange, options, placeholder = 'Choisir…' }) {
  return (
    <div style={{
      display: 'flex', alignItems: 'center', gap: 10,
      padding: '12px 14px',
      background: 'var(--bg-1)',
      border: '1px solid var(--border-2)',
      borderRadius: 10,
      boxShadow: 'inset 0 1px 2px rgba(0,0,0,0.25)',
      position: 'relative',
    }}>
      <select value={value} onChange={(e) => onChange(e.target.value)} style={{
        flex: 1, minWidth: 0,
        background: 'transparent', border: 'none', outline: 'none',
        color: value ? 'var(--ink-1)' : 'var(--ink-3)',
        fontFamily: 'var(--font-ui)', fontSize: 15,
        appearance: 'none', WebkitAppearance: 'none',
        paddingRight: 24,
      }}>
        <option value="">{placeholder}</option>
        {options.map((o) => (
          typeof o === 'string'
            ? <option key={o} value={o}>{o}</option>
            : <option key={o.value} value={o.value}>{o.label}</option>
        ))}
      </select>
      <Icon name="chevD" size={14} style={{ color: 'var(--ink-3)', position: 'absolute', right: 14, pointerEvents: 'none' }} />
    </div>
  );
}

/* ============================================================
   CheckboxItem — case à cocher (style iOS)
   Nom système : CheckboxItem
   Cas : oui/non sur une option, sélection multiple dans une liste
   ============================================================ */
function CheckboxItem({ checked, onChange, label, description }) {
  return (
    <label className="touch-press" style={{
      display: 'flex', alignItems: 'flex-start', gap: 12,
      padding: '12px 14px',
      background: 'var(--bg-3)',
      border: '1px solid var(--border-2)',
      borderRadius: 10,
      cursor: 'pointer',
      WebkitTapHighlightColor: 'transparent',
    }}>
      <span style={{
        width: 22, height: 22, borderRadius: 6,
        background: checked ? 'var(--accent)' : 'var(--bg-1)',
        border: `1.5px solid ${checked ? 'var(--accent)' : 'var(--border-3)'}`,
        display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
        color: 'var(--bg-1)',
        flex: '0 0 auto', marginTop: 1,
        boxShadow: 'inset 0 1px 2px rgba(0,0,0,0.2)',
        transition: 'all .12s',
      }}>
        {checked && <Icon name="play" size={11} />}
      </span>
      <div style={{ flex: 1, minWidth: 0 }}>
        <div style={{ fontSize: 15, color: 'var(--ink-1)', fontWeight: 500 }}>{label}</div>
        {description && <div style={{ fontSize: 12, color: 'var(--ink-3)', marginTop: 2 }}>{description}</div>}
      </div>
      <input type="checkbox" checked={checked} onChange={(e) => onChange(e.target.checked)} style={{ display: 'none' }} />
    </label>
  );
}

/* ============================================================
   RadioGroup — groupe d'options exclusives
   Nom système : RadioGroup
   ============================================================ */
function RadioGroup({ value, onChange, options }) {
  return (
    <div style={{
      background: 'var(--bg-3)',
      border: '1px solid var(--border-2)',
      borderRadius: 10,
      overflow: 'hidden',
    }}>
      {options.map((o, i) => {
        const v = typeof o === 'string' ? o : o.value;
        const l = typeof o === 'string' ? o : o.label;
        const d = typeof o === 'object' ? o.description : null;
        const active = value === v;
        return (
          <label key={v} className="touch-press" style={{
            display: 'flex', alignItems: 'center', gap: 12,
            padding: '12px 14px',
            borderTop: i > 0 ? '1px solid var(--border-1)' : 'none',
            cursor: 'pointer',
            WebkitTapHighlightColor: 'transparent',
          }}>
            <span style={{
              width: 22, height: 22, borderRadius: '50%',
              border: `2px solid ${active ? 'var(--accent)' : 'var(--border-3)'}`,
              display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
              flex: '0 0 auto',
              background: 'var(--bg-1)',
            }}>
              {active && <span style={{ width: 10, height: 10, borderRadius: '50%', background: 'var(--accent)' }} />}
            </span>
            <div style={{ flex: 1 }}>
              <div style={{ fontSize: 15, color: 'var(--ink-1)', fontWeight: 500 }}>{l}</div>
              {d && <div style={{ fontSize: 12, color: 'var(--ink-3)', marginTop: 2 }}>{d}</div>}
            </div>
            <input type="radio" checked={active} onChange={() => onChange(v)} style={{ display: 'none' }} />
          </label>
        );
      })}
    </div>
  );
}

/* ============================================================
   MediaInsert — boutons "insérer..." pour image/vidéo/audio/GPS
   Nom système : MediaInsert
   Cas : ajouter une pièce jointe dans un formulaire mobile.
   Note : utilise les API natives via <input type="file" accept="..." capture="..."/>
   et navigator.geolocation pour le GPS.
   ============================================================ */
function MediaInsert({ onPick }) {
  const items = [
    { id: 'photo',  icon: 'grid',     label: 'Photo',  hint: 'Appareil photo',  accept: 'image/*', capture: 'environment' },
    { id: 'image',  icon: 'folder',   label: 'Image',  hint: 'Depuis la galerie', accept: 'image/*' },
    { id: 'video',  icon: 'play',     label: 'Vidéo',  hint: 'Caméra ou galerie', accept: 'video/*', capture: 'environment' },
    { id: 'audio',  icon: 'terminal', label: 'Audio',  hint: 'Enregistrement vocal', accept: 'audio/*', capture: 'user' },
    { id: 'file',   icon: 'download', label: 'Fichier', hint: 'Doc, PDF, autre', accept: '*' },
    { id: 'gps',    icon: 'network',  label: 'Position', hint: 'GPS du téléphone', special: true },
  ];
  return (
    <div style={{
      display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 8,
    }}>
      {items.map((it) => (
        <label key={it.id} className="touch-press" style={{
          display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center',
          gap: 6, padding: '14px 8px',
          background: 'var(--bg-3)',
          border: '1px solid var(--border-2)',
          borderRadius: 10,
          color: 'var(--ink-1)',
          cursor: 'pointer',
          textAlign: 'center',
          WebkitTapHighlightColor: 'transparent',
          minHeight: 72,
        }}>
          <Icon name={it.icon} size={18} style={{ color: 'var(--accent)' }} />
          <span style={{ fontSize: 12, fontWeight: 600 }}>{it.label}</span>
          <span style={{ fontSize: 10, color: 'var(--ink-3)' }}>{it.hint}</span>
          {!it.special && (
            <input type="file" accept={it.accept} capture={it.capture}
              onChange={(e) => onPick && onPick(it.id, e.target.files[0])}
              style={{ display: 'none' }} />
          )}
          {it.special && (
            <input type="button" onClick={() => {
              if (!navigator.geolocation) { onPick && onPick('gps', { error: 'GPS indisponible' }); return; }
              navigator.geolocation.getCurrentPosition(
                (pos) => onPick && onPick('gps', { lat: pos.coords.latitude, lon: pos.coords.longitude }),
                (err) => onPick && onPick('gps', { error: err.message }),
              );
            }} style={{ display: 'none' }} />
          )}
        </label>
      ))}
    </div>
  );
}

/* ============================================================
   AvatarLogo — gros logo rond pour écran de connexion
   Nom système : AvatarLogo
   ============================================================ */
function AvatarLogo({ icon = 'server', size = 80, glow = true }) {
  return (
    <div style={{
      width: size, height: size, borderRadius: size * 0.28,
      background: `linear-gradient(135deg, var(--accent), color-mix(in oklch, var(--accent) 60%, black))`,
      color: 'var(--bg-1)',
      display: 'flex', alignItems: 'center', justifyContent: 'center',
      boxShadow: glow
        ? `inset 0 2px 0 rgba(255,255,255,0.25), 0 8px 24px var(--accent-glow), 0 4px 12px rgba(0,0,0,0.4)`
        : 'inset 0 2px 0 rgba(255,255,255,0.25)',
      margin: '0 auto',
    }}>
      <Icon name={icon} size={size * 0.45} />
    </div>
  );
}

/* ============================================================
   BiometricButton — bouton biométrie (Face ID / Touch ID)
   Nom système : BiometricButton
   ============================================================ */
function BiometricButton({ kind = 'face', label, onClick }) {
  const lbl = label || (kind === 'face' ? 'Face ID' : 'Touch ID');
  return (
    <button onClick={onClick} className="touch-press" style={{
      display: 'inline-flex', flexDirection: 'column', alignItems: 'center', gap: 4,
      padding: '8px 14px',
      background: 'transparent', border: 'none',
      color: 'var(--accent)', cursor: 'pointer',
      fontFamily: 'var(--font-ui)', fontSize: 13, fontWeight: 600,
      WebkitTapHighlightColor: 'transparent',
    }}>
      <Icon name={kind === 'face' ? 'user' : 'play'} size={28} />
      {lbl}
    </button>
  );
}

Object.assign(window, {
  FormField, TextInput, DateInput, Dropdown,
  CheckboxItem, RadioGroup, MediaInsert,
  AvatarLogo, BiometricButton,
});

/* ============================================================
   CATALOGUE KEYBOARD — pour la doc
   ============================================================ */
const KEYBOARD_CATALOG = [
  { name: 'text',     desc: 'Clavier standard (lettres + chiffres).', usage: 'Tout texte libre, noms.' },
  { name: 'numeric',  desc: 'Pavé numérique sans signe ni virgule.',  usage: 'Codes PIN, OTP, références numériques.' },
  { name: 'decimal',  desc: 'Pavé numérique avec virgule/point.',     usage: 'Prix, mesures, montants.' },
  { name: 'tel',      desc: 'Pavé téléphone avec + et formats.',      usage: 'Numéros de téléphone.' },
  { name: 'email',    desc: 'Clavier texte avec @ et . en accès direct.', usage: 'Adresses email.' },
  { name: 'url',      desc: 'Clavier texte avec / et .com.',           usage: 'URLs, liens.' },
  { name: 'search',   desc: 'Clavier standard, touche Entrée = "Rechercher".', usage: 'Champs de recherche.' },
  { name: 'none',     desc: 'Aucun clavier (utile avec un picker custom).', usage: 'Date picker custom, sélecteur de couleur, etc.' },
];

const AUTOCOMPLETE_CATALOG = [
  { name: 'name / given-name / family-name', usage: 'Nom complet, prénom, nom de famille' },
  { name: 'email',                            usage: 'Adresse email (autoremplie depuis le compte iOS/Android)' },
  { name: 'tel',                              usage: 'Numéro de téléphone' },
  { name: 'address-line1 / postal-code / country', usage: 'Adresse postale' },
  { name: 'current-password',                 usage: 'Mot de passe existant (Face ID/Touch ID propose le remplissage)' },
  { name: 'new-password',                     usage: 'Nouveau mot de passe (le gestionnaire propose d\'en générer un)' },
  { name: 'one-time-code',                    usage: 'Code OTP reçu par SMS (auto-lu sur iOS / Android)' },
  { name: 'off',                              usage: 'Désactive complètement les suggestions' },
];

const ENTER_HINT_CATALOG = [
  { name: 'send',     usage: 'Envoyer un message (chat, email)' },
  { name: 'search',   usage: 'Rechercher (résultat affiché en bas)' },
  { name: 'go',       usage: 'Y aller (URL, action de navigation)' },
  { name: 'done',     usage: 'Terminer la saisie et fermer le clavier' },
  { name: 'next',     usage: 'Passer au champ suivant du formulaire' },
  { name: 'previous', usage: 'Revenir au champ précédent' },
];

Object.assign(window, { KEYBOARD_CATALOG, AUTOCOMPLETE_CATALOG, ENTER_HINT_CATALOG });
