// ============ AcademIA8 · Consola — pantallas ============

// util fechas legibles
function fmtDate(s){
  if(!s) return '—';
  const [y,m,d] = s.split('-');
  const M = ['ene','feb','mar','abr','may','jun','jul','ago','sep','oct','nov','dic'];
  return `${d} ${M[+m-1]} ${y}`;
}

/* ===================================================================
   1 · LISTA DE CURSOS
=================================================================== */
function CourseList({ courses, actions, loadError, onRetry }){
  const [q, setQ] = useState('');
  const [filter, setFilter] = useState('todos');

  const statusOf = (c)=> A8.estadoToStatus(c.derivedEstado);
  const counts = {
    todos: courses.length,
    dirty: courses.filter(c=>statusOf(c)==='published-dirty').length,
    draft: courses.filter(c=>statusOf(c)==='draft-only').length,
    pub: courses.filter(c=>statusOf(c)==='published-clean').length,
  };
  let shown = courses.filter(c=>{
    const nm = (c.meta_draft?.name||'');
    return nm.toLowerCase().includes(q.toLowerCase());
  });
  if (filter==='dirty') shown = shown.filter(c=>statusOf(c)==='published-dirty');
  if (filter==='draft') shown = shown.filter(c=>statusOf(c)==='draft-only');
  if (filter==='pub') shown = shown.filter(c=>statusOf(c)==='published-clean');
  shown = shown.slice().sort((a,b)=> (a.meta_draft?.name||'').localeCompare(b.meta_draft?.name||''));

  return (
    <div className="wrap">
      <div className="flex between center">
        <div>
          <div className="page-kick">Autoría de contenido</div>
          <h1 className="page-title" style={{marginTop:'8px'}}>Cursos WhatsApp</h1>
        </div>
        <Btn variant="magenta" icon="plus" onClick={actions.createCourse}>Crear curso</Btn>
      </div>

      {loadError && (
        <div className="readonly-note" style={{marginTop:'18px',background:'var(--dirty-bg)',borderColor:'rgba(206,30,78,.35)',color:'var(--magenta)'}}>
          <Icon name="alert" /> No se pudo cargar la lista de cursos: {loadError}
          <button className="link-btn" style={{marginLeft:'10px'}} onClick={onRetry}>Reintentar</button>
        </div>
      )}

      <div className="list-toolbar">
        <div className="search">
          <Icon name="search" />
          <input placeholder="Buscar curso…" value={q} onChange={e=>setQ(e.target.value)} />
        </div>
        <div className="filter-chips">
          {[['todos','Todos'],['dirty','Con cambios'],['draft','Solo borrador'],['pub','Publicados']].map(([k,l])=>(
            <button key={k} className={`chip${filter===k?' on':''}`} onClick={()=>setFilter(k)}>
              {l}<span className="ct">{counts[k]}</span>
            </button>
          ))}
        </div>
      </div>

      {shown.length===0 ? (
        <div className="empty-state">
          <div className="es-ic"><Icon name="courses" /></div>
          <h3>No hay cursos que coincidan</h3>
          <p>Probá con otro filtro o creá un curso nuevo para empezar a trabajar en su borrador.</p>
        </div>
      ) : (
        <div className="course-grid">
          {shown.map(c=>{
            const st = statusOf(c);
            const name = c.meta_draft?.name || 'Sin nombre';
            const desc = c.meta_draft?.description || '';
            const nUnits = c._loaded && c.draft ? c.draft.units.length : null;
            return (
              <div key={c.id} className="course-card" onClick={()=>actions.openCourse(c.id)}>
                <div className="cc-top"></div>
                <div className="cc-body">
                  <div className="cc-head">
                    <h3>{name}</h3>
                    <StatusPill status={st} />
                  </div>
                  {desc && <p className="cc-desc">{desc}</p>}
                  <div className="cc-units">
                    <Icon name="layers" />
                    {nUnits===null ? 'Abrir para ver el borrador' : `${nUnits} ${nUnits===1?'unidad':'unidades'} en el borrador`}
                  </div>
                </div>
              </div>
            );
          })}
        </div>
      )}
    </div>
  );
}

