/* global React */
/* eslint-disable */
const { useState: useStateEXT, useEffect: useEffectEXT, useRef: useRefEXT } = React;
const gm = window.getMsg;

/* ---------- Features to explore ---------- */
const EX_FEATURES = [
  { id:'add',    emoji:'➕', name: gm('Agregar enlace','Ajouter un lien','Add a link'),   sub: gm('Crear recurso externo','Créer une ressource externe','Create external resource'),
    desc: gm('Al hacer clic en "+ Créer" se abre un formulario: nombre, URL, descripción, idioma y visibilidad. Como crear una entrada en tu biblioteca personal de herramientas.', 'En cliquant sur "+ Créer" un formulaire s\'ouvre : nom, URL, description, langue et visibilité. Comme créer une entrée dans ta bibliothèque d\'outils.', 'Clicking "+ Créer" opens a form: name, URL, description, language and visibility. Like creating an entry in your personal tools library.') },
  { id:'search', emoji:'🔍', name: gm('Buscar y filtrar','Rechercher et filtrer','Search and filter'), sub: gm('Búsqueda en tiempo real','Recherche en temps réel','Real-time search'),
    desc: gm('La barra de búsqueda filtra en tiempo real. Los filtros de pestaña te permiten ver: Todos, Míos, Compartidos, Públicos o solo los Privados.', 'La barre de recherche filtre en temps réel. Les filtres d\'onglet permettent de voir : Tous, Miens, Partagés, Publics ou seulement Privés.', 'The search bar filters in real time. Tab filters let you view: All, Mine, Shared, Public or just Private.') },
  { id:'vis',    emoji:'🔒', name: gm('Público o Privado','Public ou Privé','Public or Private'), sub: gm('Control de visibilidad','Contrôle de visibilité','Visibility control'),
    desc: gm('Cuando creas un enlace como Público, aparece en el directorio comunitario. Si es Privado, solo tú lo ves. Puedes cambiar la visibilidad en cualquier momento haciendo clic en el estado.', 'Quand tu crées un lien en Public, il apparaît dans le répertoire communautaire. S\'il est Privé, seul toi le vois. Tu peux changer la visibilité à tout moment en cliquant sur l\'état.', 'When you create a link as Public, it appears in the community directory. If Private, only you see it. You can change visibility anytime by clicking the status.') },
  { id:'collab', emoji:'🌐', name: gm('Base colectiva','Base collective','Collective base'),   sub: gm('Directorio comunitario','Répertoire communautaire','Community directory'),
    desc: gm('Cuando alguien marca un recurso como Público, aparece en la pestaña "Públicos" para todos. La plataforma construye colectivamente un directorio curado de herramientas para crear con IA.', 'Quand quelqu\'un marque une ressource comme Publique, elle apparaît dans l\'onglet "Publics" pour tous. La plateforme construit collectivement un répertoire d\'outils pour créer avec l\'IA.', 'When someone marks a resource as Public, it appears in the "Public" tab for everyone. The platform collectively builds a curated directory of AI creation tools.') },
];

/* ---------- Confetti (deterministic positions) ---------- */
const CF_DATA = Array.from({ length: 24 }, (_, i) => ({
  id: i,
  left: ((i * 4.37) % 96).toFixed(1),
  delay: ((i * 0.15) % 2.8).toFixed(2),
  color: ['#6366f1','#ec4899','#f59e0b','#22c55e','#06b6d4','#a855f7','#ef4444'][i % 7],
  w: 8 + (i % 5) * 1.5,
  h: 12 + (i % 4) * 2,
}));

