// ============ AcademIA8 · Consola — Campañas · EDITOR (crear/editar) + vista enviada ============

const TZ_LABEL = 'hora de Córdoba (GMT-3)';
const MESES = ['ene','feb','mar','abr','may','jun','jul','ago','sep','oct','nov','dic'];

function fmtCampDateTime(iso){
  if(!iso) return '—';
  const [d,t] = iso.split('T');
  const [y,m,day] = d.split('-');
  return `${+day} ${MESES[+m-1]} ${y}, ${t||''} hs`;
}
function tomorrowStr(){ const d = new Date('2026-07-07T00:00:00'); d.setDate(d.getDate()+1); return d.toISOString().slice(0,10); }

// ---------- modal: editar remitente (config global) ----------
function SenderModal({ remitente, onClose, onSave }){
  const [nombre, setNombre] = useState(remitente.nombre);
  const [email, setEmail] = useState(remitente.email);
  return (
    <Modal icon="settings" title="Remitente de las campañas"
      subtitle="El remitente es el mismo para todas las campañas. Se muestra como “De:” en cada correo."
      onClose={onClose}
      foot={<><div className="spacer"></div><Btn variant="subtle" onClick={onClose}>Cancelar</Btn><Btn variant="primary" icon="check" onClick={()=>onSave({nombre:nombre.trim(),email:email.trim()})}>Guardar</Btn></>}>
      <Field label="Nombre visible"><input type="text" value={nombre} onChange={e=>setNombre(e.target.value)} placeholder="AcademIA8" /></Field>
      <Field label="Dirección de correo"><input type="text" value={email} onChange={e=>setEmail(e.target.value)} placeholder="hola@academia8.com" /></Field>
    </Modal>
  );
}

// ---------- modal: confirmar envío ----------
function ConfirmSend({ n, modo, cuando, asunto, remitente, busy, onClose, onConfirm }){
  return (
    <Modal icon={modo==='ahora'?'send':'clock'} title={modo==='ahora'?'Confirmar envío':'Confirmar programación'}
      subtitle={modo==='ahora'?'Revisá los datos. El envío es inmediato y no se puede deshacer.':'La campaña se enviará automáticamente en la fecha y hora indicadas.'}
      onClose={onClose}
      foot={<>
        <div className="spacer"></div>
        <Btn variant="subtle" onClick={onClose} disabled={busy}>Volver</Btn>
        <Btn variant="magenta" icon={modo==='ahora'?'send':'clock'} onClick={onConfirm} disabled={busy}>
          {busy ? 'Procesando…' : (modo==='ahora'?'Enviar ahora':'Programar envío')}
        </Btn>
      </>}>
      <div className="confirm-big">
        <div className="confirm-n">{n.toLocaleString('es-AR')}</div>
        <div className="confirm-l">{n===1?'persona activa recibirá esta campaña':'personas activas recibirán esta campaña'}</div>
      </div>
      <div className="confirm-when">
        <Icon name={modo==='ahora'?'send':'calendar'} />
        {modo==='ahora' ? 'Se envía ahora mismo' : `${fmtCampDateTime(cuando)} · ${TZ_LABEL}`}
      </div>
      <div className="confirm-meta">
        <div className="cm-row"><span className="cm-k">Asunto</span><span className="cm-v">{asunto||'—'}</span></div>
        <div className="cm-row"><span className="cm-k">Remitente</span><span className="cm-v">{remitente.nombre} · {remitente.email}</span></div>
      </div>
    </Modal>
  );
}

// ---------- preview expandida ----------
function PreviewOverlay({ html, onClose }){
  useEffect(()=>{ const h=(e)=>{ if(e.key==='Escape') onClose(); }; window.addEventListener('keydown',h); return ()=>window.removeEventListener('keydown',h); },[]);
  return (
    <div className="prev-overlay" onMouseDown={e=>{ if(e.target===e.currentTarget) onClose(); }}>
      <div className="prev-overlay-bar">
        <Icon name="eye" /><span className="po-t">Vista previa</span>
        <div style={{marginLeft:'auto'}}><Btn variant="ghost" icon="x" onClick={onClose}>Cerrar</Btn></div>
      </div>
      <div className="prev-overlay-frame"><iframe srcDoc={html} title="Vista previa" sandbox=""></iframe></div>
    </div>
  );
}