/* ===================================================================
   2 · EDITOR DE CURSO
=================================================================== */
function CourseEditor({ course, view='borrador', actions }){
  const [modal, setModal] = useState(null); // {type, data}
  const [tab, setTab] = useState('curso'); // 'curso' | 'alumnos' | 'rag'
  const estado = course.derivedEstado;            // solo-borrador | publicado-limpio | publicado-con-cambios
  const meta = course.meta_draft;
  const hasChanges = estado==='solo-borrador' || estado==='publicado-con-cambios';

  // Vista PUBLICADO: snapshot estrictamente solo-lectura de lo que ven los alumnos.
  if (view === 'publicado'){
    return <PublishedReadOnly course={course} onBack={actions.goList} estado={estado} />;
  }

  return (
    <div className="wrap">
      {/* volver */}
      <button className="back-link" onClick={actions.goList}><Icon name="chevright" style={{width:15,height:15,transform:'rotate(180deg)'}} /> Volver a cursos</button>
      {/* encabezado */}
      <div className="flex between center" style={{gap:'16px'}}>
        <div style={{minWidth:0}}>
          <div className="flex center gap12">
            <div className="page-kick">Editor de curso</div>
            <StatusPill status={A8.estadoToStatus(estado)} />
          </div>
          <h1 className="page-title" style={{marginTop:'8px'}}>{meta?.name || 'Sin nombre'}</h1>
        </div>
        <Btn variant="ghost" icon="copy" onClick={()=>setModal({type:'duplicate'})}>Duplicar</Btn>
      </div>

      {/* pestañas del curso */}
      <div className="course-tabs">
        <button className={`ctab${tab==='curso'?' on':''}`} onClick={()=>setTab('curso')}>
          <Icon name="courses" /> Curso
        </button>
        {window.FEATURES.enrollment && (
        <button className={`ctab${tab==='alumnos'?' on':''}`} onClick={()=>setTab('alumnos')}>
          <Icon name="layers" /> Alumnos
        </button>
        )}
        {window.FEATURES.rag && (
        <button className={`ctab${tab==='rag'?' on':''}`} onClick={()=>setTab('rag')}>
          <Icon name="chat" /> Conocimiento del agente
        </button>
        )}
      </div>

      {tab==='rag' ? (
        <RagPanel course={course} />
      ) : tab==='alumnos' ? (
        <AlumnosPanel course={course} />
      ) : (
      <>
      {/* METADATA */}
      <div className="section-gap"></div>
      <div className="flex between center" style={{marginBottom:'14px'}}>
        <div className="sec-title">Metadata del curso</div>
        <Btn variant="ghost" size="sm" icon="edit" onClick={()=>setModal({type:'meta'})}>Editar metadata</Btn>
      </div>
      <div className="card card-pad">
        <div className="meta-grid">
          <MetaField k="Nombre" v={meta?.name} />
          <MetaField k="Entrega de contenido" v="Diaria · obligatoria" icon="calendar" />
          <MetaField k="Descripción" v={meta?.description} long />
          {window.FEATURES.reminders && <MetaField k="Recordatorios por inactividad" v={<RemindersDisplay list={meta?.reminders} />} icon="clock" />}
          <MetaField k="Mensaje de bienvenida" v={meta?.welcome || '—'} long />
          {window.FEATURES.postAccess && <MetaField k="Asistente tras finalizar" v={<PostAccessDisplay pa={meta?.postAccess} />} icon="chat" />}
        </div>
      </div>

      {/* CONTENIDO · organizador del borrador */}
      <div className="section-gap"></div>
      <CourseOrganizer course={course} actions={actions} />

      {/* ---- publicar (según estado derivado del backend) ---- */}
      {hasChanges && (
        <div className="publish-note">
          <div className="pn-ic"><Icon name="publish" /></div>
          <div className="pn-txt">
            <div className="pn-t">{estado==='publicado-con-cambios' ? 'Tenés cambios sin publicar' : 'Este curso todavía no se publicó'}</div>
            <div className="pn-s">{estado==='publicado-con-cambios'
              ? 'El alumno sigue viendo la última versión publicada. Tus ediciones no le llegan hasta que publiques.'
              : 'Nada de lo que ves acá es visible para el alumno hasta la primera publicación.'}</div>
          </div>
          <div className="pn-act">
            <Btn variant="ghost" size="sm" icon="eye" onClick={()=>actions.openPublish(course.id)}>Ver diferencias</Btn>
            <Btn variant="pub" size="sm" icon="publish" onClick={()=>actions.openPublish(course.id)}>Publicar</Btn>
          </div>
        </div>
      )}
      {estado==='publicado-limpio' && (
        <div className="readonly-note" style={{marginTop:'22px'}}>
          <Icon name="check" /> Borrador y publicado están sincronizados: el alumno ve exactamente este contenido.
        </div>
      )}

      {/* ---- borrar curso (permitido solo si no está publicado; el backend lo valida) ---- */}
      {!course.published && (
        <div className="course-del-row">
          <div className="cdr-txt">
            <div className="cdr-t">Borrar este curso</div>
            <div className="cdr-s">Se elimina el borrador de forma definitiva. No se puede borrar un curso ya publicado.</div>
          </div>
          <Btn variant="danger" size="sm" icon="trash" onClick={()=>setModal({type:'del-course'})}>Borrar curso</Btn>
        </div>
      )}
      </>
      )}

      {/* ---- modales ---- */}
      {modal?.type==='meta' && (
        <CourseMetaForm meta={course.meta_draft} cursoId={course.id} onClose={()=>setModal(null)}
          onSave={(m)=>{ actions.updateMeta(course.id, m); setModal(null); }} />
      )}
      {modal?.type==='del-course' && (
        <ConfirmDeleteCourse course={course} onClose={()=>setModal(null)}
          onConfirm={()=>{ actions.deleteCourse(course.id); setModal(null); }} />
      )}
      {modal?.type==='duplicate' && (
        <DuplicateCourseForm course={course} onClose={()=>setModal(null)}
          onSave={async (destino, titulo)=>{
            const ok = await actions.duplicateCourse(course.id, destino, titulo);
            if (ok) setModal(null);
          }} />
      )}
    </div>
  );
}