/* ---------- Tour steps ---------- */
const EX_STEPS = [
  { id:'welcome', progress:5,
    msgs:[
      { from:'aimy', kind:'recall' },
      { from:'aimy', text: gm('¡Bienvenido al <strong>Módulo Final</strong>! 🎉 Estás a un paso de convertirte en <strong>Creador AIMaker Certificado</strong>.', 'Bienvenue dans le <strong>Module Final</strong> ! 🎉 Tu es à un pas de devenir <strong>Créateur AIMaker Certifié</strong>.', 'Welcome to the <strong>Final Module</strong>! 🎉 You\'re one step away from becoming a <strong>Certified AIMaker Creator</strong>.') },
      { from:'aimy', text: gm('Módulo 6: <strong>Acceso Externo</strong> — tu directorio personal de herramientas y recursos de internet.', 'Module 6 : <strong>Accès Externe</strong> — ton répertoire personnel d\'outils et de ressources internet.', 'Module 6: <strong>External Access</strong> — your personal directory of tools and internet resources.') },
    ],
    quickReplies:[gm('¡Al último módulo!','Au dernier module !','To the last module!'), gm('¿Qué es Acceso Externo?','C\'est quoi Accès Externe ?','What is External Access?')],
  },

  { id:'value', progress:15,
    msgs:[
      { from:'aimy', text: gm('<em>"Una base de conocimiento colectiva de herramientas útiles para crear con IA."</em>', '<em>"Une base de connaissance collective d\'outils utiles pour créer avec l\'IA."</em>', '<em>"A collective knowledge base of useful tools for creating with AI."</em>'), kind:'quote' },
      { from:'aimy', text: gm('Guarda, organiza y comparte los links más valiosos de tu kit de creación — desde plataformas de IA hasta APIs, generadores y referencias.', 'Sauvegarde, organise et partage les liens les plus précieux de ton kit — des plateformes IA aux APIs, générateurs et références.', 'Save, organize and share the most valuable links in your creation kit — from AI platforms to APIs, generators and references.') },
      { from:'aimy', kind:'exstats' },
    ],
  },

  { id:'features', progress:35,
    spotlight:'[data-tour="ext-create"]',
    spotlightLabel: gm('4 funcionalidades clave','4 fonctionnalités clés','4 key features'),
    msgs:[
      { from:'aimy', text: gm('Acceso Externo tiene <strong>4 funcionalidades clave</strong>. Haz clic en cada una para conocerla. Explóralas todas para continuar.', 'Accès Externe a <strong>4 fonctionnalités clés</strong>. Clique sur chacune pour la connaître. Explore-les toutes pour continuer.', 'External Access has <strong>4 key features</strong>. Click on each to learn about it. Explore them all to continue.') },
      { from:'aimy', kind:'features' },
    ],
    gate: ctx => ctx.exploredFeatures.size >= 4,
    gateHint: gm('Explora las 4 funcionalidades para continuar','Explore les 4 fonctionnalités pour continuer','Explore all 4 features to continue'),
  },

  { id:'sim-1', progress:52,
    spotlight:'[data-tour="ext-create"]',
    spotlightLabel: gm('Haz clic en + Créer','Clique sur + Créer','Click + Créer'),
    msgs:[
      { from:'aimy', text: gm('¡Perfecto! Ahora <strong>practícalo tú mismo</strong>.', 'Parfait ! Maintenant <strong>pratique-le toi-même</strong>.', 'Perfect! Now <strong>practice it yourself</strong>.') },
      { from:'aimy', text: gm('Haz clic en <strong>+ Créer</strong> arriba a la derecha y agrega tu primera herramienta externa.', 'Clique sur <strong>+ Créer</strong> en haut à droite et ajoute ton premier outil externe.', 'Click <strong>+ Créer</strong> at the top right and add your first external tool.') },
      { from:'aimy', kind:'simprog' },
    ],
    gate: ctx => ctx.created >= 1,
    gateHint: gm('Agrega tu primer enlace externo','Ajoute ton premier lien externe','Add your first external link'),
  },

  { id:'sim-2', progress:66,
    spotlight:'[data-tour="ext-create"]',
    spotlightLabel: gm('Un enlace más','Un lien de plus','One more link'),
    msgs:[
      { from:'aimy', text: gm('¡Genial! 🎉 Ya tienes el primero. Agrega <strong>un enlace más</strong> para completar el reto.', 'Super ! 🎉 Tu as le premier. Ajoute <strong>un lien de plus</strong> pour compléter le défi.', 'Great! 🎉 You have the first one. Add <strong>one more link</strong> to complete the challenge.') },
      { from:'aimy', kind:'simprog' },
    ],
    gate: ctx => ctx.created >= 2,
    gateHint: gm('Agrega un segundo enlace externo','Ajoute un second lien externe','Add a second external link'),
  },

  { id:'sim-3', progress:78,
    spotlight:'[data-tour="ext-visibility"]',
    spotlightLabel: gm('Cambia a Público','Passe en Public','Switch to Public'),
    msgs:[
      { from:'aimy', text: gm('¡Dos enlaces creados! Ahora <strong>contribuye a la comunidad</strong>.', 'Deux liens créés ! Maintenant <strong>contribue à la communauté</strong>.', 'Two links created! Now <strong>contribute to the community</strong>.') },
      { from:'aimy', text: gm('Haz clic en el estado de visibilidad de uno de tus recursos y cámbialo a <strong>Público</strong>.', 'Clique sur l\'état de visibilité d\'une de tes ressources et change-le en <strong>Public</strong>.', 'Click on the visibility status of one of your resources and change it to <strong>Public</strong>.') },
      { from:'aimy', kind:'simprog' },
    ],
    gate: ctx => ctx.madePublic,
    gateHint: gm('Cambia un enlace a Público para compartirlo con la comunidad','Change un lien en Public pour le partager avec la communauté','Change a link to Public to share it with the community'),
  },

  { id:'quiz', progress:92,
    msgs:[
      { from:'aimy', text: gm('¡Reto completado! 🎉 Tu recurso ya está en el directorio de la comunidad AIMaker.', 'Défi accompli ! 🎉 Ta ressource est maintenant dans le répertoire de la communauté AIMaker.', 'Challenge complete! 🎉 Your resource is now in the AIMaker community directory.') },
      { from:'aimy', text: gm('Último quiz de toda la ruta. 3 preguntas · <strong>+25 pts</strong> por respuesta correcta:', 'Dernier quiz de tout le parcours. 3 questions · <strong>+25 pts</strong> par bonne réponse :', 'Last quiz of the entire path. 3 questions · <strong>+25 pts</strong> per correct answer:') },
      { from:'aimy', kind:'quiz' },
    ],
    gate: ctx => ctx.quizDone,
    gateHint: gm('Responde las 3 preguntas para finalizar','Réponds aux 3 questions pour terminer','Answer all 3 questions to finish'),
  },

  { id:'done', progress:100,
    msgs:[
      { from:'aimy', kind:'badge' },
      { from:'aimy', text: gm('Has completado la <strong>Ruta de Capacitación completa de AIMaker</strong>. ¡Eres un experto certificado en todo lo que la plataforma tiene para ofrecer! 🏆', 'Tu as complété la <strong>Ruta de Capacitación completa de AIMaker</strong>. Tu es un expert certifié dans tout ce que la plateforme a à offrir ! 🏆', 'You\'ve completed the <strong>complete AIMaker Training Path</strong>. You\'re a certified expert in everything the platform has to offer! 🏆') },
    ],
  },
];