// =================== EDITOR ===================
function CampaignEditor({ campId, notify, onDone }){
  const idRef = useRef(campId==='new' ? null : campId);
  const readyRef = useRef(false);
  const [loading, setLoading] = useState(true);
  const [tags, setTags] = useState([]);
  const [config, setConfig] = useState({ remitente:{nombre:'',email:''} });

  const [asunto, setAsunto] = useState('');
  const [modo, setModo] = useState('todos');       // todos | etiquetas
  const [etiquetas, setEtiquetas] = useState([]);
  const [html, setHtml] = useState('');
  const [conteo, setConteo] = useState({ total:0, excluidos:0 });
  const [pruebas, setPruebas] = useState('');
  const [pruebaRes, setPruebaRes] = useState(null);
  const [pruebaBusy, setPruebaBusy] = useState(false);
  const [warnings, setWarnings] = useState([]);

  const [sendMode, setSendMode] = useState('ahora'); // ahora | programar
  const [fecha, setFecha] = useState(tomorrowStr());
  const [hora, setHora] = useState('09:00');
  const [confirming, setConfirming] = useState(false);
  const [sendBusy, setSendBusy] = useState(false);
  const [saveState, setSaveState] = useState('idle');
  const [senderModal, setSenderModal] = useState(false);
  const [expand, setExpand] = useState(false);

  // ---- carga inicial ----
  useEffect(()=>{ (async()=>{
   try{
    const [t, cfg] = await Promise.all([CampAPI.listarEtiquetas(), CampAPI.obtenerConfig()]);
    setTags(t); setConfig(cfg);
    if (idRef.current){
      const c = await CampAPI.obtenerCampania(idRef.current);
      if (c){ setAsunto(c.asunto||''); setModo(c.destinatarios.modo); setEtiquetas(c.destinatarios.etiquetas||[]); setHtml(c.html||''); setPruebas((c.pruebasEnviadas||[]).join(', ')); }
    }
   }catch(e){ notify(e.message||'No se pudo cargar la campaña'); }
    setLoading(false);
    setTimeout(()=>{ readyRef.current = true; }, 60);
  })(); },[]);

  // ---- conteo de destinatarios en vivo ----
  useEffect(()=>{ if(loading) return; let alive=true; (async()=>{
    try{
      let r;
      if (idRef.current && saveState==='saved'){ r = await CampAPI.previewCampania(idRef.current); }
      else { r = await CampAPI.contarDestinatarios(modo, etiquetas); }
      if(alive) setConteo(r);
    }catch(e){ /* mantené el conteo previo */ }
  })(); return ()=>{ alive=false; }; },[modo, etiquetas, loading, saveState]);

  // ---- autosave (borrador) ----
  // El remitente es global (config/sender), no por campaña: no se manda en el body.
  const hasContent = ()=> asunto.trim() || html.trim() || etiquetas.length || modo==='etiquetas';
  const buildData = ()=>({ asunto, destinatarios:{ modo, etiquetas }, html });
  const persist = async ()=>{
    setSaveState('saving');
    try{
      let c;
      if (idRef.current){ c = await CampAPI.actualizarCampania(idRef.current, buildData()); }
      else { c = await CampAPI.crearCampania(buildData()); if(c) idRef.current = c.id; }
      setWarnings(c && c.warnings ? c.warnings : []);
      setSaveState('saved');
      return c;
    }catch(e){
      // "por etiqueta" sin etiqueta todavía: no se puede guardar aún, sin ruido.
      if (e && e.code==='no_recipients'){ setSaveState('dirty'); return null; }
      setSaveState('dirty');
      notify(e.message || 'No se pudo guardar el borrador');
      throw e;
    }
  };
  useEffect(()=>{
    if (!readyRef.current) return;
    if (!idRef.current && !hasContent()) return;
    setSaveState('dirty');
    const t = setTimeout(()=>{ persist().catch(()=>{}); }, 900);
    return ()=>clearTimeout(t);
  },[asunto, modo, etiquetas, html]);

  const toggleTag = (id)=> setEtiquetas(s=> s.includes(id)?s.filter(x=>x!==id):[...s,id]);

  // ---- pasos completos ----
  const okDest = conteo.total>0;
  const okAsunto = asunto.trim().length>0;
  const okHtml = html.trim().length>0;
  const okProg = sendMode==='ahora' || (fecha && hora);
  const puedeEnviar = okDest && okAsunto && okHtml && okProg;

  // ---- prueba ----
  const dirsPrueba = pruebas.split(',').map(s=>s.trim()).filter(Boolean);
  const enviarPrueba = async ()=>{
    if(!dirsPrueba.length){ notify('Ingresá al menos una dirección'); return; }
    if(dirsPrueba.length>CampAPI.MAX_PRUEBA){ notify(`El máximo es ${CampAPI.MAX_PRUEBA} direcciones de prueba`); return; }
    if(!okHtml){ notify('Primero pegá el contenido HTML'); return; }
    setPruebaBusy(true);
    try{
      if(!idRef.current){ await persist(); if(!idRef.current){ setPruebaBusy(false); notify('Elegí destinatarios antes de probar'); return; } }
      // En sandbox de Amazon SES validamos las direcciones contra las verificadas ANTES de llamar.
      let toSend = dirsPrueba, localRej = [];
      if (config.sandbox){
        const verif = (config.verificadas||[]).map(e=>e.toLowerCase());
        toSend = dirsPrueba.filter(e=> verif.includes(e.toLowerCase()));
        localRej = dirsPrueba.filter(e=> !verif.includes(e.toLowerCase()))
          .map(e=>({ email:e, ok:false, error:'No está verificada en Amazon (modo prueba). Verificala antes de enviarle.' }));
      }
      let apiRes = [];
      if (toSend.length){ const res = await CampAPI.enviarPrueba(idRef.current, toSend); apiRes = res.resultados; }
      const all = dirsPrueba.map(e=>
        apiRes.find(r=>r.email.toLowerCase()===e.toLowerCase())
        || localRej.find(r=>r.email.toLowerCase()===e.toLowerCase())
        || { email:e, ok:false, error:'No se pudo procesar' });
      setPruebaRes(all);
      const enviadas = all.filter(r=>r.ok).length;
      const rech = all.length - enviadas;
      if(rech===0) notify(`Prueba enviada a ${enviadas} dirección${enviadas===1?'':'es'}`);
      else if(enviadas) notify(`${enviadas} enviada${enviadas===1?'':'s'} · ${rech} rechazada${rech===1?'':'s'}`);
      else notify('Ninguna dirección pudo recibir la prueba');
    }catch(e){ setPruebaRes(null); notify(e.message||'No se pudo enviar la prueba'); }
    setPruebaBusy(false);
  };

  // ---- guardar remitente global (aplica a TODAS las campañas) ----
  const saveSender = async (r)=>{
    try{ const out = await CampAPI.guardarRemitente(r); setConfig(c=>({ ...c, remitente: out })); setSenderModal(false); notify('Remitente actualizado'); }
    catch(e){ notify(e.message||'No se pudo guardar el remitente'); }
  };

  // ---- confirmar envío ----
  const doSend = async ()=>{
    setSendBusy(true);
    try{
      await persist();
      if (!idRef.current){ setSendBusy(false); notify('No se pudo guardar la campaña'); return; }
      if (sendMode==='ahora'){
        await CampAPI.enviarAhora(idRef.current);
        notify('Envío iniciado · la campaña se está enviando');
      } else {
        await CampAPI.programarCampania(idRef.current, `${fecha}T${hora}`);
        notify('Campaña programada');
      }
      setConfirming(false); setSendBusy(false);
      onDone();
    }catch(e){ setSendBusy(false); notify(e.message||'No se pudo procesar el envío'); }
  };

  const saveLabel = saveState==='saving' ? 'Guardando…' : saveState==='saved' ? 'Borrador guardado' : saveState==='dirty' ? 'Sin guardar' : '';

  if (loading) return <div className="wrap"><div className="cmp-loading"><span className="cmp-spin"></span>Cargando campaña…</div></div>;

  const remitente = config.remitente || { nombre:'Academia 8', email:'cursos@'+CampAPI.DOMINIO_ENVIO };

  return (
    <div className="wrap">
      {/* barra superior del editor */}
      <a className="back-link" onClick={onDone}><Icon name="chevright" style={{width:14,height:14,transform:'rotate(180deg)'}} />Volver a campañas</a>
      <div className="camp-topbar">
        <div style={{fontFamily:'var(--serif)',fontWeight:700,fontSize:'24px',color:'var(--tinta)',lineHeight:1.2}}>{asunto.trim() || 'Nueva campaña'}</div>
        {saveLabel && <span className="camp-save-state">{saveState==='saved' && <Icon name="check" style={{color:'var(--verde-prof)'}} />}{saveLabel}</span>}
      </div>
      <div className="cmp-sub" style={{marginTop:'6px'}}>El asunto (paso 2) es el nombre de la campaña y lo que ve quien recibe el correo en su bandeja.</div>

      <div className="camp-layout">
        {/* ---------- columna principal ---------- */}
        <div className="camp-main">

          {/* 1 · DESTINATARIOS */}
          <section className={`camp-sec${okDest?' done':''}`}>
            <div className="camp-sec-head">
              <div className="camp-sec-num">1</div>
              <div style={{flex:1}}>
                <div className="camp-sec-t">Destinatarios</div>
                <div className="camp-sec-s">Elegí a quiénes les llega. Podés combinar varias etiquetas.</div>
              </div>
              {okDest && <span className="camp-sec-check"><Icon name="check" />Listo</span>}
            </div>
            <div className="camp-sec-body">
              <div className="rcpt-modes">
                <button className={`rcpt-mode${modo==='todos'?' on':''}`} onClick={()=>setModo('todos')}>
                  <span className="rcpt-radio"></span>
                  <span><span className="rcpt-mode-t">Todos los contactos</span><span className="rcpt-mode-s">Toda tu base activa</span></span>
                </button>
                <button className={`rcpt-mode${modo==='etiquetas'?' on':''}`} onClick={()=>setModo('etiquetas')}>
                  <span className="rcpt-radio"></span>
                  <span><span className="rcpt-mode-t">Por etiqueta</span><span className="rcpt-mode-s">Una o varias etiquetas</span></span>
                </button>
              </div>
              {modo==='etiquetas' && (
                <div className="rcpt-tags">
                  {tags.map(t=>(
                    <button key={t.id} className={`rcpt-tag${etiquetas.includes(t.id)?' on':''}`} onClick={()=>toggleTag(t.id)}>
                      <span className="rcpt-chk">{etiquetas.includes(t.id) && <Icon name="check" />}</span>{t.nombre}
                    </button>
                  ))}
                </div>
              )}
              <div className="rcpt-count">
                <div>
                  <div className="rcpt-count-n">{conteo.aprox?'≈ ':''}{conteo.total.toLocaleString('es-AR')}</div>
                  <div className="rcpt-count-l">{conteo.total===1?'destinatario activo':'destinatarios activos'}</div>
                  {conteo.aprox && <div style={{fontSize:'11px',color:'var(--gris)',marginTop:'5px',maxWidth:'230px',lineHeight:1.45}}>Estimado por etiqueta. El total exacto (sin bajas ni repetidos) se calcula al guardarse el borrador.</div>}
                </div>
                {conteo.excluidos>0 && (
                  <div className="rcpt-excl">Se excluyen <b>{conteo.excluidos}</b> contacto{conteo.excluidos===1?'':'s'}<br/>por baja o rebote</div>
                )}
              </div>
            </div>
          </section>

          {/* 2 · ASUNTO + REMITENTE */}
          <section className={`camp-sec${okAsunto?' done':''}`}>
            <div className="camp-sec-head">
              <div className="camp-sec-num">2</div>
              <div style={{flex:1}}>
                <div className="camp-sec-t">Asunto y remitente</div>
                <div className="camp-sec-s">El asunto es lo primero que ve la persona en su bandeja.</div>
              </div>
              {okAsunto && <span className="camp-sec-check"><Icon name="check" />Listo</span>}
            </div>
            <div className="camp-sec-body">
              <Field label="Asunto del correo">
                <input type="text" value={asunto} onChange={e=>setAsunto(e.target.value)} placeholder="Ej. Arranca tu curso de Finanzas 💸" maxLength={150} />
              </Field>
              <Field label="Remitente" hint="Es el mismo para todas las campañas. Se configura una vez, no por campaña.">
                <div className="sender-fixed">
                  <Icon name="send" />
                  <div style={{flex:1,minWidth:0}}>
                    <div className="cell-strong">{remitente.nombre}</div>
                    <div className="cell-sub" style={{fontFamily:'var(--mono)'}}>{remitente.email}</div>
                  </div>
                  <Btn variant="ghost" icon="settings" onClick={()=>setSenderModal(true)}>Editar</Btn>
                </div>
                <div className="reply-note"><Icon name="chat" />Las respuestas de los alumnos llegan a la casilla de Academia 8.</div>
              </Field>
            </div>
          </section>

          {/* 3 · CONTENIDO */}
          <section className={`camp-sec${okHtml?' done':''}`}>
            <div className="camp-sec-head">
              <div className="camp-sec-num">3</div>
              <div style={{flex:1}}>
                <div className="camp-sec-t">Contenido</div>
                <div className="camp-sec-s">Pegá el código HTML que te pasaron. La vista previa se actualiza sola.</div>
              </div>
              {okHtml && <span className="camp-sec-check"><Icon name="check" />Listo</span>}
            </div>
            <div className="camp-sec-body">
              <div className="html-note">
                <Icon name="check" />
                <span>El pie con el <b>link para darse de baja</b> se agrega automáticamente a cada correo. No hace falta incluirlo en el HTML.</span>
              </div>
              {warnings.length>0 && (
                <div style={{display:'flex',flexDirection:'column',gap:'8px',marginBottom:'2px'}}>
                  {warnings.map((w,i)=>(
                    <div key={i} className="test-toomany" style={{marginTop:0}}><Icon name="alert" /><span>{CampAPI._warningText(w)}</span></div>
                  ))}
                </div>
              )}
              <div className="html-split">
                <div className="html-pane">
                  <div className="html-pane-h"><Icon name="doc" />Código HTML</div>
                  <textarea className="html-code" value={html} onChange={e=>setHtml(e.target.value)}
                    placeholder="Pegá acá el código HTML del correo…" spellCheck={false}></textarea>
                </div>
                <div className="html-pane">
                  <div className="html-pane-h">
                    <Icon name="eye" />Vista previa
                    {okHtml && <button className="html-expand" onClick={()=>setExpand(true)}><Icon name="eye" style={{width:12,height:12}} />Expandir</button>}
                  </div>
                  {okHtml ? (
                    <div className="html-prev"><iframe srcDoc={html} title="Vista previa" sandbox=""></iframe></div>
                  ) : (
                    <div className="html-prev"><div className="html-prev-empty"><Icon name="eye" /><p>Acá vas a ver cómo queda el correo apenas pegues el HTML.</p></div></div>
                  )}
                </div>
              </div>
            </div>
          </section>

          {/* 4 · PRUEBA */}
          <section className="camp-sec">
            <div className="camp-sec-head">
              <div className="camp-sec-num">4</div>
              <div style={{flex:1}}>
                <div className="camp-sec-t">Envío de prueba</div>
                <div className="camp-sec-s">Mandate el correo a vos mismo antes del envío real. Recomendado siempre.</div>
              </div>
            </div>
            <div className="camp-sec-body">
              {config.sandbox && (
                <div className="html-note" style={{background:'rgba(206,30,78,.07)',borderColor:'rgba(206,30,78,.2)'}}>
                  <Icon name="alert" />
                  <span><b>Modo prueba de Amazon:</b> solo se puede enviar a direcciones verificadas. Las demás se rechazan automáticamente.</span>
                </div>
              )}
              <div className="test-row">
                <Field label="Direcciones de prueba" hint={`Hasta ${CampAPI.MAX_PRUEBA}, separadas por coma. Tienen que estar verificadas en Amazon.`}>
                  <input type="text" value={pruebas} onChange={e=>setPruebas(e.target.value)} placeholder="fran@academia8.com, revisor@academia8.com" />
                </Field>
                <div style={{paddingTop:'26px'}}>
                  <Btn variant="ghost" icon="send" onClick={enviarPrueba} disabled={pruebaBusy || dirsPrueba.length>CampAPI.MAX_PRUEBA}>{pruebaBusy?'Enviando…':'Enviar prueba'}</Btn>
                </div>
              </div>
              {dirsPrueba.length>CampAPI.MAX_PRUEBA && (
                <div className="test-toomany"><Icon name="alert" />Pusiste {dirsPrueba.length} direcciones — el máximo es {CampAPI.MAX_PRUEBA}.</div>
              )}
              {pruebaRes && (
                <div className="test-results">
                  {pruebaRes.map((r,i)=>(
                    <div key={i} className={`test-result${r.ok?' ok':' bad'}`}>
                      <span className="tr-ic"><Icon name={r.ok?'check':'x'} /></span>
                      <span className="tr-em">{r.email}</span>
                      <span className={`tr-msg${r.ok?' ok':' bad'}`}>{r.ok?'Enviada':r.error}</span>
                    </div>
                  ))}
                </div>
              )}
            </div>
          </section>
        </div>

        {/* ---------- rail de envío ---------- */}
        <div className="send-rail">
          <div className="rail-card">
            <div className="rail-status">
              <span className="pill pill-draft"><span className="dt"></span>Borrador</span>
              <span style={{marginLeft:'auto',fontSize:'11px',color:'var(--gris)',fontWeight:600}}>{saveState==='saved'?'Guardado':saveState==='saving'?'Guardando…':''}</span>
            </div>
            <div className="rail-body">
              <div className={`rail-check${okDest?'':' pending'}`}><span className={`rail-ic ${okDest?'ok':'no'}`}><Icon name={okDest?'check':'x'} /></span><span className="rail-check-t">{okDest?`${conteo.total.toLocaleString('es-AR')} destinatarios`:'Elegí destinatarios'}</span></div>
              <div className={`rail-check${okAsunto?'':' pending'}`}><span className={`rail-ic ${okAsunto?'ok':'no'}`}><Icon name={okAsunto?'check':'x'} /></span><span className="rail-check-t">{okAsunto?'Asunto cargado':'Falta el asunto'}</span></div>
              <div className={`rail-check${okHtml?'':' pending'}`}><span className={`rail-ic ${okHtml?'ok':'no'}`}><Icon name={okHtml?'check':'x'} /></span><span className="rail-check-t">{okHtml?'Contenido cargado':'Falta el contenido'}</span></div>
            </div>
            <div className="rail-foot">
              <div className="send-modes">
                <button className={sendMode==='ahora'?'on':''} onClick={()=>setSendMode('ahora')}>Enviar ahora</button>
                <button className={sendMode==='programar'?'on':''} onClick={()=>setSendMode('programar')}>Programar</button>
              </div>
              {sendMode==='programar' && (
                <>
                  <div className="sched-fields">
                    <input type="date" value={fecha} min={CampAPI.TODAY} onChange={e=>setFecha(e.target.value)} />
                    <input type="time" value={hora} onChange={e=>setHora(e.target.value)} style={{maxWidth:'110px'}} />
                  </div>
                  <div className="tz-note"><Icon name="clock" />Se usa la {TZ_LABEL}</div>
                </>
              )}
              <Btn variant="magenta" icon={sendMode==='ahora'?'send':'clock'} disabled={!puedeEnviar}
                onClick={()=>setConfirming(true)} style={{width:'100%'}}>
                {sendMode==='ahora'?'Enviar ahora':'Programar envío'}
              </Btn>
              {!puedeEnviar && <div style={{fontSize:'11px',color:'var(--gris)',textAlign:'center',lineHeight:1.4}}>Completá destinatarios, asunto y contenido para habilitar el envío.</div>}
            </div>
          </div>
        </div>
      </div>

      {confirming && <ConfirmSend n={conteo.total} modo={sendMode} cuando={`${fecha}T${hora}`} asunto={asunto} remitente={remitente} busy={sendBusy} onClose={()=>!sendBusy&&setConfirming(false)} onConfirm={doSend} />}
      {senderModal && <SenderModal remitente={remitente} onClose={()=>setSenderModal(false)} onSave={saveSender} />}
      {expand && <PreviewOverlay html={html} onClose={()=>setExpand(false)} />}
    </div>
  );
}