/* ---------- Modal: duplicar curso ---------- */
function DuplicateCourseForm({ course, onClose, onSave }){
  const [destino, setDestino] = useState('');
  const [titulo, setTitulo] = useState((course.meta_draft?.name || '') + ' (copia)');
  const [busy, setBusy] = useState(false);
  const slugOk = /^[a-z0-9-]+$/.test(destino.trim());
  const ok = slugOk && titulo.trim();
  const submit = async ()=>{
    if (!ok || busy) return;
    setBusy(true);
    try { await onSave(destino.trim(), titulo.trim()); }
    finally { setBusy(false); }
  };
  return (
    <Modal icon="copy" title="Duplicar curso"
      subtitle="Crea un borrador nuevo con el mismo contenido, editable desde cero. No toca este curso."
      onClose={onClose}
      foot={<><div className="spacer"></div><Btn variant="subtle" onClick={onClose}>Cancelar</Btn>
        <Btn variant="primary" icon="check" disabled={!ok || busy} onClick={submit}>{busy?'Duplicando…':'Duplicar'}</Btn></>}>
      <Field label="Id del curso nuevo" hint="Minúsculas, números y guiones. Ej: fundamentos-ia-v2">
        <input type="text" autoFocus value={destino} onChange={e=>setDestino(e.target.value)} placeholder="fundamentos-ia-v2" />
      </Field>
      <Field label="Título">
        <input type="text" value={titulo} onChange={e=>setTitulo(e.target.value)} placeholder="Título del curso nuevo" />
      </Field>
    </Modal>
  );
}

/* ---------- Vista PUBLICADO (solo lectura: lo que ven los alumnos hoy) ---------- */
function PublishedReadOnly({ course, onBack, estado }){
  const pub = course.publishedFront;
  const [expanded, setExpanded] = useState(()=>new Set());
  const toggleExp = (id)=>setExpanded(s=>{ const n=new Set(s); n.has(id)?n.delete(id):n.add(id); return n; });

  if (!pub){
    return (
      <div className="wrap">
        <button className="back-link" onClick={onBack}><Icon name="chevright" style={{width:15,height:15,transform:'rotate(180deg)'}} /> Volver a cursos</button>
        <div className="empty-state" style={{padding:'60px 20px'}}>
          <div className="es-ic"><Icon name="refresh" /></div>
          <h3>Cargando lo publicado…</h3>
          <p>Trayendo el snapshot que ven los alumnos.</p>
        </div>
      </div>
    );
  }

  const meta = pub.meta_draft;
  const units = pub.draft.units;
  const allOpen = units.length>0 && units.every(u=>expanded.has(u.id));
  const toggleAll = ()=>setExpanded(()=> allOpen ? new Set() : new Set(units.map(u=>u.id)));

  return (
    <div className="wrap">
      <button className="back-link" onClick={onBack}><Icon name="chevright" style={{width:15,height:15,transform:'rotate(180deg)'}} /> Volver a cursos</button>
      <div className="flex between center" style={{gap:'16px'}}>
        <div style={{minWidth:0}}>
          <div className="flex center gap12">
            <div className="page-kick">Vista publicada</div>
            <StatusPill status={A8.estadoToStatus(estado)} />
          </div>
          <h1 className="page-title" style={{marginTop:'8px'}}>{meta?.name || 'Sin nombre'}</h1>
        </div>
      </div>

      {/* indicador claro de solo-lectura */}
      <div className="readonly-note" style={{marginTop:'20px',background:'var(--pub-bg)',borderColor:'rgba(1,197,153,.4)',color:'var(--verde-prof)'}}>
        <Icon name="eye" />
        Estás viendo lo <b>publicado</b>: exactamente lo que los alumnos reciben hoy por WhatsApp. Es de <b>solo lectura</b>. Cambiá a <b>Borrador</b> en el selector de arriba para editar.
      </div>

      {/* METADATA (solo lectura) */}
      <div className="section-gap"></div>
      <div className="sec-title" style={{marginBottom:'14px'}}>Metadata del curso</div>
      <div className="card card-pad">
        <div className="meta-grid">
          <MetaField k="Nombre" v={meta?.name} />
          <MetaField k="Entrega de contenido" v="Diaria · obligatoria" icon="calendar" />
          <MetaField k="Descripción" v={meta?.description} long />
          <MetaField k="Mensaje de bienvenida" v={meta?.welcome || '—'} long />
        </div>
      </div>

      {/* UNIDADES (solo lectura, sin bandeja, sin acciones) */}
      <div className="section-gap"></div>
      <div className="flex between center" style={{marginBottom:'14px'}}>
        <div className="flex center gap12">
          <div className="sec-title">Unidades</div>
          <span className="mono" style={{fontSize:'11px',color:'var(--gris)',background:'var(--hueso)',padding:'2px 9px',borderRadius:'20px',fontWeight:700}}>{units.length} en orden</span>
        </div>
        {units.length>0 && <button className="link-btn" onClick={toggleAll}>{allOpen?'Contraer todas':'Expandir todas'}</button>}
      </div>
      {units.length===0 ? (
        <div className="empty-state" style={{padding:'46px 20px'}}>
          <div className="es-ic"><Icon name="layers" /></div>
          <h3>Sin unidades publicadas</h3>
          <p>Este curso todavía no tiene contenido visible para el alumno.</p>
        </div>
      ) : (
        <div style={{display:'flex',flexDirection:'column',gap:'10px'}}>
          {units.map((u,i)=>{
            const cnt = A8.countUnitContent(u);
            const isOpen = expanded.has(u.id);
            return (
              <div key={u.id} className="unit-item">
                <div className={`unit-row${isOpen?' open':''}`}>
                  <button className={`u-caret${isOpen?' open':''}`} title={isOpen?'Contraer':'Desplegar'} onClick={()=>toggleExp(u.id)}><Icon name="chevright" /></button>
                  <div className="u-pos">{i+1}</div>
                  <div className="u-main" onClick={()=>toggleExp(u.id)}>
                    <div className="u-title">{u.title}</div>
                    <div className="u-sub">
                      <span><Icon name="text" /> {cnt.frags} {cnt.frags===1?'contenido':'contenidos'}</span>
                      <span><Icon name="question" /> {cnt.chks} {cnt.chks===1?'cuestionario':'cuestionarios'}</span>
                    </div>
                  </div>
                </div>
                {isOpen && <UnitPreview u={u} />}
              </div>
            );
          })}
        </div>
      )}
    </div>
  );
}