/* ---------- Stats card ---------- */
function ExStats() {
  return (
    <div className="aimy-cards">
      <div className="stat-card"><div className="v">∞</div><div className="l">{gm('Links que puedes guardar','Liens que tu peux sauvegarder','Links you can save')}</div></div>
      <div className="stat-card"><div className="v">2</div><div className="l">{gm('Visibilidades disponibles','Visibilités disponibles','Available visibilities')}</div></div>
      <div className="stat-card"><div className="v">🌐</div><div className="l">{gm('Directorio comunitario AIMaker','Répertoire communautaire AIMaker','AIMaker community directory')}</div></div>
    </div>
  );
}

/* ---------- Features explorer ---------- */
function FeaturesCard({ explored, onExplore }) {
  const [active, setActive] = useStateEXT(null);
  return (
    <>
      <div className="feat-grid">
        {EX_FEATURES.map(f => (
          <button key={f.id}
            className={'feat-card' + (explored.has(f.id) ? ' explored' : '')}
            onClick={() => { onExplore(f.id); setActive(f); }}>
            {explored.has(f.id) && <span className="fcheck">✓</span>}
            <div className="fn"><span>{f.emoji}</span> {f.name}</div>
            <div className="fd">{f.sub}</div>
          </button>
        ))}
      </div>
      {active && (
        <div style={{marginTop:8,fontSize:12,lineHeight:1.5,paddingTop:6,borderTop:'1px solid var(--border)'}}>
          <strong style={{color:'var(--text)'}}>{active.emoji} {active.name}</strong>
          <div style={{marginTop:2,color:'var(--text-soft)'}}>{active.desc}</div>
        </div>
      )}
      <div style={{fontSize:11,color:'var(--text-soft)',marginTop:6,textAlign:'right'}}>
        {window.t('explored.fem')}: <strong>{explored.size}/4</strong>
      </div>
    </>
  );
}

