// Loading — vocabulaire commun des états de chargement.
// Trois formes, une seule esthétique :
//   · VascoSpinner / LoadingBlock  → action ponctuelle, durée inconnue
//   · Skeleton*                    → contenu dont on connaît déjà la forme
//   · TypingDots                   → l'assistant rédige
//
// Rien n'est branché sur un vrai réseau : les hooks useMockLoad / useTypingLoad
// simulent la latence pour que la démo ait le rythme d'une app connectée.
//
// Tout est préfixé LD_ / exporté sur window : les `const` de haut niveau
// deviennent des globales une fois passées par Babel (cf. patients-list.jsx).

const LD_VT = window.VT || {};
const LD_INK = LD_VT.ink || '#0a0a0a';
const LD_SUB = LD_VT.sub || '#6b7280';
const LD_SURF = LD_VT.surface || '#ffffff';
const LD_HAIR = LD_VT.hair || 'rgba(10,10,10,0.06)';
const LD_HAIR2 = LD_VT.hair2 || 'rgba(10,10,10,0.10)';
const LD_MED = LD_VT.medBlue || '#3d6b8f';

// Teintes du shimmer — assez basses pour rester crédibles sur le crème.
const LD_BASE = 'rgba(10,10,10,0.055)';
const LD_GLOW = 'rgba(10,10,10,0.015)';

// Les keyframes sont injectées une fois, à la charge du fichier : les
// composants sont rendus dans une dizaine d'endroits et une balise <style>
// par instance polluerait le DOM pour rien.
(function injectLoadingKeyframes() {
  if (document.getElementById('vasco-loading-css')) return;
  const el = document.createElement('style');
  el.id = 'vasco-loading-css';
  el.textContent = `
    @keyframes vascoSpin { to { transform: rotate(360deg); } }
    @keyframes vascoShimmer {
      from { background-position: 150% 0; }
      to   { background-position: -50% 0; }
    }
    @keyframes vascoFadeIn { from { opacity: 0; } to { opacity: 1; } }
    @keyframes vascoDot {
      0%, 60%, 100% { transform: translateY(0);    opacity: .45; }
      30%           { transform: translateY(-4px); opacity: 1;   }
    }
  `;
  document.head.appendChild(el);
})();

// ─────────────────────────────────────────────────────────────
// Hooks de latence simulée
// ─────────────────────────────────────────────────────────────

// Charge à l'arrivée puis à chaque changement de `dep` (filtre, tri, vue).
function useMockLoad(dep, ms = 420) {
  const [loading, setLoading] = React.useState(true);
  React.useEffect(() => {
    setLoading(true);
    const t = setTimeout(() => setLoading(false), ms);
    return () => clearTimeout(t);
  }, [dep, ms]);
  return loading;
}

// Frappe au clavier : reste vrai tant que ça tape, retombe `ms` après la
// dernière touche. Ne se déclenche pas au montage — sinon la recherche
// clignoterait à chaque arrivée sur l'écran.
function useTypingLoad(value, ms = 300) {
  const [loading, setLoading] = React.useState(false);
  const first = React.useRef(true);
  React.useEffect(() => {
    if (first.current) { first.current = false; return; }
    setLoading(true);
    const t = setTimeout(() => setLoading(false), ms);
    return () => clearTimeout(t);
  }, [value, ms]);
  return loading;
}

// ─────────────────────────────────────────────────────────────
// Spinner
// ─────────────────────────────────────────────────────────────
function VascoSpinner({ size = 20, color, thickness, style = {} }) {
  const w = Number(thickness) || Math.max(1.5, size / 9);
  return (
    <div style={{
      width: size, height: size, borderRadius: '50%', flexShrink: 0,
      border: `${w}px solid ${LD_HAIR2}`,
      borderTopColor: color || LD_MED,
      animation: 'vascoSpin .75s linear infinite',
      ...style,
    }} />
  );
}