/* ---------- Confirmar borrado de curso (exige escribir "confirmar") ---------- */
function ConfirmDeleteCourse({ course, onClose, onConfirm }){
  const [txt, setTxt] = useState('');
  const name = course.meta_draft?.name || course.meta_pub?.name || 'Sin nombre';
  const ok = txt.trim().toLowerCase() === 'confirmar';
  return (
    <Modal danger icon="trash" title="Borrar curso"
      subtitle="Esta acción es definitiva. Se elimina todo el contenido del curso y no hay forma de recuperarlo."
      onClose={onClose}
      foot={<>
        <Btn variant="ghost" onClick={onClose}>Cancelar</Btn>
        <div className="spacer"></div>
        <Btn variant="danger" icon="trash" disabled={!ok}
          onClick={()=>{ if(ok) onConfirm(); }}>Borrar “{name}”</Btn>
      </>}>
      <p style={{fontSize:'13.5px',lineHeight:1.55,color:'var(--grafito)'}}>
        Vas a borrar <b>“{name}”</b> con su borrador{course.published?', su versión publicada':''} y todas sus unidades, fragmentos y cuestionarios.
      </p>
      <div className="field" style={{marginTop:'18px'}}>
        <label>Para confirmar, escribí <b>confirmar</b> abajo</label>
        <input type="text" value={txt} autoFocus placeholder="confirmar"
          onChange={e=>setTxt(e.target.value)}
          onKeyDown={e=>{ if(e.key==='Enter' && ok) onConfirm(); }} />
      </div>
    </Modal>
  );
}