/* ---------- Sim progress ---------- */
function SimProgress({ created, madePublic }) {
  const steps = [
    { label: window.t('ext.sim.link1'),    done: created >= 1 },
    { label: window.t('ext.sim.link2'),    done: created >= 2 },
    { label: window.t('ext.sim.published'), done: madePublic   },
  ];
  return (
    <div className="sim-progress">
      {steps.map((s, i) => (
        <div key={i} className={'sp' + (s.done ? ' done' : '')}>
          <span className="sm">{s.done ? '✅' : '⬜'}</span>
          {s.label}
        </div>
      ))}
    </div>
  );
}

/* ---------- Recall ---------- */
function ExRecall() {
  const p = window.AIMakerProgress ? window.AIMakerProgress.get() : { modules:{}, badges:[], points:0 };
  const completed = Object.entries(p.modules).filter(([,v]) => v).map(([k]) => k);
  if (completed.length === 0) {
    return <div className="aimy-recall">{gm('¡Hola! 👋 Soy <strong>Aimy</strong>. Te guío por el módulo final de AIMaker.', '👋 Bonjour ! Je suis <strong>Aimy</strong>. Je te guide dans le module final d\'AIMaker.', '👋 Hi! I\'m <strong>Aimy</strong>. I\'ll guide you through AIMaker\'s final module.')}</div>;
  }
  const modLabel = completed.length > 1 ? gm('módulos completados','modules complétés','modules completed') : gm('módulo completado','module complété','module completed');
  return (
    <div className="aimy-recall">
      {gm('¡Hola de nuevo! 🎯 Llevas','Rebonjour ! 🎯 Tu as','Welcome back! 🎯 You have')} <strong>{completed.length} {modLabel}</strong> {gm('y','et','and')} <strong>{p.points} {window.t('quiz.pts')}</strong>. {gm('¡Ya casi terminas la ruta!','Tu es presque au bout du parcours !','You\'re almost done with the path!')}
      {p.badges.length > 0 && (
        <div className="badges">
          {p.badges.map(b => <span key={b} className="badge-mini">🛡️ {b}</span>)}
        </div>
      )}
    </div>
  );
}

/* ---------- Quiz ---------- */
const EX_QUIZ = [
  { q: gm('¿Qué puedes guardar en Acceso Externo?','Que peux-tu sauvegarder dans Accès Externe ?','What can you save in External Access?'),
    opts:[
      gm('Solo las herramientas que ya vienen en AIMaker','Seulement les outils déjà inclus dans AIMaker','Only tools already included in AIMaker'),
      gm('Links de cualquier herramienta externa: plataformas de IA, APIs, referencias...','Liens de n\'importe quel outil externe : plateformes IA, APIs, références...','Links to any external tool: AI platforms, APIs, references...'),
      gm('Únicamente código fuente y carpetas de proyecto','Uniquement le code source et des dossiers de projet','Only source code and project folders'),
    ],
    correct: 1,
  },
  { q: gm('¿Qué ocurre cuando marcas un recurso como Público?','Que se passe-t-il quand tu marques une ressource comme Publique ?','What happens when you mark a resource as Public?'),
    opts:[
      gm('Se borra de tu lista privada','Il est supprimé de ta liste privée','It gets deleted from your private list'),
      gm('Aparece en el directorio comunitario y cualquier usuario puede acceder a él','Il apparaît dans le répertoire communautaire et tout utilisateur peut y accéder','It appears in the community directory and any user can access it'),
      gm('Solo lo ven tus contactos directos','Seuls tes contacts directs le voient','Only your direct contacts see it'),
    ],
    correct: 1,
  },
  { q: gm('¿Puedes cambiar la visibilidad de un recurso después de crearlo?','Peux-tu changer la visibilité d\'une ressource après l\'avoir créée ?','Can you change the visibility of a resource after creating it?'),
    opts:[
      gm('No, la visibilidad es definitiva al crearlo','Non, la visibilité est définitive à la création','No, visibility is final when created'),
      gm('Sí, haciendo clic en el estado del recurso en cualquier momento','Oui, en cliquant sur l\'état de la ressource à tout moment','Yes, by clicking on the resource\'s status at any time'),
      gm('Solo durante las primeras 24 horas','Seulement pendant les premières 24 heures','Only during the first 24 hours'),
    ],
    correct: 1,
  },
];