// =================== VISTA CAMPAÑA ENVIADA / FALLIDA (solo lectura) ===================
function SentCampaignView({ campId, notify, onDone, onDuplicated }){
  const [c, setC] = useState(null);
  const [tagMap, setTagMap] = useState({});
  const [busy, setBusy] = useState(false);
  const polledRef = useRef(false);

  useEffect(()=>{ (async()=>{
    try{
      const [camp, tags] = await Promise.all([CampAPI.obtenerCampania(campId), CampAPI.listarEtiquetas()]);
      const m={}; tags.forEach(t=>m[t.id]=t.nombre); setTagMap(m); setC(camp);
    }catch(e){ notify(e.message||'No se pudo cargar la campaña'); }
  })(); },[campId]);

  // El fin del envío lo determina el backend: polling suave mientras esté "enviando".
  useEffect(()=>{
    if (c && c.estado==='enviando' && !polledRef.current){
      polledRef.current = true;
      let alive = true;
      CampAPI.pollCampania(campId, { onTick:(cc)=>{ if(alive) setC(cc); } })
        .then(f=>{ if(alive){ setC(f); notify(f.estado==='enviada'?'Campaña enviada':f.estado==='fallida'?'El envío falló':'Envío procesado'); } });
      return ()=>{ alive=false; };
    }
  },[c && c.estado]);

  if(!c) return <div className="wrap"><div className="cmp-loading"><span className="cmp-spin"></span>Cargando campaña…</div></div>;

  const destTxt = c.destinatarios.modo==='todos' ? 'Todos los contactos' : c.destinatarios.etiquetas.map(id=>tagMap[id]||'—').join(', ');
  const fallida = c.estado==='fallida';
  const programada = c.estado==='programada';
  const kickLbl = programada ? 'Campaña · programada' : c.estado==='enviando' ? 'Campaña · enviando' : 'Campaña · solo lectura';
  const fechaLbl = programada ? 'Programada para' : c.estado==='enviada' ? 'Enviada' : c.estado==='fallida' ? 'Intento' : 'Estado';
  const fechaVal = programada ? fmtCampDateTime(c.programadaPara) : c.estado==='enviando' ? 'En curso…' : fmtCampDateTime(c.enviadaEn);

  const duplicar = async ()=>{ setBusy(true); const nc = await CampAPI.duplicarCampania(c.id); setBusy(false); notify('Campaña duplicada como borrador'); onDuplicated(nc.id); };
  const reintentar = async ()=>{ setBusy(true); try{ await CampAPI.enviarAhora(c.id); notify('Reintentando envío…'); polledRef.current=true; const fin = await CampAPI.pollCampania(c.id,{ onTick:setC }); setC(fin); notify(fin.estado==='enviada'?'Campaña enviada':fin.estado==='fallida'?'El envío volvió a fallar':'Envío procesado'); }catch(e){ notify(e.message||'No se pudo reintentar el envío'); } setBusy(false); };
  const cancelar = async ()=>{ setBusy(true); await CampAPI.cancelarProgramacion(c.id); setBusy(false); notify('Programación cancelada · vuelve a borrador'); onDone(); };

  return (
    <div className="wrap">
      <a className="back-link" onClick={onDone}><Icon name="chevright" style={{width:14,height:14,transform:'rotate(180deg)'}} />Volver a campañas</a>
      <div className="cmp-head">
        <div>
          <div className="page-kick">{kickLbl}</div>
          <h1 className="page-title" style={{marginTop:'8px'}}>{c.nombre}</h1>
          <div style={{marginTop:'10px'}}>
            <span className={`pill pill-${c.estado}`}><span className="dt"></span>{CampAPI.ESTADO_CAMPANIA[c.estado]}</span>
          </div>
        </div>
        <div className="flex gap8">
          {fallida && <Btn variant="ghost" icon="refresh" onClick={reintentar} disabled={busy}>Reintentar envío</Btn>}
          {programada && <Btn variant="danger" icon="x" onClick={cancelar} disabled={busy}>Cancelar programación</Btn>}
          <Btn variant="magenta" icon="copy" onClick={duplicar} disabled={busy}>Duplicar</Btn>
        </div>
      </div>

      <div className="sent-grid">
        <div className="sent-prev">
          <div className="sent-prev-h"><Icon name="eye" />Contenido enviado</div>
          {c.html ? <iframe srcDoc={c.html} title="Contenido" sandbox=""></iframe>
                  : <div className="html-prev-empty" style={{height:'300px'}}><Icon name="doc" /><p>Esta campaña no tenía contenido HTML.</p></div>}
        </div>
        <div style={{display:'flex',flexDirection:'column',gap:'16px'}}>
          {(fallida || c.fallidos>0) && (
            <div className="sent-error">
              <Icon name="alert" />
              <div>
                <div className="se-t">{fallida ? 'El envío falló' : `${c.fallidos} ${c.fallidos===1?'destinatario no recibió':'destinatarios no recibieron'} el correo`}</div>
                <div className="se-s">{fallida
                  ? (c.error || 'El envío falló para todos los destinatarios. Reintentá; el sistema no reenvía a quienes ya recibieron.')
                  : `El resto de los destinatarios sí lo recibió. El sistema no reenvía a quienes ya recibieron.`}</div>
              </div>
            </div>
          )}
          <div className="sent-meta-card">
            <div className="sent-field"><div className="sf-k">Asunto</div><div className="sf-v">{c.asunto||'—'}</div></div>
            <div className="sent-field"><div className="sf-k">Remitente</div><div className="sf-v">{c.remitente?`${c.remitente.nombre} · ${c.remitente.email}`:'—'}</div></div>
            <div className="sent-field"><div className="sf-k">Destinatarios</div><div className="sf-v">{destTxt}</div></div>
            <div className="sent-field"><div className="sf-k">Alcance</div><div className="sf-v">{c.totalDestinatarios.toLocaleString('es-AR')} {programada?'destinatarios':'enviados'}{c.excluidos>0?` · ${c.excluidos} excluidos`:''}</div></div>
            {c.fallidos>0 && <div className="sent-field"><div className="sf-k">Con error</div><div className="sf-v" style={{color:'var(--dirty)',fontWeight:700}}>{c.fallidos.toLocaleString('es-AR')} {c.fallidos===1?'destinatario':'destinatarios'}</div></div>}
            <div className="sent-field"><div className="sf-k">{fechaLbl}</div><div className="sf-v">{fechaVal}{(programada||c.enviadaEn)?` · ${TZ_LABEL}`:''}</div></div>
            {c.pruebasEnviadas?.length>0 && <div className="sent-field"><div className="sf-k">Pruebas</div><div className="sf-v" style={{fontWeight:600,fontSize:'12.5px'}}>{c.pruebasEnviadas.join(', ')}</div></div>}
          </div>
        </div>
      </div>
    </div>
  );
}

Object.assign(window, { CampaignEditor, SentCampaignView, SenderModal, ConfirmSend, fmtCampDateTime });