/* ---------- Pestaña: Alumnos (datos reales, arq_05-adyacente) ---------- */
function AlumnosPanel({ course }){
  const [rows, setRows] = useState(null);
  const [loading, setLoading] = useState(true);
  const [err, setErr] = useState(null);
  const [addOpen, setAddOpen] = useState(false);
  const [busyId, setBusyId] = useState(null);

  const load = async ()=>{
    setLoading(true); setErr(null);
    try { setRows(await A8Api.listAlumnos(course.id)); }
    catch(e){ setErr(e.message || String(e)); }
    finally { setLoading(false); }
  };
  useEffect(()=>{ load(); }, [course.id]);

  const toggle = async (row)=>{
    setBusyId(row.alumno_id);
    try {
      if (row.estado === 'activa') await A8Api.pausarAlumno(course.id, row.alumno_id);
      else await A8Api.reactivarAlumno(course.id, row.alumno_id);
      await load();
    } catch(e){ setErr(e.message || String(e)); }
    finally { setBusyId(null); }
  };

  return (
    <div className="rag-wrap">
      <p className="rag-intro">
        Los alumnos inscriptos reciben el contenido del curso por WhatsApp. Pausar corta la
        entrega y los recordatorios sin perder el progreso; reactivar retoma donde quedó.
      </p>
      <div className="rag-ghead">
        <div className="rag-gt"><Icon name="courses" /> Alumnos inscriptos</div>
        <span className="rag-gc">{rows ? rows.length : '—'}</span>
        <Btn variant="magenta" size="sm" icon="plus" onClick={()=>setAddOpen(true)}>Inscribir alumno</Btn>
      </div>

      {err && (
        <div className="readonly-note" style={{marginTop:'12px',background:'var(--dirty-bg)',borderColor:'rgba(206,30,78,.35)',color:'var(--magenta)'}}>
          <Icon name="alert" /> {err}
        </div>
      )}

      {loading ? (
        <div className="empty-state" style={{padding:'40px 20px'}}>
          <div className="es-ic"><Icon name="refresh" /></div>
          <h3>Cargando alumnos…</h3>
        </div>
      ) : rows && rows.length>0 ? (
        <div className="rag-list">
          {rows.map(r=>(
            <div key={r.alumno_id} className="rag-row apoyo">
              <span className={`rag-ic ft-documento`}><Icon name="courses" /></span>
              <div className="rag-main">
                <div className="rag-name-row">
                  <div className="rag-name">{r.telefono_enmascarado} <span className="opt-tag" style={{marginLeft:'6px'}}>{r.alumno_id}</span></div>
                  <span className="rag-status-inline">
                    <span className={`rag-status ${r.estado==='activa'?'st-ok':'st-pend'}`}><span className="dt"></span>{r.estado==='activa'?'Activa':'Pausada'}</span>
                    <Btn variant={r.estado==='activa'?'subtle':'primary'} size="sm" disabled={busyId===r.alumno_id} onClick={()=>toggle(r)}>
                      {busyId===r.alumno_id ? '…' : (r.estado==='activa'?'Pausar':'Reactivar')}
                    </Btn>
                  </span>
                </div>
                <div className="rag-scope-note">
                  Unidad {r.unidad_actual ?? '—'} · máx. desbloqueada {r.posicion_maxima_desbloqueada ?? '—'} · desde {fmtDate(r.fecha_inicio ? r.fecha_inicio.slice(0,10) : null)}
                </div>
              </div>
            </div>
          ))}
        </div>
      ) : (
        <div className="rag-empty">Todavía no hay alumnos inscriptos. Inscribí el primero para que empiece a recibir el contenido por WhatsApp.</div>
      )}

      {addOpen && (
        <AddStudentForm
          onClose={()=>setAddOpen(false)}
          onSave={async (phone)=>{
            await A8Api.inscribirAlumno(course.id, phone);
            setAddOpen(false);
            await load();
          }} />
      )}
    </div>
  );
}

/* ---------- Form: inscribir alumno (mismo camino que el CLI de enrolamiento) ---------- */
function AddStudentForm({ onClose, onSave }){
  const [phone, setPhone] = useState('');
  const [busy, setBusy] = useState(false);
  const [err, setErr] = useState(null);
  const ok = phone.trim().length >= 8;
  const submit = async ()=>{
    if (!ok || busy) return;
    setBusy(true); setErr(null);
    try { await onSave(phone.trim()); }
    catch(e){ setErr(e.message || String(e)); }
    finally { setBusy(false); }
  };
  return (
    <Modal icon="plus" title="Inscribir alumno"
      subtitle="Se inscribe en este curso y empieza a recibir el contenido por WhatsApp. Mismo camino que el CLI de enrolamiento."
      onClose={onClose}
      foot={<><div className="spacer"></div><Btn variant="subtle" onClick={onClose}>Cancelar</Btn><Btn variant="primary" icon="check" disabled={!ok||busy} onClick={submit}>{busy?'Inscribiendo…':'Inscribir'}</Btn></>}>
      {err && <div className="readonly-note" style={{marginBottom:'12px',background:'var(--dirty-bg)',borderColor:'rgba(206,30,78,.35)',color:'var(--magenta)'}}><Icon name="alert" /> {err}</div>}
      <Field label="Número de WhatsApp (E.164)" hint="Con código de país, sin espacios ni guiones. Ej: +5491112345678. Argentina: agregá el 9 después del +54 (+54 9 11...) — si no, el mensaje no llega.">
        <input type="text" autoFocus value={phone} onChange={e=>setPhone(e.target.value)} placeholder="+5491112345678" onKeyDown={e=>{ if(e.key==='Enter'&&ok) submit(); }} />
      </Field>
    </Modal>
  );
}

function MetaField({ k, v, icon, long, changed, full }){
  return (
    <div className="meta-field" style={full?{gridColumn:'1 / -1'}:null}>
      <div className="mf-k">{icon && <Icon name={icon} style={{width:13,height:13}} />}{k}{changed && <span className="tag-diff tag-edit" style={{marginLeft:'4px'}}>editado</span>}</div>
      <div className={`mf-v${long?' long':''}`}>{v}</div>
    </div>
  );
}