function ExQuiz({ onDone }) {
  const [i, setI] = useStateEXT(0);
  const [picked, setPicked] = useStateEXT(null);
  const [points, setPoints] = useStateEXT(0);
  function pick(idx) {
    if (picked !== null) return;
    setPicked(idx);
    const np = points + (idx === EX_QUIZ[i].correct ? 25 : 0);
    setPoints(np);
    setTimeout(() => {
      if (i + 1 >= EX_QUIZ.length) onDone(np);
      else { setI(i + 1); setPicked(null); }
    }, 950);
  }
  const q = EX_QUIZ[i];
  return (
    <div>
      <div style={{display:'flex',justifyContent:'space-between',fontSize:11,color:'var(--text-soft)',marginBottom:6}}>
        <span>{window.t('quiz.q')} {i+1} / {EX_QUIZ.length}</span>
        <span><strong style={{color:'var(--brand)'}}>{points}</strong> {window.t('quiz.pts')}</span>
      </div>
      <p className="quiz-q">{q.q}</p>
      <div className="quiz-opts">
        {q.opts.map((o, idx) => {
          let cls = 'quiz-opt';
          if (picked !== null) {
            if (idx === q.correct) cls += ' right';
            else if (idx === picked) cls += ' wrong';
          }
          return <button key={idx} className={cls} onClick={() => pick(idx)}>{o}</button>;
        })}
      </div>
    </div>
  );
}

/* ---------- Badge ---------- */
function ExBadge({ points }) {
  return (
    <div className="badge-trophy">
      <div className="seal" style={{background:'radial-gradient(circle at 30% 30%, #fde68a, #f59e0b 60%, #b45309)'}}>🏆</div>
      <h3>{window.t('badge.external')}</h3>
      <div style={{color:'var(--text-soft)',fontSize:13}}>{window.t('badge.sub.external')}</div>
      <div className="pts">{points} {window.t('quiz.pts')} ⭐</div>
    </div>
  );
}

/* ---------- Final celebration overlay ---------- */
const PATH_MODULES = [
  { emoji:'🗄️', name: gm('Banco de datos','Banque de données','Data Bank'),  mod:'data'     },
  { emoji:'💬', name:'Fablab Chat',                                            mod:'fablab'   },
  { emoji:'⚙️', name:'Applications',                                           mod:'apps'     },
  { emoji:'📦', name: gm('Productos','Produits','Products'),                   mod:'products' },
  { emoji:'🖥️', name: gm('Servidor','Serveur','Server'),                      mod:'server'   },
  { emoji:'🔗', name: gm('Acceso Externo','Accès Externe','External Access'),  mod:'external' },
];

function FinalCelebration({ modulePoints, onClose }) {
  const p = window.AIMakerProgress ? window.AIMakerProgress.get() : { modules:{}, points: modulePoints };
  return (
    <div className="final-overlay">
      {CF_DATA.map(c => (
        <div key={c.id} className="cf" style={{
          left: c.left + '%',
          background: c.color,
          width: c.w + 'px',
          height: c.h + 'px',
          animationDelay: c.delay + 's',
        }}/>
      ))}
      <div className="final-card">
        <button className="close-final" onClick={onClose}>×</button>
        <div className="eyebrow">{window.t('final.eyebrow')}</div>
        <h1>{window.t('final.title')}</h1>
        <p className="lead">{window.t('final.lead')}</p>
        <div className="path-grid">
          {PATH_MODULES.map(step => {
            const done = p.modules[step.mod];
            return (
              <div key={step.mod} className={'path-step' + (done ? ' done' : '')}>
                <div className="pe">{step.emoji}</div>
                <div className="pn">{step.name}</div>
                {done && <div className="pcheck">✓</div>}
              </div>
            );
          })}
        </div>
        <div className="master-seal"><span>🏆</span></div>
        <div className="master-title">{window.t('final.master.title')}</div>
        <div className="master-sub">{window.t('final.master.sub')}</div>
        <div className="master-pts">{p.points} {window.t('final.pts')}</div>
        <div className="final-actions">
          <button className="final-btn primary" onClick={onClose}>{window.t('final.cta')}</button>
          <button className="final-btn ghost" onClick={() => window.location.reload()}>{window.t('btn.repeat')}</button>
        </div>
      </div>
    </div>
  );
}