// Bloc centré : transitions d'écran, sheets qui s'ouvrent sur des données.
function LoadingBlock({ label = 'Chargement…', sub, color, height }) {
  return (
    <div style={{
      flex: height ? undefined : 1, minHeight: height || 0, height,
      display: 'flex', flexDirection: 'column',
      alignItems: 'center', justifyContent: 'center', gap: 12,
      padding: '24px 32px', animation: 'vascoFadeIn .2s ease',
    }}>
      <VascoSpinner size={26} color={color} />
      <div style={{ fontSize: 13.5, fontWeight: 600, color: LD_INK, textAlign: 'center' }}>{label}</div>
      {sub && <div style={{ fontSize: 11.5, fontWeight: 500, color: LD_SUB, textAlign: 'center' }}>{sub}</div>}
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// Skeletons
// ─────────────────────────────────────────────────────────────

// Brique de base. `w` accepte un nombre (px) ou une chaîne ('60%').
function SkeletonBlock({ w = '100%', h = 12, r = 6, delay = 0, style = {} }) {
  return (
    <div style={{
      width: w, height: h, borderRadius: r, flexShrink: 0,
      background: `linear-gradient(90deg, ${LD_BASE} 20%, ${LD_GLOW} 50%, ${LD_BASE} 80%)`,
      backgroundSize: '220% 100%',
      animation: `vascoShimmer 1.25s ease-in-out ${delay}ms infinite`,
      ...style,
    }} />
  );
}

// Calque sur la géométrie de PatientListView : même carte, mêmes hauteurs.
// Le squelette doit occuper la place exacte du contenu, sinon la liste saute
// au moment où les vraies lignes arrivent.
function SkeletonPatientRows({ count = 6 }) {
  return (
    <div style={{ animation: 'vascoFadeIn .18s ease' }}>
      {Array.from({ length: count }).map((_, i) => (
        <div key={i} style={{
          display: 'flex', alignItems: 'center', gap: 12,
          background: LD_SURF, border: `1px solid ${LD_HAIR}`,
          borderRadius: 16, padding: '10px 14px', marginBottom: 8,
        }}>
          <SkeletonBlock w={36} h={36} r={12} delay={i * 70} />
          <div style={{ flex: 1, minWidth: 0, display: 'flex', flexDirection: 'column', gap: 7 }}>
            <SkeletonBlock w={`${52 + (i % 3) * 12}%`} h={11} delay={i * 70} />
            <SkeletonBlock w={`${68 + (i % 2) * 10}%`} h={9} delay={i * 70 + 40} />
          </div>
          <SkeletonBlock w={22} h={16} r={999} delay={i * 70} />
        </div>
      ))}
    </div>
  );
}

// Calque sur PatientIconView : grille 3 colonnes, pastilles de 64px.
function SkeletonIconGrid({ count = 9 }) {
  return (
    <div style={{
      display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 16,
      animation: 'vascoFadeIn .18s ease',
    }}>
      {Array.from({ length: count }).map((_, i) => (
        <div key={i} style={{
          display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 8,
        }}>
          <SkeletonBlock w={64} h={64} r="50%" delay={i * 60} />
          <SkeletonBlock w={54} h={9} delay={i * 60 + 30} />
          <SkeletonBlock w={30} h={7} delay={i * 60 + 60} />
        </div>
      ))}
    </div>
  );
}

// Calque sur les lignes de CRValidationSheet.
function SkeletonCRRows({ count = 3 }) {
  return (
    <div style={{ animation: 'vascoFadeIn .18s ease' }}>
      {Array.from({ length: count }).map((_, i) => (
        <div key={i} style={{
          display: 'flex', alignItems: 'center', gap: 12,
          padding: '12px 14px', marginBottom: 8,
          border: `1px solid ${LD_HAIR}`, borderRadius: 16,
        }}>
          <SkeletonBlock w={42} h={20} r={999} delay={i * 80} />
          <div style={{ flex: 1, minWidth: 0, display: 'flex', flexDirection: 'column', gap: 7 }}>
            <SkeletonBlock w={`${58 + (i % 3) * 11}%`} h={11} delay={i * 80} />
            <SkeletonBlock w={`${40 + (i % 2) * 14}%`} h={9} delay={i * 80 + 40} />
          </div>
          <SkeletonBlock w={62} h={32} r={999} delay={i * 80} />
        </div>
      ))}
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// Typing dots — l'assistant rédige
// ─────────────────────────────────────────────────────────────
function TypingDots({ color, size = 6 }) {
  const c = color || LD_SUB;
  return (
    <span style={{ display: 'inline-flex', alignItems: 'flex-end', gap: 4, height: size + 5 }}>
      {[0, 1, 2].map((i) => (
        <span key={i} style={{
          width: size, height: size, borderRadius: '50%', background: c,
          animation: `vascoDot 1.1s ease-in-out ${i * 150}ms infinite`,
        }} />
      ))}
    </span>
  );
}

window.useMockLoad = useMockLoad;
window.useTypingLoad = useTypingLoad;
window.VascoSpinner = VascoSpinner;
window.LoadingBlock = LoadingBlock;
window.SkeletonBlock = SkeletonBlock;
window.SkeletonPatientRows = SkeletonPatientRows;
window.SkeletonIconGrid = SkeletonIconGrid;
window.SkeletonCRRows = SkeletonCRRows;
window.TypingDots = TypingDots;
console.log('%c[VASCO] loading.jsx chargé', 'color:#3d6b8f;font-weight:bold');