/* ---------- Panel desplegable de una unidad (preview de contenido, solo lectura) ---------- */
function UnitPreview({ u }){
  const items = u.items || [];
  const frags = items.filter(i=>i.kind==='frag');
  const chks = items.filter(i=>i.kind==='chk');
  return (
    <div className="unit-expand">
      <div className="ue-grid">
        <div className="ue-block">
          <div className="ue-h"><Icon name="text" /> Contenido <span className="ue-n">{frags.length}</span></div>
          {frags.length===0
            ? <div className="ue-empty">Sin contenido</div>
            : frags.map(fr=>{
                const t = (fr.text||'').trim();
                const label = fr.title || (t ? (t.length>70 ? t.slice(0,70)+'…' : t) : '(texto vacío)');
                return (
                  <div key={fr.id} className="ue-item">
                    <span className={`ue-ic ft-${fr.type||'texto'}`}><Icon name={FRAG_ICON[fr.type||'texto']} /></span>
                    <span className="ue-t" title={label}>{label}</span>
                  </div>
                );
              })}
        </div>
        <div className="ue-block">
          <div className="ue-h"><Icon name="question" /> Cuestionarios <span className="ue-n">{chks.length}</span></div>
          {chks.length===0
            ? <div className="ue-empty">Sin cuestionarios</div>
            : chks.map(c=>(
                <div key={c.id} className="ue-item">
                  <span className="ue-ic ft-texto"><Icon name="question" /></span>
                  <span className="ue-t">{c.question}</span>
                  {c.options.length>0 && <span className="ue-tag">{c.options.length} opc.</span>}
                </div>
              ))}
        </div>
      </div>
    </div>
  );
}