/* ---------- Message renderer ---------- */
function ExMessage({ m, slot }) {
  if (m.kind === 'recall') return (
    <div className="msg"><div className="av">A</div>
      <div className="bubble" style={{maxWidth:'94%',padding:'10px 12px'}}><ExRecall/></div>
    </div>
  );
  if (m.kind === 'quote') return (
    <div className="msg"><div className="av">A</div>
      <div className="bubble"><div className="quote" dangerouslySetInnerHTML={{__html:m.text}}/></div>
    </div>
  );
  if (m.kind && slot) return (
    <div className="msg"><div className="av">A</div>
      <div className="bubble" style={{maxWidth:'94%'}}>{slot}</div>
    </div>
  );
  return (
    <div className={'msg ' + (m.from === 'user' ? 'user' : '')}>
      <div className="av">{m.from === 'user' ? gm('Tú','Toi','You') : 'A'}</div>
      <div className="bubble" dangerouslySetInnerHTML={{ __html: m.text }}/>
    </div>
  );
}

/* ---------- Spotlight ---------- */
function ExSpotlight({ selector, label }) {
  const [rect, setRect] = useStateEXT(null);
  useEffectEXT(() => {
    if (!selector) { setRect(null); return; }
    function update() {
      const el = document.querySelector(selector);
      if (!el) { setRect(null); return; }
      const r = el.getBoundingClientRect();
      setRect({ top: r.top-6, left: r.left-6, width: r.width+12, height: r.height+12 });
    }
    update();
    window.addEventListener('resize', update);
    window.addEventListener('scroll', update, true);
    const tid = setInterval(update, 300);
    return () => {
      window.removeEventListener('resize', update);
      window.removeEventListener('scroll', update, true);
      clearInterval(tid);
    };
  }, [selector]);
  if (!rect) return null;
  return (
    <div className="spotlight">
      <div className="spot-ring" style={{ top:rect.top, left:rect.left, width:rect.width, height:rect.height }}>
        {label && <span className="spot-label" style={{ left:0, top:0 }}>{label}</span>}
      </div>
    </div>
  );
}