/* ---------- Form: metadata del curso ---------- */
function CourseMetaForm({ meta, cursoId, onClose, onSave }){
  const [f, setF] = useState({ ...meta });
  const up = (k)=>(e)=>setF({ ...f, [k]:e.target.value });
  const mediaOn = window.FEATURES.mediaNonText;

  // Media real adjunta a la bienvenida (video, uploader v2) — mismo mecanismo
  // que en el organizador de contenido: presigned PUT + progreso via XHR.
  const [uploadPct,setUploadPct] = useState(f.welcomeMediaS3Key ? 100 : 0);
  const [uploadErr,setUploadErr] = useState(null);
  const [compressionStatus,setCompressionStatus] = useState(null);
  const [compressionInfo,setCompressionInfo] = useState(null);
  const welcomeFileRef = useRef(null);

  async function uploadWelcomeFile(file){
    const c = classify(file);
    if (!c.ok) { setUploadErr(c.reason); return; }
    setUploadErr(null); setUploadPct(0); setCompressionStatus(null); setCompressionInfo(null);
    try {
      const { upload_url, s3_key, tipo, content_type } = await A8Api.getMediaUploadUrl(cursoId, {
        filename: file.name, sizeBytes: file.size, unidadId: null,
      });
      await A8Api.uploadFileToS3(upload_url, file, content_type, setUploadPct);
      setF(prev=>({ ...prev, welcomeMediaS3Key: s3_key, welcomeMediaTipo: tipo }));
      setUploadPct(100);
      if(tipo==='video' && file.size > VIDEO_COMPRESS_THRESHOLD_MB*MB){
        setCompressionStatus('procesando');
        A8Api.pollMediaStatus(cursoId, s3_key, (st)=>{ setCompressionStatus(st.status); setCompressionInfo(st); });
      }
    } catch(e){
      setUploadErr((e&&e.message)||'Error al subir');
    }
  }

  return (
    <Modal wide icon="settings" title="Editar metadata del curso"
      subtitle="Estos cambios quedan en el borrador. El alumno no los ve hasta publicar."
      onClose={onClose}
      foot={<><div className="spacer"></div><Btn variant="subtle" onClick={onClose}>Cancelar</Btn><Btn variant="primary" icon="check" disabled={!f.name.trim()||!f.welcome.trim()} onClick={()=>onSave(f)}>Guardar en borrador</Btn></>}>
      <Field label="Nombre del curso"><input type="text" value={f.name} onChange={up('name')} /></Field>
      <Field label="Descripción"><textarea value={f.description} onChange={up('description')} /></Field>
      <Field label="Mensaje de bienvenida" hint="Lo primero que ve el alumno al entrar al curso. Es obligatorio."><textarea value={f.welcome} onChange={up('welcome')} placeholder="Escribí el saludo de bienvenida…" /></Field>
      {mediaOn && (
        <Field label={<>Video (u otro adjunto) de bienvenida <span className="opt-tag">opcional</span></>}
          hint={f.welcomeComoCaption
            ? "Se fusiona con el texto de bienvenida en un solo mensaje (el texto viaja como caption)."
            : "Se manda como adjunto real de WhatsApp, después del texto de bienvenida (dos mensajes)."}>
          <input ref={welcomeFileRef} type="file" style={{display:'none'}}
            onChange={e=>{ if(e.target.files[0]) uploadWelcomeFile(e.target.files[0]); e.target.value=''; }} />
          <div className="dropzone" onClick={()=>welcomeFileRef.current&&welcomeFileRef.current.click()}>
            <div className="dz-ic"><Icon name="upload" /></div>
            <div className="dz-t">{f.welcomeMediaS3Key ? 'Reemplazar archivo' : 'Elegir o arrastrar archivo'}</div>
          </div>
          {uploadPct>0 && uploadPct<100 && (
            <div className="upload-progress" style={{marginTop:'6px'}}>
              <progress value={uploadPct} max="100" style={{width:'100%'}} />
              <span className="hint">Subiendo… {uploadPct}%</span>
            </div>
          )}
          {f.welcomeMediaS3Key && uploadPct>=100 && !uploadErr && (
            <div className="bulk-status ok" style={{marginTop:'6px'}}>
              <Icon name="check" style={{width:12,height:12}} /> Archivo subido ({f.welcomeMediaS3Key.split('/').pop()})
            </div>
          )}
          {compressionStatus && (
            <div style={{marginTop:'6px'}}><CompressionStatusLine status={compressionStatus} info={compressionInfo} /></div>
          )}
          {uploadErr && (
            <div className="bulk-status bad" style={{marginTop:'6px'}}>
              <Icon name="x" style={{width:12,height:12}} />{uploadErr}
            </div>
          )}
          {f.welcomeMediaS3Key && f.welcomeMediaTipo!=='audio' && (
            <label style={{display:'flex',alignItems:'center',gap:'10px',cursor:'pointer',padding:'8px 0 0'}}>
              <input type="checkbox" checked={!!f.welcomeComoCaption}
                onChange={e=>setF({ ...f, welcomeComoCaption:e.target.checked })} />
              <span>Usar el texto de bienvenida como caption (un solo mensaje)</span>
            </label>
          )}
          {f.welcomeComoCaption && f.welcome && f.welcome.length>1024 && (
            <div className="bulk-status bad" style={{marginTop:'6px'}}><Icon name="x" style={{width:12,height:12}} /> El texto de bienvenida tiene {f.welcome.length} caracteres, supera el límite de 1024 para caption.</div>
          )}
        </Field>
      )}
      {mediaOn && f.welcomeMediaS3Key && (
        <Field label="Espera libre">
          <label style={{display:'flex',alignItems:'center',gap:'10px',padding:'4px 0',opacity:.7}}>
            <input type="checkbox" checked disabled />
            <span>Frenar acá y esperar cualquier respuesta antes de seguir</span>
          </label>
          <div className="hint">Siempre activo en la bienvenida: el guion nunca arranca hasta que el alumno responda algo.</div>
        </Field>
      )}
      <Field label="Entrega de contenido" hint="Por ahora todos los cursos entregan contenido a diario. No es configurable.">
        <div className="fixed-field" style={{maxWidth:'260px'}}><Icon name="calendar" /> Diaria · obligatoria</div>
      </Field>
      {window.FEATURES.reminders && (
      <Field label="Recordatorios por inactividad" hint="Se le avisa al alumno si pasa X días sin interactuar. Los mensajes están pre-aprobados por Meta: elegí uno de la lista. Podés encadenar varios.">
        <RemindersEditor value={f.reminders||[]} onChange={rs=>setF({ ...f, reminders:rs })} />
      </Field>
      )}
      {window.FEATURES.postAccess && (
      <Field label="Acceso al asistente tras finalizar" hint="Cuando el alumno termina el curso y recibe el certificado, definí si puede seguir conversando con el asistente para repasar dudas.">
        <PostAccessEditor value={f.postAccess} onChange={pa=>setF({ ...f, postAccess:pa })} />
      </Field>
      )}
    </Modal>
  );
}

/* ---------- Recordatorios: display + editor ---------- */
function RemindersDisplay({ list }){
  if (!list || !list.length) return <span className="muted">Sin recordatorios</span>;
  const sorted = list.slice().sort((a,b)=>a.days-b.days);
  return (
    <div className="rem-display">
      {sorted.map((r,i)=>{
        const t = A8.reminderTpl(r.templateId);
        return (
          <div key={r.id||i} className="rem-chip">
            <span className="rem-when">Tras {r.days} {r.days===1?'día':'días'}</span>
            <span className="rem-tpl">{t?.label || '— sin mensaje'}</span>
          </div>
        );
      })}
    </div>
  );
}

function RemindersEditor({ value, onChange }){
  const list = value;
  const setRow = (i, patch)=>{ const n=list.map((r,j)=>j===i?{...r,...patch}:r); onChange(n); };
  const addRow = ()=>{ if(list.length>=6) return; onChange([...list, { id:A8.uid('r'), days:(list.length?Math.max(...list.map(r=>r.days))+7:3), templateId:'t1' }]); };
  const delRow = (i)=> onChange(list.filter((_,j)=>j!==i));
  return (
    <div className="rem-editor">
      {list.length===0 && <div className="rem-empty">Todavía no hay recordatorios. El alumno no recibe ningún aviso.</div>}
      {list.map((r,i)=>{
        return (
          <div key={r.id||i} className="rem-row">
            <div className="rem-row-top">
              <span className="rem-lbl">Tras</span>
              <input className="rem-days" type="text" inputMode="numeric" value={r.days}
                onChange={e=>{ const n=parseInt(e.target.value.replace(/\D/g,''),10); setRow(i,{days:isNaN(n)?0:Math.min(n,365)}); }} />
              <span className="rem-lbl">días, enviar:</span>
              <select className="rem-select" value={r.templateId} onChange={e=>setRow(i,{templateId:e.target.value})} title="Mensajes pre-aprobados por Meta">
                {A8.REMINDER_TEMPLATES.map(t=><option key={t.id} value={t.id}>{t.text}</option>)}
              </select>
              <button className="btn-icon danger" title="Quitar recordatorio" onClick={()=>delRow(i)}><Icon name="x" /></button>
            </div>
          </div>
        );
      })}
      {list.length<6 && (
        <button className="add-row" style={{padding:'10px',marginTop:list.length?'10px':'0'}} onClick={addRow}>
          <Icon name="plus" /> Agregar recordatorio
        </button>
      )}
    </div>
  );
}

/* ---------- Acceso al asistente tras finalizar: display + editor ---------- */
function PostAccessDisplay({ pa }){
  const p = A8.normPostAccess(pa);
  const icon = p.mode==='always' ? 'infinity' : p.mode==='limited' ? 'clock' : 'x';
  return (
    <div className="pa-display">
      <span className={`pa-badge pa-${p.mode}`}><Icon name={icon} />{A8.fmtPostAccess(pa)}</span>
    </div>
  );
}

function PostAccessEditor({ value, onChange }){
  const p = A8.normPostAccess(value);
  const set = (patch)=>onChange({ ...p, ...patch });
  return (
    <div className="pa-editor">
      <div className="pa-modes">
        {A8.POST_ACCESS_MODES.map(m=>(
          <button key={m.id} type="button"
            className={`pa-mode${p.mode===m.id?' on':''}`}
            onClick={()=>set({ mode:m.id })}>
            <Icon name={m.id==='always'?'infinity':m.id==='limited'?'clock':'x'} />
            <span className="pa-mode-t">{m.label}</span>
          </button>
        ))}
      </div>
      {p.mode==='limited' && (
        <div className="pa-days">
          <span className="pa-days-lbl">Ventana de acceso:</span>
          <input className="rem-days" type="text" inputMode="numeric" value={p.days}
            onChange={e=>{ const n=parseInt(e.target.value.replace(/\D/g,''),10); set({ days:isNaN(n)?0:Math.min(n,365) }); }} />
          <span className="pa-days-lbl">días desde el certificado</span>
          <div className="pa-presets">
            {[7,30,60,90].map(d=>(
              <button key={d} type="button" className={`pa-preset${p.days===d?' on':''}`} onClick={()=>set({ days:d })}>{d}d</button>
            ))}
          </div>
        </div>
      )}
      <div className="pa-note">
        {p.mode==='none' && 'Al emitir el certificado, la conversación queda cerrada. El alumno ya no puede escribirle al asistente.'}
        {p.mode==='limited' && `El alumno puede seguir consultando al asistente durante ${p.days} ${p.days===1?'día':'días'} después de recibir el certificado. Después se cierra automáticamente.`}
        {p.mode==='always' && 'El alumno conserva el acceso al asistente de forma indefinida, incluso después de certificarse.'}
      </div>
    </div>
  );
}

/* ---------- Form: unidad (crear / renombrar) ---------- */
function UnitForm({ initial, onClose, onSave }){
  const [title, setTitle] = useState(initial || '');
  const editing = initial!==undefined;
  return (
    <Modal icon={editing?'edit':'plus'} title={editing?'Renombrar unidad':'Agregar unidad'}
      subtitle={editing?null:'Se agrega al final del borrador. Después podés cargar fragmentos y cuestionarios.'}
      onClose={onClose}
      foot={<><div className="spacer"></div><Btn variant="subtle" onClick={onClose}>Cancelar</Btn><Btn variant="primary" icon="check" disabled={!title.trim()} onClick={()=>onSave(title.trim())}>{editing?'Guardar':'Agregar unidad'}</Btn></>}>
      <Field label="Título de la unidad" hint="Ej: “Unidad 1 · Fundamentos”.">
        <input type="text" autoFocus value={title} onChange={e=>setTitle(e.target.value)} onKeyDown={e=>{ if(e.key==='Enter'&&title.trim()) onSave(title.trim()); }} placeholder="Nombre de la unidad" />
      </Field>
    </Modal>
  );
}

window.Screens = { CourseList, CourseEditor, UnitForm, fmtDate };
Object.assign(window, { CourseList, CourseEditor, UnitForm, CourseMetaForm, MetaField, UnitPreview, RemindersDisplay, RemindersEditor, fmtDate });