/* ---------- Main AimyExternal ---------- */
function AimyExternal() {
  const [open, setOpen]                       = useStateEXT(true);
  const [stepIdx, setStepIdx]                 = useStateEXT(0);
  const [exploredFeatures, setExploredFeatures] = useStateEXT(new Set());
  const [created, setCreated]                 = useStateEXT(0);
  const [madePublic, setMadePublic]           = useStateEXT(false);
  const [quizDone, setQuizDone]               = useStateEXT(false);
  const [quizPoints, setQuizPoints]           = useStateEXT(0);
  const [unread, setUnread]                   = useStateEXT(0);
  const [showFinal, setShowFinal]             = useStateEXT(false);
  const bodyRef                               = useRefEXT(null);

  useEffectEXT(() => {
    function onState(e) {
      setCreated(e.detail.created);
      setMadePublic(e.detail.madePublic);
    }
    window.addEventListener('aimy:exState', onState);
    return () => window.removeEventListener('aimy:exState', onState);
  }, []);

  useEffectEXT(() => {
    const id = EX_STEPS[stepIdx].id;
    if (id === 'sim-1' && created >= 1) {
      const t = setTimeout(() => setStepIdx(i => Math.min(i+1, EX_STEPS.length-1)), 700);
      return () => clearTimeout(t);
    }
    if (id === 'sim-2' && created >= 2) {
      const t = setTimeout(() => setStepIdx(i => Math.min(i+1, EX_STEPS.length-1)), 700);
      return () => clearTimeout(t);
    }
  }, [created, stepIdx]);

  useEffectEXT(() => {
    if (!open) return;
    requestAnimationFrame(() => {
      if (bodyRef.current) bodyRef.current.scrollTop = bodyRef.current.scrollHeight + 200;
    });
  }, [stepIdx, exploredFeatures, created, madePublic, quizDone, open]);

  const ctx = { exploredFeatures, created, madePublic, quizDone };
  const step = EX_STEPS[stepIdx];
  const canContinue = !step.gate || step.gate(ctx);

  function next() {
    if (stepIdx < EX_STEPS.length - 1) {
      const newIdx = stepIdx + 1;
      setStepIdx(newIdx);
      if (!open) setUnread(u => u + 1);
      if (EX_STEPS[newIdx].id === 'done') {
        if (window.AIMakerProgress) {
          window.AIMakerProgress.complete('external', { badge: window.t('badge.external'), points: 75 + quizPoints });
        }
        setTimeout(() => setShowFinal(true), 900);
      }
    }
  }
  function back() { if (stepIdx > 0) setStepIdx(stepIdx - 1); }

  if (!open) {
    return (
      <button className="aimy-fab" onClick={() => { setOpen(true); setUnread(0); }} aria-label={gm('Abrir Aimy','Ouvrir Aimy','Open Aimy')}>
        <span className="pulse"/>
        <svg width="26" height="26" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
          <path d="M12 8V4H8"/><rect x="2" y="2" width="20" height="8" rx="2"/>
          <path d="M2 14h20"/><path d="M2 14v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6"/>
          <path d="M6 18h.01"/><path d="M10 18h.01"/>
        </svg>
        {unread > 0 && <span className="nudge">{unread}</span>}
      </button>
    );
  }

  return (
    <>
      <ExSpotlight selector={step.spotlight} label={step.spotlightLabel}/>
      <div className="aimy-panel">
        <div className="aimy-header">
          <div className="aimy-avatar">🤖</div>
          <div className="aimy-meta">
            <div className="name">Aimy</div>
            <div className="role">{window.t('aimy.role.external')}</div>
          </div>
          <button className="min" title={window.t('aimy.minimize')} onClick={() => setOpen(false)}>
            <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round"><line x1="5" y1="12" x2="19" y2="12"/></svg>
          </button>
        </div>

        <div className="aimy-progress">
          <div style={{ width: step.progress + '%' }}/>
          <div className="aimy-progress-label">{step.progress}%</div>
        </div>

        <div className="aimy-body" ref={bodyRef}>
          {step.msgs.map((m, i) => {
            let slot = null;
            if (m.kind === 'exstats')  slot = <ExStats/>;
            if (m.kind === 'features') slot = <FeaturesCard explored={exploredFeatures} onExplore={id => setExploredFeatures(prev => { const n = new Set(prev); n.add(id); return n; })}/>;
            if (m.kind === 'simprog')  slot = <SimProgress created={created} madePublic={madePublic}/>;
            if (m.kind === 'quiz')     slot = <ExQuiz onDone={pts => { setQuizPoints(pts); setQuizDone(true); }}/>;
            if (m.kind === 'badge')    slot = <ExBadge points={75 + quizPoints}/>;
            return <ExMessage key={step.id + '-' + i} m={m} slot={slot}/>;
          })}

          {step.gateHint && !canContinue && (
            <div style={{textAlign:'center',color:'var(--text-mute)',fontSize:12,padding:'4px 0 10px'}}>
              ⓘ {step.gateHint}
            </div>
          )}

          {step.quickReplies && (
            <div className="aimy-quick">
              {step.quickReplies.map((r, ri) => (
                <button key={ri} className="quick-chip" onClick={() => next()}>{r}</button>
              ))}
            </div>
          )}
        </div>

        <div className="aimy-actions">
          <button className="aimy-btn ghost" onClick={back} disabled={stepIdx === 0}>{window.t('btn.back')}</button>
          {step.id !== 'done' ? (
            <button className="aimy-btn primary" onClick={next} disabled={!canContinue}>
              {step.id === 'welcome' ? window.t('btn.start') + ' →' : window.t('btn.continue')}
            </button>
          ) : (
            <button className="aimy-btn primary" onClick={() => setShowFinal(true)}>
              {gm('Ver certificado 🏆','Voir le certificat 🏆','View certificate 🏆')}
            </button>
          )}
        </div>
      </div>

      {showFinal && <FinalCelebration modulePoints={75 + quizPoints} onClose={() => setShowFinal(false)}/>}
    </>
  );
}

window.AimyExternal = AimyExternal;
