const { useState, useEffect, useRef, useCallback, createContext, useContext } = React;

// ─── Auth helpers ─────────────────────────────────────────────────────────────
function getToken()  { return localStorage.getItem('ll_token'); }
function getRole()   { return localStorage.getItem('ll_role') || 'tenant'; }
function saveSession(token, role) {
  localStorage.setItem('ll_token', token);
  localStorage.setItem('ll_role', role || 'tenant');
}
function clearSession() {
  localStorage.removeItem('ll_token');
  localStorage.removeItem('ll_role');
}

function apiFetch(url, opts = {}) {
  const token = getToken();
  const headers = { ...(opts.headers || {}), ...(token ? { 'Authorization': `Bearer ${token}` } : {}) };
  return window.fetch(url, { ...opts, headers }).then(r => {
    if (r.status === 401) { clearSession(); window.location.reload(); return r; }
    return r;
  });
}

// ─── API helpers ──────────────────────────────────────────────────────────────
const api = {
  list:   ()         => apiFetch('/api/agents').then(r => r.json()),
  get:    (id)       => apiFetch(`/api/agents/${id}`).then(r => r.json()),
  create: (data)     => apiFetch('/api/agents', { method:'POST', headers:{'Content-Type':'application/json'}, body: JSON.stringify(data) }).then(r => r.json()),
  update: (id, data) => apiFetch(`/api/agents/${id}`, { method:'PUT', headers:{'Content-Type':'application/json'}, body: JSON.stringify(data) }).then(r => r.json()),
  delete: (id)       => apiFetch(`/api/agents/${id}`, { method:'DELETE' }).then(r => r.json()),
  test:   (id, msg, history) => apiFetch(`/api/agents/${id}/test`, { method:'POST', headers:{'Content-Type':'application/json'}, body: JSON.stringify({ message: msg, history }) }).then(r => r.json()),
};

// ─── Pipochat data context ────────────────────────────────────────────────────
const PipochatCtx = createContext({ pipelines: [], tags: [], users: [], teams: [], chatbots: [], templates: [], meetings: [], inboxes: [], connected: false });

function usePipochat() { return useContext(PipochatCtx); }

// ─── Styles ───────────────────────────────────────────────────────────────────
// ── Pipochat logo SVG (inline, reusable) ─────────────────────────────────
const PipochatLogo = ({ size = 32 }) => (
  <svg width={size} height={size * 0.71} viewBox="0 0 170 120" fill="none" aria-hidden="true">
    <rect x="72" y="48" width="90" height="58" rx="14" fill="#3A6351" opacity="0.4"/>
    <circle cx="117" cy="77" r="7" fill="white" opacity="0.4"/>
    <path d="M88 106 L88 88 L118 106 Z" fill="#3A6351" opacity="0.4"/>
    <rect x="0" y="0" width="148" height="90" rx="20" fill="#3A6351"/>
    <circle cx="44" cy="42" r="8.5" fill="white"/>
    <circle cx="74" cy="42" r="8.5" fill="white"/>
    <circle cx="104" cy="42" r="8.5" fill="white"/>
    <path d="M24 90 L24 70 L50 90 Z" fill="#3A6351"/>
  </svg>
);

const S = {
  app: { display:'flex', height:'100vh', overflow:'hidden', background:'var(--cream)' },

  // ── Sidebar — light, Pipochat brand ──────────────────────────────────────
  sidebar: {
    width:252, background:'var(--white)',
    borderRight:'1px solid var(--border-soft)',
    display:'flex', flexDirection:'column', flexShrink:0, overflowY:'auto',
    boxShadow:'2px 0 12px rgba(15,26,20,.04)',
  },
  sideHeader: {
    padding:'18px 16px 14px',
    borderBottom:'1px solid var(--border-soft)',
    display:'flex', alignItems:'center', gap:10,
  },
  sideTitle: { fontWeight:800, fontSize:15, color:'var(--ink)', letterSpacing:'-.3px', lineHeight:1.1 },
  sideSubtitle: { fontSize:11, color:'var(--ink-3)', marginTop:2 },
  sideSection: { padding:'14px 10px 4px' },
  sideSectionLabel: {
    fontSize:10, fontWeight:700, color:'var(--ink-4)',
    textTransform:'uppercase', letterSpacing:1.2,
    padding:'0 10px 6px',
  },
  sideItem: (active) => ({
    display:'flex', alignItems:'center', gap:9, padding:'8px 12px', borderRadius:10,
    cursor:'pointer', marginBottom:2,
    background: active ? 'var(--green-light)' : 'transparent',
    color: active ? 'var(--green-hover)' : 'var(--ink-2)',
    fontWeight: active ? 600 : 400,
    fontSize:13.5, border:'none', width:'100%', textAlign:'left',
    transition:'background var(--trans), color var(--trans)',
  }),
  sideItemWithSub: (active) => ({
    display:'flex', alignItems:'flex-start', flexDirection:'column',
    padding:'8px 12px', borderRadius:10, cursor:'pointer', marginBottom:2,
    background: active ? 'var(--green-light)' : 'transparent',
    color: active ? 'var(--green-hover)' : 'var(--ink-2)',
    fontWeight: active ? 600 : 400,
    fontSize:13.5, border:'none', width:'100%', textAlign:'left',
    transition:'background var(--trans), color var(--trans)',
  }),
  sideItemLabel: { display:'flex', alignItems:'center', gap:8, width:'100%' },
  sideItemHint: (active) => ({
    fontSize:11, color: active ? 'var(--green)' : 'var(--ink-4)',
    marginTop:2, paddingLeft:22, lineHeight:1.3,
  }),
  sideItemDot: (on) => ({
    width:7, height:7, borderRadius:'50%', flexShrink:0,
    background: on ? 'var(--green)' : 'var(--border)',
    boxShadow: on ? '0 0 0 3px var(--green-light)' : 'none',
  }),
  newBtn: {
    margin:'8px 10px 10px', padding:'10px 14px',
    background:'var(--green)', color:'#fff', border:'none', borderRadius:10,
    fontSize:13, fontWeight:600, cursor:'pointer', textAlign:'center',
    transition:'background var(--trans)', boxShadow:'0 2px 8px var(--green-glow)',
  },

  // ── Main content area ────────────────────────────────────────────────────
  main: { flex:1, display:'flex', overflow:'hidden' },
  editor: { flex:1, overflowY:'auto', padding:'32px 36px', display:'flex', flexDirection:'column', gap:22, background:'var(--cream)' },

  pageTitle: { fontSize:22, fontWeight:800, color:'var(--ink)', letterSpacing:'-.4px' },
  pageSubtitle: { fontSize:13.5, color:'var(--ink-3)', marginTop:5, lineHeight:1.65, maxWidth:580 },

  // ── Cards — Pipochat feat-card style ─────────────────────────────────────
  card: {
    background:'var(--white)', border:'1px solid var(--border)',
    borderRadius:'var(--r-lg)', padding:'22px 26px', boxShadow:'var(--shadow-sm)',
    transition:'box-shadow var(--trans), border-color var(--trans)',
  },
  cardTitle: { fontSize:14, fontWeight:700, marginBottom:4, color:'var(--ink)' },
  cardDesc: { fontSize:13, color:'var(--ink-3)', marginBottom:16, lineHeight:1.6 },

  // ── Form elements ────────────────────────────────────────────────────────
  label: { fontSize:11, fontWeight:700, color:'var(--ink-3)', display:'block', marginBottom:5, textTransform:'uppercase', letterSpacing:.7 },
  textarea: { width:'100%', minHeight:130, padding:'12px 14px', border:'1.5px solid var(--border)', borderRadius:12, fontSize:13, lineHeight:1.6, resize:'vertical', outline:'none', color:'var(--ink)', boxSizing:'border-box', background:'var(--white)', transition:'border-color var(--trans)' },
  input: { width:'100%', padding:'9px 13px', border:'1.5px solid var(--border)', borderRadius:12, fontSize:13, outline:'none', color:'var(--ink)', boxSizing:'border-box', background:'var(--white)', transition:'border-color var(--trans)' },
  select: { width:'100%', padding:'9px 13px', border:'1.5px solid var(--border)', borderRadius:12, fontSize:13, outline:'none', color:'var(--ink)', background:'var(--white)', cursor:'pointer', transition:'border-color var(--trans)' },

  row: { display:'flex', gap:12 },
  col: { flex:1, display:'flex', flexDirection:'column', gap:6 },

  // ── Toggle ───────────────────────────────────────────────────────────────
  toggle: (on) => ({ width:40, height:22, borderRadius:11, background: on ? 'var(--green)' : '#D1D5DB', border:'none', cursor:'pointer', position:'relative', transition:'background .2s var(--trans)', flexShrink:0 }),
  toggleDot: (on) => ({ position:'absolute', top:3, left: on ? 19 : 3, width:16, height:16, borderRadius:'50%', background:'#fff', transition:'left .2s var(--trans)', boxShadow:'0 1px 4px rgba(0,0,0,.18)' }),

  // ── Action cards ─────────────────────────────────────────────────────────
  actionItem: { borderBottom:'1px solid var(--border-soft)', padding:'15px 0', display:'flex', flexDirection:'column', gap:0 },
  actionHeader: { display:'flex', alignItems:'center', gap:10 },
  actionIcon: { fontSize:18, width:32, height:32, display:'flex', alignItems:'center', justifyContent:'center', borderRadius:9, background:'var(--green-light)', flexShrink:0 },
  actionMeta: { flex:1 },
  actionLabel: { fontSize:13.5, fontWeight:600, color:'var(--ink)' },
  actionDesc: { fontSize:12, color:'var(--ink-3)', marginTop:2, lineHeight:1.55 },
  actionBody: { marginTop:14, paddingLeft:42 },
  expandBtn: { background:'none', border:'none', color:'var(--ink-4)', fontSize:14, cursor:'pointer', padding:'0 4px' },

  // ── Buttons ──────────────────────────────────────────────────────────────
  saveBtn: { padding:'9px 22px', background:'var(--green)', color:'#fff', border:'none', borderRadius:12, fontSize:13, fontWeight:600, cursor:'pointer', whiteSpace:'nowrap', transition:'background var(--trans)', boxShadow:'0 2px 8px var(--green-glow)' },
  outlineBtn: { padding:'9px 18px', background:'transparent', color:'var(--green)', border:'2px solid var(--green)', borderRadius:12, fontSize:13, fontWeight:600, cursor:'pointer', whiteSpace:'nowrap', transition:'background var(--trans)' },
  dangerBtn: { padding:'9px 18px', background:'transparent', color:'var(--danger)', border:'1.5px solid var(--danger)', borderRadius:12, fontSize:13, fontWeight:600, cursor:'pointer' },
  ghostBtn: { background:'none', border:'none', color:'var(--danger)', cursor:'pointer', fontSize:18, lineHeight:1, padding:'0 4px' },

  // ── Chips & badges ───────────────────────────────────────────────────────
  chip: (on) => ({ padding:'5px 14px', borderRadius:99, border:'1.5px solid', fontSize:12, fontWeight:500, cursor:'pointer', background: on ? 'var(--green)' : 'transparent', color: on ? '#fff' : 'var(--ink-3)', borderColor: on ? 'var(--green)' : 'var(--border)', transition:'all var(--trans)' }),
  badge: (color) => ({ display:'inline-flex', alignItems:'center', gap:4, padding:'3px 10px', borderRadius:99, fontSize:11, fontWeight:600, background: color+'18', color }),

  // ── Chat panel ───────────────────────────────────────────────────────────
  chatPanel: { width:340, background:'var(--white)', borderLeft:'1px solid var(--border-soft)', display:'flex', flexDirection:'column', flexShrink:0 },
  chatHeader: { padding:'14px 18px', borderBottom:'1px solid var(--border-soft)', display:'flex', alignItems:'center', justifyContent:'space-between' },
  chatTitle: { fontSize:13, fontWeight:700, color:'var(--ink)' },
  chatBody: { flex:1, overflowY:'auto', padding:'14px', display:'flex', flexDirection:'column', gap:8, background:'#ECE5DD' },
  chatBubble: (role) => ({
    maxWidth:'85%', padding:'9px 13px',
    borderRadius: role==='user' ? '16px 16px 4px 16px' : '16px 16px 16px 4px',
    background: role==='user' ? '#D9FDD3' : '#fff',
    color:'var(--ink)', fontSize:12.5, lineHeight:1.55,
    alignSelf: role==='user' ? 'flex-end' : 'flex-start',
    whiteSpace:'pre-wrap', boxShadow:'0 1px 2px rgba(0,0,0,.08)',
  }),
  chatMeta: { fontSize:10, color:'var(--ink-4)', alignSelf:'flex-start', padding:'0 2px', fontStyle:'italic' },
  chatInputRow: { padding:'10px 12px', borderTop:'1px solid var(--border-soft)', display:'flex', gap:8, background:'#F0F2F5' },
  chatInput: { flex:1, padding:'9px 12px', border:'none', borderRadius:20, fontSize:12.5, outline:'none', resize:'none', minHeight:36, maxHeight:100, lineHeight:1.4, background:'#fff', color:'var(--ink)' },
  sendBtn: { width:36, height:36, padding:0, background:'var(--green)', color:'#fff', border:'none', borderRadius:'50%', fontSize:16, fontWeight:700, cursor:'pointer', alignSelf:'flex-end', display:'flex', alignItems:'center', justifyContent:'center', flexShrink:0 },
  emptyState: { flex:1, display:'flex', flexDirection:'column', alignItems:'center', justifyContent:'center', color:'var(--ink-3)', fontSize:13, gap:10, textAlign:'center', padding:32 },

  page: { flex:1, overflowY:'auto', padding:'28px 32px', display:'flex', flexDirection:'column', gap:20 },
  pageHeader: { display:'flex', alignItems:'flex-start', justifyContent:'space-between', gap:16, marginBottom:4 },

  // ── Primary CTA button (used in panel headers) ───────────────────────────
  btnPrimary: { padding:'9px 20px', background:'var(--green)', color:'#fff', border:'none', borderRadius:12, fontSize:13, fontWeight:600, cursor:'pointer', whiteSpace:'nowrap', transition:'background var(--trans)', boxShadow:'0 2px 8px var(--green-glow)', flexShrink:0 },
};

// ─── Helpers ──────────────────────────────────────────────────────────────────
function Toggle({ on, onChange }) {
  return (
    <button style={S.toggle(on)} onClick={() => onChange(!on)}>
      <div style={S.toggleDot(on)} />
    </button>
  );
}

function Field({ label, children }) {
  return (
    <div style={{ display:'flex', flexDirection:'column', gap:5 }}>
      <label style={S.label}>{label}</label>
      {children}
    </div>
  );
}

// ─── Action configs ───────────────────────────────────────────────────────────

function CreateLeadConfig({ config, onChange }) {
  const { pipelines, connected } = usePipochat();
  const selectedPipeline = pipelines.find(p => p._id === config.pipelineId);
  const stages = selectedPipeline?.stages || [];

  if (!connected) return (
    <div style={{ fontSize:12, color:'var(--muted)', padding:'8px 0' }}>
      ⚠️ Conectá Pipochat para seleccionar pipeline y etapa.
    </div>
  );

  return (
    <div style={{ display:'flex', flexDirection:'column', gap:12 }}>
      <Field label="Pipeline">
        <select style={S.select} value={config.pipelineId || ''} onChange={e => onChange({ ...config, pipelineId: e.target.value, stageId: '' })}>
          <option value="">— Seleccionar pipeline —</option>
          {pipelines.map(p => <option key={p._id} value={p._id}>{p.title}</option>)}
        </select>
      </Field>
      <Field label="Etapa inicial">
        <select style={S.select} value={config.stageId || ''} onChange={e => onChange({ ...config, stageId: e.target.value })} disabled={!config.pipelineId}>
          <option value="">— Seleccionar etapa —</option>
          {stages.sort((a,b) => a.orderIndex - b.orderIndex).map(s => <option key={s._id} value={s._id}>{s.displayName || s.name}</option>)}
        </select>
      </Field>
      <Field label="Cuándo crear el lead">
        <select style={S.select} value={config.trigger || 'on_interest'} onChange={e => onChange({ ...config, trigger: e.target.value })}>
          <option value="on_interest">Cuando detecta interés de compra</option>
          <option value="always">Con el primer mensaje</option>
          <option value="on_qualified">Cuando el lead está calificado</option>
        </select>
      </Field>
    </div>
  );
}

function MoveLeadConfig({ config, onChange }) {
  const { pipelines, connected } = usePipochat();
  const allStages = pipelines.flatMap(p => (p.stages || []).map(s => ({ ...s, pipelineTitle: p.title })));

  if (!connected) return (
    <div style={{ fontSize:12, color:'var(--muted)' }}>⚠️ Conectá Pipochat para seleccionar la etapa.</div>
  );

  return (
    <div style={{ display:'flex', flexDirection:'column', gap:12 }}>
      <Field label="Mover a esta etapa">
        <select style={S.select} value={config.stageId || ''} onChange={e => onChange({ ...config, stageId: e.target.value })}>
          <option value="">— Seleccionar etapa —</option>
          {pipelines.map(p => (
            <optgroup key={p._id} label={p.title}>
              {(p.stages || []).sort((a,b) => a.orderIndex - b.orderIndex).map(s => (
                <option key={s._id} value={s._id}>{s.displayName || s.name}</option>
              ))}
            </optgroup>
          ))}
        </select>
      </Field>
      <Field label="Cuándo moverlo">
        <select style={S.select} value={config.trigger || 'on_interest'} onChange={e => onChange({ ...config, trigger: e.target.value })}>
          <option value="on_interest">Cuando detecta interés de compra</option>
          <option value="on_qualified">Cuando el lead está calificado</option>
          <option value="on_meeting">Cuando agenda una reunión</option>
        </select>
      </Field>
    </div>
  );
}

function TagConfig({ config, onChange, label }) {
  const { tags: availableTags, connected } = usePipochat();
  const [customInput, setCustomInput] = useState('');
  const selected = config.tags || [];

  const toggle = (name) => {
    const next = selected.includes(name) ? selected.filter(t => t !== name) : [...selected, name];
    onChange({ ...config, tags: next });
  };

  const addCustom = () => {
    const v = customInput.trim();
    if (v && !selected.includes(v)) { onChange({ ...config, tags: [...selected, v] }); }
    setCustomInput('');
  };

  return (
    <div style={{ display:'flex', flexDirection:'column', gap:10 }}>
      <label style={S.label}>{label || 'Etiquetas'}</label>

      {connected && availableTags.length > 0 && (
        <div style={{ display:'flex', flexWrap:'wrap', gap:6 }}>
          {availableTags.map(t => (
            <button key={t._id} style={S.chip(selected.includes(t.name))} onClick={() => toggle(t.name)}>
              {selected.includes(t.name) ? '✓ ' : ''}{t.name}
            </button>
          ))}
        </div>
      )}

      <div style={{ display:'flex', gap:8 }}>
        <input style={{ ...S.input, flex:1 }} value={customInput} onChange={e => setCustomInput(e.target.value)}
          onKeyDown={e => e.key === 'Enter' && addCustom()} placeholder="Etiqueta personalizada…" />
        <button style={S.outlineBtn} onClick={addCustom}>+</button>
      </div>

      {selected.length > 0 && (
        <div style={{ display:'flex', flexWrap:'wrap', gap:6 }}>
          {selected.map(t => (
            <span key={t} style={{ ...S.badge('var(--primary)'), cursor:'default' }}>
              {t}
              <button onClick={() => toggle(t)} style={{ background:'none', border:'none', color:'var(--primary)', cursor:'pointer', fontSize:13, lineHeight:1, padding:'0 0 0 2px' }}>×</button>
            </span>
          ))}
        </div>
      )}
    </div>
  );
}

function OfficeHoursConfig({ config, onChange }) {
  const days = ['monday','tuesday','wednesday','thursday','friday','saturday','sunday'];
  const labels = { monday:'Lunes', tuesday:'Martes', wednesday:'Miércoles', thursday:'Jueves', friday:'Viernes', saturday:'Sábado', sunday:'Domingo' };
  const sched = config.schedule || {};
  const updateDay = (day, field, value) => onChange({ ...config, schedule: { ...sched, [day]: { ...(sched[day] || { enabled:false, start:'09:00', end:'18:00' }), [field]: value } } });
  return (
    <div style={{ display:'flex', flexDirection:'column', gap:12 }}>
      <Field label="Zona horaria">
        <input style={S.input} value={config.timezone || ''} onChange={e => onChange({ ...config, timezone: e.target.value })} placeholder="America/Argentina/Buenos_Aires" />
      </Field>
      <div>
        <label style={S.label}>Horarios</label>
        {days.map(day => {
          const d = sched[day] || { enabled:false, start:'09:00', end:'18:00' };
          return (
            <div key={day} style={{ display:'flex', alignItems:'center', gap:10, marginBottom:7 }}>
              <Toggle on={d.enabled} onChange={v => updateDay(day, 'enabled', v)} />
              <span style={{ fontSize:12, width:76, flexShrink:0 }}>{labels[day]}</span>
              <input type="time" style={{ ...S.input, width:96 }} value={d.start} onChange={e => updateDay(day, 'start', e.target.value)} disabled={!d.enabled} />
              <span style={{ color:'var(--muted)', fontSize:12 }}>—</span>
              <input type="time" style={{ ...S.input, width:96 }} value={d.end} onChange={e => updateDay(day, 'end', e.target.value)} disabled={!d.enabled} />
            </div>
          );
        })}
      </div>
      <Field label="Mensaje fuera de horario">
        <textarea style={{ ...S.textarea, minHeight:60 }} value={config.outsideHoursMessage || ''} onChange={e => onChange({ ...config, outsideHoursMessage: e.target.value })} placeholder="Hola! Nuestro horario de atención es de lunes a viernes de 9 a 18hs." />
      </Field>
    </div>
  );
}

function HandoffConfig({ config, onChange }) {
  const { users, teams } = usePipochat();
  return (
    <div style={{ display:'flex', flexDirection:'column', gap:12 }}>
      <Field label="Mensaje antes de derivar">
        <input style={S.input} value={config.message || ''} onChange={e => onChange({ ...config, message: e.target.value })} placeholder="Voy a conectarte con un asesor…" />
      </Field>
      <div style={S.row}>
        <Field label="Derivar a equipo (opcional)">
          <select style={S.select} value={config.teamId || ''} onChange={e => onChange({ ...config, teamId: e.target.value })}>
            <option value="">— Sin equipo —</option>
            {teams.map(t => <option key={t._id} value={t._id}>{t.name}</option>)}
          </select>
        </Field>
        <Field label="Derivar a operador (opcional)">
          <select style={S.select} value={config.operatorId || ''} onChange={e => onChange({ ...config, operatorId: e.target.value })}>
            <option value="">— Sin operador —</option>
            {users.map(u => <option key={u._id} value={u._id}>{u.name}</option>)}
          </select>
        </Field>
      </div>
    </div>
  );
}

function UpdateContactConfig({ config, onChange }) {
  const attrs = config.attributes || [];
  const add = () => onChange({ ...config, attributes: [...attrs, { key:'', description:'' }] });
  const upd = (i, field, val) => { const next = [...attrs]; next[i] = { ...next[i], [field]: val }; onChange({ ...config, attributes: next }); };
  return (
    <div style={{ display:'flex', flexDirection:'column', gap:10 }}>
      <p style={{ fontSize:11, color:'var(--muted)', margin:0 }}>
        El agente extrae estos datos del contacto durante la conversación y los guarda como atributos en Pipochat.
        Definí los campos según tu negocio (ej: plan interesado, cantidad de agentes, sector).
      </p>
      {attrs.map((a, i) => (
        <div key={i} style={{ display:'flex', gap:8, alignItems:'center' }}>
          <input style={{ ...S.input, flex:1 }} value={a.key} onChange={e => upd(i,'key',e.target.value)} placeholder="Clave (ej: plan_interesado)" />
          <input style={{ ...S.input, flex:2 }} value={a.description} onChange={e => upd(i,'description',e.target.value)} placeholder="Descripción (ej: plan de Pipochat que le interesa)" />
          <button style={S.ghostBtn} onClick={() => onChange({ ...config, attributes: attrs.filter((_,j) => j!==i) })}>×</button>
        </div>
      ))}
      <button style={{ alignSelf:'flex-start', ...S.outlineBtn }} onClick={add}>+ Agregar campo</button>
    </div>
  );
}

function SendMessageConfig({ config, onChange }) {
  const msgType = config.messageType || 'text';
  return (
    <div style={{ display:'flex', flexDirection:'column', gap:12 }}>
      <Field label="Tipo de mensaje que puede enviar">
        <div style={{ display:'flex', flexWrap:'wrap', gap:7 }}>
          {[
            { v:'text',     label:'💬 Texto' },
            { v:'image',    label:'🖼️ Imagen' },
            { v:'video',    label:'🎬 Video' },
            { v:'document', label:'📎 Documento / PDF' },
            { v:'audio',    label:'🎵 Audio' },
          ].map(o => (
            <button key={o.v} style={S.chip(msgType === o.v)} onClick={() => onChange({ ...config, messageType: o.v })}>
              {o.label}
            </button>
          ))}
        </div>
      </Field>
      <Field label="Cuándo enviar el mensaje">
        <select style={S.select} value={config.trigger || 'on_response'} onChange={e => onChange({ ...config, trigger: e.target.value })}>
          <option value="on_response">Al responder cada mensaje del contacto</option>
          <option value="on_greeting">Solo en el mensaje de bienvenida</option>
          <option value="on_interest">Cuando detecta interés de compra</option>
          <option value="on_qualified">Cuando el lead está calificado</option>
          <option value="on_request">Cuando el contacto lo pide</option>
        </select>
      </Field>
      {(msgType === 'image' || msgType === 'video' || msgType === 'document' || msgType === 'audio') && (
        <Field label="URL del archivo (opcional — para envíos fijos)">
          <input style={S.input} value={config.mediaUrl || ''} onChange={e => onChange({ ...config, mediaUrl: e.target.value })} placeholder="https://... (dejá vacío para que el agente decida)" />
          <div style={{ fontSize:11, color:'var(--muted)', marginTop:3 }}>Si dejás vacío, el agente puede enviar cualquier archivo según el contexto de la conversación.</div>
        </Field>
      )}
    </div>
  );
}

function LeadAttributeConfig({ config, onChange }) {
  const attrs = config.attributes || [];
  const add = () => onChange({ ...config, attributes: [...attrs, { key:'', description:'' }] });
  const upd = (i, field, val) => { const next = [...attrs]; next[i] = { ...next[i], [field]: val }; onChange({ ...config, attributes: next }); };
  return (
    <div style={{ display:'flex', flexDirection:'column', gap:10 }}>
      <p style={{ fontSize:11, color:'var(--muted)', margin:0 }}>El agente recopila estos datos del lead durante la conversación y los guarda como atributos.</p>
      {attrs.map((a, i) => (
        <div key={i} style={{ display:'flex', gap:8, alignItems:'center' }}>
          <input style={{ ...S.input, flex:1 }} value={a.key} onChange={e => upd(i,'key',e.target.value)} placeholder="Clave (ej: presupuesto)" />
          <input style={{ ...S.input, flex:2 }} value={a.description} onChange={e => upd(i,'description',e.target.value)} placeholder="Descripción para el agente" />
          <button style={S.ghostBtn} onClick={() => onChange({ ...config, attributes: attrs.filter((_,j) => j!==i) })}>×</button>
        </div>
      ))}
      <button style={S.outlineBtn} onClick={add} style={{ alignSelf:'flex-start', ...S.outlineBtn }}>+ Agregar campo</button>
    </div>
  );
}

function AiQualifyConfig({ config: c, onChange }) {
  const inp = S.input;
  const lbl = { fontSize:12, color:'var(--muted)', display:'block', marginBottom:4 };
  return (
    <div style={{ display:'flex', flexDirection:'column', gap:12 }}>
      <div>
        <span style={lbl}>Criterio de calificación</span>
        <textarea style={{ ...inp, minHeight:70, resize:'vertical' }}
          value={c.criteria || ''}
          onChange={e => onChange({ ...c, criteria: e.target.value })}
          placeholder="El lead está calificado si muestra interés real, menciona presupuesto o tiene urgencia..." />
        <div style={{ fontSize:11, color:'var(--muted)', marginTop:3 }}>
          Claude lee toda la conversación y evalúa si el lead cumple este criterio.
        </div>
      </div>
      <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr', gap:10 }}>
        <div>
          <span style={lbl}>Etiqueta si calificado ✅</span>
          <input style={inp} value={c.qualifiedTag || ''} onChange={e => onChange({ ...c, qualifiedTag: e.target.value })} placeholder="calificado" />
        </div>
        <div>
          <span style={lbl}>Etiqueta si no calificado ❌ (opcional)</span>
          <input style={inp} value={c.notQualifiedTag || ''} onChange={e => onChange({ ...c, notQualifiedTag: e.target.value })} placeholder="no-calificado" />
        </div>
      </div>
      <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr', gap:10 }}>
        <div>
          <span style={lbl}>Evaluar después de N mensajes</span>
          <input type="number" min="2" style={inp} value={c.minMessages ?? 4} onChange={e => onChange({ ...c, minMessages: Number(e.target.value) })} />
          <div style={{ fontSize:11, color:'var(--muted)', marginTop:2 }}>Mínimo de mensajes para tener contexto suficiente.</div>
        </div>
        <div style={{ display:'flex', alignItems:'center', gap:8, paddingTop:20 }}>
          <label style={{ display:'flex', alignItems:'center', gap:6, fontSize:13, cursor:'pointer' }}>
            <input type="checkbox" checked={!!c.reevaluate} onChange={e => onChange({ ...c, reevaluate: e.target.checked })} />
            Re-evaluar en cada mensaje
          </label>
        </div>
      </div>
    </div>
  );
}

function LeadNoteConfig({ config, onChange }) {
  return (
    <Field label="Cuándo agregar la nota">
      <select style={S.select} value={config.trigger || 'always'} onChange={e => onChange({ ...config, trigger: e.target.value })}>
        <option value="always">Al final de cada conversación</option>
        <option value="on_qualified">Cuando el lead está calificado</option>
        <option value="on_handoff">Cuando se deriva a un humano</option>
      </select>
    </Field>
  );
}

function SendTemplateConfig({ config, onChange }) {
  const { templates, connected } = usePipochat();
  const selected = templates.find(t => t._id === config.templateId);
  return (
    <div style={{ display:'flex', flexDirection:'column', gap:12 }}>
      <Field label="Template de WhatsApp">
        {connected && templates.length > 0 ? (
          <select style={S.select} value={config.templateId || ''} onChange={e => onChange({ ...config, templateId: e.target.value })}>
            <option value="">— Seleccionar template —</option>
            {templates.map(t => <option key={t._id} value={t._id}>{t.name}</option>)}
          </select>
        ) : (
          <input style={S.input} value={config.templateId || ''} onChange={e => onChange({ ...config, templateId: e.target.value })} placeholder="ID del template aprobado" />
        )}
        {selected && (
          <div style={{ fontSize:11, color:'var(--muted)', marginTop:4 }}>ID: <span style={{ fontFamily:'monospace' }}>{selected._id}</span></div>
        )}
      </Field>
      <Field label="Cuándo enviarlo">
        <select style={S.select} value={config.trigger || 'on_closed_window'} onChange={e => onChange({ ...config, trigger: e.target.value })}>
          <optgroup label="Ventana cerrada (+24hs sin respuesta)">
            <option value="on_closed_window_1d">Después de 1 día sin respuesta</option>
            <option value="on_closed_window_2d">Después de 2 días sin respuesta</option>
            <option value="on_closed_window_3d">Después de 3 días sin respuesta</option>
            <option value="on_closed_window_5d">Después de 5 días sin respuesta</option>
            <option value="on_closed_window_7d">Después de 7 días (1 semana)</option>
            <option value="on_closed_window_14d">Después de 14 días (2 semanas)</option>
            <option value="on_closed_window_30d">Después de 30 días (1 mes)</option>
          </optgroup>
          <optgroup label="Otros momentos">
            <option value="on_interest">Cuando detecta interés de compra</option>
            <option value="on_handoff">Antes de derivar a un humano</option>
            <option value="always">Siempre como primer mensaje</option>
          </optgroup>
        </select>
      </Field>
      {config.trigger?.startsWith('on_closed_window') && (
        <div style={{ fontSize:11, color:'var(--muted)', background:'#fefce8', border:'1px solid #fde68a', borderRadius:6, padding:'8px 10px' }}>
          ⚠️ Los templates de WhatsApp solo se pueden enviar cuando la ventana de conversación está cerrada (más de 24hs sin respuesta del contacto).
        </div>
      )}
    </div>
  );
}

function AssignOperatorConfig({ config, onChange }) {
  const { users, connected } = usePipochat();
  return (
    <div style={{ display:'flex', flexDirection:'column', gap:12 }}>
      <Field label="Operador">
        {connected && users.length > 0 ? (
          <select style={S.select} value={config.operatorId || ''} onChange={e => onChange({ ...config, operatorId: e.target.value })}>
            <option value="">— Seleccionar operador —</option>
            {users.map(u => <option key={u._id} value={u._id}>{u.name}{u.email ? ` (${u.email})` : ''}</option>)}
          </select>
        ) : (
          <input style={S.input} value={config.operatorId || ''} onChange={e => onChange({ ...config, operatorId: e.target.value })} placeholder="ID del operador" />
        )}
      </Field>
      <Field label="Cuándo asignar">
        <select style={S.select} value={config.trigger || 'on_request'} onChange={e => onChange({ ...config, trigger: e.target.value })}>
          <option value="on_request">Cuando el usuario pide hablar con alguien</option>
          <option value="always">Siempre en cada conversación nueva</option>
          <option value="on_no_answer">Cuando el agente no puede responder</option>
        </select>
      </Field>
    </div>
  );
}

// Sub-component so useState is called at the top level (not inside .map)
function TeamKeywordRow({ entry, index, teams, connected, onUpdateTeam, onUpdateKeywords, onRemove }) {
  const [localKw, setLocalKw] = React.useState('');
  const addKw = () => {
    const v = localKw.trim();
    if (!v) return;
    const kws = entry.keywords || [];
    if (!kws.includes(v)) onUpdateKeywords([...kws, v]);
    setLocalKw('');
  };
  return (
    <div style={{ background:'#f9fafb', border:'1px solid #e5e7eb', borderRadius:8, padding:10, display:'flex', flexDirection:'column', gap:8 }}>
      <div style={{ display:'flex', gap:8, alignItems:'center' }}>
        {connected && teams.length > 0 ? (
          <select style={{ ...S.select, flex:1 }} value={entry.teamId || ''} onChange={e => onUpdateTeam(e.target.value)}>
            <option value="">— Seleccionar equipo —</option>
            {teams.map(t => <option key={t._id} value={t._id}>{t.name}</option>)}
          </select>
        ) : (
          <input style={{ ...S.input, flex:1 }} value={entry.teamId || ''} onChange={e => onUpdateTeam(e.target.value)} placeholder="ID del equipo" />
        )}
        <button style={{ ...S.ghostBtn, color:'#ef4444' }} onClick={onRemove}>×</button>
      </div>
      <div style={{ display:'flex', gap:6 }}>
        <input
          style={{ ...S.input, flex:1, fontSize:12 }}
          value={localKw}
          onChange={e => setLocalKw(e.target.value)}
          onKeyDown={e => { if (e.key === 'Enter') addKw(); }}
          placeholder="Agregar palabra clave (ej: palermo)…"
        />
        <button style={S.saveBtn} onClick={addKw}>+</button>
      </div>
      <div style={{ display:'flex', flexWrap:'wrap', gap:5 }}>
        {(entry.keywords || []).map(k => (
          <span key={k} style={{ ...S.badge('var(--primary)'), display:'flex', alignItems:'center', gap:3 }}>
            {k}
            <button onClick={() => onUpdateKeywords((entry.keywords || []).filter(x => x !== k))} style={{ background:'none', border:'none', color:'var(--primary)', cursor:'pointer', fontSize:12, padding:'0 0 0 2px', lineHeight:1 }}>×</button>
          </span>
        ))}
        {(entry.keywords || []).length === 0 && <span style={{ fontSize:11, color:'var(--muted)' }}>Sin palabras clave aún</span>}
      </div>
    </div>
  );
}

function AssignTeamConfig({ config, onChange }) {
  const { teams, connected } = usePipochat();
  const trigger = config.trigger || 'on_request';
  const teamEntries = config.teams || [];

  const addTeamEntry = () => onChange({ ...config, teams: [...teamEntries, { keywords: [], teamId: '' }] });
  const updEntry = (i, field, val) => {
    const next = [...teamEntries];
    next[i] = { ...next[i], [field]: val };
    onChange({ ...config, teams: next });
  };
  const removeEntry = (i) => onChange({ ...config, teams: teamEntries.filter((_, j) => j !== i) });

  return (
    <div style={{ display:'flex', flexDirection:'column', gap:12 }}>
      <Field label="Cuándo asignar">
        <select style={S.select} value={trigger} onChange={e => onChange({ ...config, trigger: e.target.value })}>
          <option value="on_request">Cuando el usuario lo pide</option>
          <option value="always">Siempre (primer mensaje)</option>
          <option value="on_keyword">Por palabras clave (multi-sucursal)</option>
          <option value="on_topic">Por tema detectado</option>
        </select>
      </Field>

      {trigger !== 'on_keyword' && (
        <Field label="Equipo">
          {connected && teams.length > 0 ? (
            <select style={S.select} value={config.teamId || ''} onChange={e => onChange({ ...config, teamId: e.target.value })}>
              <option value="">— Seleccionar equipo —</option>
              {teams.map(t => <option key={t._id} value={t._id}>{t.name}</option>)}
            </select>
          ) : (
            <input style={S.input} value={config.teamId || ''} onChange={e => onChange({ ...config, teamId: e.target.value })} placeholder="ID del equipo" />
          )}
        </Field>
      )}

      {trigger === 'on_keyword' && (
        <div style={{ display:'flex', flexDirection:'column', gap:10 }}>
          <p style={{ fontSize:11, color:'var(--muted)', margin:0 }}>
            Escaneá toda la conversación y asigná el equipo cuyas palabras clave aparezcan primero.
            Ideal para multi-sucursal: "palermo", "caballito", "vicente lópez", etc.
          </p>
          {teamEntries.map((entry, i) => (
            <TeamKeywordRow
              key={i}
              entry={entry}
              index={i}
              teams={teams}
              connected={connected}
              onUpdateTeam={val => updEntry(i, 'teamId', val)}
              onUpdateKeywords={kws => updEntry(i, 'keywords', kws)}
              onRemove={() => removeEntry(i)}
            />
          ))}
          <button style={{ alignSelf:'flex-start', ...S.outlineBtn }} onClick={addTeamEntry}>+ Agregar sucursal</button>
        </div>
      )}
    </div>
  );
}

function UpdateStatusConfig({ config, onChange }) {
  return (
    <div style={{ display:'flex', flexDirection:'column', gap:12 }}>
      <Field label="Nuevo estado">
        <select style={S.select} value={config.status || 'solved'} onChange={e => onChange({ ...config, status: e.target.value })}>
          <option value="open">Abierta</option>
          <option value="solved">Resuelta</option>
          <option value="pending">Pendiente</option>
          <option value="blocked">Bloqueada</option>
        </select>
      </Field>
      <Field label="Cuándo cambiarlo">
        <select style={S.select} value={config.trigger || 'on_resolved'} onChange={e => onChange({ ...config, trigger: e.target.value })}>
          <option value="on_resolved">Cuando el agente resuelve la consulta</option>
          <option value="on_handoff">Cuando se deriva a un humano</option>
          <option value="always">Siempre al finalizar</option>
        </select>
      </Field>
    </div>
  );
}

function AssignOnTopicConfig({ config, onChange }) {
  const { teams, users, connected } = usePipochat();
  const rules = config.rules || [];
  const add = () => onChange({ ...config, rules: [...rules, { topic:'', teamId:'', operatorId:'' }] });
  const upd = (i, field, val) => { const next = [...rules]; next[i] = { ...next[i], [field]: val }; onChange({ ...config, rules: next }); };
  return (
    <div style={{ display:'flex', flexDirection:'column', gap:10 }}>
      <p style={{ fontSize:11, color:'var(--muted)', margin:0 }}>Si el agente detecta ese tema, asigna al equipo u operador indicado.</p>
      {rules.map((r, i) => (
        <div key={i} style={{ display:'flex', gap:8, alignItems:'center', background:'#f9fafb', padding:'10px', borderRadius:8 }}>
          <input style={{ ...S.input, flex:2 }} value={r.topic} onChange={e => upd(i,'topic',e.target.value)} placeholder="Tema (ej: ventas, soporte)" />
          {connected && teams.length > 0 ? (
            <select style={{ ...S.select, flex:2 }} value={r.teamId} onChange={e => upd(i,'teamId',e.target.value)}>
              <option value="">— Equipo —</option>
              {teams.map(t => <option key={t._id} value={t._id}>{t.name}</option>)}
            </select>
          ) : (
            <input style={{ ...S.input, flex:2 }} value={r.teamId} onChange={e => upd(i,'teamId',e.target.value)} placeholder="Team ID" />
          )}
          {connected && users.length > 0 ? (
            <select style={{ ...S.select, flex:2 }} value={r.operatorId} onChange={e => upd(i,'operatorId',e.target.value)}>
              <option value="">— Operador —</option>
              {users.map(u => <option key={u._id} value={u._id}>{u.name}</option>)}
            </select>
          ) : (
            <input style={{ ...S.input, flex:2 }} value={r.operatorId} onChange={e => upd(i,'operatorId',e.target.value)} placeholder="Operador ID" />
          )}
          <button style={S.ghostBtn} onClick={() => onChange({ ...config, rules: rules.filter((_,j) => j!==i) })}>×</button>
        </div>
      ))}
      <button style={{ alignSelf:'flex-start', ...S.outlineBtn }} onClick={add}>+ Agregar regla</button>
    </div>
  );
}

function TriggerChatbotConfig({ config, onChange }) {
  const { chatbots, connected } = usePipochat();
  const [kw, setKw] = useState('');
  const keywords = config.keywords || [];
  const addKw = () => { const v = kw.trim(); if (v && !keywords.includes(v)) { onChange({ ...config, keywords: [...keywords, v] }); setKw(''); }};
  const selectedBot = chatbots.find(b => b._id === config.chatbotId);
  return (
    <div style={{ display:'flex', flexDirection:'column', gap:12 }}>
      {connected && chatbots.length > 0 && (
        <Field label="WA Flow (seleccioná uno)">
          <select style={S.select} value={config.chatbotId || ''} onChange={e => onChange({ ...config, chatbotId: e.target.value })}>
            <option value="">— Seleccionar WA Flow —</option>
            {chatbots.map(b => <option key={b._id} value={b._id}>{b.name || b._id}</option>)}
          </select>
          {selectedBot && <div style={{ fontSize:11, color:'var(--muted)', marginTop:3 }}>ID: <span style={{ fontFamily:'monospace' }}>{selectedBot._id}</span></div>}
        </Field>
      )}
      <Field label={connected && chatbots.length > 0 ? 'O ingresá el ID del chatbot manualmente' : 'ID del chatbot / WA Flow'}>
        <input style={S.input} value={config.chatbotId || ''} onChange={e => onChange({ ...config, chatbotId: e.target.value })} placeholder="ID del chatbot (ej: 691dd60e...)" />
        <div style={{ fontSize:11, color:'var(--muted)', marginTop:4, lineHeight:1.5 }}>
          📍 Pipochat → <strong>Automatizaciones → Chatbots</strong> → abrí el chatbot → copiá el ID de la URL
        </div>
      </Field>
      <Field label="Cuándo activarlo">
        <select style={S.select} value={config.trigger || 'on_keyword'} onChange={e => onChange({ ...config, trigger: e.target.value })}>
          <option value="on_keyword">Cuando detecta palabras clave</option>
          <option value="on_first_message">En el primer mensaje</option>
          <option value="on_interest">Cuando detecta intención de compra</option>
          <option value="on_handoff">Antes de derivar a un humano</option>
        </select>
      </Field>
      {config.trigger === 'on_keyword' && (
        <div>
          <label style={S.label}>Palabras clave</label>
          <div style={{ display:'flex', gap:8, marginBottom:8 }}>
            <input style={{ ...S.input, flex:1 }} value={kw} onChange={e => setKw(e.target.value)} onKeyDown={e => e.key==='Enter' && addKw()} placeholder="ej: precio, costo…" />
            <button style={S.saveBtn} onClick={addKw}>+</button>
          </div>
          <div style={{ display:'flex', flexWrap:'wrap', gap:6 }}>
            {keywords.map(k => (
              <span key={k} style={S.badge('var(--primary)')}>
                {k}
                <button onClick={() => onChange({ ...config, keywords: keywords.filter(x => x !== k) })} style={{ background:'none', border:'none', color:'var(--primary)', cursor:'pointer', fontSize:13, padding:'0 0 0 2px' }}>×</button>
              </span>
            ))}
          </div>
        </div>
      )}
    </div>
  );
}

function CreateActivityConfig({ config, onChange }) {
  return (
    <div style={{ display:'flex', flexDirection:'column', gap:12 }}>
      <Field label="Tipo de actividad">
        <select style={S.select} value={config.activityType || 'call'} onChange={e => onChange({ ...config, activityType: e.target.value })}>
          <option value="call">📞 Llamada</option>
          <option value="meeting">🤝 Reunión</option>
          <option value="email">📧 Email</option>
          <option value="whatsapp">💬 WhatsApp</option>
          <option value="note">📝 Nota</option>
        </select>
      </Field>
      <Field label="Título de la actividad (opcional)">
        <input style={S.input} value={config.activityTitle || ''} onChange={e => onChange({ ...config, activityTitle: e.target.value })} placeholder="ej: Primer contacto, Seguimiento post-demo…" />
      </Field>
      <Field label="Cuándo registrarla">
        <select style={S.select} value={config.trigger || 'on_qualified'} onChange={e => onChange({ ...config, trigger: e.target.value })}>
          <option value="on_qualified">Cuando el lead está calificado</option>
          <option value="on_interest">Cuando detecta interés de compra</option>
          <option value="always">Con cada conversación</option>
          <option value="on_handoff">Cuando se deriva a un humano</option>
        </select>
      </Field>
    </div>
  );
}

function SendMeetingLinkConfig({ config, onChange }) {
  const { meetings, connected } = usePipochat();
  const selectedMtg = meetings.find(m => m._id === config.meetingId);
  return (
    <div style={{ display:'flex', flexDirection:'column', gap:12 }}>
      <Field label="Agenda / Scheduler">
        {connected && meetings.length > 0 ? (
          <>
            <select style={S.select} value={config.meetingId || ''} onChange={e => onChange({ ...config, meetingId: e.target.value })}>
              <option value="">— Seleccionar agenda —</option>
              {meetings.map(m => <option key={m._id} value={m._id}>{m.name || m.slug || m._id}</option>)}
            </select>
            {selectedMtg?.slug && (
              <div style={{ fontSize:11, color:'var(--muted)', marginTop:3 }}>
                Link: <span style={{ fontFamily:'monospace' }}>/meetings/{selectedMtg.slug}</span>
              </div>
            )}
          </>
        ) : (
          <>
            <input style={S.input} value={config.meetingId || ''} onChange={e => onChange({ ...config, meetingId: e.target.value })} placeholder="ID de la agenda" />
            <div style={{ fontSize:11, color:'var(--muted)', marginTop:4 }}>
              📍 Pipochat → <strong>Activities → Meeting Scheduler</strong> → copiá el slug/ID
            </div>
          </>
        )}
      </Field>
      <Field label="Mensaje con el link">
        <textarea style={{ ...S.textarea, minHeight:70 }}
          value={config.message || ''}
          onChange={e => onChange({ ...config, message: e.target.value })}
          placeholder="¡Te comparto el link para que elijas el horario que mejor te quede: {{meeting_link}}"
        />
        <div style={{ fontSize:11, color:'var(--muted)', marginTop:3 }}>Usá <code>{'{{meeting_link}}'}</code> donde debe ir el link.</div>
      </Field>
      <Field label="Cuándo enviarlo">
        <select style={S.select} value={config.trigger || 'on_qualified'} onChange={e => onChange({ ...config, trigger: e.target.value })}>
          <option value="on_qualified">Cuando el lead está calificado</option>
          <option value="on_interest">Cuando detecta interés de compra</option>
          <option value="on_request">Cuando el contacto pide agendar</option>
          <option value="on_handoff">Antes de derivar a un humano</option>
        </select>
      </Field>
    </div>
  );
}

// Config dispatcher
function ActionConfigEditor({ action, onChange }) {
  const upd = (cfg) => onChange({ ...action, config: cfg });
  const c = action.config || {};
  switch (action.type) {
    case 'send_message':       return <SendMessageConfig config={c} onChange={upd} />;
    case 'office_hours':       return <OfficeHoursConfig config={c} onChange={upd} />;
    case 'update_contact':     return <UpdateContactConfig config={c} onChange={upd} />;
    case 'create_lead':        return <CreateLeadConfig config={c} onChange={upd} />;
    case 'move_lead':          return <MoveLeadConfig config={c} onChange={upd} />;
    case 'handoff_human':      return <HandoffConfig config={c} onChange={upd} />;
    case 'add_tag':            return <TagConfig config={c} onChange={upd} label="Etiquetas a agregar" />;
    case 'remove_tag':         return <TagConfig config={c} onChange={upd} label="Etiquetas a quitar" />;
    case 'send_template':      return <SendTemplateConfig config={c} onChange={upd} />;
    case 'assign_operator':    return <AssignOperatorConfig config={c} onChange={upd} />;
    case 'assign_team':        return <AssignTeamConfig config={c} onChange={upd} />;
    case 'update_status':      return <UpdateStatusConfig config={c} onChange={upd} />;
    case 'add_lead_attribute': return <LeadAttributeConfig config={c} onChange={upd} />;
    case 'add_lead_note':      return <LeadNoteConfig config={c} onChange={upd} />;
    case 'assign_on_topic':    return <AssignOnTopicConfig config={c} onChange={upd} />;
    case 'trigger_chatbot':    return <TriggerChatbotConfig config={c} onChange={upd} />;
    case 'create_activity':    return <CreateActivityConfig config={c} onChange={upd} />;
    case 'send_meeting_link':  return <SendMeetingLinkConfig config={c} onChange={upd} />;
    case 'ai_qualify':         return <AiQualifyConfig config={c} onChange={upd} />;
    case 'notify_operator':    return <NotifyOperatorConfig config={c} onChange={upd} />;
    default:                   return null;
  }
}

function NotifyOperatorConfig({ config, onChange }) {
  const { users, connected } = usePipochat();
  const selected = config.operatorIds || [];
  const toggle = (id) => {
    const next = selected.includes(id) ? selected.filter(i => i !== id) : [...selected, id];
    onChange({ ...config, operatorIds: next });
  };
  const useTemplate = !!config.useTemplate;
  return (
    <div style={{ display:'flex', flexDirection:'column', gap:12 }}>
      <Field label="Operadores a notificar">
        {connected && users.length > 0 ? (
          <div style={{ display:'flex', flexDirection:'column', gap:6 }}>
            {users.map(u => (
              <label key={u._id} style={{ display:'flex', alignItems:'center', gap:8, fontSize:13, cursor:'pointer' }}>
                <input type="checkbox" checked={selected.includes(u._id)} onChange={() => toggle(u._id)} />
                {u.name}{u.phone ? ` — ${u.phone}` : ''}
              </label>
            ))}
          </div>
        ) : (
          <input style={S.input} value={config.operatorPhone||''} onChange={e => onChange({ ...config, operatorPhone: e.target.value })} placeholder="+5491112345678" />
        )}
      </Field>

      <Field label="Tipo de mensaje">
        <div style={{ display:'flex', gap:8, marginBottom:8 }}>
          {[['false','✍️ Texto libre (solo 24hs)'],['true','📋 Template aprobado (siempre)']].map(([val,label])=>(
            <label key={val} style={{ display:'flex', alignItems:'center', gap:6, fontSize:12, cursor:'pointer',
              background: String(useTemplate)===val ? 'var(--green-light)' : 'var(--bg)',
              border:'1px solid var(--border)', borderRadius:8, padding:'5px 10px', userSelect:'none', flex:1 }}>
              <input type="radio" checked={String(useTemplate)===val}
                onChange={()=>onChange({...config, useTemplate: val==='true'})} style={{margin:0}} />
              {label}
            </label>
          ))}
        </div>
        <div style={{ fontSize:11, color:'var(--warning)', background:'var(--warning-light)', borderRadius:6, padding:'5px 9px' }}>
          ⚠️ Las notificaciones suelen enviarse fuera de las 24hs. Recomendamos usar template aprobado.
        </div>
      </Field>

      {useTemplate ? (
        <Field label="Template de notificación">
          <TemplateSelector
            value={config.templateId||''}
            varMapping={config.templateVarMapping||{}}
            onChange={v=>onChange({...config, templateId:v})}
            onVarChange={(slot,v)=>onChange({...config, templateVarMapping:{...(config.templateVarMapping||{}),[slot]:v}})}
          />
        </Field>
      ) : (
        <Field label="Mensaje de notificación">
          <textarea style={{ ...S.textarea, minHeight:80 }} value={config.message||''} onChange={e => onChange({ ...config, message: e.target.value })}
            placeholder="🚨 Nuevo lead calificado: {{contact_name}} — {{reason}}" />
          <div style={{ fontSize:11, color:'var(--muted)', marginTop:3 }}>Variables disponibles: {'{{contact_name}}'}, {'{{contact_phone}}'}, {'{{reason}}'}.</div>
        </Field>
      )}

      <Field label="Cuándo enviar la notificación">
        <select style={S.select} value={config.trigger||'on_qualified'} onChange={e => onChange({ ...config, trigger: e.target.value })}>
          <option value="on_qualified">Cuando el lead está calificado</option>
          <option value="on_interest">Cuando detecta interés de compra</option>
          <option value="on_handoff">Cuando el cliente pide un humano</option>
          <option value="on_meeting">Cuando agenda una reunión</option>
          <option value="always">Con cada mensaje del contacto</option>
        </select>
      </Field>
    </div>
  );
}

// ─── Action metadata ──────────────────────────────────────────────────────────
const ACTION_META = {
  knowledge_base:     { label:'Base de conocimiento',     icon:'📚', desc:'El agente consulta tus documentos antes de responder sobre productos, precios o servicios. Siempre activado.' },
  transcribe_audio:   { label:'Transcribir audios',       icon:'🎙️', desc:'Convierte mensajes de voz en texto para que el agente pueda entenderlos y responder.' },
  create_contact:     { label:'Crear contacto',           icon:'➕', desc:'Guarda automáticamente al contacto cuando llega su primer mensaje, sin que nadie tenga que hacerlo a mano.' },
  update_contact:     { label:'Guardar datos del cliente',icon:'👤', desc:'El agente detecta y anota datos del cliente durante la charla — nombre de empresa, cargo, intereses — para no tener que preguntarlos de nuevo.' },
  add_tag:            { label:'Agregar etiqueta',         icon:'🏷️', desc:'Clasifica al contacto automáticamente según lo que dice en la conversación (ej: "interesado", "ya compró", "soporte").' },
  remove_tag:         { label:'Quitar etiqueta',          icon:'✂️', desc:'Elimina una etiqueta cuando ya no aplica, manteniendo los datos del contacto actualizados.' },
  send_message:       { label:'Enviar mensaje',           icon:'💬', desc:'El agente puede enviar texto, imágenes, videos, documentos y audios como parte de la conversación.' },
  send_template:      { label:'Enviar template de WhatsApp', icon:'📋', desc:'Envía un mensaje de plantilla aprobado por Meta cuando la ventana de conversación está cerrada (+24hs sin actividad).' },
  assign_operator:    { label:'Derivar a un agente',      icon:'👨‍💼', desc:'Transfiere la conversación a una persona específica cuando el cliente necesita atención humana.' },
  assign_team:        { label:'Derivar a un equipo',      icon:'👥', desc:'Envía la conversación al equipo correcto — ventas, soporte, administración — según el contexto.' },
  update_status:      { label:'Cambiar estado',           icon:'🔄', desc:'Marca la conversación como abierta, cerrada o pendiente automáticamente según el flujo.' },
  create_lead:        { label:'Crear oportunidad de venta', icon:'💼', desc:'Agrega al contacto a tu pipeline de ventas cuando detecta intención de compra o interés real.' },
  move_lead:          { label:'Avanzar en el pipeline',   icon:'➡️', desc:'Mueve la oportunidad a la siguiente etapa del pipeline según el progreso de la conversación.' },
  add_lead_attribute: { label:'Guardar datos de la oportunidad', icon:'📝', desc:'Anota información clave de la venta — presupuesto, zona, tipo de producto — para que el equipo comercial tenga todo el contexto.' },
  add_lead_note:      { label:'Agregar nota de seguimiento', icon:'📌', desc:'Escribe automáticamente un resumen de la conversación en la oportunidad para que el equipo sepa de qué se habló.' },
  office_hours:       { label:'Horario de atención',      icon:'🕐', desc:'El agente solo responde dentro del horario que definas. Fuera de horario envía un aviso automático.' },
  handoff_human:      { label:'Detectar pedido de humano',icon:'🙋', desc:'Cuando el cliente pide hablar con una persona, el agente lo avisa y transfiere la conversación.' },
  assign_on_topic:    { label:'Derivar según el tema',    icon:'🎯', desc:'Identifica el tema de la consulta (ventas, soporte, facturación) y la manda al equipo correspondiente.' },
  trigger_chatbot:    { label:'Activar flujo de WhatsApp',icon:'🤖', desc:'Lanza un flujo automatizado de WhatsApp o un chatbot de reglas según lo que detecta en la conversación.' },
  create_activity:    { label:'Registrar actividad',      icon:'📋', desc:'Crea un registro histórico de la interacción — tipo llamada, reunión o email — en la oportunidad del contacto.' },
  send_meeting_link:  { label:'Enviar link para agendar', icon:'📅', desc:'Comparte un enlace para que el cliente elija un horario de reunión directamente desde el chat.' },
  ai_qualify:         { label:'Calificar lead con IA',    icon:'🧠', desc:'Claude analiza la conversación completa y decide si el contacto es un lead calificado, sin necesidad de keywords ni reglas.' },
  notify_operator:    { label:'Notificar operador',        icon:'📲', desc:'Envía un WhatsApp al vendedor o equipo cuando ocurre algo importante: lead calificado, handoff solicitado, interés detectado.' },
};

// Group actions for display
const ACTION_GROUPS = [
  { title:'Mensajería',       keys:['knowledge_base','transcribe_audio','send_message','send_template','office_hours','handoff_human'] },
  { title:'Datos del cliente',keys:['create_contact','update_contact','add_tag','remove_tag'] },
  { title:'CRM y ventas',     keys:['create_lead','move_lead','add_lead_attribute','add_lead_note'] },
  { title:'Derivaciones',     keys:['assign_operator','assign_team','assign_on_topic','update_status','trigger_chatbot'] },
  { title:'Seguimiento',      keys:['create_activity','send_meeting_link'] },
  { title:'Inteligencia IA',  keys:['ai_qualify'] },
  { title:'Notificaciones',   keys:['notify_operator'] },
];

function ActionCard({ action, onChange }) {
  const [expanded, setExpanded] = useState(false);
  const meta = ACTION_META[action.type] || { label:action.type, icon:'⚙️', desc:'' };
  const hasConfig = ['send_message','office_hours','update_contact','create_lead','move_lead','handoff_human','add_tag','remove_tag',
    'send_template','assign_operator','assign_team','update_status','add_lead_attribute','add_lead_note',
    'assign_on_topic','trigger_chatbot','create_activity','send_meeting_link','notify_operator','ai_qualify'].includes(action.type);

  return (
    <div style={S.actionItem}>
      <div style={S.actionHeader}>
        <span style={S.actionIcon}>{meta.icon}</span>
        <div style={S.actionMeta}>
          <div style={S.actionLabel}>{meta.label}</div>
          <div style={S.actionDesc}>{meta.desc}</div>
        </div>
        {hasConfig && (
          <button style={S.expandBtn} onClick={() => setExpanded(!expanded)}>
            {expanded ? '▲' : '▼'}
          </button>
        )}
        <Toggle on={action.enabled} onChange={v => onChange({ ...action, enabled: v })} />
      </div>
      {expanded && hasConfig && (
        <div style={S.actionBody}>
          <ActionConfigEditor action={action} onChange={onChange} />
        </div>
      )}
    </div>
  );
}

// ─── Follow-up card ───────────────────────────────────────────────────────────
// Delay options: all under 24h (regular WhatsApp message, no template needed)
const FOLLOWUP_DELAY_OPTIONS = [
  { value:5,    label:'5 minutos' },
  { value:15,   label:'15 minutos' },
  { value:30,   label:'30 minutos' },
  { value:60,   label:'1 hora' },
  { value:120,  label:'2 horas' },
  { value:240,  label:'4 horas' },
  { value:480,  label:'8 horas' },
  { value:720,  label:'12 horas' },
  { value:1380, label:'23 horas' },
];

const TEMPLATE_DELAY_OPTIONS = [
  { value:1440,  label:'1 día' },
  { value:2880,  label:'2 días' },
  { value:4320,  label:'3 días' },
  { value:7200,  label:'5 días' },
  { value:10080, label:'7 días (1 semana)' },
  { value:20160, label:'14 días (2 semanas)' },
  { value:43200, label:'30 días (1 mes)' },
];

function FollowUpCard({ followUp = {}, onChange }) {
  const { tags, templates, users, connected } = usePipochat();
  const enabled    = followUp.enabled      || false;
  const delay      = followUp.delayMinutes || 30;
  const actionType = followUp.actionType   || 'send_message';
  const message    = followUp.message      || '';

  const FOLLOWUP_ACTIONS = [
    { v:'send_message',    label:'💬 Enviar mensaje de texto' },
    { v:'send_template',   label:'📋 Enviar template de WhatsApp' },
    { v:'add_tag',         label:'🏷️ Agregar etiqueta' },
    { v:'notify_operator', label:'📲 Notificar operador' },
  ];

  return (
    <div style={S.card}>
      <div style={{ display:'flex', alignItems:'flex-start', justifyContent:'space-between', gap:12, marginBottom:12 }}>
        <div style={{ flex:1 }}>
          <div style={S.cardTitle}>⏰ Seguimiento rápido</div>
          <div style={{ fontSize:12, color:'var(--muted)', marginTop:2, lineHeight:1.5 }}>
            Ejecuta una acción si el contacto no responde dentro de la ventana de 24hs. Para reglas avanzadas (múltiples acciones, condiciones, días) usá <b>Automatizaciones → Sin respuesta</b>.
          </div>
        </div>
        <Toggle on={enabled} onChange={v => onChange({ ...followUp, enabled: v })} />
      </div>

      {enabled && (
        <div style={{ display:'flex', flexDirection:'column', gap:14 }}>
          <Field label="Ejecutar después de (máximo 23hs)">
            <select style={S.select} value={delay} onChange={e => onChange({ ...followUp, delayMinutes: Number(e.target.value) })}>
              {FOLLOWUP_DELAY_OPTIONS.map(o => <option key={o.value} value={o.value}>{o.label}</option>)}
            </select>
          </Field>

          <Field label="Acción">
            <div style={{ display:'flex', gap:7, flexWrap:'wrap' }}>
              {FOLLOWUP_ACTIONS.map(o => (
                <button key={o.v} style={S.chip(actionType === o.v)} onClick={() => onChange({ ...followUp, actionType: o.v })}>
                  {o.label}
                </button>
              ))}
            </div>
          </Field>

          {actionType === 'send_message' && (
            <Field label="Texto del mensaje">
              <textarea style={{ ...S.textarea, minHeight:80 }} value={message}
                onChange={e => onChange({ ...followUp, message: e.target.value })}
                placeholder="Hola! Te escribo para hacer un seguimiento. ¿Pudiste revisar la información? Estoy disponible para cualquier consulta 😊" />
            </Field>
          )}

          {actionType === 'send_template' && (
            <Field label="Template de WhatsApp">
              {connected && templates.length > 0
                ? <select style={S.select} value={followUp.templateId||''} onChange={e => onChange({ ...followUp, templateId: e.target.value })}>
                    <option value="">— Seleccionar template —</option>
                    {templates.map(t => <option key={t._id} value={t._id}>{t.name}</option>)}
                  </select>
                : <input style={S.input} value={followUp.templateId||''} onChange={e => onChange({ ...followUp, templateId: e.target.value })} placeholder="ID del template aprobado por Meta" />
              }
              <div style={{ fontSize:11, color:'var(--muted)', marginTop:4 }}>
                Usá un template cuando la conversación puede estar cerrada (+24hs sin actividad).
              </div>
            </Field>
          )}

          {actionType === 'add_tag' && (
            <Field label="Etiqueta a agregar">
              {connected && tags.length > 0
                ? <select style={S.select} value={followUp.tagName||''} onChange={e => onChange({ ...followUp, tagName: e.target.value })}>
                    <option value="">— Seleccionar etiqueta —</option>
                    {tags.map(t => <option key={t._id} value={t.name}>{t.name}</option>)}
                  </select>
                : <input style={S.input} value={followUp.tagName||''} onChange={e => onChange({ ...followUp, tagName: e.target.value })} placeholder="Nombre de la etiqueta" />
              }
            </Field>
          )}

          {actionType === 'notify_operator' && (
            <>
              <Field label="Operador a notificar">
                {connected && users.length > 0
                  ? <select style={S.select} value={followUp.operatorId||''} onChange={e => onChange({ ...followUp, operatorId: e.target.value })}>
                      <option value="">— Seleccionar operador —</option>
                      {users.map(u => <option key={u._id} value={u._id}>{u.name}</option>)}
                    </select>
                  : <input style={S.input} value={followUp.operatorPhone||''} onChange={e => onChange({ ...followUp, operatorPhone: e.target.value })} placeholder="+5491112345678" />
                }
              </Field>
              <Field label="Mensaje de notificación">
                <textarea style={{ ...S.textarea, minHeight:70 }} value={message}
                  onChange={e => onChange({ ...followUp, message: e.target.value })}
                  placeholder="🔔 {{contact_name}} no respondió hace {{delay}}. Revisá la conversación." />
                <div style={{ fontSize:11, color:'var(--muted)', marginTop:3 }}>Variables: {'{{contact_name}}'}, {'{{contact_phone}}'}, {'{{delay}}'}.</div>
              </Field>
            </>
          )}
        </div>
      )}
    </div>
  );
}

// ─── Test Chat ────────────────────────────────────────────────────────────────
function TestChatPanel({ agentId, agentName }) {
  const [history, setHistory] = useState([]);
  const [input, setInput] = useState('');
  const [loading, setLoading] = useState(false);
  const bodyRef = useRef(null);

  useEffect(() => { if (bodyRef.current) bodyRef.current.scrollTop = bodyRef.current.scrollHeight; }, [history, loading]);

  const send = async () => {
    const msg = input.trim();
    if (!msg || loading || !agentId) return;
    setInput('');
    setHistory(h => [...h, { role:'user', content: msg }]);
    setLoading(true);
    try {
      const res = await api.test(agentId, msg, history);
      setHistory(h => [...h, { role:'assistant', content: res.reply, tools: res.toolCalls }]);
    } catch (err) {
      setHistory(h => [...h, { role:'assistant', content: '❌ Error: ' + err.message }]);
    } finally { setLoading(false); }
  };

  return (
    <div style={S.chatPanel}>
      <div style={S.chatHeader}>
        <div>
          <div style={S.chatTitle}>🧪 Probar agente</div>
          <div style={{ fontSize:11, color:'var(--muted)' }}>Simulación — no envía mensajes reales</div>
        </div>
        {history.length > 0 && <button onClick={() => setHistory([])} style={{ background:'none', border:'none', color:'var(--muted)', fontSize:12, cursor:'pointer' }}>Limpiar</button>}
      </div>

      {!agentId ? (
        <div style={S.emptyState}>
          <span style={{ fontSize:32 }}>🤖</span>
          <span>Seleccioná un agente para probarlo</span>
        </div>
      ) : (
        <>
          <div ref={bodyRef} style={S.chatBody}>
            {history.length === 0 && (
              <div style={{ ...S.emptyState, flex:'none', paddingTop:32 }}>
                <span style={{ fontSize:24 }}>💬</span>
                <span>Escribí un mensaje para simular una conversación de WhatsApp</span>
              </div>
            )}
            {history.map((msg, i) => (
              <React.Fragment key={i}>
                <div style={S.chatBubble(msg.role)}>{msg.content}</div>
                {msg.tools && msg.tools.length > 0 && (
                  <div style={S.chatMeta}>🔧 {msg.tools.join(' → ')}</div>
                )}
              </React.Fragment>
            ))}
            {loading && <div style={{ ...S.chatBubble('assistant'), opacity:.5 }}><span style={{ letterSpacing:4 }}>···</span></div>}
          </div>
          <div style={S.chatInputRow}>
            <textarea
              style={S.chatInput} value={input}
              onChange={e => setInput(e.target.value)}
              onKeyDown={e => { if (e.key==='Enter' && !e.shiftKey) { e.preventDefault(); send(); } }}
              placeholder="Escribí un mensaje…" rows={1}
            />
            <button style={S.sendBtn} onClick={send} disabled={loading}>{loading ? '…' : '→'}</button>
          </div>
        </>
      )}
    </div>
  );
}

// ─── InboxSelector ────────────────────────────────────────────────────────────
// Multi-select dropdown for WhatsApp lines. Works with or without loaded inboxes.
function InboxSelector({ inboxes: inboxesProp, selected, onChange }) {
  const [open,         setOpen]         = useState(false);
  const [inboxes,      setInboxes]      = useState(inboxesProp || []);
  const [loadingLines, setLoadingLines] = useState(false);
  const [manualId,     setManualId]     = useState('');
  const ref = useRef(null);

  // Sync from parent prop
  useEffect(() => { if (inboxesProp?.length) setInboxes(inboxesProp); }, [inboxesProp?.length]);

  // On open: if no inboxes yet, fetch them directly
  const handleOpen = async () => {
    setOpen(v => !v);
    if (!open && inboxes.length === 0) {
      setLoadingLines(true);
      try {
        const data = await apiFetch('/api/pipochat/inboxes').then(r => r.json());
        const loaded = (data.inboxes || []).map(i => ({
          _id: i._id, name: i.name || i.phoneNumber || i._id, phoneNumber: i.phoneNumber,
        }));
        setInboxes(loaded);
      } catch {}
      setLoadingLines(false);
    }
  };

  // Close on outside click
  useEffect(() => {
    const handler = e => { if (ref.current && !ref.current.contains(e.target)) setOpen(false); };
    document.addEventListener('mousedown', handler);
    return () => document.removeEventListener('mousedown', handler);
  }, []);

  const toggle = (id) => {
    onChange(selected.includes(id) ? selected.filter(x => x !== id) : [...selected, id]);
  };

  // Build display labels: use inbox name if available, else raw id
  const idToLabel = (id) => {
    const inbox = inboxes.find(i => i._id === id);
    return inbox ? inbox.name : id;
  };

  const selectedLabels = selected.map(idToLabel);

  return (
    <div style={S.card}>
      <div style={S.cardTitle}>📱 Líneas de WhatsApp asignadas</div>
      <div style={S.cardDesc}>
        Este agente solo responderá mensajes de las líneas seleccionadas.
        Si no seleccionás ninguna, actúa como agente <strong>por defecto</strong> para cualquier línea sin agente asignado.
      </div>

      <div style={{ marginTop:10, position:'relative' }} ref={ref}>
        {/* Trigger button */}
        <button
          type="button"
          onClick={handleOpen}
          style={{
            width:'100%', textAlign:'left', padding:'8px 12px',
            background:'var(--white)', border:'1px solid var(--border)', borderRadius:8,
            cursor:'pointer', fontSize:13, display:'flex', alignItems:'center', justifyContent:'space-between',
            color: selected.length ? 'var(--ink-1)' : 'var(--ink-4)',
          }}
        >
          <span style={{ flex:1, overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap' }}>
            {selected.length === 0
              ? '— Sin asignación (agente por defecto) —'
              : selectedLabels.join(', ')}
          </span>
          <span style={{ marginLeft:8, fontSize:11, color:'var(--ink-4)' }}>
            {selected.length > 0 && <span style={{ background:'#dbeafe', color:'#1d4ed8', borderRadius:10, padding:'1px 7px', marginRight:6, fontSize:11 }}>{selected.length}</span>}
            {open ? '▲' : '▼'}
          </span>
        </button>

        {/* Dropdown panel */}
        {open && (
          <div style={{
            position:'absolute', top:'calc(100% + 4px)', left:0, right:0, zIndex:200,
            background:'var(--white)', border:'1px solid var(--border)', borderRadius:8,
            boxShadow:'0 4px 16px rgba(0,0,0,0.10)', maxHeight:280, overflowY:'auto',
          }}>
            {loadingLines ? (
              <div style={{ padding:'12px 14px', fontSize:12, color:'var(--ink-4)' }}>⏳ Cargando líneas…</div>
            ) : inboxes.length === 0 ? (
              <div style={{ padding:'12px 14px', fontSize:13 }}>
                <div style={{ color:'var(--ink-3)', marginBottom:8 }}>
                  No se detectaron líneas automáticamente.
                  <div style={{ fontSize:11, color:'var(--ink-4)', marginTop:4 }}>
                    Enviá un mensaje de WhatsApp a tu línea y volvé a abrir este menú, o ingresá el ID manualmente:
                  </div>
                </div>
                <div style={{ display:'flex', gap:6 }}>
                  <input
                    placeholder="ID de la línea…"
                    value={manualId}
                    onChange={e => setManualId(e.target.value)}
                    onKeyDown={e => {
                      if (e.key === 'Enter' && manualId.trim()) {
                        const id = manualId.trim();
                        setInboxes(prev => [...prev, { _id: id, name: id }]);
                        onChange([...selected, id]);
                        setManualId('');
                      }
                    }}
                    style={{ ...S.input, flex:1, fontSize:12, fontFamily:'monospace' }}
                  />
                  <button
                    onClick={() => {
                      if (!manualId.trim()) return;
                      const id = manualId.trim();
                      setInboxes(prev => [...prev, { _id: id, name: id }]);
                      onChange([...selected, id]);
                      setManualId('');
                    }}
                    style={{ ...S.saveBtn, fontSize:12, padding:'6px 12px' }}
                  >Agregar</button>
                </div>
                <div style={{ fontSize:11, color:'var(--ink-4)', marginTop:6 }}>
                  Encontrás el ID en <strong>Inspector de eventos → campo inboxId</strong>
                </div>
              </div>
            ) : (
              <>
                <div style={{ padding:'6px 10px 4px', fontSize:11, color:'var(--ink-4)', borderBottom:'1px solid var(--border)' }}>
                  Seleccioná las líneas que debe atender este agente
                </div>
                {inboxes.map(inbox => {
                  const isChecked = selected.includes(inbox._id);
                  return (
                    <label key={inbox._id}
                      style={{
                        display:'flex', alignItems:'center', gap:10, padding:'9px 14px',
                        cursor:'pointer', fontSize:13, borderBottom:'1px solid var(--border-soft)',
                        background: isChecked ? '#f0fdf4' : 'transparent',
                        transition:'background 0.1s',
                      }}
                    >
                      <input type="checkbox" checked={isChecked} onChange={() => toggle(inbox._id)}
                        style={{ width:15, height:15, accentColor:'var(--primary)', cursor:'pointer' }} />
                      <div style={{ flex:1 }}>
                        <div style={{ fontWeight: isChecked ? 600 : 400 }}>{inbox.name}</div>
                        {inbox.phoneNumber && <div style={{ fontSize:11, color:'var(--ink-4)' }}>{inbox.phoneNumber}</div>}
                      </div>
                      {isChecked && <span style={{ fontSize:12, color:'#16a34a' }}>✓</span>}
                    </label>
                  );
                })}
                {selected.length > 0 && (
                  <div style={{ padding:'8px 14px', borderTop:'1px solid var(--border)' }}>
                    <button type="button" onClick={() => onChange([])}
                      style={{ fontSize:12, color:'var(--danger)', background:'none', border:'none', cursor:'pointer' }}>
                      ✕ Quitar todas las asignaciones
                    </button>
                  </div>
                )}
              </>
            )}
          </div>
        )}
      </div>

      {/* Manual fallback for IDs not yet in the dropdown */}
      {selected.filter(id => !inboxes.find(i => i._id === id)).length > 0 && (
        <div style={{ marginTop:8, fontSize:11, color:'var(--ink-4)' }}>
          IDs guardados sin nombre (líneas no encontradas en Pipochat):
          <span style={{ fontFamily:'monospace', marginLeft:4 }}>
            {selected.filter(id => !inboxes.find(i => i._id === id)).join(', ')}
          </span>
        </div>
      )}
    </div>
  );
}

// ─── Action Metrics Card ──────────────────────────────────────────────────────
function ActionMetricsCard() {
  const [metrics, setMetrics] = React.useState(null);
  const [loading, setLoading] = React.useState(true);

  React.useEffect(() => {
    apiFetch('/api/agents/metrics')
      .then(r => r.json())
      .then(d => { setMetrics(d); setLoading(false); })
      .catch(() => setLoading(false));
  }, []);

  const groups = [
    {
      label: 'IA',
      items: [
        { key: 'ai_replies',        label: 'Respuestas de IA',      icon: '🤖' },
        { key: 'handoffs',          label: 'Derivaciones a humano', icon: '🙋' },
      ],
    },
    {
      label: 'CRM',
      items: [
        { key: 'leads_created',         label: 'Leads creados',         icon: '🎯' },
        { key: 'stages_advanced',       label: 'Etapas avanzadas',      icon: '📈' },
        { key: 'activities_created',    label: 'Actividades creadas',   icon: '📝' },
        { key: 'lead_notes_added',      label: 'Notas de lead',         icon: '📋' },
        { key: 'lead_attrs_updated',    label: 'Atrib. de lead',        icon: '🏷️' },
        { key: 'contact_attrs_updated', label: 'Atrib. de contacto',    icon: '👤' },
        { key: 'status_updated',        label: 'Estados actualizados',  icon: '🔄' },
      ],
    },
    {
      label: 'Engagement',
      items: [
        { key: 'tags_applied',       label: 'Etiquetas aplicadas',  icon: '🏷️' },
        { key: 'operators_assigned', label: 'Operadores asignados', icon: '👷' },
        { key: 'teams_assigned',     label: 'Equipos asignados',    icon: '👥' },
        { key: 'chatbots_triggered', label: 'Chatbots activados',   icon: '⚡' },
        { key: 'meeting_links_sent', label: 'Links de agenda',      icon: '📅' },
        { key: 'templates_sent',     label: 'Templates enviados',   icon: '📨' },
      ],
    },
    {
      label: 'Seguimiento proactivo',
      items: [
        { key: 'proactive_followups_sent', label: 'Seguimientos enviados', icon: '🤖' },
        { key: 'proactive_replies',        label: 'Re-enganchados',        icon: '💬' },
      ],
    },
    {
      label: 'Propiedades',
      items: [
        { key: 'property_searches', label: 'Búsquedas de prop.',  icon: '🔍' },
        { key: 'properties_sent',   label: 'Propiedades enviadas', icon: '🏠' },
      ],
    },
  ];

  return (
    <div style={S.card}>
      <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between', marginBottom:12 }}>
        <div style={S.cardTitle}>Acciones del agente</div>
        {metrics?.lastUpdated && (
          <div style={{ fontSize:11, color:'var(--ink-4)' }}>
            Última acción: {new Date(metrics.lastUpdated).toLocaleDateString('es-AR', { day:'2-digit', month:'2-digit', hour:'2-digit', minute:'2-digit' })}
          </div>
        )}
      </div>
      <div style={{ display:'flex', flexDirection:'column', gap:16 }}>
        {groups.map(({ label, items }) => (
          <div key={label}>
            <div style={{ fontSize:11, fontWeight:600, color:'var(--ink-4)', textTransform:'uppercase', letterSpacing:'.06em', marginBottom:8 }}>{label}</div>
            <div style={{ display:'flex', gap:8, flexWrap:'wrap' }}>
              {items.map(({ key, label: lbl, icon }) => {
                const val = metrics ? (metrics[key] ?? 0) : null;
                const active = val > 0;
                return (
                  <div key={key} style={{
                    background: active ? 'var(--green-light)' : 'var(--cream)',
                    border: `1px solid ${active ? 'var(--green-mid)' : 'var(--border-soft)'}`,
                    borderRadius: 8, padding: '10px 14px',
                    display: 'flex', flexDirection: 'column', gap: 2, minWidth: 110,
                  }}>
                    <div style={{ fontSize: 16, lineHeight: 1 }}>{icon}</div>
                    <div style={{ fontWeight: 700, fontSize: 18, color: active ? 'var(--green)' : 'var(--ink-3)', marginTop: 4 }}>
                      {loading ? '…' : (val ?? '—')}
                    </div>
                    <div style={{ fontSize: 11, color: 'var(--ink-3)' }}>{lbl}</div>
                  </div>
                );
              })}
            </div>
          </div>
        ))}
      </div>
    </div>
  );
}

// ─── Reservation Config Card ──────────────────────────────────────────────────
function ReservationConfigCard({ config, onChange, pipelines }) {
  const cfg = config || {};
  const upd = (patch) => onChange({ ...cfg, ...patch });
  const updTmpl = (patch) => upd({ reminderTemplate: { ...(cfg.reminderTemplate || {}), ...patch } });

  const selectedPipeline = pipelines.find(p => p._id === cfg.pipelineId);
  const stages           = selectedPipeline?.stages || [];
  const [tmplOpen, setTmplOpen] = useState(false);

  const reminderOn = !!cfg.reminderEnabled;
  const bodyVars   = cfg.reminderTemplate?.bodyVars?.length ? cfg.reminderTemplate.bodyVars : [''];

  return (
    <div style={S.card}>
      <div style={S.cardTitle}>🗓️ Gestión de reservas</div>
      <div style={S.cardDesc}>
        Cuando se completa el formulario de reserva, crea un lead en el pipeline y registra
        la actividad en el calendario de Pipochat. Opcionalmente envía un recordatorio automático.
      </div>

      <div style={{ display:'flex', alignItems:'center', gap:10, marginBottom: cfg.enabled ? 18 : 0 }}>
        <Toggle on={!!cfg.enabled} onChange={v => upd({ enabled: v })} />
        <span style={{ fontSize:13, color:'var(--ink-2)' }}>Activar gestión de reservas</span>
      </div>

      {cfg.enabled && (
        <div style={{ display:'flex', flexDirection:'column', gap:14 }}>

          {/* Pipeline + Stage */}
          <div style={{ display:'flex', gap:10, flexWrap:'wrap' }}>
            <div style={{ flex:1, minWidth:160 }}>
              <Field label="Pipeline de reservas">
                <select style={S.select} value={cfg.pipelineId || ''}
                  onChange={e => upd({ pipelineId: e.target.value, stageId: '' })}>
                  <option value=''>— Seleccionar pipeline —</option>
                  {pipelines.map(p => <option key={p._id} value={p._id}>{p.title || p.name}</option>)}
                </select>
              </Field>
            </div>
            <div style={{ flex:1, minWidth:160 }}>
              <Field label="Etapa inicial">
                <select style={S.select} value={cfg.stageId || ''}
                  onChange={e => upd({ stageId: e.target.value })} disabled={!cfg.pipelineId}>
                  <option value=''>— Seleccionar etapa —</option>
                  {stages.map(s => <option key={s._id} value={s._id}>{s.name}</option>)}
                </select>
              </Field>
            </div>
          </div>

          {/* Reminder toggle + config */}
          <div style={{ background:'var(--bg-2)', borderRadius:10, padding:'12px 14px' }}>
            <div style={{ display:'flex', alignItems:'center', gap:10, marginBottom: reminderOn ? 14 : 0 }}>
              <Toggle on={reminderOn} onChange={v => upd({ reminderEnabled: v })} />
              <span style={{ fontSize:13, fontWeight:600 }}>📲 Recordatorio automático por WhatsApp</span>
            </div>

            {reminderOn && (
              <div style={{ display:'flex', flexDirection:'column', gap:12 }}>

                <div style={{ display:'flex', gap:8, maxWidth:280 }}>
                  <div style={{ flex:1 }}>
                    <Field label="Horas antes">
                      <input type="number" min="0" max="72" style={S.input}
                        value={cfg.reminderHoursBefore ?? 2}
                        onChange={e => upd({ reminderHoursBefore: Math.max(0, parseInt(e.target.value) || 0) })} />
                    </Field>
                  </div>
                  <div style={{ flex:1 }}>
                    <Field label="Minutos antes">
                      <input type="number" min="0" max="59" style={S.input}
                        value={cfg.reminderMinutesBefore ?? 0}
                        onChange={e => upd({ reminderMinutesBefore: Math.min(59, Math.max(0, parseInt(e.target.value) || 0)) })} />
                    </Field>
                  </div>
                </div>

                {/* Template (collapsible) */}
                <div style={{ background:'var(--bg-3)', borderRadius:8, overflow:'hidden' }}>
                  <div style={{ display:'flex', justifyContent:'space-between', alignItems:'center', padding:'8px 12px', cursor:'pointer' }}
                    onClick={() => setTmplOpen(o => !o)}>
                    <span style={{ fontSize:12, fontWeight:600, color:'var(--ink-2)' }}>
                      📋 Template de WhatsApp
                      {cfg.reminderTemplate?.name ? ` — ${cfg.reminderTemplate.name}` : ' — sin configurar'}
                    </span>
                    <span style={{ fontSize:11, color:'var(--ink-4)' }}>{tmplOpen ? '▲' : '▼'}</span>
                  </div>

                  {tmplOpen && (
                    <div style={{ padding:'0 12px 12px', display:'flex', flexDirection:'column', gap:10 }}>

                      <div style={{ display:'flex', gap:10, flexWrap:'wrap' }}>
                        <div style={{ flex:2, minWidth:160 }}>
                          <Field label="Nombre del template">
                            <input style={S.input} value={cfg.reminderTemplate?.name || ''}
                              onChange={e => updTmpl({ name: e.target.value })}
                              placeholder="ej: otaku_recordatorio_reserva" />
                          </Field>
                        </div>
                        <div style={{ flex:1, minWidth:80 }}>
                          <Field label="Idioma">
                            <input style={S.input} value={cfg.reminderTemplate?.language || 'es'}
                              onChange={e => updTmpl({ language: e.target.value })}
                              placeholder="es" />
                          </Field>
                        </div>
                      </div>

                      <div>
                        <div style={{ fontSize:11, fontWeight:600, color:'var(--ink-3)', marginBottom:4 }}>
                          {'Variables del body ({{1}}, {{2}}, ...)'}
                        </div>
                        <div style={{ fontSize:11, color:'var(--ink-4)', background:'var(--white)', borderRadius:6, padding:'5px 9px', marginBottom:8, fontFamily:'monospace', lineHeight:1.8, border:'1px solid var(--border)' }}>
                          {'{{nombre}}'} · {'{{dia}}'} · {'{{horario}}'} · {'{{local}}'} · {'{{cantidad_personas}}'} · {'{{fecha}}'} · {'{{fecha_horario}}'}
                        </div>

                        {bodyVars.map((v, i) => (
                          <div key={i} style={{ display:'flex', gap:8, alignItems:'center', marginBottom:6 }}>
                            <span style={{ fontSize:11, color:'var(--ink-4)', minWidth:28, textAlign:'right', flexShrink:0 }}>
                              {`{{${i+1}}}`}:
                            </span>
                            <input style={{ ...S.input, flex:1 }} value={v}
                              placeholder={i === 0 ? '{{nombre}}' : i === 1 ? '{{fecha_horario}}' : '{{local}}'}
                              onChange={e => {
                                const next = [...bodyVars]; next[i] = e.target.value;
                                updTmpl({ bodyVars: next });
                              }} />
                            <button onClick={() => {
                              const next = bodyVars.filter((_, idx) => idx !== i);
                              updTmpl({ bodyVars: next.length ? next : [''] });
                            }} style={{ background:'var(--danger-light)', color:'var(--danger)', border:'none', borderRadius:6, padding:'6px 9px', cursor:'pointer', fontSize:12, flexShrink:0 }}>
                              ✕
                            </button>
                          </div>
                        ))}

                        <button onClick={() => updTmpl({ bodyVars: [...bodyVars, ''] })}
                          style={{ marginTop:2, background:'var(--green-light)', color:'var(--green)', border:'1px solid var(--green-mid)', borderRadius:7, padding:'5px 11px', fontSize:12, fontWeight:600, cursor:'pointer' }}>
                          + Variable
                        </button>
                      </div>
                    </div>
                  )}
                </div>
              </div>
            )}
          </div>

          {/* Status */}
          {cfg.pipelineId && cfg.stageId && (
            <div style={{ fontSize:12, color:'var(--green)', background:'var(--green-light)', borderRadius:8, padding:'8px 12px' }}>
              ✓ Pipeline configurado
              {reminderOn && cfg.reminderTemplate?.name
                ? ` · Recordatorio ${cfg.reminderHoursBefore || 0}h ${cfg.reminderMinutesBefore ? cfg.reminderMinutesBefore + 'min ' : ''}antes — template: ${cfg.reminderTemplate.name}`
                : reminderOn ? ' · Recordatorio activado (sin template)' : ''}
            </div>
          )}
        </div>
      )}
    </div>
  );
}

// ─── Agent Editor ─────────────────────────────────────────────────────────────
function AgentEditor({ agentId, onDelete }) {
  const { inboxes, pipelines } = usePipochat();
  const [agent, setAgent] = useState(null);
  const [saving, setSaving] = useState(false);
  const [saved, setSaved] = useState(false);
  const agentRef = useRef(null);
  const saveTimer = useRef(null);

  useEffect(() => {
    if (!agentId) { setAgent(null); return; }
    api.get(agentId).then(a => { setAgent(a); agentRef.current = a; setSaved(false); });
  }, [agentId]);

  const scheduleAutosave = (updated) => {
    agentRef.current = updated;
    clearTimeout(saveTimer.current);
    setSaved(false);
    saveTimer.current = setTimeout(async () => {
      if (!agentRef.current) return;
      setSaving(true);
      await api.update(agentRef.current.id, agentRef.current);
      setSaving(false); setSaved(true);
      setTimeout(() => setSaved(false), 2500);
    }, 1500);
  };

  const upd = (patch) => {
    setAgent(a => { const updated = { ...a, ...patch }; scheduleAutosave(updated); return updated; });
  };
  const updAction = (idx, action) => {
    setAgent(a => { const acts = [...a.actions]; acts[idx] = action; const updated = { ...a, actions: acts }; scheduleAutosave(updated); return updated; });
  };

  const handleDelete = async () => {
    if (!confirm(`¿Eliminar el agente "${agent.name}"?`)) return;
    await api.delete(agent.id);
    onDelete();
  };

  if (!agentId) return (
    <div style={{ ...S.editor, alignItems:'center', justifyContent:'center', color:'var(--muted)' }}>
      <span style={{ fontSize:48 }}>🤖</span>
      <p style={{ fontSize:14, marginTop:12 }}>Seleccioná un agente o creá uno nuevo</p>
    </div>
  );

  if (!agent) return (
    <div style={{ ...S.editor, alignItems:'center', justifyContent:'center', color:'var(--muted)' }}>
      Cargando…
    </div>
  );

  const followUp = agent.followUp || {};

  return (
    <div style={S.editor}>
      {/* Header */}
      <div style={{ display:'flex', alignItems:'flex-start', justifyContent:'space-between', gap:16 }}>
        <div style={{ flex:1 }}>
          <input
            style={{ fontSize:20, fontWeight:800, border:'none', background:'transparent', outline:'none', color:'var(--text)', width:'100%', padding:0 }}
            value={agent.name}
            onChange={e => upd({ name: e.target.value })}
            placeholder="Nombre del agente"
          />
          <input
            style={{ fontSize:13, color:'var(--muted)', border:'none', background:'transparent', outline:'none', width:'100%', padding:0, marginTop:3 }}
            value={agent.description || ''}
            onChange={e => upd({ description: e.target.value })}
            placeholder="Descripción corta (opcional)"
          />
        </div>
        <div style={{ display:'flex', alignItems:'center', gap:14, flexShrink:0 }}>
          {/* Modo Diego — switch (solo si el agente tiene diegoInstructions configuradas) */}
          {agent.diegoInstructions && (
            <div style={{ display:'flex', alignItems:'center', gap:6, fontSize:12, color:'var(--muted)', borderRight:'1px solid var(--border)', paddingRight:14 }}
                 title="Modo Diego: responde con el estilo de Diego y da precios/unidades/planos del KB. Apagado = modo conservador (deriva al asesor para precios).">
              <Toggle on={!!agent.diegoMode} onChange={v => upd({ diegoMode: v })} />
              <span style={{ whiteSpace:'nowrap' }}>{agent.diegoMode ? '🧑‍💼 Modo Diego' : '🛡️ Conservador'}</span>
            </div>
          )}
          {/* Bot conversacional toggle */}
          <div style={{ display:'flex', alignItems:'center', gap:6, fontSize:12, color:'var(--muted)', borderRight:'1px solid var(--border)', paddingRight:14 }}
               title="Cuando está apagado el agente sigue activo (acciones, Lead Ads) pero NO responde mensajes de WhatsApp">
            <Toggle
              on={agent.botEnabled !== false}
              onChange={v => upd({ botEnabled: v })}
            />
            <span style={{ whiteSpace:'nowrap' }}>
              {agent.botEnabled !== false ? '💬 Bot activo' : '🤫 Sin respuestas'}
            </span>
          </div>
          {/* Agente activo/inactivo */}
          <div style={{ display:'flex', alignItems:'center', gap:6, fontSize:12, color:'var(--muted)' }}>
            <Toggle on={agent.isActive} onChange={v => upd({ isActive: v })} />
            <span>{agent.isActive ? 'Activo' : 'Inactivo'}</span>
          </div>
          <span style={{ fontSize:12, color: saving ? 'var(--muted)' : saved ? 'var(--success)' : 'transparent' }}>
            {saving ? 'Guardando…' : '✓ Guardado'}
          </span>
        </div>
      </div>

      {/* Modo prueba — whitelist de números */}
      <div style={{ ...S.card, marginBottom:14, ...(agent.testMode ? { borderLeft:'4px solid #d97706' } : {}) }}>
        <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between', gap:12, marginBottom:4 }}>
          <div style={{ fontWeight:600, fontSize:13 }}>🧪 Modo prueba</div>
          <div style={{ display:'flex', alignItems:'center', gap:8, fontSize:12 }}>
            <Toggle on={!!agent.testMode} onChange={v => upd({ testMode: v })} />
            <span style={{ whiteSpace:'nowrap', fontWeight: agent.testMode ? 600 : 400, color: agent.testMode ? '#b45309' : 'var(--muted)' }}>
              {agent.testMode ? 'Activado' : 'Desactivado'}
            </span>
          </div>
        </div>
        <div style={{ fontSize:12, color:'var(--ink-4)', marginBottom:10, lineHeight:1.55 }}>
          Probá el bot antes del lanzamiento: con el modo prueba <b>activado</b>, el agente responde <b>solo</b> a los números de abajo
          e ignora al resto. Desactivalo para salir a producción (responde a todos) — sin borrar los números.
          <br />Formato: número con código de país (ej. <b>541140854992</b>). El <b>9</b> de celular argentino es opcional, funciona igual con o sin él.
        </div>
        <textarea
          style={{ ...S.textarea, minHeight:78, fontFamily:'monospace', fontSize:13 }}
          value={(agent.testWhitelist || []).join('\n')}
          onChange={e => upd({ testWhitelist: e.target.value.split('\n').map(s => s.trim()).filter(Boolean) })}
          placeholder={'Un número por línea, con código de país:\n5491140854992\n5491136458888'}
        />
        {agent.testMode && (agent.testWhitelist || []).length > 0 && (
          <div style={{ marginTop:10, fontSize:12.5, fontWeight:600, color:'#b45309', background:'#fffbeb', border:'1px solid #fcd34d', borderRadius:8, padding:'8px 12px' }}>
            🧪 Modo prueba activo — el bot responde solo a {(agent.testWhitelist || []).length} número{(agent.testWhitelist || []).length === 1 ? '' : 's'} e ignora a todos los demás.
          </div>
        )}
        {agent.testMode && (agent.testWhitelist || []).length === 0 && (
          <div style={{ marginTop:10, fontSize:12.5, fontWeight:600, color:'#b91c1c', background:'#fef2f2', border:'1px solid #fecaca', borderRadius:8, padding:'8px 12px' }}>
            ⚠️ Modo prueba activo pero sin números cargados: el bot no le responde a nadie. Agregá al menos un número para probar.
          </div>
        )}
        {!agent.testMode && (agent.testWhitelist || []).length > 0 && (
          <div style={{ marginTop:10, fontSize:12, color:'var(--ink-4)' }}>
            {(agent.testWhitelist || []).length} número{(agent.testWhitelist || []).length === 1 ? '' : 's'} guardado{(agent.testWhitelist || []).length === 1 ? '' : 's'}. El modo prueba está <b>desactivado</b> → el bot responde a todos (producción).
          </div>
        )}
      </div>

      {/* Motor conversacional — A/B Claude vs ChatGPT (experimental) */}
      <div style={{ ...S.card, marginBottom:14 }}>
        <div style={{ fontWeight:600, fontSize:13, marginBottom:4 }}>🧠 Motor conversacional <span style={{ fontWeight:400, color:'var(--muted)' }}>(experimental · A/B)</span></div>
        <div style={{ fontSize:12, color:'var(--ink-4)', marginBottom:10, lineHeight:1.55 }}>
          Elegí qué modelo redacta las respuestas. <b>Claude</b> es el de producción. <b>ChatGPT</b> es solo para probar la parte conversacional — usa las mismas instrucciones y herramientas. El etiquetado y las acciones de CRM no cambian.
        </div>
        <div style={{ display:'flex', gap:8 }}>
          {[{k:'claude',label:'🟣 Claude (default)'},{k:'gpt',label:'🟢 ChatGPT'}].map(o => {
            const active = String(agent.provider || 'claude').toLowerCase() === o.k;
            return (
              <button key={o.k}
                onClick={() => upd({ provider: o.k })}
                style={{ flex:1, padding:'9px 10px', borderRadius:8, fontSize:13, fontWeight:600, cursor:'pointer',
                         border: active ? '2px solid #2563eb' : '1px solid var(--border)',
                         background: active ? '#eff6ff' : 'transparent',
                         color: active ? '#2563eb' : 'var(--text)' }}>
                {o.label}
              </button>
            );
          })}
        </div>
        {String(agent.provider || 'claude').toLowerCase() === 'gpt' && (
          <div style={{ marginTop:10 }}>
            <label style={{ fontSize:12, color:'var(--muted)', display:'block', marginBottom:4 }}>Modelo de OpenAI</label>
            <select
              value={['gpt-5.5','gpt-5.4','gpt-5.4-mini','gpt-4o'].includes(agent.gptModel) ? agent.gptModel : (agent.gptModel ? '__other__' : '')}
              onChange={e => { if (e.target.value !== '__other__') upd({ gptModel: e.target.value }); }}
              style={{ width:'100%', padding:'9px 10px', borderRadius:8, border:'1px solid var(--border)', background:'var(--bg, #fff)', color:'var(--text)', outline:'none', fontSize:13, boxSizing:'border-box', cursor:'pointer' }}>
              <option value="">Elegí un modelo…</option>
              <option value="gpt-5.5">gpt-5.5 — flagship (recomendado)</option>
              <option value="gpt-5.4">gpt-5.4</option>
              <option value="gpt-5.4-mini">gpt-5.4-mini — rápido/barato</option>
              <option value="gpt-4o">gpt-4o</option>
              <option value="__other__">Otro (escribir abajo)…</option>
            </select>
            <input
              style={{ width:'100%', marginTop:6, padding:'7px 10px', borderRadius:8, border:'1px solid var(--border)', background:'transparent', color:'var(--muted)', outline:'none', fontFamily:'monospace', fontSize:12.5, boxSizing:'border-box' }}
              value={agent.gptModel || ''}
              onChange={e => upd({ gptModel: e.target.value.trim() })}
              placeholder="o escribí el id exacto (ej. gpt-5.5)"
            />
            <div style={{ marginTop:8, fontSize:12, color:'#b45309', background:'#fffbeb', border:'1px solid #fcd34d', borderRadius:8, padding:'8px 12px', lineHeight:1.5 }}>
              ⚠️ ChatGPT activo: las respuestas las redacta OpenAI (necesita OPENAI_API_KEY en el server). Para producción dejá <b>Claude</b>.
            </div>
          </div>
        )}
      </div>

      {/* Entrenadores — enseñar desde WhatsApp */}
      <div style={{ ...S.card, marginBottom:14 }}>
        <div style={{ fontWeight:600, fontSize:13, marginBottom:4 }}>👨‍🏫 Entrenadores — enseñar desde WhatsApp</div>
        <div style={{ fontSize:12, color:'var(--ink-4)', marginBottom:10, lineHeight:1.55 }}>
          Números autorizados a corregir al bot desde el chat. El entrenador escribe <b>/enseñar</b> seguido de la corrección
          (ej. <i>/enseñar la cuota se paga en 12 sin interés</i>) y el agente lo aprende y lo aplica de ahí en más.
          También sirve <b>/aprende</b> o <b>#corregir</b>. El bot confirma con “✅ Aprendido”.
        </div>
        <textarea
          style={{ ...S.textarea, minHeight:64, fontFamily:'monospace', fontSize:13 }}
          value={(agent.trainers || []).join('\n')}
          onChange={e => upd({ trainers: e.target.value.split('\n').map(s => s.trim()).filter(Boolean) })}
          placeholder={'Un número por línea, con código de país:\n5491140854992'}
        />
        {(agent.trainers || []).length > 0 && (
          <div style={{ marginTop:8, fontSize:12, color:'var(--ink-4)' }}>
            {(agent.trainers || []).length} entrenador{(agent.trainers || []).length === 1 ? '' : 'es'} autorizado{(agent.trainers || []).length === 1 ? '' : 's'}.
          </div>
        )}
      </div>

      {/* Toolset selector */}
      <div style={{ ...S.card, marginBottom:14 }}>
        <div style={{ fontWeight:600, fontSize:13, marginBottom:4 }}>🤖 Tipo de agente</div>
        <div style={{ fontSize:12, color:'var(--ink-4)', marginBottom:12 }}>Define qué puede hacer el agente en las conversaciones</div>
        <div style={{ display:'flex', gap:10, flexWrap:'wrap' }}>
          {[
            { value: 'default',    label: '💬 General', desc: 'Responde consultas, gestiona contactos, crea leads y ejecuta acciones automáticas' },
            { value: 'properties', label: '🏠 Inmobiliario', desc: 'Todo lo anterior + puede buscar propiedades en Tokko y compartirlas en el chat' },
          ].map(opt => {
            const active = (agent.toolset || 'default') === opt.value;
            return (
              <div key={opt.value} onClick={() => upd({ toolset: opt.value })}
                style={{ flex:'1 1 200px', border:`2px solid ${active ? 'var(--green)' : 'var(--border)'}`, borderRadius:10,
                  padding:'12px 16px', cursor:'pointer', background: active ? '#f0fdf4' : 'var(--white)',
                  transition:'border-color .15s, background .15s' }}>
                <div style={{ fontWeight:600, fontSize:13, color: active ? 'var(--green)' : 'var(--ink)', marginBottom:4 }}>{opt.label}</div>
                <div style={{ fontSize:12, color:'var(--ink-4)', lineHeight:1.4 }}>{opt.desc}</div>
              </div>
            );
          })}
        </div>
        {(agent.toolset === 'properties') && (
          <div style={{ marginTop:10, fontSize:12, color:'var(--ink-3)', background:'var(--cream)', borderRadius:8, padding:'8px 12px' }}>
            💡 Usará IA avanzada cuando detecte consultas sobre propiedades, y el modelo estándar para conversación — optimizando el costo automáticamente.
          </div>
        )}
      </div>

      {/* Conversion stages for CTWA analytics — one per pipeline */}
      {(() => {
        // Normalize: merge legacy single-stage field into the array
        const stages = (() => {
          const arr = agent.conversionStages ? [...agent.conversionStages] : [];
          if (agent.conversionStageId && !arr.some(s => s.stageId === agent.conversionStageId)) {
            arr.unshift({ pipelineId: agent.conversionPipelineId || '', stageId: agent.conversionStageId });
          }
          return arr;
        })();

        const updateStages = (newStages) => upd({ conversionStages: newStages, conversionStageId: undefined, conversionPipelineId: undefined });

        const addRow    = () => updateStages([...stages, { pipelineId: '', stageId: '' }]);
        const removeRow = (i) => updateStages(stages.filter((_, idx) => idx !== i));
        const setRow    = (i, patch) => {
          const next = stages.map((r, idx) => idx === i ? { ...r, ...patch } : r);
          updateStages(next);
        };

        return (
          <div style={S.card}>
            <div style={S.cardTitle}>📊 Etapas de conversión (CTWA)</div>
            <div style={S.cardDesc}>Definí qué etapa de cada pipeline representa una conversión. Podés agregar una por pipeline.</div>

            {stages.length === 0 && (
              <div style={{ fontSize:12, color:'var(--ink-4)', marginBottom:12 }}>
                No hay etapas configuradas — agregá al menos una para ver métricas de conversión.
              </div>
            )}

            {stages.map((row, i) => {
              const pipelineStages = (pipelines.find(p => p._id === row.pipelineId)?.stages || []);
              return (
                <div key={i} style={{ display:'flex', gap:8, alignItems:'flex-end', marginBottom:8, flexWrap:'wrap' }}>
                  <div style={{ flex:1, minWidth:150 }}>
                    {i === 0 && <div style={{ fontSize:11, color:'var(--ink-4)', marginBottom:4 }}>Pipeline</div>}
                    <select style={S.select} value={row.pipelineId || ''}
                      onChange={e => setRow(i, { pipelineId: e.target.value, stageId: '' })}>
                      <option value=''>— Pipeline —</option>
                      {pipelines.map(p => <option key={p._id} value={p._id}>{p.title || p.name}</option>)}
                    </select>
                  </div>
                  <div style={{ flex:1, minWidth:150 }}>
                    {i === 0 && <div style={{ fontSize:11, color:'var(--ink-4)', marginBottom:4 }}>Etapa de conversión</div>}
                    <select style={S.select} value={row.stageId || ''}
                      onChange={e => setRow(i, { stageId: e.target.value })}
                      disabled={!row.pipelineId}>
                      <option value=''>— Etapa —</option>
                      {pipelineStages.map(s => <option key={s._id} value={s._id}>{s.name}</option>)}
                    </select>
                  </div>
                  <button onClick={() => removeRow(i)}
                    style={{ background:'var(--danger-light)', color:'var(--danger)', border:'none', borderRadius:8, padding:'8px 12px', fontSize:13, cursor:'pointer', flexShrink:0, marginBottom:1 }}>
                    ✕
                  </button>
                </div>
              );
            })}

            <button onClick={addRow}
              style={{ marginTop:4, background:'var(--green-light)', color:'var(--green)', border:'1px solid var(--green-mid)', borderRadius:8, padding:'7px 14px', fontSize:13, fontWeight:600, cursor:'pointer' }}>
              + Agregar pipeline
            </button>

            {stages.some(s => s.stageId) && (
              <div style={{ marginTop:10, fontSize:12, color:'var(--green)', background:'var(--green-light)', borderRadius:8, padding:'8px 12px' }}>
                ✓ {stages.filter(s => s.stageId).length} etapa{stages.filter(s => s.stageId).length > 1 ? 's' : ''} de conversión configurada{stages.filter(s => s.stageId).length > 1 ? 's' : ''}
              </div>
            )}
          </div>
        );
      })()}

      {/* Reservation management */}
      <ReservationConfigCard
        config={agent.reservationConfig || {}}
        onChange={v => upd({ reservationConfig: v })}
        pipelines={pipelines}
      />

      {/* Inbox / Line assignment */}
      <InboxSelector
        inboxes={inboxes}
        selected={agent.inboxIds || []}
        onChange={ids => upd({ inboxIds: ids })}
      />

      {/* Instructions */}
      <div style={S.card}>
        <div style={S.cardTitle}>📝 Instrucciones del agente</div>
        <div style={S.cardDesc}>Definí la personalidad, el rol y las reglas del agente. Escribí en primera persona como si le hablaras directamente.</div>
        <textarea
          style={S.textarea}
          value={agent.instructions || ''}
          onChange={e => upd({ instructions: e.target.value })}
          placeholder={`Sos un asistente de ventas de ${agent.name}. Tu objetivo es ayudar a los clientes, responder consultas y calificar leads.\n\nSiempre respondé en español, con un tono amigable y profesional. Si el cliente muestra interés en comprar, recopilá su nombre, presupuesto y zona antes de derivar al equipo de ventas.`}
        />
      </div>

      {/* Follow-up */}
      <FollowUpCard key={agent.id} followUp={followUp} onChange={v => upd({ followUp: v })} />

      {/* Actions by group — always show all action types, merge saved config with defaults */}
      {ACTION_GROUPS.map(group => {
        const savedActions = agent.actions || [];
        const groupActions = group.keys.map(key => {
          const saved = savedActions.find(a => a.type === key);
          return saved || { type: key, enabled: false, config: {} };
        });
        return (
          <div key={group.title} style={S.card}>
            <div style={S.cardTitle}>⚡ {group.title}</div>
            <div>
              {groupActions.map(action => {
                const idx = savedActions.findIndex(a => a.type === action.type);
                const handleChange = (a) => {
                  if (idx >= 0) {
                    updAction(idx, a);
                  } else {
                    upd({ actions: [...savedActions, a] });
                  }
                };
                return <ActionCard key={action.type} action={action} onChange={handleChange} />;
              })}
            </div>
          </div>
        );
      })}

      {/* Danger */}
      <div style={{ ...S.card, borderColor:'#fee2e2', marginBottom:40 }}>
        <div style={{ ...S.cardTitle, color:'var(--danger)' }}>⚠️ Zona peligrosa</div>
        <div style={S.cardDesc}>Eliminar el agente no se puede deshacer.</div>
        <button style={S.dangerBtn} onClick={handleDelete}>Eliminar agente</button>
      </div>
    </div>
  );
}

// ─── New Agent Modal ──────────────────────────────────────────────────────────
function NewAgentModal({ onClose, onCreate }) {
  const [name, setName] = useState('');
  const [desc, setDesc] = useState('');
  const [instructions, setInstructions] = useState('');

  const submit = async () => {
    if (!name.trim()) return;
    const agent = await api.create({ name: name.trim(), description: desc.trim(), instructions: instructions.trim() });
    onCreate(agent); onClose();
  };

  return (
    <div style={{ position:'fixed', inset:0, background:'rgba(0,0,0,.45)', display:'flex', alignItems:'center', justifyContent:'center', zIndex:100 }} onClick={onClose}>
      <div style={{ background:'var(--surface)', borderRadius:14, padding:'28px 32px', width:520, boxShadow:'var(--shadow-lg)', display:'flex', flexDirection:'column', gap:18 }} onClick={e => e.stopPropagation()}>
        <div style={{ fontSize:18, fontWeight:800 }}>Nuevo agente</div>
        <Field label="Nombre *">
          <input style={S.input} value={name} onChange={e => setName(e.target.value)} placeholder="ej: Agente de Ventas" autoFocus />
        </Field>
        <Field label="Descripción (opcional)">
          <input style={S.input} value={desc} onChange={e => setDesc(e.target.value)} placeholder="ej: Califica leads y responde consultas de precios" />
        </Field>
        <Field label="Instrucciones iniciales">
          <textarea style={{ ...S.textarea, minHeight:90 }} value={instructions} onChange={e => setInstructions(e.target.value)} placeholder="Sos un asistente de ventas. Tu objetivo es..." />
        </Field>
        <div style={{ display:'flex', gap:10, justifyContent:'flex-end' }}>
          <button style={S.dangerBtn} onClick={onClose}>Cancelar</button>
          <button style={S.saveBtn} onClick={submit} disabled={!name.trim()}>Crear agente</button>
        </div>
      </div>
    </div>
  );
}

// ─── Knowledge Base Panel ─────────────────────────────────────────────────────
function KBPanel() {
  const [files, setFiles] = useState([]);
  const [uploading, setUploading] = useState(false);
  const [msg, setMsg] = useState('');
  const [preview, setPreview] = useState(null);
  const [urlInput, setUrlInput] = useState('');
  const [urlName, setUrlName] = useState('');
  const [fetchingUrl, setFetchingUrl] = useState(false);
  const fileRef = useRef();

  const loadFiles = () => apiFetch('/api/kb').then(r => r.json()).then(setFiles).catch(() => {});
  useEffect(() => { loadFiles(); }, []);

  const handleFile = (e) => {
    const file = e.target.files[0];
    if (!file) return;
    if (!file.name.match(/\.(txt|md)$/i)) { setMsg('❌ Solo se permiten archivos .txt y .md'); return; }
    const reader = new FileReader();
    reader.onload = async (ev) => {
      setUploading(true); setMsg('');
      try {
        const res = await apiFetch('/api/kb/upload', {
          method:'POST', headers:{'Content-Type':'application/json'},
          body: JSON.stringify({ filename: file.name, content: ev.target.result }),
        });
        const data = await res.json();
        if (data.success) { setMsg(`✅ "${file.name}" subido correctamente`); loadFiles(); }
        else setMsg('❌ Error: ' + (data.error || 'desconocido'));
      } catch (err) { setMsg('❌ ' + err.message); }
      finally { setUploading(false); e.target.value = ''; }
    };
    reader.readAsText(file);
  };

  const handleUrl = async () => {
    if (!urlInput.trim()) return;
    setFetchingUrl(true); setMsg('');
    try {
      const res = await apiFetch('/api/kb/url', {
        method: 'POST', headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ url: urlInput.trim(), name: urlName.trim() || undefined }),
      });
      const data = await res.json();
      if (data.success) {
        setMsg(`✅ "${data.filename}" importado (${(data.size/1024).toFixed(0)} KB de texto)`);
        setUrlInput(''); setUrlName('');
        loadFiles();
      } else setMsg('❌ ' + (data.error || 'Error desconocido'));
    } catch (err) { setMsg('❌ ' + err.message); }
    finally { setFetchingUrl(false); }
  };

  const deleteFile = async (name) => {
    if (!confirm(`¿Eliminar "${name}"?`)) return;
    await apiFetch(`/api/kb/${encodeURIComponent(name)}`, { method:'DELETE' });
    if (preview?.name === name) setPreview(null);
    loadFiles();
  };

  const showPreview = async (name) => {
    if (preview?.name === name) { setPreview(null); return; }
    const res = await apiFetch(`/api/kb/${encodeURIComponent(name)}`);
    const data = await res.json();
    setPreview(data);
  };

  return (
    <div style={{ ...S.editor }}>
      <div>
        <div style={S.pageTitle}>📚 Base de conocimiento</div>
        <div style={S.pageSubtitle}>Documentos que el agente usa para responder sobre tus productos, servicios y precios.</div>
      </div>

      <div style={S.card}>
        <div style={S.cardTitle}>Subir documento</div>
        <div style={S.cardDesc}>
          Subí archivos .txt o .md con información de tu negocio: lista de productos, precios, preguntas frecuentes, procedimientos, etc.<br/>
          El agente busca automáticamente en estos documentos antes de responder.
        </div>
        <input ref={fileRef} type="file" accept=".txt,.md" style={{ display:'none' }} onChange={handleFile} />
        <button style={S.saveBtn} onClick={() => fileRef.current.click()} disabled={uploading}>
          {uploading ? 'Subiendo…' : '⬆️  Subir archivo .txt / .md'}
        </button>
        {msg && <div style={{ marginTop:10, fontSize:13, color: msg.startsWith('✅') ? 'var(--success)' : 'var(--danger)' }}>{msg}</div>}
      </div>

      <div style={S.card}>
        <div style={S.cardTitle}>🌐 Importar desde URL</div>
        <div style={S.cardDesc}>
          Pegá la URL de una página web, Google Doc público, Notion, o cualquier sitio. El agente extrae el texto y lo usa como conocimiento.
        </div>
        <div style={{ display:'flex', flexDirection:'column', gap:8, marginTop:4 }}>
          <input
            style={S.input}
            placeholder="https://mi-sitio.com/productos"
            value={urlInput}
            onChange={e => setUrlInput(e.target.value)}
            onKeyDown={e => e.key === 'Enter' && handleUrl()}
          />
          <div style={{ display:'flex', gap:8 }}>
            <input
              style={{ ...S.input, flex:1 }}
              placeholder="Nombre del documento (opcional)"
              value={urlName}
              onChange={e => setUrlName(e.target.value)}
            />
            <button style={{ ...S.saveBtn, whiteSpace:'nowrap' }} onClick={handleUrl} disabled={fetchingUrl || !urlInput.trim()}>
              {fetchingUrl ? 'Importando…' : '⬇️  Importar URL'}
            </button>
          </div>
        </div>
      </div>

      <div style={S.card}>
        <div style={{ display:'flex', justifyContent:'space-between', alignItems:'center', marginBottom:4 }}>
          <div style={S.cardTitle}>Documentos cargados ({files.filter(f=>f.enabled).length}/{files.length} activos)</div>
        </div>
        {files.length === 0 ? (
          <div style={{ fontSize:13, color:'var(--muted)', padding:'16px 0', textAlign:'center' }}>
            <span style={{ fontSize:32, display:'block', marginBottom:8 }}>📂</span>
            Sin documentos aún. Subí tu primer archivo para que el agente pueda usarlo.
          </div>
        ) : (
          <div style={{ display:'flex', flexDirection:'column', gap:8, marginTop:8 }}>
            {files.map(f => (
              <div key={f.name}>
                <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between', padding:'12px 14px', background: f.enabled ? '#f9fafb' : '#f3f4f6', borderRadius:8, border:`1px solid ${f.enabled ? 'var(--border)' : '#e5e7eb'}`, opacity: f.enabled ? 1 : 0.6 }}>
                  <div style={{ flex:1 }}>
                    <div style={{ fontSize:14, fontWeight:600 }}>📄 {f.name}</div>
                    <div style={{ fontSize:11, color:'var(--muted)', marginTop:1 }}>{(f.size / 1024).toFixed(1)} KB · {new Date(f.updatedAt).toLocaleDateString('es-AR')} · <span style={{ color: f.enabled ? 'var(--success)' : 'var(--muted)' }}>{f.enabled ? 'Activo' : 'Desactivado'}</span></div>
                  </div>
                  <div style={{ display:'flex', gap:8, alignItems:'center' }}>
                    <button onClick={() => showPreview(f.name)} style={{ background:'none', border:'none', color:'var(--primary)', fontSize:13, cursor:'pointer', fontWeight:600 }}>
                      {preview?.name === f.name ? 'Cerrar' : 'Ver'}
                    </button>
                    {/* Toggle */}
                    <div onClick={async () => {
                      const newEnabled = !f.enabled;
                      await apiFetch(`/api/kb/${encodeURIComponent(f.name)}/enabled`, {
                        method:'PATCH', headers:{'Content-Type':'application/json'},
                        body: JSON.stringify({ enabled: newEnabled }),
                      });
                      setFiles(prev => prev.map(x => x.name === f.name ? { ...x, enabled: newEnabled } : x));
                    }} style={{ width:40, height:22, borderRadius:11, background: f.enabled ? 'var(--primary)' : '#d1d5db', cursor:'pointer', position:'relative', transition:'background 0.2s', flexShrink:0 }}>
                      <div style={{ position:'absolute', top:3, left: f.enabled ? 21 : 3, width:16, height:16, borderRadius:'50%', background:'#fff', transition:'left 0.2s' }} />
                    </div>
                    <button onClick={() => deleteFile(f.name)} style={{ background:'none', border:'none', color:'var(--danger)', fontSize:13, cursor:'pointer', fontWeight:600 }}>Eliminar</button>
                  </div>
                </div>
                {preview?.name === f.name && (
                  <div style={{ background:'#f0f9ff', border:'1px solid #bae6fd', borderRadius:8, padding:'14px', marginTop:4 }}>
                    <pre style={{ fontSize:11, color:'#0c4a6e', whiteSpace:'pre-wrap', wordBreak:'break-word', margin:0, maxHeight:300, overflowY:'auto' }}>{preview.content}</pre>
                  </div>
                )}
              </div>
            ))}
          </div>
        )}
      </div>
    </div>
  );
}

// ─── Tags Panel ───────────────────────────────────────────────────────────────
function TagsPanel() {
  const { tags: pipochatTags, connected } = usePipochat();
  const [registry, setRegistry] = useState({});
  const [saving, setSaving] = useState(false);
  const [msg, setMsg] = useState('');

  useEffect(() => {
    apiFetch('/api/tag-registry').then(r => r.json()).then(setRegistry).catch(() => {});
  }, []);

  const syncFromPipochat = async () => {
    if (!pipochatTags.length) return;
    const toAdd = {};
    pipochatTags.forEach(t => { if (!registry[t.name]) toAdd[t.name] = t._id; });
    if (Object.keys(toAdd).length === 0) { setMsg('✅ Ya están sincronizadas'); setTimeout(() => setMsg(''), 2000); return; }
    const updated = { ...registry, ...toAdd };
    setSaving(true);
    const res = await apiFetch('/api/tag-registry', { method:'PUT', headers:{'Content-Type':'application/json'}, body: JSON.stringify(updated) });
    const data = await res.json();
    if (data.success) { setRegistry(data.registry); setMsg(`✅ ${Object.keys(toAdd).length} etiqueta(s) importadas de Pipochat`); setTimeout(() => setMsg(''), 3000); }
    setSaving(false);
  };

  const removeTag = async (name) => {
    const updated = { ...registry }; delete updated[name];
    await apiFetch('/api/tag-registry', { method:'PUT', headers:{'Content-Type':'application/json'}, body: JSON.stringify(updated) });
    setRegistry(updated);
  };

  const [newName, setNewName] = useState('');
  const [newId, setNewId] = useState('');
  const addTag = async () => {
    if (!newName.trim() || !newId.trim()) return;
    const updated = { ...registry, [newName.trim()]: newId.trim() };
    setSaving(true);
    const res = await apiFetch('/api/tag-registry', { method:'PUT', headers:{'Content-Type':'application/json'}, body: JSON.stringify(updated) });
    const data = await res.json();
    if (data.success) { setRegistry(data.registry); setNewName(''); setNewId(''); setMsg('✅ Guardado'); setTimeout(() => setMsg(''), 2000); }
    setSaving(false);
  };

  return (
    <div style={{ ...S.editor }}>
      <div>
        <div style={S.pageTitle}>🏷️ Etiquetas</div>
        <div style={S.pageSubtitle}>Registrá las etiquetas que usás para clasificar contactos. El agente las aplica automáticamente durante las conversaciones según el contexto.</div>
      </div>

      {connected && pipochatTags.length > 0 && (
        <div style={S.card}>
          <div style={S.cardTitle}>Importar desde Pipochat</div>
          <div style={S.cardDesc}>
            Tenés <strong>{pipochatTags.length} etiquetas</strong> en Pipochat. Podés importarlas todas de una vez.
          </div>
          <div style={{ display:'flex', flexWrap:'wrap', gap:6, marginBottom:14 }}>
            {pipochatTags.map(t => (
              <span key={t._id} style={{ ...S.badge(registry[t.name] ? 'var(--success)' : 'var(--primary)') }}>
                {registry[t.name] ? '✓ ' : ''}{t.name}
              </span>
            ))}
          </div>
          <button style={S.saveBtn} onClick={syncFromPipochat} disabled={saving}>
            {saving ? 'Importando…' : '⬇️  Importar todas las etiquetas'}
          </button>
          {msg && <div style={{ marginTop:8, fontSize:13, color:'var(--success)' }}>{msg}</div>}
        </div>
      )}


      <div style={S.card}>
        <div style={S.cardTitle}>Agregar etiqueta manualmente</div>
        <div style={S.cardDesc}>Si ya existe en Pipochat, ingresá su nombre y el ID.</div>
        <div style={{ display:'flex', gap:10 }}>
          <input style={{ ...S.input, flex:1 }} value={newName} onChange={e => setNewName(e.target.value)} placeholder='Nombre (ej: "calificado")' />
          <input style={{ ...S.input, flex:2 }} value={newId} onChange={e => setNewId(e.target.value)} placeholder="ID de Pipochat (ej: 69bfef…)" />
          <button style={S.saveBtn} onClick={addTag} disabled={saving || !newName || !newId}>Agregar</button>
        </div>
        {!connected && <div style={{ marginTop:8, fontSize:12, color:'var(--muted)' }}>💡 Tip: si Pipochat está conectado, podés usar el botón de importar arriba.</div>}
        {msg && !connected && <div style={{ marginTop:8, fontSize:13, color:'var(--success)' }}>{msg}</div>}
      </div>

      <div style={S.card}>
        <div style={S.cardTitle}>Etiquetas configuradas ({Object.keys(registry).length})</div>
        {Object.keys(registry).length === 0 ? (
          <div style={{ fontSize:13, color:'var(--muted)', padding:'12px 0' }}>Sin etiquetas configuradas aún.</div>
        ) : (
          <div style={{ display:'flex', flexDirection:'column', gap:8, marginTop:8 }}>
            {Object.entries(registry).map(([name, id]) => (
              <div key={name} style={{ display:'flex', alignItems:'center', justifyContent:'space-between', padding:'10px 14px', background:'#f9fafb', borderRadius:8, border:'1px solid var(--border)' }}>
                <div>
                  <div style={{ fontSize:14, fontWeight:600 }}>🏷️ {name}</div>
                  <div style={{ fontSize:11, color:'var(--muted)', fontFamily:'monospace', marginTop:1 }}>{id}</div>
                </div>
                <button onClick={() => removeTag(name)} style={{ background:'none', border:'none', color:'var(--danger)', fontSize:13, cursor:'pointer', fontWeight:600 }}>Quitar</button>
              </div>
            ))}
          </div>
        )}
      </div>
    </div>
  );
}

// ─── Nurturing Panel ──────────────────────────────────────────────────────────

const CONDITION_TYPES = [
  { v:'days_in_stage',      label:'Lead lleva X+ días en etapa' },
  { v:'lead_in_stage',      label:'Lead está en etapa (exacto)' },
  { v:'days_since_created', label:'Lead creado hace X+ días' },
  { v:'has_tag',            label:'Contacto tiene etiqueta' },
  { v:'missing_tag',        label:'Contacto NO tiene etiqueta' },
  { v:'has_attribute',      label:'Atributo del contacto = valor' },
  { v:'attribute_gte',      label:'Atributo del contacto ≥ número' },
];

const ACTION_TYPES_NURTURING = [
  { v:'send_text',         label:'💬 Enviar mensaje de texto' },
  { v:'send_interactive',  label:'🔘 Enviar botones interactivos' },
  { v:'send_template',     label:'📋 Enviar template de WhatsApp' },
  { v:'add_tag',           label:'🏷️ Agregar etiqueta' },
  { v:'move_stage',        label:'➡️ Mover a otra etapa' },
  { v:'send_meeting_link', label:'📅 Enviar link de agenda' },
  { v:'assign_operator',   label:'👨‍💼 Asignar a operador' },
  { v:'assign_team',       label:'👥 Asignar a equipo' },
  { v:'notify_operator',   label:'📲 Notificar operador por WhatsApp' },
];

function ConditionEditor({ cond, onChange, onRemove }) {
  const { pipelines, tags, connected } = usePipochat();
  const allStages = pipelines.flatMap(p => (p.stages||[]).map(s => ({ ...s, pipelineTitle: p.title })));

  return (
    <div style={{ display:'flex', gap:8, alignItems:'flex-start', background:'#f9fafb', padding:10, borderRadius:8, border:'1px solid var(--border)' }}>
      <div style={{ flex:1, display:'flex', flexDirection:'column', gap:8 }}>
        <select style={S.select} value={cond.type} onChange={e => onChange({ ...cond, type: e.target.value })}>
          {CONDITION_TYPES.map(t => <option key={t.v} value={t.v}>{t.label}</option>)}
        </select>

        {(cond.type === 'days_in_stage' || cond.type === 'lead_in_stage') && (
          <div style={S.row}>
            <div style={S.col}>
              <label style={S.label}>Etapa</label>
              <select style={S.select} value={cond.stageId||''} onChange={e => onChange({ ...cond, stageId: e.target.value })}>
                <option value="">— Cualquier etapa —</option>
                {pipelines.map(p => (
                  <optgroup key={p._id} label={p.title}>
                    {(p.stages||[]).sort((a,b)=>a.orderIndex-b.orderIndex).map(s => (
                      <option key={s._id} value={s._id}>{s.displayName||s.name}</option>
                    ))}
                  </optgroup>
                ))}
              </select>
            </div>
            {cond.type === 'days_in_stage' && (
              <div style={S.col}>
                <label style={S.label}>Días mínimos</label>
                <input style={S.input} type="number" min="1" value={cond.days||3}
                  onChange={e => onChange({ ...cond, days: Number(e.target.value) })} />
              </div>
            )}
          </div>
        )}

        {cond.type === 'days_since_created' && (
          <Field label="Días desde creación">
            <input style={S.input} type="number" min="1" value={cond.days||7}
              onChange={e => onChange({ ...cond, days: Number(e.target.value) })} />
          </Field>
        )}

        {(cond.type === 'has_tag' || cond.type === 'missing_tag') && (
          <Field label="Etiqueta">
            {connected && tags.length > 0
              ? <select style={S.select} value={cond.tagName||''} onChange={e => onChange({ ...cond, tagName: e.target.value })}>
                  <option value="">— Seleccionar —</option>
                  {tags.map(t => <option key={t._id} value={t.name}>{t.name}</option>)}
                </select>
              : <input style={S.input} value={cond.tagName||''} onChange={e => onChange({ ...cond, tagName: e.target.value })} placeholder="Nombre de la etiqueta" />
            }
          </Field>
        )}

        {(cond.type === 'has_attribute' || cond.type === 'attribute_gte') && (
          <div style={S.row}>
            <Field label="Clave del atributo">
              <input style={S.input} value={cond.attributeKey||''} onChange={e => onChange({ ...cond, attributeKey: e.target.value })} placeholder="ej: agentes" />
            </Field>
            <Field label={cond.type === 'attribute_gte' ? 'Valor mínimo (número)' : 'Valor exacto (opcional)'}>
              <input style={S.input} value={cond.attributeValue||''} onChange={e => onChange({ ...cond, attributeValue: e.target.value })} placeholder={cond.type === 'attribute_gte' ? '5' : 'ej: Business'} />
            </Field>
          </div>
        )}
      </div>
      <button style={{ ...S.ghostBtn, marginTop:2 }} onClick={onRemove}>×</button>
    </div>
  );
}

function ActionEditor({ action, onChange }) {
  const { pipelines, tags, users, teams, templates, meetings, connected } = usePipochat();
  const allStages = pipelines.flatMap(p => (p.stages||[]).map(s => ({ ...s, pipelineTitle: p.title })));

  return (
    <div style={{ display:'flex', flexDirection:'column', gap:12 }}>
      <Field label="Tipo de acción">
        <select style={S.select} value={action.type} onChange={e => onChange({ ...action, type: e.target.value })}>
          {ACTION_TYPES_NURTURING.map(t => <option key={t.v} value={t.v}>{t.label}</option>)}
        </select>
      </Field>

      {action.type === 'send_text' && (
        <Field label="Mensaje (podés usar {{name}} y {{stage}})">
          <textarea style={{ ...S.textarea, minHeight:80 }} value={action.message||''} onChange={e => onChange({ ...action, message: e.target.value })}
            placeholder="Hola {{name}}! Te escribo porque estás evaluando nuestros planes. ¿Pudiste revisar la info? 😊" />
        </Field>
      )}

      {action.type === 'send_interactive' && (
        <Field label="Mensaje interactivo con botones">
          <InteractiveMessageBuilder
            value={action.interactive}
            onChange={iv => onChange({ ...action, interactive: iv })} />
        </Field>
      )}

      {action.type === 'send_template' && (
        <Field label="Template de WhatsApp">
          {connected && templates.length > 0
            ? <select style={S.select} value={action.templateId||''} onChange={e => onChange({ ...action, templateId: e.target.value })}>
                <option value="">— Seleccionar template —</option>
                {templates.map(t => <option key={t._id} value={t._id}>{t.name}</option>)}
              </select>
            : <input style={S.input} value={action.templateId||''} onChange={e => onChange({ ...action, templateId: e.target.value })} placeholder="ID del template aprobado" />
          }
        </Field>
      )}

      {action.type === 'add_tag' && (
        <Field label="Etiqueta a agregar">
          {connected && tags.length > 0
            ? <select style={S.select} value={action.tagName||''} onChange={e => onChange({ ...action, tagName: e.target.value })}>
                <option value="">— Seleccionar —</option>
                {tags.map(t => <option key={t._id} value={t.name}>{t.name}</option>)}
              </select>
            : <input style={S.input} value={action.tagName||''} onChange={e => onChange({ ...action, tagName: e.target.value })} placeholder="Nombre de la etiqueta" />
          }
        </Field>
      )}

      {action.type === 'move_stage' && (
        <Field label="Mover a etapa">
          <select style={S.select} value={action.stageId||''} onChange={e => onChange({ ...action, stageId: e.target.value })}>
            <option value="">— Seleccionar etapa —</option>
            {pipelines.map(p => (
              <optgroup key={p._id} label={p.title}>
                {(p.stages||[]).sort((a,b)=>a.orderIndex-b.orderIndex).map(s => (
                  <option key={s._id} value={s._id}>{s.displayName||s.name}</option>
                ))}
              </optgroup>
            ))}
          </select>
        </Field>
      )}

      {action.type === 'send_meeting_link' && (
        <>
          <Field label="Agenda">
            {connected && meetings.length > 0
              ? <select style={S.select} value={action.meetingId||''} onChange={e => onChange({ ...action, meetingId: e.target.value })}>
                  <option value="">— Seleccionar —</option>
                  {meetings.map(m => <option key={m._id} value={m._id}>{m.name||m.slug||m._id}</option>)}
                </select>
              : <input style={S.input} value={action.meetingId||''} onChange={e => onChange({ ...action, meetingId: e.target.value })} placeholder="ID de la agenda" />
            }
          </Field>
          <Field label="Mensaje (usá {{meeting_link}} para el link)">
            <textarea style={{ ...S.textarea, minHeight:70 }} value={action.message||''} onChange={e => onChange({ ...action, message: e.target.value })}
              placeholder="{{name}}, acá te comparto el link para que elijas el horario: {{meeting_link}}" />
          </Field>
        </>
      )}

      {action.type === 'assign_operator' && (
        <Field label="Operador">
          {connected && users.length > 0
            ? <select style={S.select} value={action.operatorId||''} onChange={e => onChange({ ...action, operatorId: e.target.value })}>
                <option value="">— Seleccionar operador —</option>
                {users.map(u => <option key={u._id} value={u._id}>{u.name}</option>)}
              </select>
            : <input style={S.input} value={action.operatorId||''} onChange={e => onChange({ ...action, operatorId: e.target.value })} placeholder="ID del operador" />
          }
        </Field>
      )}

      {action.type === 'assign_team' && (
        <Field label="Equipo">
          {connected && teams.length > 0
            ? <select style={S.select} value={action.teamId||''} onChange={e => onChange({ ...action, teamId: e.target.value })}>
                <option value="">— Seleccionar equipo —</option>
                {teams.map(t => <option key={t._id} value={t._id}>{t.name}</option>)}
              </select>
            : <input style={S.input} value={action.teamId||''} onChange={e => onChange({ ...action, teamId: e.target.value })} placeholder="ID del equipo" />
          }
        </Field>
      )}

      {action.type === 'notify_operator' && (
        <>
          <Field label="Operador a notificar">
            {connected && users.length > 0
              ? <select style={S.select} value={action.operatorId||''} onChange={e => onChange({ ...action, operatorId: e.target.value })}>
                  <option value="">— Seleccionar operador —</option>
                  {users.map(u => <option key={u._id} value={u._id}>{u.name}</option>)}
                </select>
              : <input style={S.input} value={action.operatorPhone||''} onChange={e => onChange({ ...action, operatorPhone: e.target.value })} placeholder="+5491112345678" />
            }
          </Field>
          <Field label="Mensaje de notificación">
            <textarea style={{ ...S.textarea, minHeight:70 }} value={action.message||''} onChange={e => onChange({ ...action, message: e.target.value })}
              placeholder="🔔 {{name}} lleva {{days}} días sin avanzar en el pipeline. Revisá la oportunidad." />
            <div style={{ fontSize:11, color:'var(--muted)', marginTop:3 }}>Variables: {'{{name}}'}, {'{{stage}}'}, {'{{days}}'}.</div>
          </Field>
        </>
      )}
    </div>
  );
}

const EMPTY_RULE = {
  name: '',
  enabled: false,
  pipelineId: '',
  conditionOperator: 'AND',
  conditions: [],
  action: { type: 'send_text', message: '' },
  cooldownDays: 7,
  maxFires: 1,
};

function RuleModal({ rule, onClose, onSave }) {
  const { pipelines } = usePipochat();
  const [draft, setDraft] = useState(rule ? { ...rule } : { ...EMPTY_RULE });
  const [saving, setSaving] = useState(false);

  const upd = (patch) => setDraft(d => ({ ...d, ...patch }));
  const updCond = (i, c) => setDraft(d => { const cs = [...d.conditions]; cs[i] = c; return { ...d, conditions: cs }; });
  const removeCond = (i) => setDraft(d => ({ ...d, conditions: d.conditions.filter((_,j)=>j!==i) }));
  const addCond = () => setDraft(d => ({ ...d, conditions: [...d.conditions, { type:'days_in_stage', stageId:'', days:3 }] }));

  const save = async () => {
    if (!draft.name.trim()) return;
    setSaving(true);
    try {
      const method = rule ? 'PUT' : 'POST';
      const url = rule ? `/api/nurturing/${rule.id}` : '/api/nurturing';
      const res = await apiFetch(url, { method, headers:{'Content-Type':'application/json'}, body: JSON.stringify(draft) });
      const data = await res.json();
      onSave(data);
      onClose();
    } finally { setSaving(false); }
  };

  return (
    <div style={{ position:'fixed', inset:0, background:'rgba(0,0,0,.5)', display:'flex', alignItems:'center', justifyContent:'center', zIndex:200, overflowY:'auto' }} onClick={onClose}>
      <div style={{ background:'var(--surface)', borderRadius:14, padding:'28px 32px', width:640, maxHeight:'90vh', overflowY:'auto', boxShadow:'var(--shadow-lg)', display:'flex', flexDirection:'column', gap:18 }} onClick={e=>e.stopPropagation()}>
        <div style={{ fontSize:18, fontWeight:800 }}>{rule ? 'Editar regla' : 'Nueva regla de nurturing'}</div>

        <Field label="Nombre de la regla *">
          <input style={S.input} value={draft.name} onChange={e=>upd({name:e.target.value})} placeholder="ej: Lead estancado en Qualified 3+ días" autoFocus />
        </Field>

        <Field label="Pipeline (opcional — si está vacío aplica a todos)">
          <select style={S.select} value={draft.pipelineId||''} onChange={e=>upd({pipelineId:e.target.value})}>
            <option value="">— Todos los pipelines —</option>
            {pipelines.map(p=><option key={p._id} value={p._id}>{p.title}</option>)}
          </select>
        </Field>

        {/* Conditions */}
        <div>
          <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between', marginBottom:10 }}>
            <label style={S.label}>Condiciones</label>
            <div style={{ display:'flex', alignItems:'center', gap:8 }}>
              <span style={{ fontSize:12, color:'var(--muted)' }}>Combinar con:</span>
              <button style={{ ...S.chip(draft.conditionOperator==='AND'), padding:'3px 10px', fontSize:12 }} onClick={()=>upd({conditionOperator:'AND'})}>Y (AND)</button>
              <button style={{ ...S.chip(draft.conditionOperator==='OR'), padding:'3px 10px', fontSize:12 }} onClick={()=>upd({conditionOperator:'OR'})}>O (OR)</button>
            </div>
          </div>
          <div style={{ display:'flex', flexDirection:'column', gap:8 }}>
            {draft.conditions.map((c,i) => (
              <ConditionEditor key={i} cond={c} onChange={nc=>updCond(i,nc)} onRemove={()=>removeCond(i)} />
            ))}
            <button style={{ alignSelf:'flex-start', ...S.outlineBtn }} onClick={addCond}>+ Agregar condición</button>
          </div>
        </div>

        {/* Action */}
        <div style={{ ...S.card, padding:'16px 20px' }}>
          <div style={{ ...S.cardTitle, marginBottom:12 }}>⚡ Acción a ejecutar</div>
          <ActionEditor action={draft.action} onChange={a=>upd({action:a})} />
        </div>

        {/* Frequency control */}
        <div style={{ ...S.card, padding:'16px 20px' }}>
          <div style={{ ...S.cardTitle, marginBottom:12 }}>🔁 Control de frecuencia</div>
          <div style={S.row}>
            <Field label="Cooldown (días entre reenvíos)">
              <input style={S.input} type="number" min="0" value={draft.cooldownDays} onChange={e=>upd({cooldownDays:Number(e.target.value)})} />
              <div style={{ fontSize:11, color:'var(--muted)', marginTop:3 }}>0 = sin límite de tiempo</div>
            </Field>
            <Field label="Máximo de envíos por contacto">
              <input style={S.input} type="number" min="0" value={draft.maxFires} onChange={e=>upd({maxFires:Number(e.target.value)})} />
              <div style={{ fontSize:11, color:'var(--muted)', marginTop:3 }}>0 = ilimitado</div>
            </Field>
          </div>
        </div>

        <div style={{ display:'flex', gap:10, justifyContent:'flex-end' }}>
          <button style={S.dangerBtn} onClick={onClose}>Cancelar</button>
          <button style={S.saveBtn} onClick={save} disabled={saving || !draft.name.trim()}>
            {saving ? 'Guardando…' : 'Guardar regla'}
          </button>
        </div>
      </div>
    </div>
  );
}

function RuleCard({ rule, onEdit, onDelete, onToggle }) {
  const actionLabel = ACTION_TYPES_NURTURING.find(a=>a.v===rule.action.type)?.label || rule.action.type;
  const condSummary = rule.conditions.map(c => {
    const t = CONDITION_TYPES.find(x=>x.v===c.type);
    if (c.type==='days_in_stage' || c.type==='days_since_created') return `${t?.label} (${c.days}d)`;
    if (c.type==='has_tag'||c.type==='missing_tag') return `${t?.label}: "${c.tagName}"`;
    if (c.type==='has_attribute'||c.type==='attribute_gte') return `${t?.label}: ${c.attributeKey}${c.attributeValue?' = '+c.attributeValue:''}`;
    return t?.label;
  }).join(` ${rule.conditionOperator} `);

  return (
    <div style={{ ...S.card, display:'flex', flexDirection:'column', gap:10 }}>
      <div style={{ display:'flex', alignItems:'flex-start', justifyContent:'space-between', gap:12 }}>
        <div style={{ flex:1 }}>
          <div style={{ display:'flex', alignItems:'center', gap:8, marginBottom:4 }}>
            <span style={{ fontSize:14, fontWeight:700 }}>{rule.name}</span>
            <span style={{ ...S.badge(rule.enabled ? '#22c55e' : '#9ca3af'), fontSize:10 }}>
              {rule.enabled ? 'Activa' : 'Inactiva'}
            </span>
          </div>
          <div style={{ fontSize:12, color:'var(--muted)', marginBottom:6 }}>
            SI {condSummary}
          </div>
          <div style={{ fontSize:12, color:'var(--primary)', fontWeight:500 }}>
            → {actionLabel}
            {rule.action.message && <span style={{ color:'var(--muted)', fontWeight:400 }}> — "{rule.action.message.slice(0,60)}{rule.action.message.length>60?'…':''}"</span>}
          </div>
          <div style={{ fontSize:11, color:'var(--muted)', marginTop:6, display:'flex', gap:12 }}>
            <span>⏱ Cooldown: {rule.cooldownDays === 0 ? 'ninguno' : `${rule.cooldownDays} días`}</span>
            <span>🔢 Máx: {rule.maxFires === 0 ? 'ilimitado' : `${rule.maxFires} vez/veces`}</span>
          </div>
        </div>
        <div style={{ display:'flex', alignItems:'center', gap:8, flexShrink:0 }}>
          <Toggle on={rule.enabled} onChange={() => onToggle(rule)} />
          <button style={{ background:'none', border:'none', color:'var(--primary)', cursor:'pointer', fontSize:13, fontWeight:600, padding:'4px 8px' }} onClick={() => onEdit(rule)}>Editar</button>
          <button style={{ background:'none', border:'none', color:'var(--danger)', cursor:'pointer', fontSize:13, fontWeight:600, padding:'4px 8px' }} onClick={() => onDelete(rule)}>Eliminar</button>
        </div>
      </div>
    </div>
  );
}

// ─── Media Library ───────────────────────────────────────────────────────────

function MediaPanel() {
  const [files, setFiles] = useState([]);
  const [uploading, setUploading] = useState(false);
  const [copied, setCopied] = useState(null);
  const fileRef = useRef();

  const load = () => apiFetch('/api/media').then(r=>r.json()).then(setFiles).catch(()=>{});
  useEffect(() => { load(); }, []);

  const handleUpload = async (e) => {
    const files = Array.from(e.target.files);
    if (!files.length) return;
    setUploading(true);
    try {
      const token = getToken();
      const errors = [];
      await Promise.all(files.map(async (file) => {
        const formData = new FormData();
        formData.append('file', file);
        const res = await fetch('/api/media/upload', {
          method: 'POST',
          headers: token ? { Authorization: `Bearer ${token}` } : {},
          body: formData,
        }).then(r => r.json());
        if (res.error) errors.push(`${file.name}: ${res.error}`);
      }));
      if (errors.length) alert(errors.join('\n'));
      load();
    } finally {
      setUploading(false);
      e.target.value = '';
    }
  };

  const deleteFile = async (name) => {
    if (!confirm(`¿Eliminar "${name}"?`)) return;
    await apiFetch(`/api/media/${encodeURIComponent(name)}`, { method:'DELETE' });
    setFiles(fs => fs.filter(f=>f.name!==name));
  };

  const copyUrl = (url) => {
    const full = window.location.origin + url;
    navigator.clipboard.writeText(full);
    setCopied(url);
    setTimeout(() => setCopied(null), 2000);
  };

  const fmt = (bytes) => bytes > 1024*1024 ? `${(bytes/1024/1024).toFixed(1)} MB` : `${(bytes/1024).toFixed(0)} KB`;

  const isImage = (f) => /\.(jpg|jpeg|png|gif|webp)$/i.test(f.name);
  const isPdf   = (f) => /\.pdf$/i.test(f.name);
  const isVideo = (f) => /\.(mp4|mov|webm)$/i.test(f.name);

  return (
    <div style={{ ...S.editor }}>
      <div style={{ display:'flex', justifyContent:'space-between', alignItems:'flex-start', marginBottom:24 }}>
        <div>
          <div style={{ fontSize:22, fontWeight:800, marginBottom:4 }}>📎 Librería de medios</div>
          <div style={{ fontSize:13, color:'var(--muted)' }}>Subí imágenes, PDFs y videos para usar en mensajes, templates y catálogo de productos.</div>
        </div>
        <div>
          <input type="file" ref={fileRef} style={{ display:'none' }} multiple
            accept=".jpg,.jpeg,.png,.gif,.webp,.pdf,.mp4,.mov,.webm"
            onChange={handleUpload} />
          <button onClick={() => fileRef.current.click()} disabled={uploading}
            style={{ padding:'9px 18px', borderRadius:9, border:'none', background:'var(--primary)', color:'#fff', cursor:'pointer', fontWeight:700 }}>
            {uploading ? 'Subiendo...' : '+ Subir archivo'}
          </button>
        </div>
      </div>

      {files.length === 0 ? (
        <div style={{ textAlign:'center', padding:'60px 24px', color:'var(--muted)', border:'2px dashed var(--border)', borderRadius:14 }}
          onDragOver={e=>e.preventDefault()}
          onDrop={e=>{e.preventDefault(); const f=e.dataTransfer.files[0]; if(f){fileRef.current.files=e.dataTransfer.files; handleUpload({target:{files:e.dataTransfer.files}});}}}>
          <div style={{ fontSize:40, marginBottom:12 }}>📎</div>
          <div style={{ fontWeight:600, marginBottom:6 }}>Sin archivos todavía</div>
          <div style={{ fontSize:13 }}>Subí imágenes (JPG/PNG), PDFs o videos (MP4)</div>
        </div>
      ) : (
        <div style={{ display:'grid', gridTemplateColumns:'repeat(auto-fill, minmax(200px,1fr))', gap:14 }}>
          {files.map(f => (
            <div key={f.name} style={{ background:'var(--surface)', border:'1px solid var(--border)', borderRadius:12, overflow:'hidden' }}>
              {/* Preview */}
              <div style={{ height:130, background:'var(--bg)', display:'flex', alignItems:'center', justifyContent:'center', overflow:'hidden' }}>
                {isImage(f) ? (
                  <img src={f.url} alt={f.name} style={{ width:'100%', height:'100%', objectFit:'cover' }} />
                ) : isPdf(f) ? (
                  <div style={{ textAlign:'center', color:'var(--muted)' }}>
                    <div style={{ fontSize:40 }}>📄</div>
                    <div style={{ fontSize:11 }}>PDF</div>
                  </div>
                ) : isVideo(f) ? (
                  <div style={{ textAlign:'center', color:'var(--muted)' }}>
                    <div style={{ fontSize:40 }}>🎬</div>
                    <div style={{ fontSize:11 }}>Video</div>
                  </div>
                ) : <div style={{ fontSize:32 }}>📁</div>}
              </div>
              {/* Info */}
              <div style={{ padding:'10px 12px' }}>
                <div style={{ fontSize:12, fontWeight:600, marginBottom:2, overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap' }} title={f.name}>{f.name}</div>
                <div style={{ fontSize:11, color:'var(--muted)', marginBottom:8 }}>{fmt(f.size)}</div>
                <div style={{ display:'flex', gap:6 }}>
                  <button onClick={() => copyUrl(f.url)}
                    style={{ flex:1, padding:'5px 0', borderRadius:7, border:'1px solid var(--border)', background: copied===f.url ? '#d1fae5' : 'transparent', cursor:'pointer', fontSize:11, color: copied===f.url ? '#10b981' : 'var(--text)', fontWeight:600 }}>
                    {copied===f.url ? '✓ Copiado' : 'Copiar URL'}
                  </button>
                  <button onClick={() => deleteFile(f.name)}
                    style={{ padding:'5px 8px', borderRadius:7, border:'none', background:'#fee2e2', color:'#ef4444', cursor:'pointer', fontSize:11, fontWeight:600 }}>✕</button>
                </div>
              </div>
            </div>
          ))}
        </div>
      )}

      <div style={{ marginTop:20, padding:'12px 16px', background:'var(--bg)', borderRadius:10, border:'1px solid var(--border)', fontSize:12, color:'var(--muted)' }}>
        <strong>Formatos soportados:</strong> JPG, PNG, GIF, WEBP, PDF, MP4, MOV, WEBM. La URL copiada se puede usar directamente en mensajes de reglas, catálogo de productos o templates.
      </div>
    </div>
  );
}

// ─── Catalog (Products / Branches) ───────────────────────────────────────────

function CatalogModal({ entry, onClose, onSaved }) {
  const { pipelines, users, teams, templates } = usePipochat();
  const [mediaFiles, setMediaFiles] = useState([]);
  const defaultBranch = { address:'', neighborhood:'', phone:'', whatsapp:'', scheduleWeekdays:'', scheduleWeekends:'', services:'', instructors:'', extraInfo:'' };
  const initRoutingMode = (e) => (e?.roundRobinIds?.length) ? 'roundrobin' : e?.assignTeamId ? 'team' : e?.assignOperatorId ? 'operator' : 'none';
  const [routingMode, setRoutingMode] = useState(initRoutingMode(entry));
  const [form, setForm] = useState(entry ? { ...entry, branch: entry.branch || defaultBranch } : {
    type: 'branch', name: '', description: '', keywords: [],
    enabled: false, priority: 10, useAiDetection: true,
    responseText: '', mediaUrl: '', mediaType: '',
    assignOperatorId: '', assignTeamId: '', roundRobinIds: [],
    onlineOnly: false, fallbackAll: true,
    pipelineId: '', stageId: '', tagNames: [], fireOnce: true,
    branch: defaultBranch,
  });
  const [saving, setSaving] = useState(false);
  const [kwInput, setKwInput] = useState((entry?.keywords || []).join(', '));

  useEffect(() => { apiFetch('/api/media').then(r=>r.json()).then(setMediaFiles).catch(()=>{}); }, []);

  const setField = (k, v) => setForm(f => ({ ...f, [k]: v }));
  const setBranch = (k, v) => setForm(f => ({ ...f, branch: { ...f.branch, [k]: v } }));
  const stagesOf = (pid) => (pipelines.find(p => p._id === pid)?.stages || []);

  const save = async () => {
    if (!form.name.trim()) return alert('Necesitás un nombre');
    const kws = kwInput.split(',').map(k=>k.trim()).filter(Boolean);
    setSaving(true);
    const body = { ...form, keywords: kws };
    const url = entry ? `/api/catalog/${entry.id}` : '/api/catalog';
    const method = entry ? 'PUT' : 'POST';
    const res = await apiFetch(url, { method, headers:{'Content-Type':'application/json'}, body:JSON.stringify(body) }).then(r=>r.json());
    setSaving(false);
    if (res.error) return alert(res.error);
    onSaved(res); onClose();
  };

  const modal = { position:'fixed', inset:0, background:'rgba(0,0,0,0.5)', display:'flex', alignItems:'flex-start', justifyContent:'center', zIndex:1000, padding:'24px 16px', overflowY:'auto' };
  const box   = { background:'var(--surface)', borderRadius:14, padding:'28px 28px 24px', width:'100%', maxWidth:700, boxShadow:'0 20px 60px rgba(0,0,0,0.3)', marginBottom:24 };
  const inp   = { padding:'7px 10px', borderRadius:8, border:'1px solid var(--border)', background:'var(--bg)', color:'var(--text)', fontSize:13, width:'100%', boxSizing:'border-box' };
  const lbl   = { fontSize:12, color:'var(--muted)', display:'block', marginBottom:4 };
  const sec   = { marginBottom:18 };
  return (
    <div style={modal} onClick={e => e.target===e.currentTarget && onClose()}>
      <div style={box}>
        <div style={{ display:'flex', justifyContent:'space-between', alignItems:'center', marginBottom:22 }}>
          <div style={{ fontSize:18, fontWeight:800 }}>{entry ? 'Editar' : 'Nueva'} {form.type === 'branch' ? 'sucursal' : 'producto'}</div>
          <button onClick={onClose} style={{ background:'none', border:'none', cursor:'pointer', fontSize:20, color:'var(--muted)' }}>✕</button>
        </div>

        {/* Type + Name + Priority */}
        <div style={{ display:'grid', gridTemplateColumns:'auto 1fr auto', gap:10, ...sec }}>
          <div>
            <span style={lbl}>Tipo</span>
            <select style={inp} value={form.type} onChange={e=>setField('type',e.target.value)}>
              <option value="branch">Sucursal</option>
              <option value="product">Producto</option>
            </select>
          </div>
          <div>
            <span style={lbl}>Nombre</span>
            <input style={inp} value={form.name} onChange={e=>setField('name',e.target.value)} placeholder="Ej: Sucursal Palermo, Plan Business" />
          </div>
          <div>
            <span style={lbl}>Prioridad</span>
            <input type="number" style={{ ...inp, width:70 }} value={form.priority} onChange={e=>setField('priority',Number(e.target.value))} />
          </div>
        </div>

        {/* Keywords + AI detection */}
        <div style={sec}>
          <div style={{ display:'flex', justifyContent:'space-between', alignItems:'center', marginBottom:4 }}>
            <span style={lbl}>Keywords de activación (separadas por coma)</span>
            <label style={{ display:'flex', alignItems:'center', gap:5, fontSize:12, cursor:'pointer', whiteSpace:'nowrap' }}>
              <input type="checkbox" checked={!!form.useAiDetection} onChange={e=>setField('useAiDetection',e.target.checked)} />
              Detección por IA si no hay keyword exacta
            </label>
          </div>
          <input style={inp} value={kwInput} onChange={e=>setKwInput(e.target.value)}
            placeholder="palermo, av santa fe, santa fe 3500..." />
          <div style={{ fontSize:11, color:'var(--muted)', marginTop:3 }}>
            Si el mensaje contiene alguna de estas palabras, se activa inmediatamente. Si no coincide nada, la IA intenta detectar a cuál sucursal se refiere el cliente.
          </div>
        </div>

        {/* Branch structured fields */}
        {form.type === 'branch' && (
          <div style={{ ...sec, background:'var(--bg)', borderRadius:10, padding:'14px 14px 10px', border:'1px solid var(--border)' }}>
            <div style={{ fontWeight:700, fontSize:13, marginBottom:12 }}>📍 Datos de la sucursal</div>
            <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr', gap:8, marginBottom:8 }}>
              <div>
                <span style={lbl}>Dirección completa</span>
                <input style={inp} value={form.branch?.address||''} onChange={e=>setBranch('address',e.target.value)} placeholder="Av. Santa Fe 3500, CABA" />
              </div>
              <div>
                <span style={lbl}>Barrio / Zona</span>
                <input style={inp} value={form.branch?.neighborhood||''} onChange={e=>setBranch('neighborhood',e.target.value)} placeholder="Palermo" />
              </div>
              <div>
                <span style={lbl}>Teléfono</span>
                <input style={inp} value={form.branch?.phone||''} onChange={e=>setBranch('phone',e.target.value)} placeholder="+5491112345678" />
              </div>
              <div>
                <span style={lbl}>WhatsApp sucursal (si tiene)</span>
                <input style={inp} value={form.branch?.whatsapp||''} onChange={e=>setBranch('whatsapp',e.target.value)} placeholder="+5491187654321" />
              </div>
              <div>
                <span style={lbl}>Horario semana</span>
                <input style={inp} value={form.branch?.scheduleWeekdays||''} onChange={e=>setBranch('scheduleWeekdays',e.target.value)} placeholder="Lun-Vie 7:00–22:00hs" />
              </div>
              <div>
                <span style={lbl}>Horario fin de semana</span>
                <input style={inp} value={form.branch?.scheduleWeekends||''} onChange={e=>setBranch('scheduleWeekends',e.target.value)} placeholder="Sáb-Dom 9:00–19:00hs" />
              </div>
            </div>
            <div style={{ marginBottom:8 }}>
              <span style={lbl}>Actividades / Servicios (separados por coma)</span>
              <input style={inp} value={form.branch?.services||''} onChange={e=>setBranch('services',e.target.value)} placeholder="Spinning, CrossFit, Yoga, Pilates, Natación" />
            </div>
            <div style={{ marginBottom:8 }}>
              <span style={lbl}>Instructores destacados (opcional)</span>
              <input style={inp} value={form.branch?.instructors||''} onChange={e=>setBranch('instructors',e.target.value)} placeholder="Juan López, María García" />
            </div>
            <div>
              <span style={lbl}>Info adicional</span>
              <input style={inp} value={form.branch?.extraInfo||''} onChange={e=>setBranch('extraInfo',e.target.value)} placeholder="Estacionamiento gratuito, pileta olímpica, etc." />
            </div>
            <div style={{ fontSize:11, color:'var(--primary)', marginTop:8 }}>
              💡 Si no escribís un mensaje personalizado abajo, el sistema genera la respuesta automáticamente con estos datos.
            </div>
          </div>
        )}

        {/* Custom response text (optional override) */}
        <div style={sec}>
          <span style={{ fontWeight:700, fontSize:13, display:'block', marginBottom:6 }}>
            Mensaje personalizado {form.type === 'branch' ? '(opcional — se auto-genera si lo dejás vacío)' : ''}
          </span>
          <textarea style={{ ...inp, minHeight:60, resize:'vertical', marginBottom:8 }}
            placeholder={form.type === 'branch' ? 'Dejá vacío para auto-generar desde los datos de la sucursal...' : 'Hola {{name}}! Te cuento sobre...'}
            value={form.responseText || ''} onChange={e=>setField('responseText',e.target.value)} />
          <div style={{ display:'grid', gridTemplateColumns:'1fr auto', gap:8 }}>
            <div>
              <span style={lbl}>Imagen / PDF / Video (URL de Archivos)</span>
              <input list="media-urls-cat" style={inp} placeholder="https://... o dejá vacío"
                value={form.mediaUrl || ''} onChange={e=>setField('mediaUrl',e.target.value)} />
              <datalist id="media-urls-cat">
                {mediaFiles.map(f => <option key={f.name} value={window.location.origin + f.url} />)}
              </datalist>
            </div>
            <div>
              <span style={lbl}>Tipo media</span>
              <select style={inp} value={form.mediaType || ''} onChange={e=>setField('mediaType',e.target.value)}>
                <option value="">Sin media</option>
                <option value="image">Imagen</option>
                <option value="document">PDF</option>
                <option value="video">Video</option>
              </select>
            </div>
          </div>
        </div>

        {/* Routing */}
        <div style={sec}>
          <span style={{ fontWeight:700, fontSize:13, display:'block', marginBottom:8 }}>Asignación al recibir consulta</span>
          <div style={{ display:'flex', gap:8, marginBottom:10 }}>
            {[['none','Sin asignar'],['operator','Operador fijo'],['team','Equipo'],['roundrobin','Round-robin']].map(([v,l]) => (
              <button key={v} onClick={() => {
                setRoutingMode(v);
                setField('assignOperatorId', v==='operator' ? (users[0]?._id||'') : '');
                setField('assignTeamId',     v==='team'     ? (teams[0]?._id||'') : '');
                if (v !== 'roundrobin') setField('roundRobinIds', []);
              }}
                style={{ padding:'5px 12px', borderRadius:7, border:'1px solid var(--border)', cursor:'pointer', fontSize:12,
                  background:routingMode===v?'var(--primary)':'transparent', color:routingMode===v?'#fff':'var(--text)' }}>{l}</button>
            ))}
          </div>
          {routingMode==='operator' && <select style={inp} value={form.assignOperatorId||''} onChange={e=>setField('assignOperatorId',e.target.value)}><option value="">— Operador —</option>{users.map(u=><option key={u._id} value={u._id}>{u.name}</option>)}</select>}
          {routingMode==='team' && <select style={inp} value={form.assignTeamId||''} onChange={e=>setField('assignTeamId',e.target.value)}><option value="">— Equipo —</option>{teams.map(t=><option key={t._id} value={t._id}>{t.name}</option>)}</select>}
          {routingMode==='roundrobin' && (
            <div>
              <div style={{ display:'grid', gridTemplateColumns:'repeat(auto-fill, minmax(160px,1fr))', gap:4, marginBottom:8 }}>
                {users.map(u=>(
                  <label key={u._id} style={{ display:'flex', alignItems:'center', gap:6, fontSize:13, cursor:'pointer' }}>
                    <input type="checkbox" checked={(form.roundRobinIds||[]).includes(u._id)}
                      onChange={e=>{ const cur=form.roundRobinIds||[]; setField('roundRobinIds',e.target.checked?[...cur,u._id]:cur.filter(id=>id!==u._id)); }} />
                    {u.name}
                  </label>
                ))}
              </div>
              <label style={{ display:'flex', alignItems:'center', gap:6, fontSize:12, cursor:'pointer' }}>
                <input type="checkbox" checked={!!form.onlineOnly} onChange={e=>setField('onlineOnly',e.target.checked)} />
                Solo operadores online en este momento
              </label>
              {form.onlineOnly && <label style={{ display:'flex', alignItems:'center', gap:6, fontSize:12, cursor:'pointer', paddingLeft:18, marginTop:4 }}>
                <input type="checkbox" checked={!!form.fallbackAll} onChange={e=>setField('fallbackAll',e.target.checked)} />
                Si no hay nadie online, asignar igual
              </label>}
            </div>
          )}
        </div>

        {/* Pipeline + Tags + Options */}
        <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr', gap:14, ...sec }}>
          <div>
            <span style={lbl}>Pipeline (opcional)</span>
            <select style={{ ...inp, marginBottom:6 }} value={form.pipelineId||''} onChange={e=>setField('pipelineId',e.target.value)}>
              <option value="">— Sin pipeline —</option>
              {pipelines.map(p=><option key={p._id} value={p._id}>{p.title||p.name}</option>)}
            </select>
            {form.pipelineId && <select style={inp} value={form.stageId||''} onChange={e=>setField('stageId',e.target.value)}>
              <option value="">— Etapa —</option>
              {stagesOf(form.pipelineId).map(s=><option key={s._id} value={s._id}>{s.displayName||s.name}</option>)}
            </select>}
          </div>
          <div>
            <span style={lbl}>Etiquetas (separadas por coma)</span>
            <input style={inp} placeholder="sucursal-palermo, interesado..."
              value={(form.tagNames||[]).join(', ')}
              onChange={e=>setField('tagNames',e.target.value.split(',').map(k=>k.trim()).filter(Boolean))} />
            <label style={{ display:'flex', alignItems:'center', gap:6, fontSize:12, cursor:'pointer', marginTop:10 }}>
              <input type="checkbox" checked={form.fireOnce} onChange={e=>setField('fireOnce',e.target.checked)} />
              Disparar solo 1 vez por conversación
            </label>
          </div>
        </div>

        <div style={{ display:'flex', gap:10, justifyContent:'flex-end' }}>
          <button onClick={onClose} style={{ padding:'8px 18px', borderRadius:8, border:'1px solid var(--border)', background:'transparent', cursor:'pointer', color:'var(--text)' }}>Cancelar</button>
          <button onClick={save} disabled={saving} style={{ padding:'8px 18px', borderRadius:8, border:'none', background:'var(--primary)', color:'#fff', cursor:'pointer', fontWeight:600 }}>
            {saving ? 'Guardando...' : entry ? 'Guardar' : 'Crear'}
          </button>
        </div>
      </div>
    </div>
  );
}

function CatalogCard({ entry, onEdit, onDelete, onToggle }) {
  const badge = (color, text) => (
    <span style={{ fontSize:10, padding:'2px 7px', borderRadius:20, background:color+'22', color, fontWeight:600, border:`1px solid ${color}44` }}>{text}</span>
  );
  const b = entry.branch;
  const kwPreview = (entry.keywords || []).slice(0,5).join(', ') + (entry.keywords?.length > 5 ? '...' : '');

  return (
    <div style={{ background:'var(--surface)', border:'1px solid var(--border)', borderRadius:12, overflow:'hidden', display:'flex' }}>
      {entry.mediaUrl && entry.mediaType === 'image' ? (
        <div style={{ width:80, flexShrink:0, overflow:'hidden' }}>
          <img src={entry.mediaUrl} alt={entry.name} style={{ width:'100%', height:'100%', objectFit:'cover' }} />
        </div>
      ) : (
        <div style={{ width:80, flexShrink:0, background:'var(--bg)', display:'flex', alignItems:'center', justifyContent:'center', fontSize:28 }}>
          {entry.type === 'branch' ? '🏪' : '📦'}
        </div>
      )}
      <div style={{ flex:1, padding:'12px 16px' }}>
        <div style={{ display:'flex', justifyContent:'space-between', alignItems:'flex-start' }}>
          <div style={{ flex:1 }}>
            <div style={{ display:'flex', alignItems:'center', gap:8, marginBottom:4, flexWrap:'wrap' }}>
              <span style={{ fontWeight:700, fontSize:14 }}>{entry.name}</span>
              {badge(entry.enabled ? '#10b981' : '#94a3b8', entry.enabled ? 'Activo' : 'Inactivo')}
              {entry.useAiDetection && badge('#8b5cf6', '🤖 IA')}
            </div>
            {b?.address && <div style={{ fontSize:12, color:'var(--muted)', marginBottom:2 }}>📍 {b.address}</div>}
            {b?.scheduleWeekdays && <div style={{ fontSize:12, color:'var(--muted)', marginBottom:2 }}>🕐 {b.scheduleWeekdays}{b.scheduleWeekends ? ' | ' + b.scheduleWeekends : ''}</div>}
            {b?.services && <div style={{ fontSize:12, color:'var(--muted)', marginBottom:2 }}>💪 {b.services}</div>}
            {kwPreview && <div style={{ fontSize:11, color:'var(--muted)', marginTop:4 }}>Keywords: {kwPreview}</div>}
          </div>
          <div style={{ display:'flex', gap:6, alignItems:'center', marginLeft:10, flexShrink:0 }}>
            <label style={{ cursor:'pointer' }}>
              <input type="checkbox" checked={entry.enabled} onChange={e=>onToggle(entry.id,e.target.checked)} style={{ width:16, height:16 }} />
            </label>
            <button onClick={()=>onEdit(entry)} style={{ padding:'5px 10px', borderRadius:7, border:'1px solid var(--border)', background:'transparent', cursor:'pointer', fontSize:12 }}>Editar</button>
            <button onClick={()=>onDelete(entry.id)} style={{ padding:'5px 10px', borderRadius:7, border:'none', background:'#fee2e2', color:'#ef4444', cursor:'pointer', fontSize:12, fontWeight:600 }}>Eliminar</button>
          </div>
        </div>
      </div>
    </div>
  );
}

function CatalogPanel() {
  const [entries, setEntries] = useState([]);
  const [showModal, setShowModal] = useState(false);
  const [editing, setEditing] = useState(null);
  const [filter, setFilter] = useState('all');
  const [search, setSearch] = useState('');
  const [importing, setImporting] = useState(false);
  const csvRef = useRef();

  const load = () => apiFetch('/api/catalog').then(r=>r.json()).then(setEntries).catch(()=>{});
  useEffect(() => { load(); }, []);

  const handleSave = (saved) => {
    setEntries(es => { const idx=es.findIndex(e=>e.id===saved.id); if(idx>=0){const n=[...es];n[idx]=saved;return n;} return [...es,saved]; });
  };

  const deleteEntry = async (id) => {
    if (!confirm('¿Eliminar?')) return;
    await apiFetch(`/api/catalog/${id}`, { method:'DELETE' });
    setEntries(es => es.filter(e=>e.id!==id));
  };

  const toggleEntry = async (id, enabled) => {
    const updated = await apiFetch(`/api/catalog/${id}`, {
      method:'PATCH', headers:{'Content-Type':'application/json'}, body:JSON.stringify({ enabled })
    }).then(r=>r.json());
    setEntries(es => es.map(e=>e.id===id ? updated : e));
  };

  const handleCsvImport = async (e) => {
    const file = e.target.files[0];
    if (!file) return;
    setImporting(true);
    const text = await file.text();
    const res = await apiFetch('/api/catalog/import-csv', {
      method:'POST', headers:{'Content-Type':'application/json'},
      body: JSON.stringify({ csv: text, type: 'branch' })
    }).then(r=>r.json());
    setImporting(false);
    if (res.error) { alert(res.error); return; }
    alert(`✅ Importadas: ${res.imported} sucursales${res.errors.length ? `\n⚠️ Errores: ${res.errors.join('\n')}` : ''}`);
    load();
  };

  const downloadTemplate = () => {
    apiFetch('/api/catalog/csv-template')
      .then(r => r.blob())
      .then(blob => {
        const url = URL.createObjectURL(blob);
        const a = document.createElement('a');
        a.href = url; a.download = 'plantilla-sucursales.csv';
        document.body.appendChild(a); a.click();
        document.body.removeChild(a); URL.revokeObjectURL(url);
      });
  };

  const filtered = entries
    .filter(e => filter==='all' || e.type===filter)
    .filter(e => !search || e.name.toLowerCase().includes(search.toLowerCase()) || (e.branch?.neighborhood||'').toLowerCase().includes(search.toLowerCase()))
    .sort((a,b)=>a.priority-b.priority);

  const branchCount = entries.filter(e=>e.type==='branch').length;
  const productCount = entries.filter(e=>e.type==='product').length;

  return (
    <div style={{ ...S.editor }}>
      {showModal && <CatalogModal entry={editing} onClose={()=>{setShowModal(false);setEditing(null);}} onSaved={handleSave} />}

      <div style={{ display:'flex', justifyContent:'space-between', alignItems:'flex-start', marginBottom:20 }}>
        <div>
          <div style={{ fontSize:22, fontWeight:800, marginBottom:4 }}>🏪 Productos y Sucursales</div>
          <div style={{ fontSize:13, color:'var(--muted)' }}>
            {entries.length > 0 ? `${branchCount} sucursal${branchCount!==1?'es':''} · ${productCount} producto${productCount!==1?'s':''}` : 'Cuando un cliente mencione una sucursal, enviá su info y derivalo al equipo correcto.'}
          </div>
        </div>
        <div style={{ display:'flex', gap:8, flexWrap:'wrap', justifyContent:'flex-end' }}>
          <input type="file" ref={csvRef} accept=".csv" style={{ display:'none' }} onChange={handleCsvImport} />
          <button onClick={downloadTemplate}
            style={{ padding:'8px 14px', borderRadius:8, border:'1px solid var(--border)', background:'transparent', cursor:'pointer', fontSize:12, color:'var(--muted)' }}>
            📥 Plantilla CSV
          </button>
          <button onClick={()=>csvRef.current.click()} disabled={importing}
            style={{ padding:'8px 14px', borderRadius:8, border:'1px solid var(--primary)', background:'transparent', cursor:'pointer', fontSize:12, color:'var(--primary)', fontWeight:600 }}>
            {importing ? 'Importando...' : '📤 Importar CSV'}
          </button>
          <button onClick={()=>{setEditing(null);setShowModal(true);}}
            style={{ padding:'8px 14px', borderRadius:8, border:'none', background:'var(--primary)', color:'#fff', cursor:'pointer', fontWeight:700, fontSize:13 }}>
            + Nueva entrada
          </button>
        </div>
      </div>

      {/* Search + filter */}
      {entries.length > 0 && (
        <div style={{ display:'flex', gap:10, marginBottom:16, alignItems:'center' }}>
          <input style={{ flex:1, padding:'7px 12px', borderRadius:8, border:'1px solid var(--border)', background:'var(--bg)', color:'var(--text)', fontSize:13 }}
            placeholder="Buscar por nombre o barrio..." value={search} onChange={e=>setSearch(e.target.value)} />
          <div style={{ display:'flex', gap:6 }}>
            {[['all',`Todos (${entries.length})`],['branch',`Sucursales (${branchCount})`],['product',`Productos (${productCount})`]].map(([v,l]) => (
              <button key={v} onClick={()=>setFilter(v)}
                style={{ padding:'6px 12px', borderRadius:7, border:'1px solid var(--border)', cursor:'pointer', fontSize:12, fontWeight:600, whiteSpace:'nowrap',
                  background:filter===v?'var(--primary)':'transparent', color:filter===v?'#fff':'var(--text)' }}>{l}</button>
            ))}
          </div>
        </div>
      )}

      {filtered.length === 0 && entries.length === 0 ? (
        <div style={{ textAlign:'center', padding:'50px 24px', color:'var(--muted)', border:'2px dashed var(--border)', borderRadius:14 }}>
          <div style={{ fontSize:40, marginBottom:12 }}>🏪</div>
          <div style={{ fontWeight:700, fontSize:16, marginBottom:8 }}>¿Tenés 40 sucursales?</div>
          <div style={{ fontSize:13, marginBottom:16 }}>Descargá la plantilla CSV, completá los datos y subila de una sola vez.</div>
          <div style={{ display:'flex', gap:10, justifyContent:'center' }}>
            <button onClick={downloadTemplate} style={{ padding:'10px 20px', borderRadius:9, border:'1px solid var(--border)', background:'transparent', cursor:'pointer', fontSize:13 }}>📥 Descargar plantilla CSV</button>
            <button onClick={()=>{setEditing(null);setShowModal(true);}} style={{ padding:'10px 20px', borderRadius:9, border:'none', background:'var(--primary)', color:'#fff', cursor:'pointer', fontSize:13, fontWeight:700 }}>+ Crear manualmente</button>
          </div>
        </div>
      ) : filtered.length === 0 ? (
        <div style={{ textAlign:'center', padding:'30px', color:'var(--muted)' }}>Sin resultados para "{search}"</div>
      ) : (
        <div style={{ display:'flex', flexDirection:'column', gap:8 }}>
          {filtered.map(e => (
            <CatalogCard key={e.id} entry={e} onEdit={en=>{setEditing(en);setShowModal(true);}} onDelete={deleteEntry} onToggle={toggleEntry} />
          ))}
        </div>
      )}

      <div style={{ marginTop:20, padding:'14px 16px', background:'var(--bg)', borderRadius:10, border:'1px solid var(--border)', fontSize:12, color:'var(--muted)' }}>
        <strong>Cómo funciona para gimnasios:</strong> Cuando llega un mensaje, primero busca keywords exactas ("palermo", "santa fe 3500"). Si no coincide nada, la IA (Haiku) lee el mensaje y determina a cuál sucursal se refiere — incluso frases como "el del shopping", "el que está en el centro". Luego envía la ficha de esa sucursal y asigna al equipo correspondiente.
      </div>
    </div>
  );
}

// ─── Conversation Rules Engine UI ────────────────────────────────────────────

const CONV_CONDITION_TYPES = [
  { value:'first_message',       label:'Primer mensaje',               fields:[] },
  { value:'message_count_eq',    label:'Mensaje número N (exacto)',     fields:['count'] },
  { value:'message_count_gte',   label:'A partir del mensaje N',       fields:['count'] },
  { value:'message_count_lte',   label:'Hasta el mensaje N',           fields:['count'] },
  { value:'message_contains',    label:'Mensaje contiene (alguna)',     fields:['keywords'] },
  { value:'message_contains_all',label:'Mensaje contiene (todas)',      fields:['keywords'] },
  { value:'message_not_contains',label:'Mensaje NO contiene',          fields:['keywords'] },
  { value:'has_tag',             label:'Contacto tiene etiqueta',      fields:['tagName'] },
  { value:'missing_tag',         label:'Contacto NO tiene etiqueta',   fields:['tagName'] },
  { value:'has_lead',            label:'Ya tiene lead en pipeline',    fields:[] },
  { value:'no_lead',             label:'No tiene lead aún',            fields:[] },
  { value:'hour_between',        label:'Horario entre H1 y H2',        fields:['hourFrom','hourTo'] },
  { value:'day_of_week',         label:'Día de la semana',             fields:['days'] },
  { value:'contact_attr_equals', label:'Atributo contacto = valor',    fields:['attributeKey','attributeValue'] },
  { value:'contact_attr_exists', label:'Atributo contacto existe',     fields:['attributeKey'] },
  { value:'always',              label:'Siempre (sin condición)',       fields:[] },
  { value:'ai_matches',          label:'🧠 IA evalúa criterio',         fields:['aiCriteria'] },
];

// ─── WhatsApp Interactive Message Builder ─────────────────────────────────────

function WaInteractivePreview({ interactive }) {
  if (!interactive) return null;
  const { type, body, footer, action } = interactive;
  const bodyText   = typeof body   === 'object' ? (body?.text   || '') : (body   || '');
  const footerText = typeof footer === 'object' ? (footer?.text || '') : (footer || '');
  const buttons    = action?.buttons || [];
  const rows       = action?.sections?.[0]?.rows || [];
  const listLabel  = action?.button || 'Ver opciones';

  // ── Carousel preview ─────────────────────────────────────────────────────────
  if (type === 'carousel') {
    const cards = action?.sections?.[0]?.cards || [];
    if (!cards.length) return null;
    return (
      <div style={{ marginTop:6 }}>
        <div style={{ fontSize:11, color:'var(--muted)', marginBottom:5 }}>Vista previa WhatsApp</div>
        <div style={{ background:'#e5ddd5', borderRadius:12, padding:8, fontFamily:'system-ui,sans-serif' }}>
          {bodyText && (
            <div style={{ background:'white', borderRadius:10, padding:'8px 12px', marginBottom:8, fontSize:13, color:'#111', boxShadow:'0 1px 2px rgba(0,0,0,.1)' }}>
              {bodyText}
            </div>
          )}
          <div style={{ display:'flex', gap:8, overflowX:'auto', paddingBottom:4 }}>
            {cards.map((card, i) => {
              const imgUrl = card.header?.image?.link || '';
              const cBody  = card.body?.text || '';
              const cFoot  = card.footer?.text || '';
              const cBtns  = card.action?.buttons || [];
              return (
                <div key={i} style={{ background:'white', borderRadius:10, overflow:'hidden', minWidth:170, maxWidth:170, flexShrink:0, boxShadow:'0 1px 2px rgba(0,0,0,.1)' }}>
                  {imgUrl
                    ? <img src={imgUrl} style={{ width:170, height:95, objectFit:'cover', display:'block' }} alt="" onError={e => { e.target.style.display='none'; }} />
                    : <div style={{ width:170, height:95, background:'#f0f0f0', display:'flex', alignItems:'center', justifyContent:'center', color:'#bbb', fontSize:11 }}>📷 imagen</div>
                  }
                  <div style={{ padding:'7px 10px' }}>
                    {cBody && <div style={{ fontSize:12, color:'#111', marginBottom: cFoot ? 3 : 0, lineHeight:1.4 }}>{cBody}</div>}
                    {cFoot && <div style={{ fontSize:10, color:'#888' }}>{cFoot}</div>}
                  </div>
                  {cBtns.some(b => b.reply?.title || b.cta_url?.display_text) && (
                    <div style={{ borderTop:'1px solid #f0f0f0' }}>
                      {cBtns.map((btn, bi) => {
                        const t = btn.type === 'cta_url' ? btn.cta_url?.display_text : btn.reply?.title;
                        return t ? (
                          <div key={bi} style={{ color:'#00a884', textAlign:'center', padding:'6px 10px', fontSize:12, borderTop: bi>0?'1px solid #f0f0f0':'none', display:'flex', alignItems:'center', justifyContent:'center', gap:3 }}>
                            {btn.type === 'cta_url' ? '🔗' : ''} {t}
                          </div>
                        ) : null;
                      })}
                    </div>
                  )}
                </div>
              );
            })}
          </div>
        </div>
      </div>
    );
  }

  // ── Button / List preview ────────────────────────────────────────────────────
  if (!bodyText && !buttons.some(b => b.reply?.title) && !rows.some(r => r.title)) return null;
  return (
    <div style={{ marginTop:6 }}>
      <div style={{ fontSize:11, color:'var(--muted)', marginBottom:5 }}>Vista previa WhatsApp</div>
      <div style={{ background:'#e5ddd5', borderRadius:12, padding:8, maxWidth:260, fontFamily:'system-ui,sans-serif' }}>
        <div style={{ background:'white', borderRadius:10, overflow:'hidden', boxShadow:'0 1px 2px rgba(0,0,0,.1)' }}>
          <div style={{ padding:'10px 12px' }}>
            {bodyText   && <div style={{ fontSize:13, color:'#111', whiteSpace:'pre-wrap', marginBottom: footerText ? 4 : 0 }}>{bodyText}</div>}
            {footerText && <div style={{ fontSize:11, color:'#888' }}>{footerText}</div>}
          </div>
          {type === 'button' && buttons.some(b => b.reply?.title) && (
            <div style={{ borderTop:'1px solid #f0f0f0' }}>
              {buttons.filter(b => b.reply?.title).map((btn, i) => (
                <div key={i} style={{ color:'#00a884', textAlign:'center', padding:'8px 12px', fontSize:13, borderTop: i>0?'1px solid #f0f0f0':'none' }}>
                  {btn.reply.title}
                </div>
              ))}
            </div>
          )}
          {type === 'list' && (
            <div style={{ borderTop:'1px solid #f0f0f0', padding:'8px 12px', color:'#00a884', textAlign:'center', fontSize:13, display:'flex', alignItems:'center', justifyContent:'center', gap:6 }}>
              ☰ {listLabel}
            </div>
          )}
        </div>
      </div>
    </div>
  );
}

function InteractiveMessageBuilder({ value, onChange }) {
  const iv        = value || { type:'button', body:{ text:'' }, action:{ buttons:[{ type:'reply', reply:{ id:'opt_0', title:'' } }] } };
  const itype     = iv.type || 'button';
  const bodyText  = typeof iv.body   === 'object' ? (iv.body?.text   || '') : (iv.body   || '');
  const footerText= typeof iv.footer === 'object' ? (iv.footer?.text || '') : (iv.footer || '');
  const buttons   = iv.action?.buttons || [];
  const rows      = iv.action?.sections?.[0]?.rows || [];
  const listLabel = iv.action?.button || 'Ver opciones';

  const inp  = { padding:'7px 10px', borderRadius:8, border:'1px solid var(--border)', background:'var(--bg)', color:'var(--text)', fontSize:13, width:'100%', boxSizing:'border-box' };
  const chip = (active) => ({ padding:'5px 12px', borderRadius:20, border:`1.5px solid ${active?'var(--green)':'var(--border)'}`, background:active?'var(--green-light)':'transparent', color:active?'var(--green)':'var(--ink-3)', fontSize:12, cursor:'pointer', fontWeight:active?600:400 });
  const xBtn = { padding:'3px 8px', borderRadius:6, border:'1px solid var(--border)', background:'transparent', cursor:'pointer', color:'var(--muted)', fontSize:13, flexShrink:0 };

  // ── Flow helpers ─────────────────────────────────────────────────────────────
  const flowParams    = iv.action?.parameters || {};
  const flowId        = flowParams.flow_id        || '';
  const flowCta       = flowParams.flow_cta       || 'Completar formulario';
  const flowHeader    = typeof iv.header === 'object' ? (iv.header?.text || '') : (iv.header || '');
  const updFlow = (patch) => onChange({
    ...iv, type: 'flow',
    action: { name: 'flow', parameters: { flow_message_version: '3', flow_token: 'UNUSED', flow_action: 'navigate', ...flowParams, ...patch } },
  });

  const mkCarouselCard = (idx) => ({
    header: { type:'image', image:{ link:'' } },
    body:   { text:'' },
    footer: { text:'' },
    action: { buttons:[{ type:'reply', reply:{ id:`c${idx}_b0`, title:'' } }] },
  });

  const switchType = (t) => {
    if (t === 'button')   onChange({ ...iv, type:'button',   action:{ buttons: buttons.length ? buttons : [{ type:'reply', reply:{ id:'opt_0', title:'' } }] } });
    else if (t === 'list') onChange({ ...iv, type:'list',    action:{ button: listLabel, sections:[{ rows: rows.length ? rows : [{ id:'opt_0', title:'' }] }] } });
    else if (t === 'carousel') onChange({ type:'carousel', body:{ text: bodyText || '' }, action:{ sections:[{ cards:[mkCarouselCard(0), mkCarouselCard(1)] }] } });
    else if (t === 'flow')    onChange({ type:'flow', body:{ text: bodyText || '' }, header:{ type:'text', text:'' }, action:{ name:'flow', parameters:{ flow_message_version:'3', flow_token:'UNUSED', flow_action:'navigate', flow_id:'', flow_cta:'Completar formulario' } } });
  };

  const updBtns  = (b) => onChange({ ...iv, type:'button', action:{ buttons: b } });
  const updRows  = (r) => onChange({ ...iv, type:'list',   action:{ button: listLabel, sections:[{ rows: r }] } });
  const updLabel = (l) => onChange({ ...iv, type:'list',   action:{ button: l, sections:[{ rows }] } });

  // ── Carousel helpers ──────────────────────────────────────────────────────────
  const carouselCards = iv.action?.sections?.[0]?.cards || [];
  const setCards = (nc) => onChange({ ...iv, type:'carousel', action:{ sections:[{ cards: nc }] } });
  const addCard  = ()    => carouselCards.length < 10 && setCards([...carouselCards, mkCarouselCard(carouselCards.length)]);
  const rmCard   = (i)   => carouselCards.length > 2 && setCards(carouselCards.filter((_,j) => j !== i));
  const updCard  = (i, patch) => setCards(carouselCards.map((c,j) => j === i ? { ...c, ...patch } : c));

  return (
    <div style={{ display:'flex', flexDirection:'column', gap:10 }}>

      {/* Type selector */}
      <div style={{ display:'flex', gap:6, flexWrap:'wrap' }}>
        {[{ v:'button', l:'🔘 Botones (≤3)' }, { v:'list', l:'📋 Lista (≤10)' }, { v:'carousel', l:'🎠 Carrusel' }, { v:'flow', l:'📋 WhatsApp Flow' }].map(o => (
          <button key={o.v} onClick={() => switchType(o.v)} style={chip(itype === o.v)}>{o.l}</button>
        ))}
      </div>

      {/* Body text — shared by button / list / carousel. Flow has its own layout. */}
      {itype !== 'flow' && (
        <div>
          <div style={{ fontSize:11, color:'var(--muted)', marginBottom:4 }}>
            {itype === 'carousel' ? 'Texto introductorio (sobre las tarjetas)' : 'Texto del mensaje'}
          </div>
          <textarea style={{ ...inp, minHeight:60, resize:'vertical' }} value={bodyText}
            onChange={e => onChange({ ...iv, body:{ text: e.target.value } })}
            placeholder={itype === 'carousel' ? 'Ej: ¡Mirá nuestros productos!' : 'Ej: ¿Cómo te puedo ayudar?'} />
        </div>
      )}

      {/* ── Botones ── */}
      {itype === 'button' && (
        <div style={{ display:'flex', flexDirection:'column', gap:6 }}>
          <div style={{ fontSize:11, color:'var(--muted)' }}>Botones (máx 3, 20 caracteres c/u)</div>
          {buttons.map((btn, i) => (
            <div key={i} style={{ display:'flex', gap:6, alignItems:'center' }}>
              <input style={{ ...inp, flex:1 }} maxLength={20} value={btn.reply?.title || ''}
                onChange={e => { const b=[...buttons]; b[i]={ type:'reply', reply:{ id:`opt_${i}`, title:e.target.value } }; updBtns(b); }}
                placeholder={`Botón ${i+1}`} />
              <span style={{ fontSize:11, color:'var(--muted)', minWidth:32, textAlign:'right' }}>{(btn.reply?.title||'').length}/20</span>
              {buttons.length > 1 && <button style={xBtn} onClick={() => updBtns(buttons.filter((_,j)=>j!==i))}>×</button>}
            </div>
          ))}
          {buttons.length < 3 && (
            <button onClick={() => updBtns([...buttons, { type:'reply', reply:{ id:`opt_${buttons.length}`, title:'' } }])}
              style={{ alignSelf:'flex-start', padding:'4px 12px', borderRadius:8, border:'1px dashed var(--border)', background:'transparent', cursor:'pointer', color:'var(--ink-3)', fontSize:12 }}>
              + Agregar botón
            </button>
          )}
        </div>
      )}

      {/* ── Lista ── */}
      {itype === 'list' && (
        <div style={{ display:'flex', flexDirection:'column', gap:6 }}>
          <div>
            <div style={{ fontSize:11, color:'var(--muted)', marginBottom:4 }}>Texto del botón desplegable</div>
            <input style={inp} maxLength={20} value={listLabel} onChange={e => updLabel(e.target.value)} placeholder="Ver opciones" />
          </div>
          <div style={{ fontSize:11, color:'var(--muted)' }}>Opciones (máx 10, 24 caracteres c/u)</div>
          {rows.map((row, i) => (
            <div key={i} style={{ display:'flex', gap:6, alignItems:'center' }}>
              <input style={{ ...inp, flex:1 }} maxLength={24} value={row.title || ''}
                onChange={e => { const r=[...rows]; r[i]={ id:`opt_${i}`, title:e.target.value }; updRows(r); }}
                placeholder={`Opción ${i+1}`} />
              <span style={{ fontSize:11, color:'var(--muted)', minWidth:32, textAlign:'right' }}>{(row.title||'').length}/24</span>
              {rows.length > 1 && <button style={xBtn} onClick={() => updRows(rows.filter((_,j)=>j!==i))}>×</button>}
            </div>
          ))}
          {rows.length < 10 && (
            <button onClick={() => updRows([...rows, { id:`opt_${rows.length}`, title:'' }])}
              style={{ alignSelf:'flex-start', padding:'4px 12px', borderRadius:8, border:'1px dashed var(--border)', background:'transparent', cursor:'pointer', color:'var(--ink-3)', fontSize:12 }}>
              + Agregar opción
            </button>
          )}
        </div>
      )}

      {/* ── Carrusel ── */}
      {itype === 'carousel' && (
        <div style={{ display:'flex', flexDirection:'column', gap:10 }}>
          <div style={{ fontSize:11, color:'var(--muted)' }}>Tarjetas ({carouselCards.length}/10 · mínimo 2)</div>
          {carouselCards.map((card, ci) => {
            const imgUrl  = card.header?.image?.link || '';
            const cBody   = card.body?.text || '';
            const cFoot   = card.footer?.text || '';
            const cBtns   = card.action?.buttons || [];
            const updCBtns = (b) => updCard(ci, { action:{ buttons: b } });
            return (
              <div key={ci} style={{ border:'1px solid var(--border)', borderRadius:10, padding:12, display:'flex', flexDirection:'column', gap:8, background:'var(--cream)' }}>
                <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between' }}>
                  <span style={{ fontSize:12, fontWeight:700, color:'var(--ink-2)' }}>Tarjeta {ci+1}</span>
                  {carouselCards.length > 2 && (
                    <button onClick={() => rmCard(ci)} style={{ background:'none', border:'none', color:'var(--muted)', cursor:'pointer', fontSize:16, lineHeight:1 }}>✕</button>
                  )}
                </div>

                {/* Image URL */}
                <div>
                  <div style={{ fontSize:11, color:'var(--muted)', marginBottom:3 }}>URL de imagen *</div>
                  <input style={{ ...inp, fontSize:12 }} value={imgUrl}
                    onChange={e => updCard(ci, { header:{ type:'image', image:{ link:e.target.value } } })}
                    placeholder="https://mi-web.com/producto.jpg" />
                </div>

                {/* Body */}
                <div>
                  <div style={{ fontSize:11, color:'var(--muted)', marginBottom:3 }}>Texto de la tarjeta * · {cBody.length}/160</div>
                  <textarea style={{ ...inp, minHeight:46, resize:'vertical', fontSize:12 }} maxLength={160} value={cBody}
                    onChange={e => updCard(ci, { body:{ text:e.target.value } })}
                    placeholder="Descripción del producto o contenido" />
                </div>

                {/* Footer */}
                <div>
                  <div style={{ fontSize:11, color:'var(--muted)', marginBottom:3 }}>Pie de tarjeta (opcional) · {cFoot.length}/60</div>
                  <input style={{ ...inp, fontSize:12 }} maxLength={60} value={cFoot}
                    onChange={e => updCard(ci, { footer:{ text:e.target.value } })}
                    placeholder="Precio, fecha, info extra..." />
                </div>

                {/* Card buttons (1-2) */}
                <div>
                  <div style={{ fontSize:11, color:'var(--muted)', marginBottom:4 }}>Botones de la tarjeta (máx 2)</div>
                  {cBtns.map((btn, bi) => {
                    const isLink = btn.type === 'cta_url';
                    const title  = isLink ? (btn.cta_url?.display_text || '') : (btn.reply?.title || '');
                    const url    = btn.cta_url?.url || '';
                    const setBtn = (patch) => { const b=[...cBtns]; b[bi]={ ...b[bi], ...patch }; updCBtns(b); };
                    return (
                      <div key={bi} style={{ background:'var(--white)', borderRadius:8, padding:'8px 10px', border:'1px solid var(--border-soft)', marginBottom:6, display:'flex', flexDirection:'column', gap:5 }}>
                        <div style={{ display:'flex', gap:4, alignItems:'center' }}>
                          <button onClick={() => setBtn({ type:'reply', reply:{ id:`c${ci}_b${bi}`, title }, cta_url:undefined })}
                            style={{ ...chip(!isLink), fontSize:11, padding:'3px 10px' }}>↩ Respuesta</button>
                          <button onClick={() => setBtn({ type:'cta_url', cta_url:{ display_text:title, url }, reply:undefined })}
                            style={{ ...chip(isLink), fontSize:11, padding:'3px 10px' }}>🔗 Link URL</button>
                          {cBtns.length > 1 && (
                            <button onClick={() => updCBtns(cBtns.filter((_,j)=>j!==bi))}
                              style={{ marginLeft:'auto', background:'none', border:'none', color:'var(--muted)', cursor:'pointer', fontSize:15 }}>✕</button>
                          )}
                        </div>
                        <input style={{ ...inp, fontSize:12 }} maxLength={20} value={title}
                          onChange={e => setBtn(isLink
                            ? { type:'cta_url', cta_url:{ display_text:e.target.value, url } }
                            : { type:'reply',   reply:{ id:`c${ci}_b${bi}`, title:e.target.value } })}
                          placeholder="Texto del botón (máx 20 car.)" />
                        {isLink && (
                          <input style={{ ...inp, fontSize:12 }} value={url}
                            onChange={e => setBtn({ type:'cta_url', cta_url:{ display_text:title, url:e.target.value } })}
                            placeholder="https://mi-web.com/producto" />
                        )}
                      </div>
                    );
                  })}
                  {cBtns.length < 2 && (
                    <button onClick={() => updCBtns([...cBtns, { type:'reply', reply:{ id:`c${ci}_b${cBtns.length}`, title:'' } }])}
                      style={{ padding:'3px 10px', borderRadius:8, border:'1px dashed var(--border)', background:'transparent', cursor:'pointer', color:'var(--ink-3)', fontSize:11 }}>
                      + Agregar botón
                    </button>
                  )}
                </div>
              </div>
            );
          })}
          {carouselCards.length < 10 && (
            <button onClick={addCard}
              style={{ alignSelf:'flex-start', padding:'6px 16px', borderRadius:8, border:'1px dashed var(--border)', background:'transparent', cursor:'pointer', color:'var(--ink-3)', fontSize:12 }}>
              + Agregar tarjeta
            </button>
          )}
        </div>
      )}

      {/* ── WhatsApp Flow ── */}
      {itype === 'flow' && (
        <div style={{ display:'flex', flexDirection:'column', gap:10 }}>

          {/* Flow ID */}
          <div>
            <div style={{ display:'flex', alignItems:'center', gap:6, marginBottom:4 }}>
              <div style={{ fontSize:11, color:'var(--muted)' }}>Flow ID <span style={{ color:'var(--danger)' }}>*</span></div>
              <a href="https://pipochat.com/whatsapp-flows" target="_blank" rel="noopener"
                style={{ fontSize:10, color:'var(--green)', textDecoration:'none' }}>
                Ver mis flows →
              </a>
            </div>
            <input style={{ ...inp, fontFamily:'monospace', fontSize:12 }} value={flowId}
              onChange={e => updFlow({ flow_id: e.target.value })}
              placeholder="1234567890123456" />
          </div>

          {/* CTA button text */}
          <div>
            <div style={{ fontSize:11, color:'var(--muted)', marginBottom:4 }}>Texto del botón CTA <span style={{ fontSize:10 }}>({flowCta.length}/20)</span></div>
            <input style={inp} maxLength={20} value={flowCta}
              onChange={e => updFlow({ flow_cta: e.target.value })}
              placeholder="Completar formulario" />
          </div>

          {/* Header (optional) */}
          <div>
            <div style={{ fontSize:11, color:'var(--muted)', marginBottom:4 }}>Header (opcional)</div>
            <input style={inp} maxLength={60} value={flowHeader}
              onChange={e => onChange({ ...iv, type:'flow', header: e.target.value ? { type:'text', text:e.target.value } : undefined })}
              placeholder="Ej: Elegí tu sede" />
          </div>

          {/* Info box */}
          <div style={{ background:'var(--green-light)', border:'1px solid var(--green-mid)', borderRadius:8, padding:'10px 12px', fontSize:12, color:'var(--green-hover)', lineHeight:1.5 }}>
            <strong>💡 Cómo funciona:</strong> el agente manda un mensaje con el botón "<em>{flowCta || 'Completar formulario'}</em>". El usuario lo toca y se abre el formulario nativo de WhatsApp. Al enviarlo, los campos se guardan automáticamente como atributos del contacto.
          </div>

          {/* Preview */}
          {flowId && (
            <div style={{ marginTop:2 }}>
              <div style={{ fontSize:11, color:'var(--muted)', marginBottom:5 }}>Vista previa WhatsApp</div>
              <div style={{ background:'#e5ddd5', borderRadius:12, padding:8, maxWidth:260, fontFamily:'system-ui,sans-serif' }}>
                <div style={{ background:'white', borderRadius:10, overflow:'hidden', boxShadow:'0 1px 2px rgba(0,0,0,.1)' }}>
                  {flowHeader && <div style={{ padding:'10px 12px 0', fontSize:12, fontWeight:600, color:'#111' }}>{flowHeader}</div>}
                  <div style={{ padding:'10px 12px', fontSize:13, color:'#111', whiteSpace:'pre-wrap' }}>{bodyText || '...'}</div>
                  <div style={{ borderTop:'1px solid #f0f0f0', padding:'8px 12px', color:'#00a884', textAlign:'center', fontSize:13, display:'flex', alignItems:'center', justifyContent:'center', gap:6 }}>
                    📋 {flowCta || 'Completar formulario'}
                  </div>
                </div>
              </div>
            </div>
          )}
        </div>
      )}

      {/* Footer — only for button / list */}
      {itype !== 'carousel' && itype !== 'flow' && (
        <div>
          <div style={{ fontSize:11, color:'var(--muted)', marginBottom:4 }}>Footer (opcional)</div>
          <input style={inp} value={footerText} onChange={e => onChange({ ...iv, footer: e.target.value ? { text:e.target.value } : undefined })}
            placeholder="Texto pequeño debajo del mensaje" />
        </div>
      )}

      <WaInteractivePreview interactive={iv} />
    </div>
  );
}

// ─── Conversation Rule Action Types ───────────────────────────────────────────

const CONV_ACTION_TYPES = [
  { value:'add_tag',             label:'Agregar etiqueta(s)' },
  { value:'create_lead',         label:'Crear lead en pipeline' },
  { value:'move_lead',           label:'Mover lead a etapa' },
  { value:'assign_operator',     label:'Asignar a operador' },
  { value:'assign_team',         label:'Asignar a equipo' },
  { value:'assign_roundrobin',   label:'Round-robin operadores' },
  { value:'send_text',           label:'💬 Enviar mensaje de texto' },
  { value:'send_interactive',    label:'🔘 Enviar botones interactivos' },
  { value:'send_template',       label:'Enviar template' },
  { value:'update_status',       label:'Cambiar estado conversación' },
  { value:'add_lead_attribute',  label:'Agregar atributo al lead' },
  { value:'update_contact_attr', label:'Agregar atributo al contacto' },
  { value:'handoff',             label:'🤝 Handoff a humano (con resumen IA)' },
  { value:'score_lead',          label:'⭐ Puntuar lead con IA' },
];

const DAYS_LABELS = ['Dom','Lun','Mar','Mié','Jue','Vie','Sáb'];

function ConvConditionEditor({ cond, onChange, onRemove, tags }) {
  const def = CONV_CONDITION_TYPES.find(t => t.value === cond.type) || CONV_CONDITION_TYPES[0];
  const s = { input: { padding:'5px 8px', borderRadius:6, border:'1px solid var(--border)', background:'var(--bg)', color:'var(--text)', fontSize:13, width:'100%', boxSizing:'border-box' } };

  return (
    <div style={{ display:'flex', gap:6, alignItems:'flex-start', marginBottom:6 }}>
      <div style={{ flex:1, display:'flex', gap:6, flexWrap:'wrap', alignItems:'center' }}>
        <select style={{ ...s.input, width:'auto', minWidth:190 }}
          value={cond.type} onChange={e => onChange({ ...cond, type: e.target.value })}>
          {CONV_CONDITION_TYPES.map(t => <option key={t.value} value={t.value}>{t.label}</option>)}
        </select>

        {def.fields.includes('count') && (
          <input type="number" min={1} style={{ ...s.input, width:70 }} placeholder="N"
            value={cond.count ?? ''} onChange={e => onChange({ ...cond, count: Number(e.target.value) })} />
        )}
        {def.fields.includes('keywords') && (
          <input style={{ ...s.input, flex:1, minWidth:140 }} placeholder="palabras, separadas, por coma"
            value={(cond.keywords || []).join(', ')}
            onChange={e => onChange({ ...cond, keywords: e.target.value.split(',').map(k => k.trim()).filter(Boolean) })} />
        )}
        {def.fields.includes('tagName') && (
          <input list="tag-names-list" style={{ ...s.input, flex:1, minWidth:140 }} placeholder="nombre etiqueta"
            value={cond.tagName || ''}
            onChange={e => onChange({ ...cond, tagName: e.target.value })} />
        )}
        {def.fields.includes('hourFrom') && (
          <>
            <input type="number" min={0} max={23} style={{ ...s.input, width:55 }} placeholder="Desde"
              value={cond.hourFrom ?? ''} onChange={e => onChange({ ...cond, hourFrom: Number(e.target.value) })} />
            <span style={{ fontSize:12, color:'var(--muted)' }}>a</span>
            <input type="number" min={0} max={23} style={{ ...s.input, width:55 }} placeholder="Hasta"
              value={cond.hourTo ?? ''} onChange={e => onChange({ ...cond, hourTo: Number(e.target.value) })} />
          </>
        )}
        {def.fields.includes('days') && (
          <div style={{ display:'flex', gap:4 }}>
            {DAYS_LABELS.map((d, i) => (
              <label key={i} style={{ display:'flex', alignItems:'center', gap:3, fontSize:12, cursor:'pointer' }}>
                <input type="checkbox" checked={(cond.days || []).includes(i)}
                  onChange={e => {
                    const cur = cond.days || [];
                    onChange({ ...cond, days: e.target.checked ? [...cur, i] : cur.filter(x => x !== i) });
                  }} />
                {d}
              </label>
            ))}
          </div>
        )}
        {def.fields.includes('attributeKey') && (
          <input style={{ ...s.input, flex:1, minWidth:120 }} placeholder="clave atributo"
            value={cond.attributeKey || ''}
            onChange={e => onChange({ ...cond, attributeKey: e.target.value })} />
        )}
        {def.fields.includes('attributeValue') && (
          <input style={{ ...s.input, flex:1, minWidth:120 }} placeholder="valor esperado"
            value={cond.attributeValue || ''}
            onChange={e => onChange({ ...cond, attributeValue: e.target.value })} />
        )}
        {def.fields.includes('aiCriteria') && (
          <div style={{ width:'100%', marginTop:4 }}>
            <textarea style={{ ...s.input, minHeight:56, resize:'vertical', fontSize:12 }}
              placeholder="El lead muestra intención real de compra, menciona presupuesto o tiene urgencia..."
              value={cond.aiCriteria || ''}
              onChange={e => onChange({ ...cond, aiCriteria: e.target.value })} />
            <div style={{ fontSize:11, color:'var(--muted)', marginTop:2 }}>
              Claude lee toda la conversación y evalúa si se cumple este criterio. Solo se llama cuando las demás condiciones AND ya se cumplieron.
            </div>
          </div>
        )}
      </div>
      <button onClick={onRemove} style={{ background:'none', border:'none', cursor:'pointer', color:'var(--muted)', fontSize:16, padding:'4px 2px', flexShrink:0 }}>✕</button>
    </div>
  );
}

function ConvActionEditor({ action, onChange, onRemove, pipelines, tags, users, teams, templates }) {
  const s = { input: { padding:'5px 8px', borderRadius:6, border:'1px solid var(--border)', background:'var(--bg)', color:'var(--text)', fontSize:13, width:'100%', boxSizing:'border-box' } };

  const stagesForPipeline = (pipelineId) => {
    const pl = pipelines.find(p => p._id === pipelineId);
    return pl?.stages || [];
  };

  return (
    <div style={{ display:'flex', gap:6, alignItems:'flex-start', marginBottom:6 }}>
      <div style={{ flex:1, display:'flex', gap:6, flexWrap:'wrap', alignItems:'flex-start' }}>
        <select style={{ ...s.input, width:'auto', minWidth:200 }}
          value={action.type} onChange={e => onChange({ ...action, type: e.target.value })}>
          {CONV_ACTION_TYPES.map(t => <option key={t.value} value={t.value}>{t.label}</option>)}
        </select>

        {/* add_tag */}
        {action.type === 'add_tag' && (
          <div style={{ flex:1, minWidth:200 }}>
            <div style={{ fontSize:11, color:'var(--muted)', marginBottom:3 }}>Etiquetas (nombres separados por coma)</div>
            <input style={s.input} placeholder="etiqueta1, etiqueta2"
              value={(action.tagNames || []).join(', ')}
              onChange={e => onChange({ ...action, tagNames: e.target.value.split(',').map(k=>k.trim()).filter(Boolean) })} />
            <div style={{ fontSize:10, color:'var(--muted)', marginTop:2 }}>Se resuelven automáticamente desde el Registro de Etiquetas</div>
          </div>
        )}

        {/* create_lead / move_lead */}
        {(action.type === 'create_lead' || action.type === 'move_lead') && (
          <div style={{ flex:1, minWidth:200, display:'flex', flexDirection:'column', gap:6 }}>
            {action.type === 'create_lead' && (
              <select style={s.input} value={action.pipelineId || ''}
                onChange={e => onChange({ ...action, pipelineId: e.target.value, stageId: '' })}>
                <option value="">— Pipeline —</option>
                {pipelines.map(p => <option key={p._id} value={p._id}>{p.title||p.name}</option>)}
              </select>
            )}
            <select style={s.input} value={action.stageId || ''}
              onChange={e => onChange({ ...action, stageId: e.target.value })}>
              <option value="">— Etapa —</option>
              {stagesForPipeline(action.pipelineId).map(s2 => <option key={s2._id} value={s2._id}>{s2.displayName || s2.name}</option>)}
            </select>
          </div>
        )}

        {/* assign_operator */}
        {action.type === 'assign_operator' && (
          <select style={{ ...s.input, flex:1, minWidth:180 }} value={action.operatorId || ''}
            onChange={e => onChange({ ...action, operatorId: e.target.value })}>
            <option value="">— Operador —</option>
            {users.map(u => <option key={u._id} value={u._id}>{u.name}</option>)}
          </select>
        )}

        {/* assign_team */}
        {action.type === 'assign_team' && (
          <select style={{ ...s.input, flex:1, minWidth:180 }} value={action.teamId || ''}
            onChange={e => onChange({ ...action, teamId: e.target.value })}>
            <option value="">— Equipo —</option>
            {teams.map(t => <option key={t._id} value={t._id}>{t.name}</option>)}
          </select>
        )}

        {/* assign_roundrobin */}
        {action.type === 'assign_roundrobin' && (() => {
          const tf = action.teamFilter || '';
          const tmObj = (teams || []).find(t => t._id === tf);
          const visibleUsers = tmObj ? users.filter(u => (tmObj.operatorIds || []).includes(u._id)) : users;
          const selCount = (action.operatorIds || []).filter(id => visibleUsers.some(u => u._id === id)).length;
          const btn = { padding:'2px 8px', borderRadius:6, border:'1px solid var(--border)', cursor:'pointer', fontSize:11, background:'transparent', color:'var(--text)' };
          return (
            <div style={{ flex:1, minWidth:240, display:'flex', flexDirection:'column', gap:6 }}>
              {(teams || []).length > 0 && (
                <select style={s.input} value={tf}
                  onChange={e => { const id = e.target.value; const tm = (teams || []).find(t => t._id === id); onChange({ ...action, teamFilter: id, operatorIds: id ? ((tm && tm.operatorIds) || []) : (action.operatorIds || []) }); }}>
                  <option value="">— Equipo (todos los operadores) —</option>
                  {(teams || []).map(t => <option key={t._id} value={t._id}>{t.name} ({(t.operatorIds || []).length})</option>)}
                </select>
              )}
              <div style={{ display:'flex', gap:8, alignItems:'center', flexWrap:'wrap' }}>
                <span style={{ fontSize:11, color:'var(--muted)' }}>Operadores en rotación</span>
                <button type="button" onClick={() => onChange({ ...action, operatorIds: visibleUsers.map(u => u._id) })} style={btn}>✓ Todos</button>
                <button type="button" onClick={() => onChange({ ...action, operatorIds: [] })} style={btn}>✕ Ninguno</button>
                <span style={{ fontSize:11, color:'var(--muted)' }}>{selCount}/{visibleUsers.length}{tf ? ' (equipo)' : ''}</span>
              </div>
              <div style={{ display:'flex', flexDirection:'column', gap:4, maxHeight:200, overflowY:'auto' }}>
                {visibleUsers.map(u => (
                  <label key={u._id} style={{ display:'flex', alignItems:'center', gap:6, fontSize:13, cursor:'pointer' }}>
                    <input type="checkbox"
                      checked={(action.operatorIds || []).includes(u._id)}
                      onChange={e => {
                        const cur = action.operatorIds || [];
                        onChange({ ...action, operatorIds: e.target.checked ? [...cur, u._id] : cur.filter(id => id !== u._id) });
                      }} />
                    {u.name}
                  </label>
                ))}
              </div>
              <label style={{ display:'flex', alignItems:'center', gap:6, fontSize:12, cursor:'pointer' }}>
                <input type="checkbox" checked={!!action.onlineOnly}
                  onChange={e => onChange({ ...action, onlineOnly: e.target.checked })} />
                Solo operadores online en este momento
              </label>
              {action.onlineOnly && (
                <label style={{ display:'flex', alignItems:'center', gap:6, fontSize:12, cursor:'pointer', paddingLeft:18 }}>
                  <input type="checkbox" checked={!!action.fallbackAll}
                    onChange={e => onChange({ ...action, fallbackAll: e.target.checked })} />
                  Si no hay nadie online, asignar igual entre todos
                </label>
              )}
              <label style={{ display:'flex', alignItems:'center', gap:6, fontSize:12, cursor:'pointer', borderTop:'1px solid var(--border)', paddingTop:6, marginTop:2 }}>
                <input type="checkbox" checked={!!action.sticky}
                  onChange={e => onChange({ ...action, sticky: e.target.checked })} />
                Mantener el mismo operador para el mismo contacto (no re-rotar)
              </label>
              {action.sticky && (
                <div style={{ paddingLeft:18, display:'flex', flexDirection:'column', gap:6 }}>
                  <div style={{ fontSize:11, color:'var(--muted)' }}>
                    Si el contacto ya fue asignado, vuelve al mismo operador. Si está offline y tenés "solo online" activo, cae a uno online.
                  </div>
                  <label style={{ display:'flex', alignItems:'center', gap:6, fontSize:12 }}>
                    Mantenerlo por
                    <input type="number" min={0} style={{ ...s.input, width:62 }} value={action.stickyDays ?? 0}
                      onChange={e => onChange({ ...action, stickyDays: Math.max(0, parseInt(e.target.value) || 0) })} />
                    días <span style={{ color:'var(--muted)', fontSize:11 }}>(0 = para siempre; pasado ese tiempo vuelve al round-robin entre los online)</span>
                  </label>
                </div>
              )}
            </div>
          );
        })()}

        {/* send_text */}
        {action.type === 'send_text' && (
          <textarea style={{ ...s.input, flex:1, minWidth:220, minHeight:60, resize:'vertical' }}
            placeholder="Mensaje. Podés usar {{name}} y {{phone}}"
            value={action.message || ''}
            onChange={e => onChange({ ...action, message: e.target.value })} />
        )}

        {/* send_interactive */}
        {action.type === 'send_interactive' && (
          <div style={{ flex:1, minWidth:280 }}>
            <InteractiveMessageBuilder
              value={action.interactive}
              onChange={iv => onChange({ ...action, interactive: iv })} />
          </div>
        )}

        {/* send_template */}
        {action.type === 'send_template' && (
          <select style={{ ...s.input, flex:1, minWidth:200 }} value={action.templateId || ''}
            onChange={e => onChange({ ...action, templateId: e.target.value })}>
            <option value="">— Template —</option>
            {templates.map(t => <option key={t._id} value={t._id}>{t.name}</option>)}
          </select>
        )}

        {/* update_status */}
        {action.type === 'update_status' && (
          <select style={{ ...s.input, flex:1, minWidth:150 }} value={action.status || ''}
            onChange={e => onChange({ ...action, status: e.target.value })}>
            <option value="">— Estado —</option>
            <option value="open">Abierta</option>
            <option value="pending">Pendiente</option>
            <option value="solved">Resuelta</option>
          </select>
        )}

        {/* add_lead_attribute / update_contact_attr */}
        {(action.type === 'add_lead_attribute' || action.type === 'update_contact_attr') && (
          <>
            <input style={{ ...s.input, flex:1, minWidth:100 }} placeholder="clave"
              value={action.attributeKey || ''}
              onChange={e => onChange({ ...action, attributeKey: e.target.value })} />
            <input style={{ ...s.input, flex:1, minWidth:100 }} placeholder="valor"
              value={action.attributeValue || ''}
              onChange={e => onChange({ ...action, attributeValue: e.target.value })} />
          </>
        )}
      </div>
      <button onClick={onRemove} style={{ background:'none', border:'none', cursor:'pointer', color:'var(--muted)', fontSize:16, padding:'4px 2px', flexShrink:0 }}>✕</button>
    </div>
  );
}

function ConvRuleModal({ rule, onClose, onSaved }) {
  const { pipelines, tags, users, teams, templates } = usePipochat();
  const [form, setForm] = useState(rule ? { ...rule } : {
    name: '', description: '', enabled: false, priority: 50,
    conditionOperator: 'AND', conditions: [], actions: [],
    fireOnce: true, stopOnMatch: false,
  });
  const [saving, setSaving] = useState(false);

  const setField = (k, v) => setForm(f => ({ ...f, [k]: v }));

  const addCondition = () => setForm(f => ({ ...f, conditions: [...f.conditions, { type: 'first_message' }] }));
  const updateCondition = (i, c) => setForm(f => { const cs=[...f.conditions]; cs[i]=c; return {...f,conditions:cs}; });
  const removeCondition = (i) => setForm(f => ({ ...f, conditions: f.conditions.filter((_,j)=>j!==i) }));

  const addAction = () => setForm(f => ({ ...f, actions: [...f.actions, { type: 'add_tag' }] }));
  const updateAction = (i, a) => setForm(f => { const as=[...f.actions]; as[i]=a; return {...f,actions:as}; });
  const removeAction = (i) => setForm(f => ({ ...f, actions: f.actions.filter((_,j)=>j!==i) }));

  const save = async () => {
    if (!form.name.trim()) return alert('La regla necesita un nombre');
    if (!form.conditions.length) return alert('Agregá al menos una condición');
    if (!form.actions.length) return alert('Agregá al menos una acción');
    setSaving(true);
    const url = rule ? `/api/conv-rules/${rule.id}` : '/api/conv-rules';
    const method = rule ? 'PUT' : 'POST';
    const res = await apiFetch(url, { method, headers:{'Content-Type':'application/json'}, body: JSON.stringify(form) }).then(r=>r.json());
    setSaving(false);
    if (res.error) return alert(res.error);
    onSaved(res);
    onClose();
  };

  const modal = { position:'fixed', inset:0, background:'rgba(0,0,0,0.5)', display:'flex', alignItems:'flex-start', justifyContent:'center', zIndex:1000, padding:'24px 16px', overflowY:'auto' };
  const box = { background:'var(--surface)', borderRadius:14, padding:'28px 28px 24px', width:'100%', maxWidth:720, boxShadow:'0 20px 60px rgba(0,0,0,0.3)', marginBottom:24 };
  const inp = { padding:'7px 10px', borderRadius:8, border:'1px solid var(--border)', background:'var(--bg)', color:'var(--text)', fontSize:13, width:'100%', boxSizing:'border-box' };
  const label = { fontSize:12, color:'var(--muted)', display:'block', marginBottom:4 };

  return (
    <div style={modal} onClick={e => e.target===e.currentTarget && onClose()}>
      <div style={box}>
        <div style={{ display:'flex', justifyContent:'space-between', alignItems:'center', marginBottom:22 }}>
          <div style={{ fontSize:18, fontWeight:800 }}>{rule ? 'Editar regla' : 'Nueva regla de conversación'}</div>
          <button onClick={onClose} style={{ background:'none', border:'none', cursor:'pointer', fontSize:20, color:'var(--muted)' }}>✕</button>
        </div>

        {/* Name + priority */}
        <div style={{ display:'grid', gridTemplateColumns:'1fr auto auto', gap:12, marginBottom:16 }}>
          <div>
            <span style={label}>Nombre</span>
            <input style={inp} value={form.name} onChange={e=>setField('name',e.target.value)} placeholder="Ej: Crear lead al 2do mensaje" />
          </div>
          <div>
            <span style={label}>Prioridad</span>
            <input type="number" style={{ ...inp, width:80 }} value={form.priority} onChange={e=>setField('priority',Number(e.target.value))} />
          </div>
          <div style={{ display:'flex', flexDirection:'column', gap:4, paddingTop:18 }}>
            <label style={{ display:'flex', alignItems:'center', gap:6, fontSize:13, cursor:'pointer', whiteSpace:'nowrap' }}>
              <input type="checkbox" checked={form.fireOnce} onChange={e=>setField('fireOnce',e.target.checked)} /> Solo 1 vez por conv.
            </label>
            <label style={{ display:'flex', alignItems:'center', gap:6, fontSize:13, cursor:'pointer', whiteSpace:'nowrap' }}>
              <input type="checkbox" checked={form.stopOnMatch} onChange={e=>setField('stopOnMatch',e.target.checked)} /> Detener si aplica
            </label>
          </div>
        </div>

        {/* Conditions */}
        <div style={{ marginBottom:16 }}>
          <div style={{ display:'flex', justifyContent:'space-between', alignItems:'center', marginBottom:8 }}>
            <span style={{ fontWeight:700, fontSize:14 }}>SI (condiciones)</span>
            <div style={{ display:'flex', gap:8, alignItems:'center' }}>
              <span style={{ fontSize:12, color:'var(--muted)' }}>Operador:</span>
              {['AND','OR'].map(op => (
                <button key={op} onClick={()=>setField('conditionOperator',op)}
                  style={{ padding:'3px 10px', borderRadius:6, border:'1px solid var(--border)', cursor:'pointer', fontSize:12,
                    background: form.conditionOperator===op ? 'var(--primary)' : 'transparent',
                    color: form.conditionOperator===op ? '#fff' : 'var(--text)' }}>
                  {op}
                </button>
              ))}
            </div>
          </div>
          <div style={{ background:'var(--bg)', borderRadius:8, padding:12, border:'1px solid var(--border)' }}>
            {form.conditions.length === 0 && (
              <div style={{ fontSize:13, color:'var(--muted)', textAlign:'center', padding:'8px 0' }}>Sin condiciones</div>
            )}
            {form.conditions.map((c, i) => (
              <ConvConditionEditor key={i} cond={c} onChange={nc=>updateCondition(i,nc)} onRemove={()=>removeCondition(i)} tags={tags} />
            ))}
            <button onClick={addCondition} style={{ fontSize:12, color:'var(--primary)', background:'none', border:'none', cursor:'pointer', padding:'4px 0' }}>+ Agregar condición</button>
          </div>
        </div>

        {/* Actions */}
        <div style={{ marginBottom:20 }}>
          <div style={{ fontWeight:700, fontSize:14, marginBottom:8 }}>ENTONCES (acciones)</div>
          <div style={{ background:'var(--bg)', borderRadius:8, padding:12, border:'1px solid var(--border)' }}>
            {form.actions.length === 0 && (
              <div style={{ fontSize:13, color:'var(--muted)', textAlign:'center', padding:'8px 0' }}>Sin acciones</div>
            )}
            {form.actions.map((a, i) => (
              <ConvActionEditor key={i} action={a} onChange={na=>updateAction(i,na)} onRemove={()=>removeAction(i)}
                pipelines={pipelines} tags={tags} users={users} teams={teams} templates={templates} />
            ))}
            <button onClick={addAction} style={{ fontSize:12, color:'var(--primary)', background:'none', border:'none', cursor:'pointer', padding:'4px 0' }}>+ Agregar acción</button>
          </div>
        </div>

        {/* datalist for tag names */}
        <datalist id="tag-names-list">
          {tags.map(t => <option key={t._id} value={t.name} />)}
        </datalist>

        {/* Footer */}
        <div style={{ display:'flex', gap:10, justifyContent:'flex-end' }}>
          <button onClick={onClose} style={{ padding:'8px 18px', borderRadius:8, border:'1px solid var(--border)', background:'transparent', cursor:'pointer', color:'var(--text)' }}>Cancelar</button>
          <button onClick={save} disabled={saving} style={{ padding:'8px 18px', borderRadius:8, border:'none', background:'var(--primary)', color:'#fff', cursor:'pointer', fontWeight:600 }}>
            {saving ? 'Guardando...' : rule ? 'Guardar cambios' : 'Crear regla'}
          </button>
        </div>
      </div>
    </div>
  );
}

function ConvRuleCard({ rule, onEdit, onDelete, onToggle }) {
  const condCount = rule.conditions?.length || 0;
  const actCount  = rule.actions?.length || 0;

  const badge = (color, text) => (
    <span style={{ fontSize:10, padding:'2px 7px', borderRadius:20, background:color+'22', color, fontWeight:600, border:`1px solid ${color}44` }}>{text}</span>
  );

  const condSummary = (rule.conditions || []).map(c => {
    const def = CONV_CONDITION_TYPES.find(t=>t.value===c.type);
    return def?.label || c.type;
  }).join(` ${rule.conditionOperator} `);

  const actSummary = (rule.actions || []).map(a => {
    const def = CONV_ACTION_TYPES.find(t=>t.value===a.type);
    return def?.label || a.type;
  }).join(' → ');

  return (
    <div style={{ background:'var(--surface)', border:'1px solid var(--border)', borderRadius:12, padding:'14px 16px', marginBottom:10 }}>
      <div style={{ display:'flex', justifyContent:'space-between', alignItems:'flex-start' }}>
        <div style={{ flex:1 }}>
          <div style={{ display:'flex', alignItems:'center', gap:8, marginBottom:4 }}>
            <span style={{ fontWeight:700, fontSize:15 }}>{rule.name}</span>
            {badge(rule.enabled ? '#10b981' : '#94a3b8', rule.enabled ? 'Activa' : 'Inactiva')}
            {badge('#6366f1', `P${rule.priority}`)}
            {rule.fireOnce && badge('#f59e0b', '1 vez')}
            {rule.stopOnMatch && badge('#ef4444', 'Stop')}
          </div>
          <div style={{ fontSize:12, color:'var(--muted)', marginBottom:3 }}>
            <strong>SI:</strong> {condSummary || '—'}
          </div>
          <div style={{ fontSize:12, color:'var(--muted)' }}>
            <strong>ENTONCES:</strong> {actSummary || '—'}
          </div>
        </div>
        <div style={{ display:'flex', gap:6, alignItems:'center', marginLeft:12 }}>
          <label style={{ display:'flex', alignItems:'center', cursor:'pointer' }}>
            <input type="checkbox" checked={rule.enabled} onChange={e=>onToggle(rule.id, e.target.checked)}
              style={{ width:16, height:16, cursor:'pointer' }} />
          </label>
          <button onClick={()=>onEdit(rule)} style={{ padding:'5px 10px', borderRadius:7, border:'1px solid var(--border)', background:'transparent', cursor:'pointer', fontSize:12, color:'var(--text)' }}>Editar</button>
          <button onClick={()=>onDelete(rule.id)} style={{ padding:'5px 10px', borderRadius:7, border:'none', background:'#fee2e2', color:'#ef4444', cursor:'pointer', fontSize:12, fontWeight:600 }}>Eliminar</button>
        </div>
      </div>
    </div>
  );
}

const EXAMPLE_CONV_RULES = [
  {
    label: '1er mensaje → Crear lead + Asignar equipo',
    rule: { name:'Lead al primer contacto', priority:10, conditionOperator:'AND', fireOnce:true, stopOnMatch:false,
      conditions:[{type:'first_message'}],
      actions:[{type:'create_lead',pipelineId:'',stageId:''},{type:'assign_team',teamId:''}] }
  },
  {
    label: '2do mensaje → Agregar etiqueta "interesado"',
    rule: { name:'Marcar como interesado', priority:20, conditionOperator:'AND', fireOnce:true, stopOnMatch:false,
      conditions:[{type:'message_count_eq',count:2}],
      actions:[{type:'add_tag',tagNames:['interesado']}] }
  },
  {
    label: 'Mensaje con "precio" o "costo" → Round-robin ventas',
    rule: { name:'Consulta de precio → Ventas', priority:30, conditionOperator:'AND', fireOnce:true, stopOnMatch:false,
      conditions:[{type:'message_contains',keywords:['precio','costo','cuánto','cuanto','tarifa','plan']}],
      actions:[{type:'assign_roundrobin',operatorIds:[],onlineOnly:true,fallbackAll:true}] }
  },
  {
    label: 'Fuera de horario laboral → Respuesta automática',
    rule: { name:'Fuera de horario', priority:5, conditionOperator:'AND', fireOnce:false, stopOnMatch:false,
      conditions:[{type:'first_message'},{type:'hour_between',hourFrom:18,hourTo:9}],
      actions:[{type:'send_text',message:'Hola {{name}}! 👋 Recibimos tu mensaje. Nuestro equipo te responde en horario laboral (9-18hs). Te contactamos pronto!'}] }
  },
  {
    label: 'Lead calificado (≥3 mensajes) → Mover etapa',
    rule: { name:'Calificado al 3er mensaje', priority:40, conditionOperator:'AND', fireOnce:true, stopOnMatch:false,
      conditions:[{type:'message_count_gte',count:3},{type:'has_lead'}],
      actions:[{type:'move_lead',stageId:''}] }
  },
];

// ─── Operator Timeout Panel ───────────────────────────────────────────────────

function OperatorTimeoutModal({ rule, onClose, onSaved }) {
  const { users, teams, pipelines } = usePipochat();
  const defaultForm = {
    name: '', enabled: false, minutesWithoutReply: 30, pipelineId: '',
    action: 'reassign_roundrobin', operatorId: '', teamId: '',
    operatorIds: [], onlineOnly: false, fallbackAll: true, notifyText: '',
  };
  const [form, setForm] = useState(rule ? { ...defaultForm, ...rule } : defaultForm);
  const [saving, setSaving] = useState(false);
  const [rrTeam, setRrTeam] = useState('');
  const setField = (k, v) => setForm(f => ({ ...f, [k]: v }));

  const save = async () => {
    if (!form.name.trim()) return alert('Poné un nombre para la regla');
    setSaving(true);
    const url = rule ? `/api/operator-timeout/${rule.id}` : '/api/operator-timeout';
    const method = rule ? 'PUT' : 'POST';
    const res = await apiFetch(url, { method, headers: {'Content-Type':'application/json'}, body: JSON.stringify(form) }).then(r => r.json());
    setSaving(false);
    if (res.error) return alert(res.error);
    onSaved(res); onClose();
  };

  const modal = { position:'fixed', inset:0, background:'rgba(0,0,0,0.5)', display:'flex', alignItems:'flex-start', justifyContent:'center', zIndex:1000, padding:'24px 16px', overflowY:'auto' };
  const box   = { background:'var(--surface)', borderRadius:14, padding:'28px 28px 24px', width:'100%', maxWidth:620, boxShadow:'0 20px 60px rgba(0,0,0,0.3)', marginBottom:24 };
  const inp   = { padding:'7px 10px', borderRadius:8, border:'1px solid var(--border)', background:'var(--bg)', color:'var(--text)', fontSize:13, width:'100%', boxSizing:'border-box' };
  const lbl   = { fontSize:12, color:'var(--muted)', display:'block', marginBottom:4 };
  const sec   = { marginBottom:18 };

  return (
    <div style={modal} onClick={e => e.target===e.currentTarget && onClose()}>
      <div style={box}>
        <div style={{ display:'flex', justifyContent:'space-between', alignItems:'center', marginBottom:22 }}>
          <div style={{ fontSize:18, fontWeight:800 }}>{rule ? 'Editar' : 'Nueva'} regla de timeout</div>
          <button onClick={onClose} style={{ background:'none', border:'none', cursor:'pointer', fontSize:20, color:'var(--muted)' }}>✕</button>
        </div>

        {/* Name + Enable */}
        <div style={{ display:'grid', gridTemplateColumns:'1fr auto', gap:10, alignItems:'end', ...sec }}>
          <div>
            <span style={lbl}>Nombre de la regla</span>
            <input style={inp} value={form.name} onChange={e=>setField('name',e.target.value)} placeholder="Timeout 30 min - reasignar al equipo de ventas" />
          </div>
          <label style={{ display:'flex', alignItems:'center', gap:6, fontSize:13, cursor:'pointer', whiteSpace:'nowrap', paddingBottom:2 }}>
            <input type="checkbox" checked={form.enabled} onChange={e=>setField('enabled',e.target.checked)} />
            Activa
          </label>
        </div>

        {/* Timeout minutes */}
        <div style={sec}>
          <span style={lbl}>Tiempo sin respuesta del operador</span>
          <div style={{ display:'flex', alignItems:'center', gap:8 }}>
            <input type="number" min="1" style={{ ...inp, width:100 }} value={form.minutesWithoutReply} onChange={e=>setField('minutesWithoutReply',Number(e.target.value))} />
            <span style={{ fontSize:13, color:'var(--muted)' }}>minutos</span>
          </div>
          <div style={{ fontSize:11, color:'var(--muted)', marginTop:4 }}>
            Si el cliente envió el último mensaje y pasaron estos minutos sin respuesta del operador, se dispara la acción.
          </div>
        </div>

        {/* Pipeline filter */}
        <div style={sec}>
          <span style={lbl}>Aplicar solo a conversaciones en este pipeline (opcional)</span>
          <select style={inp} value={form.pipelineId||''} onChange={e=>setField('pipelineId',e.target.value)}>
            <option value="">— Todos los pipelines —</option>
            {pipelines.map(p=><option key={p._id} value={p._id}>{p.title||p.name}</option>)}
          </select>
        </div>

        {/* Action */}
        <div style={sec}>
          <span style={{ fontWeight:700, fontSize:13, display:'block', marginBottom:8 }}>Acción al timeout</span>
          <div style={{ display:'flex', gap:8, flexWrap:'wrap', marginBottom:10 }}>
            {[['reassign_roundrobin','Round-robin'],['reassign_operator','Operador fijo'],['reassign_team','Equipo'],['unassign','Desasignar']].map(([v,l]) => (
              <button key={v} onClick={()=>setField('action',v)}
                style={{ padding:'5px 12px', borderRadius:7, border:'1px solid var(--border)', cursor:'pointer', fontSize:12,
                  background:form.action===v?'var(--primary)':'transparent', color:form.action===v?'#fff':'var(--text)' }}>{l}</button>
            ))}
          </div>

          {form.action === 'reassign_operator' && (
            <select style={inp} value={form.operatorId||''} onChange={e=>setField('operatorId',e.target.value)}>
              <option value="">— Seleccioná un operador —</option>
              {users.map(u=><option key={u._id} value={u._id}>{u.name}</option>)}
            </select>
          )}

          {form.action === 'reassign_team' && (
            <div>
              <select style={inp} value={form.teamId||''}
                onChange={e=>{ const tid=e.target.value; setField('teamId',tid); const tm=(teams||[]).find(t=>t._id===tid); setField('operatorIds', (tm&&tm.operatorIds)||[]); }}>
                <option value="">— Seleccioná un equipo —</option>
                {teams.map(t=><option key={t._id} value={t._id}>{t.name} ({(t.operatorIds||[]).length})</option>)}
              </select>
              {form.teamId && (() => {
                const tm = (teams||[]).find(t=>t._id===form.teamId);
                const teamUsers = tm ? users.filter(u=>(tm.operatorIds||[]).includes(u._id)) : [];
                return (
                  <div style={{ marginTop:10 }}>
                    <div style={{ fontSize:12, color:'var(--muted)', marginBottom:6 }}>Operadores del equipo para el round-robin (si no marcás ninguno, se asigna al equipo completo y Pipochat distribuye):</div>
                    <div style={{ display:'flex', gap:10, marginBottom:6 }}>
                      <button type="button" onClick={()=>setField('operatorIds', teamUsers.map(u=>u._id))} style={{ padding:'3px 9px', borderRadius:7, border:'1px solid var(--border)', cursor:'pointer', fontSize:12, background:'transparent', color:'var(--text)' }}>✓ Todos</button>
                      <button type="button" onClick={()=>setField('operatorIds', [])} style={{ padding:'3px 9px', borderRadius:7, border:'1px solid var(--border)', cursor:'pointer', fontSize:12, background:'transparent', color:'var(--text)' }}>✕ Ninguno</button>
                    </div>
                    <div style={{ display:'grid', gridTemplateColumns:'repeat(auto-fill, minmax(160px,1fr))', gap:4, marginBottom:8 }}>
                      {teamUsers.map(u=>(
                        <label key={u._id} style={{ display:'flex', alignItems:'center', gap:6, fontSize:13, cursor:'pointer' }}>
                          <input type="checkbox" checked={(form.operatorIds||[]).includes(u._id)}
                            onChange={e=>{ const cur=form.operatorIds||[]; setField('operatorIds', e.target.checked?[...cur,u._id]:cur.filter(id=>id!==u._id)); }} />
                          {u.name}
                        </label>
                      ))}
                      {!teamUsers.length && <span style={{ fontSize:12, color:'var(--muted)' }}>Este equipo no tiene operadores.</span>}
                    </div>
                    <label style={{ display:'flex', alignItems:'center', gap:6, fontSize:12, cursor:'pointer', marginBottom:4 }}>
                      <input type="checkbox" checked={!!form.onlineOnly} onChange={e=>setField('onlineOnly',e.target.checked)} />
                      Solo operadores online en este momento
                    </label>
                    {form.onlineOnly && (
                      <label style={{ display:'flex', alignItems:'center', gap:6, fontSize:12, cursor:'pointer', paddingLeft:18 }}>
                        <input type="checkbox" checked={!!form.fallbackAll} onChange={e=>setField('fallbackAll',e.target.checked)} />
                        Si no hay nadie online, asignar igual
                      </label>
                    )}
                  </div>
                );
              })()}
            </div>
          )}

          {form.action === 'reassign_roundrobin' && (
            <div>
              <div style={{ fontSize:12, color:'var(--muted)', marginBottom:6 }}>Operadores del round-robin (el siguiente turno se asigna si el timeout se dispara):</div>
              {(teams||[]).length > 0 && (
                <select style={{ ...inp, marginBottom:8 }} value={rrTeam}
                  onChange={e=>{ const tid=e.target.value; setRrTeam(tid); if(tid){ const tm=(teams||[]).find(t=>t._id===tid); setField('operatorIds', (tm&&tm.operatorIds)||[]); } }}>
                  <option value="">— Todos los equipos —</option>
                  {(teams||[]).map(t=><option key={t._id} value={t._id}>{t.name} ({(t.operatorIds||[]).length})</option>)}
                </select>
              )}
              <div style={{ display:'flex', gap:10, marginBottom:6 }}>
                <button type="button" onClick={()=>{ const vis=(rrTeam?users.filter(u=>{ const tm=(teams||[]).find(t=>t._id===rrTeam); return tm && (tm.operatorIds||[]).includes(u._id); }):users); setField('operatorIds', vis.map(u=>u._id)); }} style={{ padding:'3px 9px', borderRadius:7, border:'1px solid var(--border)', cursor:'pointer', fontSize:12, background:'transparent', color:'var(--text)' }}>✓ Todos</button>
                <button type="button" onClick={()=>setField('operatorIds', [])} style={{ padding:'3px 9px', borderRadius:7, border:'1px solid var(--border)', cursor:'pointer', fontSize:12, background:'transparent', color:'var(--text)' }}>✕ Ninguno</button>
              </div>
              <div style={{ display:'grid', gridTemplateColumns:'repeat(auto-fill, minmax(160px,1fr))', gap:4, marginBottom:8 }}>
                {(rrTeam ? users.filter(u=>{ const tm=(teams||[]).find(t=>t._id===rrTeam); return tm && (tm.operatorIds||[]).includes(u._id); }) : users).map(u=>(
                  <label key={u._id} style={{ display:'flex', alignItems:'center', gap:6, fontSize:13, cursor:'pointer' }}>
                    <input type="checkbox" checked={(form.operatorIds||[]).includes(u._id)}
                      onChange={e=>{ const cur=form.operatorIds||[]; setField('operatorIds', e.target.checked?[...cur,u._id]:cur.filter(id=>id!==u._id)); }} />
                    {u.name}
                  </label>
                ))}
              </div>
              <label style={{ display:'flex', alignItems:'center', gap:6, fontSize:12, cursor:'pointer', marginBottom:4 }}>
                <input type="checkbox" checked={!!form.onlineOnly} onChange={e=>setField('onlineOnly',e.target.checked)} />
                Solo operadores online en este momento
              </label>
              {form.onlineOnly && (
                <label style={{ display:'flex', alignItems:'center', gap:6, fontSize:12, cursor:'pointer', paddingLeft:18 }}>
                  <input type="checkbox" checked={!!form.fallbackAll} onChange={e=>setField('fallbackAll',e.target.checked)} />
                  Si no hay nadie online, asignar igual
                </label>
              )}
            </div>
          )}

          {form.action === 'unassign' && (
            <div style={{ fontSize:12, color:'var(--muted)', padding:'8px 10px', background:'var(--bg)', borderRadius:8 }}>
              La conversación quedará sin operador asignado. Podés combinarlo con una regla de conv-rules para reasignar automáticamente.
            </div>
          )}
        </div>

        {/* Optional message */}
        <div style={sec}>
          <span style={lbl}>Mensaje automático al cliente cuando salta el timeout (opcional)</span>
          <textarea style={{ ...inp, minHeight:50, resize:'vertical' }}
            placeholder="Estamos reasignando tu consulta a otro asesor disponible, en breve te contactamos..."
            value={form.notifyText||''} onChange={e=>setField('notifyText',e.target.value)} />
        </div>

        <div style={{ display:'flex', gap:10, justifyContent:'flex-end' }}>
          <button onClick={onClose} style={{ padding:'8px 18px', borderRadius:8, border:'1px solid var(--border)', background:'transparent', cursor:'pointer', color:'var(--text)' }}>Cancelar</button>
          <button onClick={save} disabled={saving} style={{ padding:'8px 20px', borderRadius:8, border:'none', background:'var(--primary)', color:'#fff', cursor:'pointer', fontWeight:600 }}>
            {saving ? 'Guardando...' : 'Guardar'}
          </button>
        </div>
      </div>
    </div>
  );
}

function RoundRobinSimulator() {
  const [users, setUsers] = useState([]);
  const [selected, setSelected] = useState({});
  const [onlineOnly, setOnlineOnly] = useState(true);
  const [fallbackAll, setFallbackAll] = useState(true);
  const [rounds, setRounds] = useState(6);
  const [result, setResult] = useState(null);
  const [loading, setLoading] = useState(false);
  const [open, setOpen] = useState(false);
  const [err, setErr] = useState('');
  const [teams, setTeams] = useState([]);
  const [teamId, setTeamId] = useState('');

  useEffect(() => {
    if (!open || users.length) return;
    apiFetch('/api/pipochat/users').then(r=>r.json()).then(d=>{
      const us = d.users || [];
      setUsers(us);
      const sel = {}; us.forEach(u=>{ sel[u._id||u.id] = true; }); setSelected(sel);
    }).catch(()=>setErr('No se pudieron cargar los operadores'));
    apiFetch('/api/pipochat/teams').then(r=>r.json()).then(d=>setTeams(d.teams||[])).catch(()=>{});
  }, [open]);

  const nameOf = (u) => u.firstName ? `${u.firstName} ${u.lastName||''}`.trim() : (u.name||u.email||(u._id||u.id));
  const teamOpIds = teamId ? ((teams.find(t=>t._id===teamId)||{}).operatorIds || []) : null;
  const visibleUsers = teamOpIds ? users.filter(u=>teamOpIds.includes(u._id||u.id)) : users;
  const onTeamChange = (tid) => {
    setTeamId(tid);
    if (tid) { const ids = (teams.find(t=>t._id===tid)||{}).operatorIds || []; const sel={}; ids.forEach(id=>{sel[id]=true;}); setSelected(sel); }
  };

  const run = async () => {
    setLoading(true); setErr(''); setResult(null);
    const operatorIds = Object.keys(selected).filter(id=>selected[id]);
    try {
      const r = await apiFetch('/api/operator-timeout/simulate', {
        method:'POST', headers:{'Content-Type':'application/json'},
        body: JSON.stringify({ operatorIds, onlineOnly, fallbackAll, rounds: Number(rounds) })
      }).then(r=>r.json());
      if (r.error) setErr(r.error); else setResult(r);
    } catch(e){ setErr('Error al simular'); }
    setLoading(false);
  };

  return (
    <div style={{ marginTop:18, background:'var(--surface)', border:'1px solid var(--border)', borderRadius:12, padding:'14px 16px' }}>
      <div onClick={()=>setOpen(o=>!o)} style={{ display:'flex', alignItems:'center', justifyContent:'space-between', cursor:'pointer' }}>
        <div style={{ fontWeight:700, fontSize:14 }}>🧪 Probar round-robin</div>
        <span style={{ color:'var(--muted)', fontSize:13 }}>{open?'▲':'▼'}</span>
      </div>
      {open && (
        <div style={{ marginTop:12 }}>
          <div style={{ fontSize:12, color:'var(--muted)', marginBottom:10 }}>Simulá a quién le tocaría según la regla, sin asignar ninguna conversación. Usa el estado online real de Pipochat en este momento.</div>
          {teams.length > 0 && (
            <div style={{ marginBottom:10 }}>
              <span style={{ fontSize:12, color:'var(--muted)', marginRight:8 }}>Equipo:</span>
              <select value={teamId} onChange={e=>onTeamChange(e.target.value)} style={{ padding:'5px 9px', borderRadius:7, border:'1px solid var(--border)', background:'var(--bg)', color:'var(--text)', fontSize:13 }}>
                <option value="">Todos los operadores</option>
                {teams.map(t=><option key={t._id} value={t._id}>{t.name} ({(t.operatorIds||[]).length})</option>)}
              </select>
            </div>
          )}
          <div style={{ display:'flex', alignItems:'center', gap:10, marginBottom:8, flexWrap:'wrap' }}>
            <button onClick={()=>{ const s={...selected}; visibleUsers.forEach(u=>{ s[u._id||u.id]=true; }); setSelected(s); }} style={{ padding:'4px 10px', borderRadius:7, border:'1px solid var(--border)', cursor:'pointer', fontSize:12, background:'transparent', color:'var(--text)' }}>✓ Marcar todos</button>
            <button onClick={()=>{ const s={...selected}; visibleUsers.forEach(u=>{ s[u._id||u.id]=false; }); setSelected(s); }} style={{ padding:'4px 10px', borderRadius:7, border:'1px solid var(--border)', cursor:'pointer', fontSize:12, background:'transparent', color:'var(--text)' }}>✕ Desmarcar todos</button>
            <span style={{ fontSize:12, color:'var(--muted)' }}>{visibleUsers.filter(u=>selected[u._id||u.id]).length} de {visibleUsers.length} seleccionados{teamId?' (equipo)':''}</span>
          </div>
          <div style={{ display:'flex', flexWrap:'wrap', gap:8, marginBottom:10 }}>
            {visibleUsers.map(u=>{ const id=u._id||u.id; return (
              <label key={id} style={{ display:'flex', alignItems:'center', gap:6, fontSize:13, border:'1px solid var(--border)', borderRadius:8, padding:'5px 9px', cursor:'pointer' }}>
                <input type="checkbox" checked={!!selected[id]} onChange={e=>setSelected(s=>({...s,[id]:e.target.checked}))} />
                {nameOf(u)}
              </label>
            );})}
            {!users.length && <span style={{ fontSize:12, color:'var(--muted)' }}>Cargando operadores…</span>}
          </div>
          <div style={{ display:'flex', flexWrap:'wrap', gap:16, alignItems:'center', marginBottom:12 }}>
            <label style={{ display:'flex', alignItems:'center', gap:6, fontSize:13 }}><input type="checkbox" checked={onlineOnly} onChange={e=>setOnlineOnly(e.target.checked)} /> Solo operadores online</label>
            <label style={{ display:'flex', alignItems:'center', gap:6, fontSize:13, opacity: onlineOnly?1:0.5 }}><input type="checkbox" checked={fallbackAll} disabled={!onlineOnly} onChange={e=>setFallbackAll(e.target.checked)} /> Si no hay nadie online, asignar igual</label>
            <label style={{ display:'flex', alignItems:'center', gap:6, fontSize:13 }}>Rondas: <input type="number" min="1" max="50" value={rounds} onChange={e=>setRounds(e.target.value)} style={{ width:60, padding:'4px 6px', borderRadius:6, border:'1px solid var(--border)', background:'var(--bg)', color:'var(--text)' }} /></label>
            <button onClick={run} disabled={loading} style={S.btnPrimary}>{loading?'Simulando…':'Simular'}</button>
          </div>
          {err && <div style={{ color:'#ef4444', fontSize:12, marginBottom:8 }}>{err}</div>}
          {result && (
            <div style={{ borderTop:'1px solid var(--border)', paddingTop:12 }}>
              <div style={{ fontSize:13, marginBottom:8 }}>
                {result.selected.map(o=>(
                  <span key={o.id} style={{ display:'inline-flex', alignItems:'center', gap:5, marginRight:12, fontSize:12 }}>
                    <span style={{ width:8, height:8, borderRadius:'50%', background:o.online?'#22c55e':'#9ca3af', display:'inline-block' }}></span>
                    {o.name} {o.online?'(online)':'(offline)'}
                  </span>
                ))}
              </div>
              <div style={{ fontSize:12, color: result.fellBack?'#b45309':'var(--muted)', marginBottom:10 }}>{result.fellBack?'⚠️ ':''}{result.note}</div>
              {result.sequence.length ? (
                <table style={{ width:'100%', fontSize:13, borderCollapse:'collapse' }}>
                  <thead><tr style={{ textAlign:'left', color:'var(--muted)', fontSize:11 }}><th style={{ padding:'4px 8px' }}>Ronda</th><th style={{ padding:'4px 8px' }}>Le toca a</th><th style={{ padding:'4px 8px' }}>Estado</th></tr></thead>
                  <tbody>
                    {result.sequence.map(s=>(
                      <tr key={s.round} style={{ borderTop:'1px solid var(--border)' }}>
                        <td style={{ padding:'5px 8px' }}>#{s.round}</td>
                        <td style={{ padding:'5px 8px', fontWeight:600 }}>{s.name}</td>
                        <td style={{ padding:'5px 8px' }}>{s.online?'🟢 online':'⚪ offline'}</td>
                      </tr>
                    ))}
                  </tbody>
                </table>
              ) : <div style={{ fontSize:13, color:'#ef4444' }}>No se asignaría a nadie con esta configuración.</div>}
            </div>
          )}
        </div>
      )}
    </div>
  );
}

function OperatorTimeoutPanel() {
  const [rules, setRules] = useState([]);
  const [showModal, setShowModal] = useState(false);
  const [editing, setEditing] = useState(null);

  const load = () => apiFetch('/api/operator-timeout').then(r=>r.json()).then(setRules).catch(()=>{});
  useEffect(() => { load(); }, []);

  const handleSave = (saved) => {
    setRules(rs => {
      const idx = rs.findIndex(r=>r.id===saved.id);
      return idx>=0 ? rs.map((r,i)=>i===idx?saved:r) : [...rs, saved];
    });
  };
  const toggle = async (rule) => {
    const updated = await apiFetch(`/api/operator-timeout/${rule.id}`, {
      method:'PATCH', headers:{'Content-Type':'application/json'},
      body: JSON.stringify({ enabled: !rule.enabled })
    }).then(r=>r.json());
    if (!updated.error) setRules(rs => rs.map(r=>r.id===updated.id?updated:r));
  };
  const del = async (id) => {
    if (!confirm('¿Eliminar esta regla?')) return;
    await apiFetch(`/api/operator-timeout/${id}`, { method:'DELETE' });
    setRules(rs => rs.filter(r=>r.id!==id));
  };

  const actionLabel = (r) => {
    if (r.action==='reassign_roundrobin') return `Round-robin${r.onlineOnly?' (online)':''} (${(r.operatorIds||[]).length} ops)`;
    if (r.action==='reassign_team') return `Equipo`;
    if (r.action==='reassign_operator') return `Operador fijo`;
    if (r.action==='unassign') return `Desasignar`;
    return r.action;
  };

  return (
    <div style={S.page}>
      <div style={S.pageHeader}>
        <div>
          <div style={{ fontSize:22, fontWeight:800, marginBottom:4 }}>⏱️ Timeout de operador</div>
          <div style={S.pageSubtitle}>Cuando un operador lleva demasiado tiempo sin responder, la conversación se reasigna automáticamente — evitás que los clientes queden esperando sin atención.</div>
        </div>
        <button onClick={()=>{ setEditing(null); setShowModal(true); }} style={S.btnPrimary}>+ Nueva regla</button>
      </div>

      {rules.length === 0 ? (
        <div style={{ textAlign:'center', padding:'60px 20px', color:'var(--muted)' }}>
          <div style={{ fontSize:40, marginBottom:12 }}>⏱️</div>
          <div style={{ fontSize:16, fontWeight:600, marginBottom:8 }}>Sin reglas de timeout</div>
          <div style={{ fontSize:13, maxWidth:420, margin:'0 auto', lineHeight:1.5 }}>
            Configurá cuánto tiempo puede pasar sin que un operador responda antes de que la conversación se reasigne automáticamente.
          </div>
        </div>
      ) : (
        <div style={{ display:'flex', flexDirection:'column', gap:10 }}>
          {rules.map(rule => (
            <div key={rule.id} style={{ background:'var(--surface)', border:'1px solid var(--border)', borderRadius:12, padding:'14px 16px', display:'flex', alignItems:'center', gap:12 }}>
              <div style={{ flex:1 }}>
                <div style={{ display:'flex', alignItems:'center', gap:8, marginBottom:4 }}>
                  <span style={{ fontWeight:700, fontSize:14 }}>{rule.name}</span>
                  <span style={{ fontSize:11, background: rule.enabled?'#d1fae5':'var(--bg)', color: rule.enabled?'#065f46':'var(--muted)', padding:'2px 7px', borderRadius:12, border:'1px solid var(--border)' }}>
                    {rule.enabled ? 'Activa' : 'Inactiva'}
                  </span>
                </div>
                <div style={{ fontSize:12, color:'var(--muted)', display:'flex', gap:16 }}>
                  <span>⏱️ {rule.minutesWithoutReply} min sin respuesta</span>
                  <span>🔀 {actionLabel(rule)}</span>
                  {rule.notifyText && <span>💬 Con mensaje</span>}
                  {rule.pipelineId && <span>📊 Pipeline filtrado</span>}
                </div>
              </div>
              <div style={{ display:'flex', gap:6 }}>
                <button onClick={()=>toggle(rule)} style={{ padding:'5px 10px', borderRadius:7, border:'1px solid var(--border)', cursor:'pointer', fontSize:12, background:'transparent', color:'var(--text)' }}>
                  {rule.enabled ? 'Desactivar' : 'Activar'}
                </button>
                <button onClick={()=>{ setEditing(rule); setShowModal(true); }} style={{ padding:'5px 10px', borderRadius:7, border:'1px solid var(--border)', cursor:'pointer', fontSize:12, background:'transparent', color:'var(--text)' }}>Editar</button>
                <button onClick={()=>del(rule.id)} style={{ padding:'5px 10px', borderRadius:7, border:'1px solid #fee2e2', cursor:'pointer', fontSize:12, background:'transparent', color:'#ef4444' }}>Eliminar</button>
              </div>
            </div>
          ))}
        </div>
      )}

      <RoundRobinSimulator />

      {showModal && <OperatorTimeoutModal rule={editing} onClose={()=>{ setShowModal(false); setEditing(null); }} onSaved={handleSave} />}
    </div>
  );
}

// ─── Contact No-Reply Panel ───────────────────────────────────────────────────

const NOREPLY_ACTION_TYPES = [
  { v:'send_text',         label:'Enviar mensaje de texto' },
  { v:'send_ai',           label:'🤖 Mensaje con IA (lee el contexto y redacta)' },
  { v:'send_interactive',  label:'🔘 Enviar botones interactivos' },
  { v:'send_template',     label:'Enviar template de WhatsApp' },
  { v:'add_tag',           label:'Agregar etiqueta' },
  { v:'assign_operator',   label:'Asignar operador' },
  { v:'assign_team',       label:'Asignar equipo' },
  { v:'assign_roundrobin', label:'Round-robin de operadores' },
  { v:'update_status',     label:'Cambiar estado de conversación' },
  { v:'move_lead',         label:'Mover lead a etapa' },
  { v:'notify_operator',   label:'Notificar operador por WhatsApp' },
];

function NoReplyActionEditor({ action, onChange, onRemove }) {
  const { users, teams, pipelines, tags, templates, connected } = usePipochat();
  const inp = { padding:'7px 10px', borderRadius:8, border:'1px solid var(--border)', background:'var(--bg)', color:'var(--text)', fontSize:13, width:'100%', boxSizing:'border-box' };
  const lbl = { fontSize:12, color:'var(--muted)', display:'block', marginBottom:4 };

  return (
    <div style={{ border:'1px solid var(--border)', borderRadius:10, padding:'12px 14px', background:'var(--bg)', marginBottom:8 }}>
      <div style={{ display:'flex', gap:8, alignItems:'center', marginBottom:10 }}>
        <select style={{ ...inp, flex:1 }} value={action.type} onChange={e => onChange({ ...action, type: e.target.value })}>
          {NOREPLY_ACTION_TYPES.map(t => <option key={t.v} value={t.v}>{t.label}</option>)}
        </select>
        <button onClick={onRemove} style={{ padding:'5px 10px', borderRadius:7, border:'1px solid #fee2e2', background:'transparent', color:'#ef4444', cursor:'pointer', fontSize:12, flexShrink:0 }}>Quitar</button>
      </div>

      {action.type === 'send_text' && (
        <div>
          <span style={lbl}>Mensaje</span>
          <textarea style={{ ...inp, minHeight:60, resize:'vertical' }} value={action.message||''} onChange={e => onChange({ ...action, message: e.target.value })}
            placeholder="Ej: Hola! Te escribo porque no recibimos tu respuesta. ¿Podemos ayudarte?" />
        </div>
      )}

      {action.type === 'send_ai' && (
        <div>
          <span style={lbl}>Objetivo del mensaje (opcional — la IA lee la conversación y los datos del lead, y redacta el follow-up)</span>
          <textarea style={{ ...inp, minHeight:60, resize:'vertical' }} value={action.aiPrompt||''} onChange={e => onChange({ ...action, aiPrompt: e.target.value })}
            placeholder="Ej: Retomar la conversación aportando un dato de valor sobre el proyecto que le interesó. Si dudaba del precio, mencionar la financiación." />
          <div style={{ fontSize:11.5, color:'var(--muted)', marginTop:6 }}>
            ⚠️ Solo funciona dentro de las 24 h del último mensaje del cliente (regla de WhatsApp). Para reglas de más tiempo usá "Enviar template". Nunca inventa datos: si falta info, ofrece que el asesor la pase.
          </div>
        </div>
      )}

      {action.type === 'send_interactive' && (
        <div>
          <span style={lbl}>Botones / Lista interactiva</span>
          <InteractiveMessageBuilder
            value={action.interactive}
            onChange={iv => onChange({ ...action, interactive: iv })} />
        </div>
      )}

      {action.type === 'send_template' && (
        <div>
          <span style={lbl}>Template de WhatsApp</span>
          {connected && templates.length > 0
            ? <select style={inp} value={action.templateId||''} onChange={e => onChange({ ...action, templateId: e.target.value })}>
                <option value="">— Seleccionar template —</option>
                {templates.map(t => <option key={t._id} value={t._id}>{t.name}</option>)}
              </select>
            : <input style={inp} value={action.templateId||''} onChange={e => onChange({ ...action, templateId: e.target.value })} placeholder="ID del template aprobado" />
          }
        </div>
      )}

      {action.type === 'add_tag' && (
        <div>
          <span style={lbl}>Etiqueta</span>
          {connected && tags.length > 0
            ? <select style={inp} value={(action.tagIds||[])[0]||''} onChange={e => onChange({ ...action, tagIds: e.target.value ? [e.target.value] : [] })}>
                <option value="">— Seleccionar etiqueta —</option>
                {tags.map(t => <option key={t._id} value={t._id}>{t.name}</option>)}
              </select>
            : <input style={inp} value={(action.tagIds||[])[0]||''} onChange={e => onChange({ ...action, tagIds: e.target.value ? [e.target.value] : [] })} placeholder="ID de la etiqueta" />
          }
        </div>
      )}

      {action.type === 'assign_operator' && (
        <div>
          <span style={lbl}>Operador</span>
          {connected && users.length > 0
            ? <select style={inp} value={action.operatorId||''} onChange={e => onChange({ ...action, operatorId: e.target.value })}>
                <option value="">— Seleccionar operador —</option>
                {users.map(u => <option key={u._id} value={u._id}>{u.name}</option>)}
              </select>
            : <input style={inp} value={action.operatorId||''} onChange={e => onChange({ ...action, operatorId: e.target.value })} placeholder="ID del operador" />
          }
        </div>
      )}

      {action.type === 'assign_team' && (
        <div>
          <span style={lbl}>Equipo</span>
          {connected && teams.length > 0
            ? <select style={inp} value={action.teamId||''} onChange={e => onChange({ ...action, teamId: e.target.value })}>
                <option value="">— Seleccionar equipo —</option>
                {teams.map(t => <option key={t._id} value={t._id}>{t.name}</option>)}
              </select>
            : <input style={inp} value={action.teamId||''} onChange={e => onChange({ ...action, teamId: e.target.value })} placeholder="ID del equipo" />
          }
        </div>
      )}

      {action.type === 'assign_roundrobin' && (() => {
        const tf = action.teamFilter || '';
        const tmObj = (teams || []).find(t => t._id === tf);
        const visibleUsers = tmObj ? users.filter(u => (tmObj.operatorIds || []).includes(u._id)) : users;
        const selCount = (action.operatorIds || []).filter(id => visibleUsers.some(u => u._id === id)).length;
        const btn = { padding:'2px 8px', borderRadius:6, border:'1px solid var(--border)', cursor:'pointer', fontSize:11, background:'transparent', color:'var(--text)' };
        return (
        <div>
          <span style={lbl}>Operadores del round-robin</span>
          {(teams || []).length > 0 && (
            <select style={{ ...inp, marginBottom:6 }} value={tf}
              onChange={e => { const id = e.target.value; const tm = (teams || []).find(t => t._id === id); onChange({ ...action, teamFilter: id, operatorIds: id ? ((tm && tm.operatorIds) || []) : (action.operatorIds || []) }); }}>
              <option value="">— Equipo (todos los operadores) —</option>
              {(teams || []).map(t => <option key={t._id} value={t._id}>{t.name} ({(t.operatorIds || []).length})</option>)}
            </select>
          )}
          <div style={{ display:'flex', gap:8, alignItems:'center', marginBottom:4, flexWrap:'wrap' }}>
            <button type="button" onClick={() => onChange({ ...action, operatorIds: visibleUsers.map(u => u._id) })} style={btn}>✓ Todos</button>
            <button type="button" onClick={() => onChange({ ...action, operatorIds: [] })} style={btn}>✕ Ninguno</button>
            <span style={{ fontSize:11, color:'var(--muted)' }}>{selCount}/{visibleUsers.length}{tf ? ' (equipo)' : ''}</span>
          </div>
          <div style={{ display:'grid', gridTemplateColumns:'repeat(auto-fill, minmax(160px,1fr))', gap:4, marginBottom:6, maxHeight:200, overflowY:'auto' }}>
            {visibleUsers.map(u => (
              <label key={u._id} style={{ display:'flex', alignItems:'center', gap:6, fontSize:13, cursor:'pointer' }}>
                <input type="checkbox" checked={(action.operatorIds||[]).includes(u._id)}
                  onChange={e => { const cur=action.operatorIds||[]; onChange({ ...action, operatorIds: e.target.checked?[...cur,u._id]:cur.filter(id=>id!==u._id) }); }} />
                {u.name}
              </label>
            ))}
          </div>
          <label style={{ display:'flex', alignItems:'center', gap:6, fontSize:12, cursor:'pointer' }}>
            <input type="checkbox" checked={!!action.onlineOnly} onChange={e => onChange({ ...action, onlineOnly: e.target.checked })} />
            Solo operadores online
          </label>
          {action.onlineOnly && (
            <label style={{ display:'flex', alignItems:'center', gap:6, fontSize:12, cursor:'pointer', paddingLeft:18 }}>
              <input type="checkbox" checked={!!action.fallbackAll} onChange={e => onChange({ ...action, fallbackAll: e.target.checked })} />
              Si no hay nadie online, asignar igual
            </label>
          )}
          <label style={{ display:'flex', alignItems:'center', gap:6, fontSize:12, cursor:'pointer', borderTop:'1px solid var(--border)', paddingTop:6, marginTop:6 }}>
            <input type="checkbox" checked={!!action.sticky} onChange={e => onChange({ ...action, sticky: e.target.checked })} />
            Mantener el mismo operador para el mismo contacto (no re-rotar)
          </label>
        </div>
        );
      })()}

      {action.type === 'update_status' && (
        <div>
          <span style={lbl}>Nuevo estado</span>
          <select style={inp} value={action.status||'pending'} onChange={e => onChange({ ...action, status: e.target.value })}>
            <option value="open">Abierta</option>
            <option value="pending">Pendiente</option>
            <option value="solved">Resuelta</option>
          </select>
        </div>
      )}

      {action.type === 'move_lead' && (
        <div>
          <span style={lbl}>Mover a etapa</span>
          <select style={inp} value={action.stageId||''} onChange={e => {
            const stage = pipelines.flatMap(p=>(p.stages||[]).map(s=>({...s,pipelineId:p._id}))).find(s=>s._id===e.target.value);
            onChange({ ...action, stageId: e.target.value, pipelineId: stage?.pipelineId });
          }}>
            <option value="">— Seleccionar etapa —</option>
            {pipelines.map(p => (
              <optgroup key={p._id} label={p.title||p.name}>
                {(p.stages||[]).sort((a,b)=>a.orderIndex-b.orderIndex).map(s => (
                  <option key={s._id} value={s._id}>{s.displayName||s.name}</option>
                ))}
              </optgroup>
            ))}
          </select>
        </div>
      )}

      {action.type === 'notify_operator' && (
        <div style={{ display:'flex', flexDirection:'column', gap:8 }}>
          <div>
            <span style={lbl}>Operador a notificar</span>
            {connected && users.length > 0
              ? <select style={inp} value={action.operatorId||''} onChange={e => onChange({ ...action, operatorId: e.target.value })}>
                  <option value="">— Seleccionar operador —</option>
                  {users.map(u => <option key={u._id} value={u._id}>{u.name}</option>)}
                </select>
              : <input style={inp} value={action.operatorPhone||''} onChange={e => onChange({ ...action, operatorPhone: e.target.value })} placeholder="+5491112345678" />
            }
          </div>
          <div>
            <span style={lbl}>Mensaje de notificación</span>
            <textarea style={{ ...inp, minHeight:60, resize:'vertical' }} value={action.message||''} onChange={e => onChange({ ...action, message: e.target.value })}
              placeholder="🔔 {{contact_name}} no respondió. Revisá la conversación." />
            <span style={{ fontSize:11, color:'var(--muted)' }}>Variables: {'{{contact_name}}'}, {'{{contact_phone}}'}.</span>
          </div>
        </div>
      )}
    </div>
  );
}

const DAY_LABELS = ['Dom','Lun','Mar','Mié','Jue','Vie','Sáb'];

function NoReplyConditionEditor({ cond, onChange, onRemove }) {
  const { tags, pipelines } = usePipochat();
  const inp = { padding:'6px 10px', borderRadius:7, border:'1px solid var(--border)', background:'var(--bg)', color:'var(--text)', fontSize:13, width:'100%', boxSizing:'border-box' };
  const lbl = { fontSize:12, color:'var(--muted)', display:'block', marginBottom:3 };

  const allStages = pipelines.flatMap(p => (p.stages||[]).map(s => ({ ...s, pipelineTitle: p.title||p.name, pipelineId: p._id })));

  return (
    <div style={{ border:'1px solid var(--border)', borderRadius:9, padding:'10px 12px', background:'var(--bg)', marginBottom:6, display:'flex', gap:10, alignItems:'flex-start' }}>
      <div style={{ flex:1, display:'flex', flexDirection:'column', gap:8 }}>
        <div>
          <span style={lbl}>Tipo de condición</span>
          <select style={inp} value={cond.type} onChange={e => onChange({ type: e.target.value })}>
            <optgroup label="Horario">
              <option value="hour_between">Solo en cierto horario</option>
              <option value="day_of_week">Solo en ciertos días</option>
            </optgroup>
            <optgroup label="Etiqueta del contacto">
              <option value="has_tag">Contacto TIENE la etiqueta</option>
              <option value="missing_tag">Contacto NO TIENE la etiqueta</option>
            </optgroup>
            <optgroup label="Lead">
              <option value="has_lead">Conversación tiene lead</option>
              <option value="no_lead">Conversación NO tiene lead</option>
              <option value="lead_in_stage">Lead está en etapa</option>
              <option value="lead_in_pipeline">Lead está en pipeline</option>
              <option value="lead_attr_equals">Atributo del lead = valor</option>
            </optgroup>
            <optgroup label="Atributos del contacto">
              <option value="contact_attr_equals">Atributo del contacto = valor</option>
              <option value="contact_attr_exists">Atributo del contacto existe</option>
              <option value="contact_attr_not_exists">Atributo del contacto NO existe</option>
            </optgroup>
            <optgroup label="Conversación">
              <option value="message_count_gte">Cantidad de mensajes ≥ N</option>
            </optgroup>
          </select>
        </div>

        {cond.type === 'hour_between' && (
          <div style={{ display:'flex', alignItems:'center', gap:8 }}>
            <div style={{ flex:1 }}>
              <span style={lbl}>Desde (hora)</span>
              <input type="number" min="0" max="23" style={inp} value={cond.hourFrom ?? 8} onChange={e => onChange({ ...cond, hourFrom: Number(e.target.value) })} />
            </div>
            <div style={{ flex:1 }}>
              <span style={lbl}>Hasta (hora)</span>
              <input type="number" min="0" max="23" style={inp} value={cond.hourTo ?? 20} onChange={e => onChange({ ...cond, hourTo: Number(e.target.value) })} />
            </div>
            <div style={{ fontSize:11, color:'var(--muted)', paddingTop:18, whiteSpace:'nowrap' }}>Hora del servidor (0-23)</div>
          </div>
        )}

        {cond.type === 'day_of_week' && (
          <div>
            <span style={lbl}>Días activos</span>
            <div style={{ display:'flex', gap:4, flexWrap:'wrap' }}>
              {DAY_LABELS.map((d,i) => {
                const active = (cond.days||[]).includes(i);
                return (
                  <button key={i} onClick={() => {
                    const cur = cond.days || [];
                    onChange({ ...cond, days: active ? cur.filter(x=>x!==i) : [...cur,i] });
                  }} style={{ padding:'4px 10px', borderRadius:6, border:'1px solid var(--border)', cursor:'pointer', fontSize:12,
                    background: active ? 'var(--primary)' : 'transparent', color: active ? '#fff' : 'var(--text)' }}>{d}</button>
                );
              })}
            </div>
          </div>
        )}

        {(cond.type === 'has_tag' || cond.type === 'missing_tag') && (
          <div>
            <span style={lbl}>Etiqueta</span>
            {tags.length > 0
              ? <select style={inp} value={cond.tagId||''} onChange={e => onChange({ ...cond, tagId: e.target.value })}>
                  <option value="">— Seleccionar —</option>
                  {tags.map(t => <option key={t._id} value={t._id}>{t.name}</option>)}
                </select>
              : <input style={inp} value={cond.tagId||''} onChange={e => onChange({ ...cond, tagId: e.target.value })} placeholder="ID de la etiqueta" />
            }
          </div>
        )}

        {(cond.type === 'has_lead' || cond.type === 'no_lead') && (
          <div style={{ fontSize:12, color:'var(--muted)', padding:'6px 8px', background:'var(--surface)', borderRadius:7 }}>
            {cond.type === 'has_lead'
              ? 'Solo se dispara si la conversación ya tiene un lead asociado en algún pipeline.'
              : 'Solo se dispara si la conversación aún no tiene lead asociado.'}
          </div>
        )}

        {cond.type === 'lead_in_stage' && (
          <div>
            <span style={lbl}>Etapa del lead</span>
            <select style={inp} value={cond.stageId||''} onChange={e => onChange({ ...cond, stageId: e.target.value })}>
              <option value="">— Seleccionar etapa —</option>
              {pipelines.map(p => (
                <optgroup key={p._id} label={p.title||p.name}>
                  {(p.stages||[]).sort((a,b)=>a.orderIndex-b.orderIndex).map(s => (
                    <option key={s._id} value={s._id}>{s.displayName||s.name}</option>
                  ))}
                </optgroup>
              ))}
            </select>
          </div>
        )}

        {cond.type === 'lead_in_pipeline' && (
          <div>
            <span style={lbl}>Pipeline del lead</span>
            <select style={inp} value={cond.pipelineId||''} onChange={e => onChange({ ...cond, pipelineId: e.target.value })}>
              <option value="">— Seleccionar pipeline —</option>
              {pipelines.map(p => <option key={p._id} value={p._id}>{p.title||p.name}</option>)}
            </select>
          </div>
        )}

        {(cond.type === 'lead_attr_equals' || cond.type === 'contact_attr_equals') && (
          <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr', gap:8 }}>
            <div>
              <span style={lbl}>Clave del atributo</span>
              <input style={inp} value={cond.attributeKey||''} onChange={e => onChange({ ...cond, attributeKey: e.target.value })}
                placeholder={cond.type === 'lead_attr_equals' ? 'tipo_cliente' : 'pais'} />
            </div>
            <div>
              <span style={lbl}>Valor esperado</span>
              <input style={inp} value={cond.attributeValue||''} onChange={e => onChange({ ...cond, attributeValue: e.target.value })}
                placeholder={cond.type === 'lead_attr_equals' ? 'empresa' : 'Argentina'} />
            </div>
          </div>
        )}

        {(cond.type === 'contact_attr_exists' || cond.type === 'contact_attr_not_exists') && (
          <div>
            <span style={lbl}>Clave del atributo</span>
            <input style={inp} value={cond.attributeKey||''} onChange={e => onChange({ ...cond, attributeKey: e.target.value })}
              placeholder="fuente" />
            <div style={{ fontSize:11, color:'var(--muted)', marginTop:3 }}>
              {cond.type === 'contact_attr_exists'
                ? 'Solo dispara si el contacto tiene este campo completado.'
                : 'Solo dispara si el contacto NO tiene este campo completado.'}
            </div>
          </div>
        )}

        {cond.type === 'message_count_gte' && (
          <div>
            <span style={lbl}>Mínimo de mensajes en la conversación</span>
            <div style={{ display:'flex', alignItems:'center', gap:8 }}>
              <input type="number" min="1" style={{ ...inp, width:90 }} value={cond.count ?? 3} onChange={e => onChange({ ...cond, count: Number(e.target.value) })} />
              <span style={{ fontSize:12, color:'var(--muted)' }}>mensajes o más</span>
            </div>
          </div>
        )}
      </div>
      <button onClick={onRemove} style={{ padding:'4px 8px', borderRadius:6, border:'1px solid #fee2e2', background:'transparent', color:'#ef4444', cursor:'pointer', fontSize:12, flexShrink:0, marginTop:16 }}>✕</button>
    </div>
  );
}

function ContactNoReplyModal({ rule, onClose, onSaved }) {
  const { pipelines } = usePipochat();
  const defaultForm = {
    name: '', enabled: false, minutesWithoutReply: 30,
    pipelineId: '', conditions: [], fireOnce: true, actions: [],
  };
  const [form, setForm] = useState(rule ? { ...defaultForm, ...rule } : defaultForm);
  const [saving, setSaving] = useState(false);
  const setField = (k, v) => setForm(f => ({ ...f, [k]: v }));

  const addCondition = () => setField('conditions', [...(form.conditions||[]), { type: 'hour_between', hourFrom: 8, hourTo: 20 }]);
  const updateCondition = (i, c) => setField('conditions', (form.conditions||[]).map((x,j) => j===i ? c : x));
  const removeCondition = (i) => setField('conditions', (form.conditions||[]).filter((_,j) => j!==i));

  const addAction = () => setField('actions', [...form.actions, { type: 'send_text', message: '' }]);
  const updateAction = (i, a) => setField('actions', form.actions.map((x,j) => j===i ? a : x));
  const removeAction = (i) => setField('actions', form.actions.filter((_,j) => j!==i));

  const save = async () => {
    if (!form.name.trim()) return alert('Poné un nombre para la regla');
    if (!form.actions.length) return alert('Agregá al menos una acción');
    setSaving(true);
    const url = rule ? `/api/contact-noreply/${rule.id}` : '/api/contact-noreply';
    const method = rule ? 'PUT' : 'POST';
    const res = await apiFetch(url, { method, headers:{'Content-Type':'application/json'}, body: JSON.stringify(form) }).then(r => r.json());
    setSaving(false);
    if (res.error) return alert(res.error);
    onSaved(res); onClose();
  };

  const modal = { position:'fixed', inset:0, background:'rgba(0,0,0,0.5)', display:'flex', alignItems:'flex-start', justifyContent:'center', zIndex:1000, padding:'24px 16px', overflowY:'auto' };
  const box   = { background:'var(--surface)', borderRadius:14, padding:'28px 28px 24px', width:'100%', maxWidth:640, boxShadow:'0 20px 60px rgba(0,0,0,0.3)', marginBottom:24 };
  const inp   = { padding:'7px 10px', borderRadius:8, border:'1px solid var(--border)', background:'var(--bg)', color:'var(--text)', fontSize:13, width:'100%', boxSizing:'border-box' };
  const lbl   = { fontSize:12, color:'var(--muted)', display:'block', marginBottom:4 };
  const sec   = { marginBottom:18 };

  return (
    <div style={modal} onClick={e => e.target===e.currentTarget && onClose()}>
      <div style={box}>
        <div style={{ display:'flex', justifyContent:'space-between', alignItems:'center', marginBottom:22 }}>
          <div style={{ fontSize:18, fontWeight:800 }}>{rule ? 'Editar' : 'Nueva'} regla de no-respuesta</div>
          <button onClick={onClose} style={{ background:'none', border:'none', cursor:'pointer', fontSize:20, color:'var(--muted)' }}>✕</button>
        </div>

        {/* Name + Enable */}
        <div style={{ display:'grid', gridTemplateColumns:'1fr auto', gap:10, alignItems:'end', ...sec }}>
          <div>
            <span style={lbl}>Nombre de la regla</span>
            <input style={inp} value={form.name} onChange={e=>setField('name',e.target.value)} placeholder="Seguimiento a los 30 min sin respuesta" />
          </div>
          <label style={{ display:'flex', alignItems:'center', gap:6, fontSize:13, cursor:'pointer', whiteSpace:'nowrap', paddingBottom:2 }}>
            <input type="checkbox" checked={form.enabled} onChange={e=>setField('enabled',e.target.checked)} />
            Activa
          </label>
        </div>

        {/* Timeout minutes */}
        <div style={sec}>
          <span style={lbl}>Tiempo sin respuesta del contacto</span>
          <div style={{ display:'flex', alignItems:'center', gap:8 }}>
            <input type="number" min="1" style={{ ...inp, width:100 }} value={form.minutesWithoutReply} onChange={e=>setField('minutesWithoutReply',Number(e.target.value))} />
            <span style={{ fontSize:13, color:'var(--muted)' }}>minutos desde el último mensaje del bot</span>
          </div>
          <div style={{ fontSize:11, color:'var(--muted)', marginTop:4 }}>
            Si el bot envió el último mensaje y el contacto no respondió en este tiempo, se disparan las acciones.
          </div>
        </div>

        {/* Pipeline filter */}
        <div style={sec}>
          <span style={lbl}>Aplicar solo a conversaciones en este pipeline (opcional)</span>
          <select style={inp} value={form.pipelineId||''} onChange={e=>setField('pipelineId',e.target.value)}>
            <option value="">— Todos los pipelines —</option>
            {pipelines.map(p=><option key={p._id} value={p._id}>{p.title||p.name}</option>)}
          </select>
        </div>

        {/* Conditions */}
        <div style={sec}>
          <div style={{ display:'flex', justifyContent:'space-between', alignItems:'center', marginBottom:8 }}>
            <div>
              <span style={{ fontWeight:700, fontSize:13 }}>Condiciones adicionales</span>
              <span style={{ fontSize:11, color:'var(--muted)', marginLeft:8 }}>todas deben cumplirse (AND)</span>
            </div>
            <button onClick={addCondition} style={{ padding:'4px 12px', borderRadius:7, border:'1px solid var(--primary)', background:'transparent', color:'var(--primary)', cursor:'pointer', fontSize:12 }}>+ Agregar</button>
          </div>
          {(!form.conditions || form.conditions.length === 0) && (
            <div style={{ fontSize:12, color:'var(--muted)', padding:'8px 10px', background:'var(--bg)', borderRadius:8, border:'1px dashed var(--border)' }}>
              Sin condiciones — se aplica a todas las conversaciones abiertas. Agregá filtros de horario, etiqueta, etc.
            </div>
          )}
          {(form.conditions||[]).map((cond, i) => (
            <NoReplyConditionEditor key={i} cond={cond} onChange={c => updateCondition(i, c)} onRemove={() => removeCondition(i)} />
          ))}
        </div>

        {/* Fire once */}
        <div style={{ ...sec, padding:'10px 12px', background:'var(--bg)', borderRadius:9, border:'1px solid var(--border)' }}>
          <label style={{ display:'flex', alignItems:'flex-start', gap:8, cursor:'pointer' }}>
            <input type="checkbox" checked={form.fireOnce} onChange={e=>setField('fireOnce',e.target.checked)} style={{ marginTop:2 }} />
            <div>
              <div style={{ fontSize:13, fontWeight:600 }}>Disparar solo una vez por conversación</div>
              <div style={{ fontSize:11, color:'var(--muted)', marginTop:2 }}>
                Desactivar si querés que se reenvíe cada vez que el bot mande un nuevo mensaje sin obtener respuesta.
              </div>
            </div>
          </label>
        </div>

        {/* Actions */}
        <div style={sec}>
          <div style={{ display:'flex', justifyContent:'space-between', alignItems:'center', marginBottom:8 }}>
            <span style={{ fontWeight:700, fontSize:13 }}>Acciones al dispararse</span>
            <button onClick={addAction} style={{ padding:'4px 12px', borderRadius:7, border:'1px solid var(--primary)', background:'transparent', color:'var(--primary)', cursor:'pointer', fontSize:12 }}>+ Agregar acción</button>
          </div>
          {form.actions.length === 0 && (
            <div style={{ fontSize:12, color:'var(--muted)', padding:'10px 12px', background:'var(--bg)', borderRadius:8, border:'1px dashed var(--border)' }}>
              Sin acciones configuradas. Hacé clic en "+ Agregar acción".
            </div>
          )}
          {form.actions.map((action, i) => (
            <NoReplyActionEditor key={i} action={action} onChange={a => updateAction(i, a)} onRemove={() => removeAction(i)} />
          ))}
        </div>

        <div style={{ display:'flex', gap:10, justifyContent:'flex-end' }}>
          <button onClick={onClose} style={{ padding:'8px 18px', borderRadius:8, border:'1px solid var(--border)', background:'transparent', cursor:'pointer', color:'var(--text)' }}>Cancelar</button>
          <button onClick={save} disabled={saving} style={{ padding:'8px 20px', borderRadius:8, border:'none', background:'var(--primary)', color:'#fff', cursor:'pointer', fontWeight:600 }}>
            {saving ? 'Guardando...' : 'Guardar'}
          </button>
        </div>
      </div>
    </div>
  );
}

function ContactNoReplyPanel() {
  const [rules, setRules] = useState([]);
  const [showModal, setShowModal] = useState(false);
  const [editing, setEditing] = useState(null);

  const load = () => apiFetch('/api/contact-noreply').then(r=>r.json()).then(setRules).catch(()=>{});
  useEffect(() => { load(); }, []);

  const handleSave = (saved) => {
    setRules(rs => {
      const idx = rs.findIndex(r=>r.id===saved.id);
      return idx>=0 ? rs.map((r,i)=>i===idx?saved:r) : [...rs, saved];
    });
  };
  const toggle = async (rule) => {
    const updated = await apiFetch(`/api/contact-noreply/${rule.id}`, {
      method:'PATCH', headers:{'Content-Type':'application/json'},
      body: JSON.stringify({ enabled: !rule.enabled })
    }).then(r=>r.json());
    if (!updated.error) setRules(rs => rs.map(r=>r.id===updated.id?updated:r));
  };
  const del = async (id) => {
    if (!confirm('¿Eliminar esta regla?')) return;
    await apiFetch(`/api/contact-noreply/${id}`, { method:'DELETE' });
    setRules(rs => rs.filter(r=>r.id!==id));
  };

  const actionSummary = (rule) => {
    return (rule.actions||[]).map(a => {
      if (a.type==='send_text') return '💬 Mensaje';
      if (a.type==='send_template') return '📋 Template';
      if (a.type==='add_tag') return '🏷️ Etiqueta';
      if (a.type==='assign_operator') return '👤 Operador';
      if (a.type==='assign_team') return '👥 Equipo';
      if (a.type==='assign_roundrobin') return '🔀 Round-robin';
      if (a.type==='update_status') return `📌 ${a.status}`;
      if (a.type==='move_lead') return '📊 Mover lead';
      return a.type;
    }).join(' · ') || '—';
  };

  return (
    <div style={S.page}>
      <div style={S.pageHeader}>
        <div>
          <div style={{ fontSize:22, fontWeight:800, marginBottom:4 }}>💤 Sin respuesta</div>
          <div style={S.pageSubtitle}>El bot mandó un mensaje y el cliente no respondió. Definí qué pasa en ese caso: enviar un seguimiento, cambiar de etapa, asignar a un operador, o cualquier combinación de acciones con condiciones.</div>
        </div>
        <button onClick={()=>{ setEditing(null); setShowModal(true); }} style={S.btnPrimary}>+ Nueva regla</button>
      </div>

      {rules.length === 0 ? (
        <div style={{ textAlign:'center', padding:'60px 20px', color:'var(--muted)' }}>
          <div style={{ fontSize:40, marginBottom:12 }}>💤</div>
          <div style={{ fontSize:16, fontWeight:600, marginBottom:8 }}>Sin reglas configuradas</div>
          <div style={{ fontSize:13, maxWidth:460, margin:'0 auto', lineHeight:1.5 }}>
            Configurá qué hacer cuando un contacto no responde a un mensaje del bot en determinado tiempo — enviar un seguimiento, cambiar etapa, asignar a un operador, etc.
          </div>
        </div>
      ) : (
        <div style={{ display:'flex', flexDirection:'column', gap:10 }}>
          {rules.map(rule => (
            <div key={rule.id} style={{ background:'var(--surface)', border:'1px solid var(--border)', borderRadius:12, padding:'14px 16px', display:'flex', alignItems:'center', gap:12 }}>
              <div style={{ flex:1 }}>
                <div style={{ display:'flex', alignItems:'center', gap:8, marginBottom:4 }}>
                  <span style={{ fontWeight:700, fontSize:14 }}>{rule.name}</span>
                  <span style={{ fontSize:11, background: rule.enabled?'#d1fae5':'var(--bg)', color: rule.enabled?'#065f46':'var(--muted)', padding:'2px 7px', borderRadius:12, border:'1px solid var(--border)' }}>
                    {rule.enabled ? 'Activa' : 'Inactiva'}
                  </span>
                  {rule.fireOnce && <span style={{ fontSize:11, background:'var(--primary-light)', color:'var(--primary)', padding:'2px 7px', borderRadius:12 }}>1 vez</span>}
                </div>
                <div style={{ fontSize:12, color:'var(--muted)', display:'flex', gap:16, flexWrap:'wrap' }}>
                  <span>💤 {rule.minutesWithoutReply} min sin respuesta</span>
                  <span>{actionSummary(rule)}</span>
                  {rule.pipelineId && <span>📊 Pipeline filtrado</span>}
                </div>
              </div>
              <div style={{ display:'flex', gap:6 }}>
                <button onClick={()=>toggle(rule)} style={{ padding:'5px 10px', borderRadius:7, border:'1px solid var(--border)', cursor:'pointer', fontSize:12, background:'transparent', color:'var(--text)' }}>
                  {rule.enabled ? 'Desactivar' : 'Activar'}
                </button>
                <button onClick={()=>{ setEditing(rule); setShowModal(true); }} style={{ padding:'5px 10px', borderRadius:7, border:'1px solid var(--border)', cursor:'pointer', fontSize:12, background:'transparent', color:'var(--text)' }}>Editar</button>
                <button onClick={()=>del(rule.id)} style={{ padding:'5px 10px', borderRadius:7, border:'1px solid #fee2e2', cursor:'pointer', fontSize:12, background:'transparent', color:'#ef4444' }}>Eliminar</button>
              </div>
            </div>
          ))}
        </div>
      )}

      {showModal && <ContactNoReplyModal rule={editing} onClose={()=>{ setShowModal(false); setEditing(null); }} onSaved={handleSave} />}
    </div>
  );
}

function ConvRulesPanel() {
  const [rules, setRules] = useState([]);
  const [showModal, setShowModal] = useState(false);
  const [editingRule, setEditingRule] = useState(null);

  const load = () => apiFetch('/api/conv-rules').then(r=>r.json()).then(setRules).catch(()=>{});
  useEffect(() => { load(); }, []);

  const handleSave = (saved) => {
    setRules(rs => {
      const idx = rs.findIndex(r=>r.id===saved.id);
      if (idx>=0) { const n=[...rs]; n[idx]=saved; return n; }
      return [...rs, saved];
    });
  };

  const deleteRule = async (id) => {
    if (!confirm('¿Eliminar esta regla?')) return;
    await apiFetch(`/api/conv-rules/${id}`, { method:'DELETE' });
    setRules(rs => rs.filter(r=>r.id!==id));
  };

  const toggleRule = async (id, enabled) => {
    const updated = await apiFetch(`/api/conv-rules/${id}`, {
      method:'PATCH', headers:{'Content-Type':'application/json'}, body:JSON.stringify({ enabled })
    }).then(r=>r.json());
    setRules(rs => rs.map(r => r.id===id ? updated : r));
  };

  const loadExample = async (ex) => {
    const res = await apiFetch('/api/conv-rules', {
      method:'POST', headers:{'Content-Type':'application/json'}, body:JSON.stringify(ex.rule)
    }).then(r=>r.json());
    if (!res.error) setRules(rs => [...rs, res]);
  };

  const sorted = [...rules].sort((a,b) => a.priority - b.priority);

  return (
    <div style={{ ...S.editor }}>
      {showModal && <ConvRuleModal rule={editingRule} onClose={()=>{setShowModal(false);setEditingRule(null);}} onSaved={handleSave} />}

      <div style={{ display:'flex', justifyContent:'space-between', alignItems:'flex-start', marginBottom:24 }}>
        <div>
          <div style={{ fontSize:22, fontWeight:800, marginBottom:4 }}>⚡ Reglas de conversación</div>
          <div style={{ fontSize:13, color:'var(--muted)' }}>
            Acciones que se ejecutan automáticamente cuando pasa algo en un chat — un mensaje con cierta palabra, un cambio de etapa, el primer contacto, etc. Son determinísticas: no dependen de la IA, siempre se ejecutan igual.
          </div>
        </div>
        <button onClick={()=>{setEditingRule(null);setShowModal(true);}}
          style={{ padding:'9px 18px', borderRadius:9, border:'none', background:'var(--primary)', color:'#fff', cursor:'pointer', fontWeight:700, whiteSpace:'nowrap', marginLeft:16 }}>
          + Nueva regla
        </button>
      </div>

      {/* Examples */}
      {rules.length === 0 && (
        <div style={{ background:'var(--bg)', border:'1px solid var(--border)', borderRadius:12, padding:'20px 20px 16px', marginBottom:24 }}>
          <div style={{ fontWeight:700, fontSize:14, marginBottom:12 }}>Ejemplos rápidos</div>
          <div style={{ display:'flex', flexWrap:'wrap', gap:8 }}>
            {EXAMPLE_CONV_RULES.map((ex, i) => (
              <button key={i} onClick={()=>loadExample(ex)}
                style={{ padding:'6px 12px', borderRadius:8, border:'1px solid var(--border)', background:'transparent', cursor:'pointer', fontSize:12, color:'var(--text)', textAlign:'left' }}>
                {ex.label}
              </button>
            ))}
          </div>
        </div>
      )}

      {/* Rules list */}
      {sorted.length === 0 ? (
        <div style={{ textAlign:'center', padding:'48px 24px', color:'var(--muted)' }}>
          <div style={{ fontSize:32, marginBottom:12 }}>⚡</div>
          <div style={{ fontSize:14, fontWeight:600, marginBottom:6 }}>Sin reglas de conversación</div>
          <div style={{ fontSize:13 }}>Creá tu primera regla para automatizar tags, leads, asignaciones y más.</div>
        </div>
      ) : (
        sorted.map(rule => (
          <ConvRuleCard key={rule.id} rule={rule}
            onEdit={r=>{setEditingRule(r);setShowModal(true);}}
            onDelete={deleteRule}
            onToggle={toggleRule} />
        ))
      )}

      <div style={{ marginTop:20, padding:'14px 16px', background:'var(--bg)', borderRadius:10, border:'1px solid var(--border)', fontSize:12, color:'var(--muted)' }}>
        <strong>Cómo funciona:</strong> Cada vez que llega un mensaje, el motor evalúa todas las reglas activas en orden de prioridad. Si se cumplen las condiciones, se ejecutan las acciones en secuencia. Las reglas con "Solo 1 vez" no vuelven a dispararse en la misma conversación. "Detener si aplica" evita que reglas de menor prioridad se evalúen.
      </div>
    </div>
  );
}

const EXAMPLE_RULES = [
  { label:'Lead +3 días en Qualified → mensaje de seguimiento', rule:{ name:'Seguimiento Qualified', conditionOperator:'AND', conditions:[{type:'days_in_stage',stageId:'',days:3}], action:{type:'send_text',message:'Hola {{name}}! 👋 Te escribo para hacer un seguimiento. ¿Pudiste revisar la info que te mandamos? Cualquier duda acá estoy 😊'}, cooldownDays:7, maxFires:2 } },
  { label:'Lead grande (+5 agentes) sin avance → asignar a operador', rule:{ name:'Lead grande sin avance', conditionOperator:'AND', conditions:[{type:'attribute_gte',attributeKey:'agentes',attributeValue:'5'},{type:'days_in_stage',days:5}], action:{type:'assign_operator'}, cooldownDays:3, maxFires:1 } },
  { label:'Lead en Follow Up +7 días → enviar template', rule:{ name:'Reactivación Follow Up', conditionOperator:'AND', conditions:[{type:'days_in_stage',stageId:'',days:7},{type:'has_tag',tagName:'client'}], action:{type:'send_template'}, cooldownDays:14, maxFires:1 } },
  { label:'Lead interesado en plan Business → link de agenda', rule:{ name:'Demo para plan Business', conditionOperator:'AND', conditions:[{type:'has_attribute',attributeKey:'planes',attributeValue:'Business'}], action:{type:'send_meeting_link',message:'{{name}}, vi que estás evaluando el plan Business. ¿Querés que armemos una demo de 15 min? Elegí el horario que mejor te quede: {{meeting_link}}'}, cooldownDays:7, maxFires:1 } },
  { label:'Lead creado +14 días sin moverse → mensaje de reengagement', rule:{ name:'Reengagement 2 semanas', conditionOperator:'AND', conditions:[{type:'days_since_created',days:14}], action:{type:'send_text',message:'{{name}}, hace 2 semanas que hablamos. ¿Cómo va la evaluación? Si querés lo retomamos cuando tengas 5 minutos 🙌'}, cooldownDays:30, maxFires:1 } },
];

function NurturingPanel() {
  const [rules, setRules] = useState([]);
  const [showModal, setShowModal] = useState(false);
  const [editingRule, setEditingRule] = useState(null);

  const load = () => apiFetch('/api/nurturing').then(r=>r.json()).then(setRules).catch(()=>{});
  useEffect(() => { load(); }, []);

  const handleSave = (saved) => {
    setRules(rs => {
      const idx = rs.findIndex(r=>r.id===saved.id);
      if (idx>=0) { const next=[...rs]; next[idx]=saved; return next; }
      return [...rs, saved];
    });
  };

  const handleDelete = async (rule) => {
    if (!confirm(`¿Eliminar la regla "${rule.name}"?`)) return;
    await apiFetch(`/api/nurturing/${rule.id}`, { method:'DELETE' });
    setRules(rs => rs.filter(r=>r.id!==rule.id));
  };

  const handleToggle = async (rule) => {
    const updated = await apiFetch(`/api/nurturing/${rule.id}`, {
      method:'PATCH', headers:{'Content-Type':'application/json'},
      body: JSON.stringify({ enabled: !rule.enabled }),
    }).then(r=>r.json());
    handleSave(updated);
  };

  const loadExample = async (example) => {
    const res = await apiFetch('/api/nurturing', {
      method:'POST', headers:{'Content-Type':'application/json'},
      body: JSON.stringify({ ...example.rule, enabled: false }),
    });
    const saved = await res.json();
    setRules(rs=>[...rs, saved]);
  };

  return (
    <div style={{ ...S.editor }}>
      <div>
        <div style={S.pageTitle}>🌱 Nurturing</div>
        <div style={S.pageSubtitle}>Secuencias de mensajes que se envían automáticamente cuando un lead lleva X días sin avanzar en el pipeline. Ideal para reactivar oportunidades sin intervención manual.</div>
      </div>

      {/* Examples */}
      <div style={S.card}>
        <div style={S.cardTitle}>💡 Ejemplos rápidos</div>
        <div style={{ ...S.cardDesc, marginBottom:10 }}>Cargá una regla de ejemplo para empezar rápido. Podés editarla después.</div>
        <div style={{ display:'flex', flexDirection:'column', gap:6 }}>
          {EXAMPLE_RULES.map((ex,i) => (
            <div key={i} style={{ display:'flex', alignItems:'center', justifyContent:'space-between', padding:'8px 12px', background:'#f9fafb', borderRadius:8, border:'1px solid var(--border)' }}>
              <span style={{ fontSize:13 }}>{ex.label}</span>
              <button style={{ ...S.outlineBtn, padding:'4px 12px', fontSize:12 }} onClick={()=>loadExample(ex)}>Cargar</button>
            </div>
          ))}
        </div>
      </div>

      {/* Rules list */}
      <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between' }}>
        <div style={{ fontWeight:700, fontSize:14 }}>Mis reglas ({rules.length})</div>
        <button style={S.saveBtn} onClick={() => { setEditingRule(null); setShowModal(true); }}>+ Nueva regla</button>
      </div>

      {rules.length === 0 ? (
        <div style={{ ...S.card, textAlign:'center', color:'var(--muted)', padding:'40px 24px' }}>
          <div style={{ fontSize:40, marginBottom:12 }}>🌱</div>
          <div style={{ fontSize:14, fontWeight:600, marginBottom:6 }}>Sin reglas de nurturing</div>
          <div style={{ fontSize:13 }}>Cargá un ejemplo de arriba o creá tu primera regla.</div>
        </div>
      ) : (
        <div style={{ display:'flex', flexDirection:'column', gap:12 }}>
          {rules.map(rule => (
            <RuleCard
              key={rule.id}
              rule={rule}
              onEdit={r => { setEditingRule(r); setShowModal(true); }}
              onDelete={handleDelete}
              onToggle={handleToggle}
            />
          ))}
        </div>
      )}

      <div style={{ ...S.card, background:'#f0fdf4', border:'1px solid #bbf7d0', marginBottom:40 }}>
        <div style={{ fontSize:13, color:'#15803d', lineHeight:1.6 }}>
          <strong>¿Cómo funciona?</strong><br/>
          El motor de nurturing corre automáticamente cada hora. Evalúa todas las reglas activas contra los leads del pipeline y ejecuta la acción cuando se cumplen las condiciones.
          El cooldown evita reenvíos molestos — si ya se ejecutó la regla para un contacto, espera X días antes de volver a hacerlo. El máximo de envíos limita cuántas veces puede dispararse por contacto.
        </div>
      </div>

      {showModal && (
        <RuleModal
          rule={editingRule}
          onClose={() => setShowModal(false)}
          onSave={handleSave}
        />
      )}
    </div>
  );
}

// ─── Login Screen ─────────────────────────────────────────────────────────────
function LoginScreen({ onLogin }) {
  const [tab, setTab] = useState('tenant'); // 'tenant' | 'admin' | 'tester'
  const [form, setForm] = useState({ email:'', password:'', accountNumber:'', pipochatApiUrl:'https://pipochat.com/api-server/v1', pipochatApiToken:'' });
  const [adminForm, setAdminForm] = useState({ email:'', password:'' });
  const [testerForm, setTesterForm] = useState({ email:'', password:'' });
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState('');

  const set = (k, v) => setForm(f => ({ ...f, [k]: v }));

  const loginTenant = async () => {
    setLoading(true); setError('');
    try {
      const r = await fetch('/api/auth/login', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(form),
      });
      const data = await r.json();
      if (!r.ok) { setError(data.error || 'Error al iniciar sesión'); return; }
      saveSession(data.token, 'tenant');
      onLogin('tenant');
    } catch { setError('Error de conexión'); }
    finally { setLoading(false); }
  };

  const loginAdmin = async () => {
    setLoading(true); setError('');
    try {
      const r = await fetch('/api/admin/login', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(adminForm),
      });
      const data = await r.json();
      if (!r.ok) { setError(data.error || 'Credenciales incorrectas'); return; }
      saveSession(data.token, 'admin');
      onLogin('admin');
    } catch { setError('Error de conexión'); }
    finally { setLoading(false); }
  };

  const loginTester = async () => {
    setLoading(true); setError('');
    try {
      const r = await fetch('/api/auth/tester-login', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(testerForm),
      });
      const data = await r.json();
      if (!r.ok) { setError(data.error || 'Credenciales incorrectas'); return; }
      saveSession(data.token, 'tenant');
      onLogin('tenant');
    } catch { setError('Error de conexión'); }
    finally { setLoading(false); }
  };

  const loginField = (label, key, type='text', placeholder='', form2, setForm2) => (
    <div style={{ display:'flex', flexDirection:'column', gap:5, marginBottom:14 }}>
      <label style={{ fontSize:11, fontWeight:700, color:'var(--ink-3)', textTransform:'uppercase', letterSpacing:.7 }}>{label}</label>
      <input type={type} placeholder={placeholder}
        value={form2 ? form2[key] : form[key]}
        onChange={e => form2 ? setForm2(f => ({ ...f, [key]: e.target.value })) : set(key, e.target.value)}
        style={{ padding:'10px 13px', border:'1.5px solid var(--border)', borderRadius:10, fontSize:13.5, outline:'none', color:'var(--ink)', background:'var(--white)', transition:'border-color var(--trans)' }}
        onKeyDown={e => e.key === 'Enter' && (form2 ? loginAdmin() : loginTenant())}
      />
    </div>
  );

  return (
    <div style={{ display:'flex', height:'100vh', background:'var(--cream)' }}>
      {/* Left panel — brand */}
      <div style={{ width:400, background:'var(--green)', display:'flex', flexDirection:'column', alignItems:'center', justifyContent:'center', padding:48, flexShrink:0 }}>
        <PipochatLogo size={64} />
        <div style={{ marginTop:20, textAlign:'center' }}>
          <div style={{ fontSize:28, fontWeight:900, color:'#fff', letterSpacing:'-.5px', lineHeight:1.1 }}>
            <span style={{ opacity:.7 }}>pipo</span>chat
          </div>
          <div style={{ fontSize:14, color:'rgba(255,255,255,.6)', marginTop:8, lineHeight:1.6 }}>
            Plataforma de AI Agents<br/>para WhatsApp Business
          </div>
        </div>
        <div style={{ marginTop:48, display:'flex', flexDirection:'column', gap:14, width:'100%', maxWidth:260 }}>
          {[
            { icon:'🤖', text:'Agentes IA con lenguaje natural' },
            { icon:'⚡', text:'Automatizaciones sin código' },
            { icon:'📊', text:'CRM integrado con pipelines' },
            { icon:'💬', text:'Multi-línea WhatsApp Business' },
          ].map(({ icon, text }) => (
            <div key={text} style={{ display:'flex', alignItems:'center', gap:10, color:'rgba(255,255,255,.85)', fontSize:13 }}>
              <span style={{ fontSize:16 }}>{icon}</span> {text}
            </div>
          ))}
        </div>
      </div>

      {/* Right panel — form */}
      <div style={{ flex:1, display:'flex', alignItems:'center', justifyContent:'center', padding:48 }}>
        <div style={{ width:'100%', maxWidth:400 }}>
          <div style={{ marginBottom:32 }}>
            <div style={{ fontSize:24, fontWeight:800, color:'var(--ink)', letterSpacing:'-.4px', marginBottom:6 }}>
              Ingresar al dashboard
            </div>
            <div style={{ fontSize:14, color:'var(--ink-3)' }}>
              Usá tus credenciales de Pipochat para acceder.
            </div>
          </div>

          {/* Tabs */}
          <div style={{ display:'flex', gap:4, marginBottom:24, background:'var(--cream-mid)', borderRadius:10, padding:4 }}>
            {[['tenant','Mi cuenta'],['tester','Demo'],['admin','Admin']].map(([t, label]) => (
              <button key={t} onClick={() => { setTab(t); setError(''); }}
                style={{ flex:1, padding:'8px 0', borderRadius:8, border:'none', cursor:'pointer', fontSize:13, fontWeight:600,
                  background: tab === t ? '#fff' : 'transparent',
                  color: tab === t ? 'var(--green)' : 'var(--ink-3)',
                  boxShadow: tab === t ? 'var(--shadow-sm)' : 'none',
                  transition:'all var(--trans)' }}>
                {label}
              </button>
            ))}
          </div>

          {tab === 'tenant' && (
            <>
              {loginField('Pipochat URL', 'pipochatApiUrl', 'text', 'https://pipochat.com/api-server/v1')}
              {loginField('API Token', 'pipochatApiToken', 'password', 'Tu token de Pipochat')}
              {loginField('Email', 'email', 'email', 'tu@empresa.com')}
              {loginField('Contraseña', 'password', 'password')}
              {loginField('ID de cuenta', 'accountNumber', 'text', 'Número de cuenta Pipochat')}
              {error && (
                <div style={{ background:'var(--danger-light)', color:'var(--danger)', fontSize:12.5, padding:'10px 13px', borderRadius:8, marginBottom:14, fontWeight:500 }}>
                  ⚠️ {error}
                </div>
              )}
              <button onClick={loginTenant} disabled={loading}
                style={{ width:'100%', padding:'13px', background:'var(--green)', color:'#fff', border:'none', borderRadius:12, fontSize:15, fontWeight:700, cursor: loading ? 'wait' : 'pointer', boxShadow:'0 4px 16px var(--green-glow)', transition:'background var(--trans)' }}>
                {loading ? 'Ingresando…' : 'Ingresar →'}
              </button>
            </>
          )}

          {tab === 'tester' && (
            <>
              <div style={{ background:'var(--green-light)', border:'1px solid var(--green-mid)', borderRadius:10, padding:'12px 14px', marginBottom:20, fontSize:13, color:'var(--green)', lineHeight:1.5 }}>
                🔍 Acceso de revisión — modo solo lectura con datos de demostración de Looplead.
              </div>
              {loginField('Email', 'email', 'email', 'tester@thelooplead.com', testerForm, setTesterForm)}
              {loginField('Contraseña', 'password', 'password', '', testerForm, setTesterForm)}
              {error && (
                <div style={{ background:'var(--danger-light)', color:'var(--danger)', fontSize:12.5, padding:'10px 13px', borderRadius:8, marginBottom:14, fontWeight:500 }}>
                  ⚠️ {error}
                </div>
              )}
              <button onClick={loginTester} disabled={loading}
                style={{ width:'100%', padding:'13px', background:'var(--green)', color:'#fff', border:'none', borderRadius:12, fontSize:15, fontWeight:700, cursor: loading ? 'wait' : 'pointer', boxShadow:'0 4px 16px var(--green-glow)', transition:'background var(--trans)' }}>
                {loading ? 'Ingresando…' : 'Acceso Demo →'}
              </button>
            </>
          )}

          {tab === 'admin' && (
            <>
              {loginField('Email', 'email', 'email', 'admin@empresa.com', adminForm, setAdminForm)}
              {loginField('Contraseña', 'password', 'password', '', adminForm, setAdminForm)}
              {error && (
                <div style={{ background:'var(--danger-light)', color:'var(--danger)', fontSize:12.5, padding:'10px 13px', borderRadius:8, marginBottom:14, fontWeight:500 }}>
                  ⚠️ {error}
                </div>
              )}
              <button onClick={loginAdmin} disabled={loading}
                style={{ width:'100%', padding:'13px', background:'var(--ink)', color:'#fff', border:'none', borderRadius:12, fontSize:15, fontWeight:700, cursor: loading ? 'wait' : 'pointer', transition:'background var(--trans)' }}>
                {loading ? 'Ingresando…' : 'Acceso Admin →'}
              </button>
            </>
          )}
        </div>
      </div>
    </div>
  );
}

// ─── Backup Panel ────────────────────────────────────────────────────────────
function BackupPanel() {
  const [backups, setBackups]     = useState([]);
  const [loading, setLoading]     = useState(true);
  const [restoring, setRestoring] = useState(false);
  const [msg, setMsg]             = useState(null); // { ok: bool, text: string }
  const [confirm, setConfirm]     = useState(false);

  const load = async () => {
    setLoading(true);
    try {
      const r = await apiFetch('/api/backup/list');
      const d = await r.json();
      setBackups(d.backups || []);
    } catch { setBackups([]); }
    setLoading(false);
  };

  useEffect(() => { load(); }, []);

  const latest = backups[0] || null;

  const doRestore = async () => {
    setConfirm(false);
    setRestoring(true);
    setMsg(null);
    try {
      const r  = await apiFetch('/api/backup/restore', { method: 'POST', body: JSON.stringify({}) });
      const d  = await r.json();
      if (!r.ok) throw new Error(d.error || 'Error desconocido');
      setMsg({ ok: true, text: `✅ ${d.message}` });
    } catch (e) {
      setMsg({ ok: false, text: `❌ ${e.message}` });
    }
    setRestoring(false);
  };

  const fmtSize = (bytes) => {
    if (bytes < 1024)        return `${bytes} B`;
    if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
    return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
  };

  const fmtDate = (iso) => {
    if (!iso) return '—';
    try {
      return new Date(iso).toLocaleString('es-AR', { day:'2-digit', month:'2-digit', year:'numeric', hour:'2-digit', minute:'2-digit' });
    } catch { return iso; }
  };

  return (
    <div style={{ maxWidth: 560, margin: '0 auto', padding: 32 }}>
      <div style={{ marginBottom: 24 }}>
        <h2 style={{ fontSize: 20, fontWeight: 700, margin: 0 }}>💾 Backup & Restauración</h2>
        <p style={{ fontSize: 13, color: 'var(--ink-4)', marginTop: 6 }}>
          Los backups se generan automáticamente cada día a las 3am. Se guardan los últimos 7.
        </p>
      </div>

      {/* Latest backup card */}
      <div style={{ background: 'var(--white)', border: '1px solid var(--border-soft)', borderRadius: 14, padding: 20, marginBottom: 20 }}>
        <div style={{ fontSize: 12, fontWeight: 600, color: 'var(--ink-4)', textTransform: 'uppercase', letterSpacing: '.05em', marginBottom: 12 }}>
          Último backup disponible
        </div>

        {loading ? (
          <div style={{ fontSize: 13, color: 'var(--ink-4)' }}>Cargando...</div>
        ) : !latest ? (
          <div style={{ fontSize: 13, color: 'var(--ink-4)' }}>
            No hay backups disponibles aún. El primero se genera esta noche a las 3am.
          </div>
        ) : (
          <div style={{ display: 'flex', alignItems: 'center', gap: 16 }}>
            <div style={{ fontSize: 32 }}>🗂️</div>
            <div style={{ flex: 1 }}>
              <div style={{ fontSize: 14, fontWeight: 600 }}>{fmtDate(latest.createdAt)}</div>
              <div style={{ fontSize: 12, color: 'var(--ink-4)', marginTop: 3 }}>
                {fmtSize(latest.sizeBytes)} · {latest.filename}
              </div>
            </div>
          </div>
        )}
      </div>

      {/* Restore button */}
      {latest && !confirm && (
        <button
          onClick={() => setConfirm(true)}
          disabled={restoring}
          style={{
            width: '100%', padding: '12px 20px',
            background: 'var(--green)', color: '#fff',
            border: 'none', borderRadius: 12,
            fontSize: 14, fontWeight: 700, cursor: restoring ? 'not-allowed' : 'pointer',
            opacity: restoring ? .6 : 1,
          }}>
          {restoring ? '⏳ Restaurando...' : '↩ Restaurar último backup'}
        </button>
      )}

      {/* Confirm dialog */}
      {confirm && (
        <div style={{ background: '#FFF8ED', border: '1.5px solid #F59E0B', borderRadius: 12, padding: 18, marginTop: 4 }}>
          <div style={{ fontSize: 14, fontWeight: 600, color: '#92400E', marginBottom: 8 }}>
            ⚠️ ¿Confirmar restauración?
          </div>
          <div style={{ fontSize: 13, color: '#92400E', marginBottom: 16 }}>
            Esto va a reemplazar la configuración actual (agentes, promos, reglas) con la del backup del {fmtDate(latest.createdAt)}.
            Los cambios que hiciste después de esa fecha se van a perder.
          </div>
          <div style={{ display: 'flex', gap: 10 }}>
            <button
              onClick={doRestore}
              style={{ flex: 1, padding: '10px 0', background: '#D97706', color: '#fff', border: 'none', borderRadius: 10, fontSize: 13, fontWeight: 700, cursor: 'pointer' }}>
              Sí, restaurar
            </button>
            <button
              onClick={() => setConfirm(false)}
              style={{ flex: 1, padding: '10px 0', background: 'transparent', color: '#92400E', border: '1.5px solid #F59E0B', borderRadius: 10, fontSize: 13, fontWeight: 700, cursor: 'pointer' }}>
              Cancelar
            </button>
          </div>
        </div>
      )}

      {/* Result message */}
      {msg && (
        <div style={{
          marginTop: 16, padding: '12px 16px', borderRadius: 10, fontSize: 13, fontWeight: 500,
          background: msg.ok ? 'var(--success-light, #F0FDF4)' : 'var(--danger-light)',
          color: msg.ok ? 'var(--success, #16A34A)' : 'var(--danger)',
          border: `1px solid ${msg.ok ? '#BBF7D0' : 'var(--danger)'}`,
        }}>
          {msg.text}
        </div>
      )}

      {/* All backups list */}
      {backups.length > 1 && (
        <div style={{ marginTop: 28 }}>
          <div style={{ fontSize: 12, fontWeight: 600, color: 'var(--ink-4)', textTransform: 'uppercase', letterSpacing: '.05em', marginBottom: 10 }}>
            Historial ({backups.length})
          </div>
          <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
            {backups.map((b, i) => (
              <div key={b.filename} style={{
                display: 'flex', alignItems: 'center', justifyContent: 'space-between',
                padding: '10px 14px', borderRadius: 10,
                background: i === 0 ? 'var(--green-light, #F0FDF4)' : 'var(--bg)',
                border: `1px solid ${i === 0 ? '#BBF7D0' : 'var(--border-soft)'}`,
                fontSize: 13,
              }}>
                <span style={{ fontWeight: i === 0 ? 600 : 400 }}>
                  {i === 0 && '⭐ '}{fmtDate(b.createdAt)}
                </span>
                <span style={{ color: 'var(--ink-4)', fontSize: 12 }}>{fmtSize(b.sizeBytes)}</span>
              </div>
            ))}
          </div>
        </div>
      )}
    </div>
  );
}

// ─── Admin Panel ──────────────────────────────────────────────────────────────
function AdminPanel({ onLogout }) {
  const [tenants, setTenants] = useState([]);
  const [usage, setUsage] = useState({});
  const [loading, setLoading] = useState(true);

  const load = async () => {
    setLoading(true);
    const [tr, ur] = await Promise.all([
      apiFetch('/api/admin/tenants').then(r => r.json()),
      apiFetch('/api/admin/usage').then(r => r.json()),
    ]);
    setTenants(tr.tenants || []);
    const usageMap = {};
    (ur.usage || []).forEach(u => { usageMap[u.tenantId] = u.usage; });
    setUsage(usageMap);
    setLoading(false);
  };

  useEffect(() => { load(); }, []);

  const deleteTenant = async (id) => {
    if (!confirm(`¿Eliminar tenant ${id}?`)) return;
    await apiFetch(`/api/admin/tenants/${id}`, { method: 'DELETE' });
    load();
  };

  const enterTenant = async (t) => {
    const r = await apiFetch(`/api/admin/impersonate/${t.id}`, { method: 'POST' });
    const d = await r.json().catch(() => ({}));
    if (!d.token) { alert(d.error || 'No se pudo entrar al tenant'); return; }
    localStorage.setItem('ll_admin_token', getToken()); // para poder volver al admin
    saveSession(d.token, 'tenant');
    window.location.reload();
  };

  const fmt = (n) => n >= 1000000 ? (n/1000000).toFixed(1)+'M' : n >= 1000 ? (n/1000).toFixed(0)+'K' : String(n||0);
  const fmtUsd = (n) => '$' + (n||0).toFixed(4);

  return (
    <div style={{ display:'flex', height:'100vh', overflow:'hidden', background:'var(--bg)' }}>
      {/* Sidebar */}
      <div style={{ width:200, background:'var(--surface)', borderRight:'1px solid var(--border)', display:'flex', flexDirection:'column' }}>
        <div style={{ padding:'18px 16px 14px', borderBottom:'1px solid var(--border)' }}>
          <div style={{ fontWeight:800, fontSize:15, color:'var(--text)' }}>Looplead</div>
          <div style={{ fontSize:11, color:'#ef4444', marginTop:2 }}>⚡ Super Admin</div>
        </div>
        <div style={{ flex:1 }} />
        <button onClick={() => { clearSession(); onLogout(); }}
          style={{ margin:12, padding:'8px 14px', background:'transparent', color:'var(--danger)', border:'1px solid var(--danger)', borderRadius:8, fontSize:12, fontWeight:600, cursor:'pointer' }}>
          Cerrar sesión
        </button>
      </div>

      {/* Main */}
      <div style={{ flex:1, overflowY:'auto', padding:'28px 32px' }}>
        <div style={{ fontSize:20, fontWeight:800, marginBottom:4 }}>Tenants</div>
        <div style={{ fontSize:13, color:'var(--muted)', marginBottom:24 }}>Todos los negocios conectados · {tenants.length} total</div>

        {loading ? (
          <div style={{ color:'var(--muted)', fontSize:13 }}>Cargando...</div>
        ) : tenants.length === 0 ? (
          <div style={{ color:'var(--muted)', fontSize:13 }}>Sin tenants registrados.</div>
        ) : (
          <div style={{ display:'flex', flexDirection:'column', gap:12 }}>
            {tenants.map(t => {
              const u = usage[t.id] || {};
              const month = new Date().toISOString().slice(0,7);
              const mo = u.monthly?.[month] || {};
              return (
                <div key={t.id} style={{ background:'var(--surface)', border:'1px solid var(--border)', borderRadius:10, padding:'16px 20px', display:'flex', alignItems:'center', gap:16 }}>
                  <div style={{ flex:1 }}>
                    <div style={{ fontWeight:700, fontSize:14 }}>{t.agentName ? '🤖 ' + t.agentName : (t.name || t.id)}</div>
                    <div style={{ fontSize:12, color:'var(--muted)', marginTop:2 }}>{t.email} · #{t.accountNumber}</div>
                    <div style={{ fontSize:11, color:'var(--muted)', marginTop:1 }}>{t.pipochatApiUrl}</div>
                  </div>
                  <div style={{ textAlign:'right', minWidth:140 }}>
                    <div style={{ fontSize:13, fontWeight:700, color:'var(--primary)' }}>Este mes: {fmtUsd(mo.costUsd)}</div>
                    <div style={{ fontSize:11, color:'var(--muted)' }}>↑ {fmt(mo.input)} / ↓ {fmt(mo.output)} tokens</div>
                    <div style={{ fontSize:11, color:'var(--muted)' }}>Total: {fmtUsd(u.totalCostUsd)}</div>
                  </div>
                  <button onClick={() => enterTenant(t)}
                    style={{ background:'var(--primary)', border:'none', color:'#fff', borderRadius:6, padding:'7px 14px', fontSize:12, cursor:'pointer', fontWeight:700, whiteSpace:'nowrap' }}>
                    Entrar →
                  </button>
                  <button onClick={() => deleteTenant(t.id)}
                    style={{ background:'none', border:'1px solid #fca5a5', color:'#ef4444', borderRadius:6, padding:'6px 12px', fontSize:12, cursor:'pointer', fontWeight:600, whiteSpace:'nowrap' }}>
                    Eliminar
                  </button>
                </div>
              );
            })}
          </div>
        )}
      </div>
    </div>
  );
}

// ─── Tenant Dashboard ─────────────────────────────────────────────────────────
// ─── Onboarding Wizard ────────────────────────────────────────────────────────

const EXEC_STEP_ICONS = { operators:'👤', teams:'👥', pipeline:'📊', tags:'🏷️', agent:'🤖', kb:'📚', rule_welcome:'👋', rule_ooh:'🌙', rule_followup:'💬' };
const STEP_ICONS = EXEC_STEP_ICONS; // alias used by AI panel

const ONBOARDING_EXAMPLES = [
  'Somos Otaku Sushi, una cadena de sushi con 5 locales en Buenos Aires (Palermo, Vicente López, Mataderos, Caballito, Belgrano). Tenemos ~20 operadores. El agente debe derivar a cada local según las palabras clave de la conversación.',
  'Somos RE/MAX Norte, inmobiliaria con 8 asesores. El agente debe calificar leads, agendar visitas y derivar según zona (norte, sur, centro). Horario 9-18 lunes a viernes.',
  'Soy coach de fitness con clientes online y presenciales. Ofrezco planes de entrenamiento personalizados. Quiero un agente que responda consultas, agende sesiones de prueba y haga seguimiento automático.',
];

const WIZARD_STEPS = [
  { id:'business',  icon:'🏢', label:'Tu negocio'   },
  { id:'operators', icon:'👤', label:'Operadores'   },
  { id:'teams',     icon:'👥', label:'Equipos'      },
  { id:'pipeline',  icon:'📊', label:'Pipeline'     },
  { id:'tags',      icon:'🏷️', label:'Etiquetas'    },
  { id:'agent',     icon:'🤖', label:'Agente AI'    },
  { id:'knowledge', icon:'📚', label:'Conocimiento' },
  { id:'rules',     icon:'⚡', label:'Acciones'     },
  { id:'review',    icon:'✅', label:'Revisar'      },
];

const BTYPE_OPTIONS = [
  { value:'restaurant',    label:'🍽️ Restaurant / Gastronomía' },
  { value:'inmobiliaria',  label:'🏠 Inmobiliaria' },
  { value:'gym',           label:'💪 Gimnasio / Salud' },
  { value:'ecommerce',     label:'🛒 E-commerce / Tienda' },
  { value:'clinica',       label:'🏥 Clínica / Salud' },
  { value:'educacion',     label:'📖 Educación' },
  { value:'agencia',       label:'📣 Agencia de marketing' },
  { value:'otro',          label:'⚙️ Otro' },
];

const DAYS_SHORT = ['Dom','Lun','Mar','Mié','Jue','Vie','Sáb'];

const WIZARD_EMPTY = {
  businessName:'', businessType:'restaurant', businessDescription:'', language:'es',
  phoneToConnect:'',
  assignment:{ enabled:true, onlineOnly:true },
  operators:[], teams:[],
  pipelineEnabled:true, pipelineName:'Pipeline de Ventas',
  pipelineStages:['Nuevo','Contactado','Calificado','Propuesta enviada','Cerrado ganado'],
  tags:[],
  agentName:'', agentTone:'friendly', scheduleStart:9, scheduleEnd:18, workDays:[1,2,3,4,5],
  agentInstructions:'',
  knowledgeBase:'',
  ruleWelcome:{ enabled:true,  message:'¡Hola! ¿En qué te puedo ayudar?' },
  ruleOoh:{ enabled:true, message:'Gracias por escribirnos. Te respondemos en el próximo horario de atención.', hourStart:9, hourEnd:18, days:[1,2,3,4,5] },
  ruleFollowup:{ enabled:false, minutes:30, message:'¡Hola! ¿Pudiste revisar la info? ¿Tenés alguna duda? 😊' },
  actionCreateLead:false, actionLeadStage:'',
  actionSaveData:false, actionSaveDataFields:[],
};

function buildPlanFromWizard(w) {
  const plan = {
    businessSummary: w.businessName + (w.businessDescription ? ' — ' + w.businessDescription.slice(0,100) : ''),
    operators: w.operators,
    teams: w.teams,
    pipeline: w.pipelineEnabled ? { title: w.pipelineName, stages: w.pipelineStages } : null,
    tags: w.tags,
    agent: {
      name: w.agentName || (w.businessName + ' — Asistente'),
      instructions: w.agentInstructions,
      language: w.language,
      scheduleStart: w.scheduleStart,
      scheduleEnd: w.scheduleEnd,
      workDays: w.workDays,
    },
    knowledgeBase: w.knowledgeBase,
    agentActions: [],
    rules: {
      welcome:    w.ruleWelcome,
      outOfHours: w.ruleOoh.enabled ? { ...w.ruleOoh, enabled:true } : null,
      followUp:   w.ruleFollowup.enabled ? { ...w.ruleFollowup, enabled:true } : null,
    },
    phone: w.phoneToConnect || '',
    assignment: w.assignment || { enabled:false, onlineOnly:true },
  };
  if (w.actionCreateLead && w.actionLeadStage) {
    plan.agentActions.push({ type:'create_lead', enabled:true, config:{ trigger:'always', stageId: w.actionLeadStage } });
  }
  if (w.actionSaveData && w.actionSaveDataFields.length > 0) {
    plan.agentActions.push({ type:'add_lead_attribute', enabled:true, config:{ attributes: w.actionSaveDataFields } });
  }
  return plan;
}

// ── Wizard step wrapper ──────────────────────────────────────────────────────

function WizardChrome({ step, total, title, subtitle, onBack, onNext, nextLabel, nextDisabled, children }) {
  const progress = ((step) / (total - 1)) * 100;
  return (
    <div style={{ width:'100%' }}>
      {/* Progress bar */}
      <div style={{ height:4, background:'var(--border)', borderRadius:2, marginBottom:28, overflow:'hidden' }}>
        <div style={{ height:'100%', width: progress + '%', background:'var(--primary)', borderRadius:2, transition:'width 0.3s' }} />
      </div>
      {/* Step indicators */}
      <div style={{ display:'flex', justifyContent:'space-between', marginBottom:28, overflowX:'auto', gap:4 }}>
        {WIZARD_STEPS.map((s, i) => (
          <div key={s.id} style={{ display:'flex', flexDirection:'column', alignItems:'center', gap:4, minWidth:52 }}>
            <div style={{ width:32, height:32, borderRadius:'50%', display:'flex', alignItems:'center', justifyContent:'center', fontSize:14,
              background: i < step ? 'var(--primary)' : i === step ? 'var(--primary)' : 'var(--border)',
              color: i <= step ? '#fff' : 'var(--muted)', fontWeight:700,
              boxShadow: i === step ? '0 0 0 3px var(--primary-light)' : 'none', transition:'all 0.2s' }}>
              {i < step ? '✓' : s.icon}
            </div>
            <div style={{ fontSize:10, color: i === step ? 'var(--primary)' : 'var(--muted)', fontWeight: i === step ? 700 : 400, textAlign:'center' }}>{s.label}</div>
          </div>
        ))}
      </div>
      {/* Content */}
      <div style={{ background:'var(--surface)', border:'1px solid var(--border)', borderRadius:14, padding:'28px 32px', marginBottom:20 }}>
        <div style={{ fontSize:20, fontWeight:800, marginBottom:4 }}>{title}</div>
        {subtitle && <div style={{ fontSize:13, color:'var(--muted)', marginBottom:20 }}>{subtitle}</div>}
        {children}
      </div>
      {/* Actions */}
      <div style={{ display:'flex', justifyContent:'space-between', paddingBottom:32 }}>
        <button onClick={onBack} style={{ padding:'10px 20px', borderRadius:9, border:'1px solid var(--border)', background:'transparent', cursor:'pointer', color:'var(--text)', fontWeight:500 }}>
          {step === 0 ? 'Cancelar' : '← Atrás'}
        </button>
        <button onClick={onNext} disabled={nextDisabled}
          style={{ padding:'10px 28px', borderRadius:9, border:'none', background:'var(--primary)', color:'#fff', fontWeight:700, fontSize:14,
            cursor: nextDisabled ? 'not-allowed' : 'pointer', opacity: nextDisabled ? 0.5 : 1 }}>
          {nextLabel || 'Siguiente →'}
        </button>
      </div>
    </div>
  );
}

// ── Step components ──────────────────────────────────────────────────────────

function StepBusiness({ w, set }) {
  return (
    <div style={{ display:'flex', flexDirection:'column', gap:16 }}>
      <Field label="Nombre del negocio *">
        <input style={S.input} value={w.businessName} onChange={e => set('businessName', e.target.value)} placeholder="Ej: Otaku Sushi, RE/MAX Norte, Gimnasio Body..." />
      </Field>
      <Field label="📞 Número de WhatsApp a conectar">
        <input style={S.input} value={w.phoneToConnect} onChange={e => set('phoneToConnect', e.target.value)} placeholder="Ej: +54 9 11 1234-5678 (el alta del número se hace manual en Pipochat)" />
      </Field>
      <Field label="Tipo de negocio">
        <select style={S.select} value={w.businessType} onChange={e => set('businessType', e.target.value)}>
          {BTYPE_OPTIONS.map(o => <option key={o.value} value={o.value}>{o.label}</option>)}
        </select>
      </Field>
      <Field label="Descripción breve (opcional)">
        <textarea style={{ ...S.input, minHeight:80, resize:'vertical' }} value={w.businessDescription}
          onChange={e => set('businessDescription', e.target.value)}
          placeholder="Qué hacen, qué ofrecen, qué hace especial a este negocio..." />
      </Field>
      <Field label="Idioma del agente">
        <select style={S.select} value={w.language} onChange={e => set('language', e.target.value)}>
          <option value="es">🇦🇷 Español</option>
          <option value="en">🇺🇸 English</option>
          <option value="pt">🇧🇷 Português</option>
        </select>
      </Field>
    </div>
  );
}

function StepOperators({ w, set }) {
  const [form, setForm] = React.useState({ firstName:'', lastName:'', email:'', role:'operator' });
  const [err, setErr] = React.useState('');
  const add = () => {
    if (!form.firstName.trim() || !form.email.trim()) { setErr('Nombre y email son obligatorios'); return; }
    if (w.operators.some(o => o.email === form.email)) { setErr('Ese email ya está en la lista'); return; }
    set('operators', [...w.operators, { ...form, firstName: form.firstName.trim(), lastName: form.lastName.trim() }]);
    setForm({ firstName:'', lastName:'', email:'', role:'operator' }); setErr('');
  };
  const remove = email => set('operators', w.operators.filter(o => o.email !== email));
  return (
    <div style={{ display:'flex', flexDirection:'column', gap:12 }}>
      <p style={{ fontSize:13, color:'var(--muted)', margin:0 }}>Agregá a cada persona que va a usar Pipochat — operadores y administradores.</p>
      {/* Add form */}
      <div style={{ background:'var(--bg)', border:'1px solid var(--border)', borderRadius:10, padding:14, display:'flex', flexDirection:'column', gap:10 }}>
        <div style={{ display:'flex', gap:8 }}>
          <input style={{ ...S.input, flex:1 }} value={form.firstName} onChange={e => setForm({...form, firstName:e.target.value})} placeholder="Nombre *" />
          <input style={{ ...S.input, flex:1 }} value={form.lastName} onChange={e => setForm({...form, lastName:e.target.value})} placeholder="Apellido" />
        </div>
        <div style={{ display:'flex', gap:8 }}>
          <input style={{ ...S.input, flex:2 }} value={form.email} onChange={e => setForm({...form, email:e.target.value})} onKeyDown={e => e.key==='Enter' && add()} placeholder="email@empresa.com *" type="email" />
          <select style={{ ...S.select, flex:1 }} value={form.role} onChange={e => setForm({...form, role:e.target.value})}>
            <option value="operator">Operador</option>
            <option value="admin">Administrador</option>
            <option value="template-manager">Gestor de templates</option>
          </select>
          <button style={S.saveBtn} onClick={add}>+ Agregar</button>
        </div>
        {err && <div style={{ fontSize:12, color:'var(--danger)' }}>{err}</div>}
      </div>
      {/* List */}
      {w.operators.length > 0 && (
        <div style={{ display:'flex', flexDirection:'column', gap:6 }}>
          {w.operators.map(op => (
            <div key={op.email} style={{ display:'flex', alignItems:'center', gap:10, background:'var(--bg)', border:'1px solid var(--border)', borderRadius:8, padding:'8px 12px' }}>
              <div style={{ width:32, height:32, borderRadius:'50%', background:'var(--primary-light)', color:'var(--primary)', display:'flex', alignItems:'center', justifyContent:'center', fontWeight:700, fontSize:13 }}>
                {op.firstName[0]}{op.lastName?.[0] || ''}
              </div>
              <div style={{ flex:1 }}>
                <div style={{ fontSize:13, fontWeight:600 }}>{op.firstName} {op.lastName}</div>
                <div style={{ fontSize:11, color:'var(--muted)' }}>{op.email} · {op.role}</div>
              </div>
              <button onClick={() => remove(op.email)} style={{ background:'none', border:'none', color:'var(--danger)', cursor:'pointer', fontSize:16 }}>×</button>
            </div>
          ))}
        </div>
      )}
      {w.operators.length === 0 && (
        <div style={{ textAlign:'center', padding:'20px 0', color:'var(--muted)', fontSize:13 }}>Todavía no hay operadores. Podés continuar sin agregarlos si estás probando.</div>
      )}
    </div>
  );
}

function StepTeams({ w, set }) {
  const [kwInputs, setKwInputs] = React.useState({});
  const ops = w.operators;
  const addTeam = () => set('teams', [...w.teams, { title:'', leaderEmail: ops[0]?.email || '', memberEmails:[], keywords:[] }]);
  const updTeam = (i, field, val) => { const next=[...w.teams]; next[i]={...next[i],[field]:val}; set('teams',next); };
  const removeTeam = i => set('teams', w.teams.filter((_,j)=>j!==i));
  const addKw = (i, kw) => { if (!kw) return; const t=w.teams[i]; if(!(t.keywords||[]).includes(kw)) updTeam(i,'keywords',[...(t.keywords||[]),kw]); };
  const removeKw = (i, kw) => updTeam(i, 'keywords', (w.teams[i].keywords||[]).filter(k=>k!==kw));
  const toggleMember = (i, email) => {
    const current = w.teams[i].memberEmails || [];
    updTeam(i, 'memberEmails', current.includes(email) ? current.filter(e=>e!==email) : [...current, email]);
  };
  return (
    <div style={{ display:'flex', flexDirection:'column', gap:12 }}>
      <p style={{ fontSize:13, color:'var(--muted)', margin:0 }}>
        Agrupá a los operadores en equipos. Para negocios con sucursales, un equipo por local.
        Agregá <strong>palabras clave</strong> por equipo para asignación automática.
      </p>
      {w.teams.map((team, i) => (
        <div key={i} style={{ background:'var(--bg)', border:'1px solid var(--border)', borderRadius:10, padding:14, display:'flex', flexDirection:'column', gap:10 }}>
          <div style={{ display:'flex', gap:8, alignItems:'center' }}>
            <input style={{ ...S.input, flex:1 }} value={team.title} onChange={e=>updTeam(i,'title',e.target.value)} placeholder="Nombre del equipo / sucursal" />
            <button onClick={()=>removeTeam(i)} style={{ background:'none', border:'none', color:'var(--danger)', cursor:'pointer', fontSize:18, padding:'0 4px' }}>×</button>
          </div>
          <Field label="Líder del equipo">
            <select style={S.select} value={team.leaderEmail} onChange={e=>updTeam(i,'leaderEmail',e.target.value)}>
              <option value="">— Seleccionar —</option>
              {ops.map(o=><option key={o.email} value={o.email}>{o.firstName} {o.lastName} ({o.email})</option>)}
            </select>
          </Field>
          {ops.length > 1 && (
            <Field label="Miembros adicionales">
              <div style={{ display:'flex', flexWrap:'wrap', gap:6 }}>
                {ops.filter(o=>o.email!==team.leaderEmail).map(o=>(
                  <label key={o.email} style={{ display:'flex', alignItems:'center', gap:5, fontSize:12, cursor:'pointer',
                    background: (team.memberEmails||[]).includes(o.email) ? 'var(--primary-light)' : 'var(--surface)',
                    border:`1px solid ${(team.memberEmails||[]).includes(o.email) ? 'var(--primary)' : 'var(--border)'}`,
                    borderRadius:6, padding:'4px 8px', color:(team.memberEmails||[]).includes(o.email)?'var(--primary)':'var(--text)' }}>
                    <input type="checkbox" style={{display:'none'}} checked={(team.memberEmails||[]).includes(o.email)} onChange={()=>toggleMember(i,o.email)} />
                    {o.firstName} {o.lastName}
                  </label>
                ))}
              </div>
            </Field>
          )}
          <Field label="Palabras clave para asignación automática (opcional)">
            <div style={{ display:'flex', gap:6, marginBottom:6 }}>
              <input style={{ ...S.input, flex:1, fontSize:12 }} value={kwInputs[i]||''} onChange={e=>setKwInputs({...kwInputs,[i]:e.target.value})}
                onKeyDown={e=>{if(e.key==='Enter'){addKw(i,(kwInputs[i]||'').trim());setKwInputs({...kwInputs,[i]:''});}}}
                placeholder="ej: palermo, soho, santa fe..." />
              <button style={S.saveBtn} onClick={()=>{addKw(i,(kwInputs[i]||'').trim());setKwInputs({...kwInputs,[i]:''});}}>+</button>
            </div>
            <div style={{ display:'flex', flexWrap:'wrap', gap:5 }}>
              {(team.keywords||[]).map(k=>(
                <span key={k} style={{ ...S.badge('var(--primary)'), display:'flex', alignItems:'center', gap:3 }}>
                  {k}<button onClick={()=>removeKw(i,k)} style={{background:'none',border:'none',color:'var(--primary)',cursor:'pointer',fontSize:12,padding:'0 0 0 2px'}}>×</button>
                </span>
              ))}
              {(team.keywords||[]).length===0 && <span style={{fontSize:11,color:'var(--muted)'}}>Sin palabras clave — el agente no asignará este equipo automáticamente</span>}
            </div>
          </Field>
        </div>
      ))}
      <button style={{ alignSelf:'flex-start', ...S.outlineBtn }} onClick={addTeam}>+ Agregar equipo</button>
      {w.teams.length === 0 && <div style={{ fontSize:13, color:'var(--muted)' }}>Podés continuar sin equipos si tu negocio no los necesita.</div>}
    </div>
  );
}

function StepPipeline({ w, set }) {
  const [newStage, setNewStage] = React.useState('');
  const addStage = () => { const v=newStage.trim(); if(v&&!w.pipelineStages.includes(v)){set('pipelineStages',[...w.pipelineStages,v]);setNewStage('');} };
  const removeStage = i => set('pipelineStages', w.pipelineStages.filter((_,j)=>j!==i));
  return (
    <div style={{ display:'flex', flexDirection:'column', gap:16 }}>
      <label style={{ display:'flex', alignItems:'center', gap:10, cursor:'pointer' }}>
        <Toggle on={w.pipelineEnabled} onChange={v=>set('pipelineEnabled',v)} />
        <span style={{ fontWeight:600 }}>Activar pipeline de ventas</span>
      </label>
      {w.pipelineEnabled && <>
        <Field label="Nombre del pipeline">
          <input style={S.input} value={w.pipelineName} onChange={e=>set('pipelineName',e.target.value)} placeholder="Pipeline de Ventas" />
        </Field>
        <Field label="Etapas (en orden)">
          <div style={{ display:'flex', flexDirection:'column', gap:6, marginBottom:8 }}>
            {w.pipelineStages.map((s,i)=>(
              <div key={i} style={{ display:'flex', alignItems:'center', gap:8, background:'var(--bg)', border:'1px solid var(--border)', borderRadius:8, padding:'8px 12px' }}>
                <span style={{ color:'var(--muted)', fontSize:12, minWidth:18 }}>{i+1}.</span>
                <span style={{ flex:1, fontSize:13 }}>{s}</span>
                <button onClick={()=>removeStage(i)} style={{ background:'none', border:'none', color:'var(--muted)', cursor:'pointer', fontSize:16 }}>×</button>
              </div>
            ))}
          </div>
          <div style={{ display:'flex', gap:8 }}>
            <input style={{ ...S.input, flex:1 }} value={newStage} onChange={e=>setNewStage(e.target.value)} onKeyDown={e=>e.key==='Enter'&&addStage()} placeholder="Nueva etapa..." />
            <button style={S.saveBtn} onClick={addStage}>+</button>
          </div>
        </Field>
      </>}
      {!w.pipelineEnabled && <div style={{ fontSize:13, color:'var(--muted)' }}>Sin pipeline — las conversaciones no se vincularán a oportunidades de venta.</div>}
    </div>
  );
}

function StepTags({ w, set }) {
  const [input, setInput] = React.useState('');
  const add = () => { const v=input.trim(); if(v&&!w.tags.includes(v)){set('tags',[...w.tags,v]);setInput('');} };
  const SUGGESTIONS = { restaurant:['cliente-frecuente','pedido-confirmado','consulta-menu','delivery','local-palermo'],
    inmobiliaria:['interesado','calificado','cliente','sin-interes','seguimiento'],
    gym:['miembro','consulta-precio','clase-prueba','baja'],
    default:['interesado','calificado','cliente','sin-interes','seguimiento'] };
  const suggs = (SUGGESTIONS[w.businessType] || SUGGESTIONS.default).filter(s=>!w.tags.includes(s));
  return (
    <div style={{ display:'flex', flexDirection:'column', gap:14 }}>
      <p style={{ fontSize:13, color:'var(--muted)', margin:0 }}>Las etiquetas permiten clasificar contactos automáticamente. El agente las aplica según el contexto de la conversación.</p>
      <div style={{ display:'flex', gap:8 }}>
        <input style={{ ...S.input, flex:1 }} value={input} onChange={e=>setInput(e.target.value)} onKeyDown={e=>e.key==='Enter'&&add()} placeholder="Agregar etiqueta..." />
        <button style={S.saveBtn} onClick={add}>+</button>
      </div>
      {w.tags.length > 0 && (
        <div style={{ display:'flex', flexWrap:'wrap', gap:6 }}>
          {w.tags.map(t=>(
            <span key={t} style={{ ...S.badge('var(--primary)'), display:'flex', alignItems:'center', gap:3 }}>
              {t}<button onClick={()=>set('tags',w.tags.filter(x=>x!==t))} style={{background:'none',border:'none',color:'var(--primary)',cursor:'pointer',fontSize:12,padding:'0 0 0 2px'}}>×</button>
            </span>
          ))}
        </div>
      )}
      {suggs.length > 0 && (
        <div>
          <div style={{ fontSize:11, color:'var(--muted)', marginBottom:6, fontWeight:600 }}>SUGERENCIAS PARA TU NEGOCIO</div>
          <div style={{ display:'flex', flexWrap:'wrap', gap:6 }}>
            {suggs.map(s=>(
              <button key={s} onClick={()=>set('tags',[...w.tags,s])}
                style={{ fontSize:12, padding:'4px 10px', borderRadius:20, border:'1px dashed var(--border)', background:'transparent', cursor:'pointer', color:'var(--muted)' }}>
                + {s}
              </button>
            ))}
          </div>
        </div>
      )}
    </div>
  );
}

function StepAgent({ w, set }) {
  const [generating, setGenerating] = React.useState(false);
  const generateInstructions = async () => {
    setGenerating(true);
    try {
      const prompt = `Negocio: ${w.businessName}\nTipo: ${w.businessType}\nDescripción: ${w.businessDescription}\nIdioma: ${w.language}\nTono: ${w.agentTone}`;
      const res = await apiFetch('/api/onboarding/plan', { method:'POST', headers:{'Content-Type':'application/json'}, body:JSON.stringify({prompt}) });
      const data = await res.json();
      if (data.agent?.instructions) set('agentInstructions', data.agent.instructions);
    } catch(e) { alert('Error generando instrucciones: ' + e.message); }
    setGenerating(false);
  };
  return (
    <div style={{ display:'flex', flexDirection:'column', gap:16 }}>
      <Field label="Nombre del asistente">
        <input style={S.input} value={w.agentName} onChange={e=>set('agentName',e.target.value)} placeholder={`Ej: ${w.businessName || 'Asistente'} AI`} />
      </Field>
      <Field label="Tono de comunicación">
        <select style={S.select} value={w.agentTone} onChange={e=>set('agentTone',e.target.value)}>
          <option value="friendly">😊 Amigable e informal</option>
          <option value="professional">💼 Profesional y formal</option>
          <option value="neutral">⚖️ Neutro y directo</option>
        </select>
      </Field>
      <div style={{ display:'flex', gap:12 }}>
        <Field label="Desde">
          <select style={S.select} value={w.scheduleStart} onChange={e=>set('scheduleStart',+e.target.value)}>
            {Array.from({length:24},(_,i)=><option key={i} value={i}>{String(i).padStart(2,'0')}:00</option>)}
          </select>
        </Field>
        <Field label="Hasta">
          <select style={S.select} value={w.scheduleEnd} onChange={e=>set('scheduleEnd',+e.target.value)}>
            {Array.from({length:24},(_,i)=><option key={i} value={i}>{String(i).padStart(2,'0')}:00</option>)}
          </select>
        </Field>
      </div>
      <Field label="Días laborables">
        <div style={{ display:'flex', gap:6 }}>
          {DAYS_SHORT.map((d,i)=>(
            <button key={i} onClick={()=>set('workDays', w.workDays.includes(i)?w.workDays.filter(x=>x!==i):[...w.workDays,i].sort())}
              style={{ width:40, height:40, borderRadius:8, border:`2px solid ${w.workDays.includes(i)?'var(--primary)':'var(--border)'}`,
                background: w.workDays.includes(i)?'var(--primary-light)':'transparent', color:w.workDays.includes(i)?'var(--primary)':'var(--muted)',
                cursor:'pointer', fontWeight:700, fontSize:11 }}>
              {d}
            </button>
          ))}
        </div>
      </Field>
      <Field label="Instrucciones del agente">
        <div style={{ marginBottom:8 }}>
          <button onClick={generateInstructions} disabled={generating || !w.businessName}
            style={{ fontSize:12, padding:'6px 14px', borderRadius:8, border:'1px solid var(--primary)', background:'transparent',
              color:'var(--primary)', cursor:generating||!w.businessName?'not-allowed':'pointer', opacity:!w.businessName?0.5:1, fontWeight:600 }}>
            {generating ? '⏳ Generando...' : '✨ Generar con IA'}
          </button>
          <span style={{ fontSize:11, color:'var(--muted)', marginLeft:8 }}>o escribí las instrucciones manualmente</span>
        </div>
        <textarea style={{ ...S.input, minHeight:140, resize:'vertical', fontSize:12, lineHeight:1.6 }}
          value={w.agentInstructions} onChange={e=>set('agentInstructions',e.target.value)}
          placeholder="Describí cómo debe comportarse el agente: personalidad, qué puede y no puede hacer, cuándo derivar a un humano..." />
      </Field>
    </div>
  );
}

function StepKnowledge({ w, set }) {
  const [generating, setGenerating] = React.useState(false);
  const generate = async () => {
    setGenerating(true);
    try {
      const prompt = `Negocio: ${w.businessName}\nTipo: ${w.businessType}\nDescripción: ${w.businessDescription}`;
      const res = await apiFetch('/api/onboarding/plan', { method:'POST', headers:{'Content-Type':'application/json'}, body:JSON.stringify({prompt}) });
      const data = await res.json();
      if (data.knowledgeBase) set('knowledgeBase', data.knowledgeBase);
    } catch(e) { alert('Error: ' + e.message); }
    setGenerating(false);
  };
  return (
    <div style={{ display:'flex', flexDirection:'column', gap:14 }}>
      <p style={{ fontSize:13, color:'var(--muted)', margin:0 }}>El agente consulta esta base de conocimiento para responder preguntas sobre productos, precios, servicios y procesos.</p>
      <div style={{ marginBottom:4 }}>
        <button onClick={generate} disabled={generating||!w.businessName}
          style={{ fontSize:12, padding:'6px 14px', borderRadius:8, border:'1px solid var(--primary)', background:'transparent',
            color:'var(--primary)', cursor:generating||!w.businessName?'not-allowed':'pointer', opacity:!w.businessName?0.5:1, fontWeight:600 }}>
          {generating ? '⏳ Generando...' : '✨ Generar con IA'}
        </button>
        <span style={{ fontSize:11, color:'var(--muted)', marginLeft:8 }}>o pegá el contenido manualmente</span>
      </div>
      <textarea style={{ ...S.input, minHeight:200, resize:'vertical', fontSize:12, lineHeight:1.6 }}
        value={w.knowledgeBase} onChange={e=>set('knowledgeBase',e.target.value)}
        placeholder="Información del negocio: servicios, precios, preguntas frecuentes, horarios, políticas, proceso de compra..." />
      <div style={{ fontSize:11, color:'var(--muted)' }}>
        💡 Cuanto más detallada, mejor responderá el agente. Incluí precios, horarios, preguntas frecuentes y cualquier info que los clientes suelen preguntar.
      </div>
    </div>
  );
}

function StepRules({ w, set }) {
  const [newField, setNewField] = React.useState('');
  const addField = () => { const v=newField.trim(); if(v&&!w.actionSaveDataFields.includes(v)){set('actionSaveDataFields',[...w.actionSaveDataFields,v]);setNewField('');} };
  return (
    <div style={{ display:'flex', flexDirection:'column', gap:0 }}>
      {/* Conversations rules */}
      <div style={{ fontWeight:700, fontSize:12, color:'var(--muted)', letterSpacing:1, marginBottom:10 }}>REGLAS AUTOMÁTICAS</div>

      {/* Welcome */}
      <div style={{ borderBottom:'1px solid var(--border)', paddingBottom:16, marginBottom:16 }}>
        <div style={{ display:'flex', alignItems:'center', gap:10, marginBottom: w.ruleWelcome.enabled?10:0 }}>
          <Toggle on={w.ruleWelcome.enabled} onChange={v=>set('ruleWelcome',{...w.ruleWelcome,enabled:v})} />
          <div><div style={{ fontWeight:600, fontSize:14 }}>👋 Mensaje de bienvenida</div><div style={{ fontSize:12, color:'var(--muted)' }}>Se envía al primer mensaje de cada nuevo contacto</div></div>
        </div>
        {w.ruleWelcome.enabled && <textarea style={{ ...S.input, minHeight:60, resize:'vertical', fontSize:12 }} value={w.ruleWelcome.message} onChange={e=>set('ruleWelcome',{...w.ruleWelcome,message:e.target.value})} placeholder="Mensaje de bienvenida..." />}
      </div>

      {/* Out of hours */}
      <div style={{ borderBottom:'1px solid var(--border)', paddingBottom:16, marginBottom:16 }}>
        <div style={{ display:'flex', alignItems:'center', gap:10, marginBottom: w.ruleOoh.enabled?10:0 }}>
          <Toggle on={w.ruleOoh.enabled} onChange={v=>set('ruleOoh',{...w.ruleOoh,enabled:v})} />
          <div><div style={{ fontWeight:600, fontSize:14 }}>🌙 Fuera de horario</div><div style={{ fontSize:12, color:'var(--muted)' }}>Responde automáticamente cuando el agente no está activo</div></div>
        </div>
        {w.ruleOoh.enabled && <textarea style={{ ...S.input, minHeight:60, resize:'vertical', fontSize:12 }} value={w.ruleOoh.message} onChange={e=>set('ruleOoh',{...w.ruleOoh,message:e.target.value})} placeholder="Mensaje fuera de horario..." />}
      </div>

      {/* Follow-up */}
      <div style={{ borderBottom:'1px solid var(--border)', paddingBottom:16, marginBottom:20 }}>
        <div style={{ display:'flex', alignItems:'center', gap:10, marginBottom: w.ruleFollowup.enabled?10:0 }}>
          <Toggle on={w.ruleFollowup.enabled} onChange={v=>set('ruleFollowup',{...w.ruleFollowup,enabled:v})} />
          <div><div style={{ fontWeight:600, fontSize:14 }}>💬 Seguimiento automático</div><div style={{ fontSize:12, color:'var(--muted)' }}>Re-contacta si el cliente no responde</div></div>
        </div>
        {w.ruleFollowup.enabled && (
          <div style={{ display:'flex', flexDirection:'column', gap:8 }}>
            <div style={{ display:'flex', alignItems:'center', gap:8 }}>
              <span style={{ fontSize:13 }}>Después de</span>
              <input type="number" style={{ ...S.input, width:70 }} value={w.ruleFollowup.minutes} onChange={e=>set('ruleFollowup',{...w.ruleFollowup,minutes:+e.target.value})} min={5} />
              <span style={{ fontSize:13 }}>minutos sin respuesta</span>
            </div>
            <textarea style={{ ...S.input, minHeight:60, resize:'vertical', fontSize:12 }} value={w.ruleFollowup.message} onChange={e=>set('ruleFollowup',{...w.ruleFollowup,message:e.target.value})} placeholder="Mensaje de seguimiento..." />
          </div>
        )}
      </div>

      {/* Round-robin assignment */}
      <div style={{ borderBottom:'1px solid var(--border)', paddingBottom:16, marginBottom:20 }}>
        <div style={{ display:'flex', alignItems:'center', gap:10, marginBottom: w.assignment.enabled?10:0 }}>
          <Toggle on={w.assignment.enabled} onChange={v=>set('assignment',{...w.assignment,enabled:v})} />
          <div><div style={{ fontWeight:600, fontSize:14 }}>🎯 Asignación round-robin</div><div style={{ fontSize:12, color:'var(--muted)' }}>Reparte cada conversación nueva de forma equitativa entre los operadores</div></div>
        </div>
        {w.assignment.enabled && (
          <label style={{ display:'flex', alignItems:'center', gap:8, fontSize:13, marginLeft:54, cursor:'pointer' }}>
            <input type="checkbox" checked={!!w.assignment.onlineOnly} onChange={e=>set('assignment',{...w.assignment,onlineOnly:e.target.checked})} />
            Solo entre operadores online en ese momento
          </label>
        )}
      </div>

      {/* Actions */}
      <div style={{ fontWeight:700, fontSize:12, color:'var(--muted)', letterSpacing:1, marginBottom:10 }}>ACCIONES DEL AGENTE</div>

      {/* Create lead */}
      <div style={{ borderBottom:'1px solid var(--border)', paddingBottom:16, marginBottom:16 }}>
        <div style={{ display:'flex', alignItems:'center', gap:10 }}>
          <Toggle on={w.actionCreateLead} onChange={v=>set('actionCreateLead',v)} />
          <div><div style={{ fontWeight:600, fontSize:14 }}>📊 Crear lead automáticamente</div><div style={{ fontSize:12, color:'var(--muted)' }}>Agrega cada nuevo contacto al pipeline de ventas</div></div>
        </div>
      </div>

      {/* Auto assign team */}
      {w.teams.some(t=>(t.keywords||[]).length>0) && (
        <div style={{ borderBottom:'1px solid var(--border)', paddingBottom:16, marginBottom:16 }}>
          <div style={{ display:'flex', alignItems:'center', gap:10 }}>
            <div style={{ width:44, height:24, borderRadius:12, background:'var(--primary)', display:'flex', alignItems:'center', padding:3 }}>
              <div style={{ width:18, height:18, borderRadius:'50%', background:'#fff', marginLeft:'auto' }} />
            </div>
            <div>
              <div style={{ fontWeight:600, fontSize:14 }}>👥 Asignación automática por sucursal <span style={{ fontSize:11, background:'var(--primary-light)', color:'var(--primary)', padding:'2px 6px', borderRadius:4, marginLeft:4 }}>Activo</span></div>
              <div style={{ fontSize:12, color:'var(--muted)' }}>
                Configurado en el paso de Equipos ·{' '}
                {w.teams.filter(t=>(t.keywords||[]).length>0).map(t=>t.title||'Sin nombre').join(', ')}
              </div>
            </div>
          </div>
        </div>
      )}

      {/* Save client data */}
      <div style={{ paddingBottom:4 }}>
        <div style={{ display:'flex', alignItems:'center', gap:10, marginBottom: w.actionSaveData?10:0 }}>
          <Toggle on={w.actionSaveData} onChange={v=>set('actionSaveData',v)} />
          <div><div style={{ fontWeight:600, fontSize:14 }}>💾 Guardar datos del cliente</div><div style={{ fontSize:12, color:'var(--muted)' }}>El agente extrae y guarda info clave del contacto durante la charla</div></div>
        </div>
        {w.actionSaveData && (
          <div style={{ paddingLeft:54 }}>
            <div style={{ display:'flex', gap:8, marginBottom:8 }}>
              <input style={{ ...S.input, flex:1, fontSize:12 }} value={newField} onChange={e=>setNewField(e.target.value)} onKeyDown={e=>e.key==='Enter'&&addField()} placeholder="Campo a guardar (ej: local, empresa, cargo)..." />
              <button style={S.saveBtn} onClick={addField}>+</button>
            </div>
            <div style={{ display:'flex', flexWrap:'wrap', gap:6 }}>
              {w.actionSaveDataFields.map(f=>(
                <span key={f} style={{ ...S.badge('var(--primary)'), display:'flex', alignItems:'center', gap:3 }}>
                  {f}<button onClick={()=>set('actionSaveDataFields',w.actionSaveDataFields.filter(x=>x!==f))} style={{background:'none',border:'none',color:'var(--primary)',cursor:'pointer',fontSize:12}}>×</button>
                </span>
              ))}
            </div>
          </div>
        )}
      </div>
    </div>
  );
}

function StepReview({ w }) {
  const plan = buildPlanFromWizard(w);
  const row = (label, val) => val ? (
    <div style={{ display:'flex', gap:8, padding:'6px 0', borderBottom:'1px solid var(--border)', fontSize:13 }}>
      <span style={{ color:'var(--muted)', minWidth:140 }}>{label}</span>
      <span style={{ color:'var(--text)', flex:1 }}>{val}</span>
    </div>
  ) : null;
  return (
    <div style={{ display:'flex', flexDirection:'column', gap:14 }}>
      <div style={{ background:'var(--primary-light)', border:'1px solid var(--primary)', borderRadius:10, padding:'12px 16px', fontSize:13, color:'var(--primary)' }}>
        ✅ Todo listo para configurar. Revisá el resumen y hacé click en <strong>Ejecutar</strong>.
      </div>
      {row('Negocio', w.businessName + (w.businessDescription ? ` — ${w.businessDescription.slice(0,60)}...` : ''))}
      {row('Operadores', w.operators.length > 0 ? w.operators.map(o=>`${o.firstName} ${o.lastName}`).join(', ') : 'Ninguno')}
      {row('Equipos', w.teams.length > 0 ? w.teams.map(t=>`${t.title}${(t.keywords||[]).length>0?' 🔑':''}`).join(', ') : 'Ninguno')}
      {row('Pipeline', w.pipelineEnabled ? `${w.pipelineName} (${w.pipelineStages.length} etapas)` : 'No')}
      {row('Etiquetas', w.tags.length > 0 ? w.tags.join(', ') : 'Ninguna')}
      {row('Agente', `${w.agentName || w.businessName + ' AI'} · ${w.scheduleStart}:00–${w.scheduleEnd}:00 · ${w.workDays.map(d=>DAYS_SHORT[d]).join('/')}`)}
      {row('Base de conocimiento', w.knowledgeBase ? `${w.knowledgeBase.length} caracteres` : 'Vacía')}
      {row('Bienvenida', w.ruleWelcome.enabled ? '✓ Activa' : '✗')}
      {row('Fuera de horario', w.ruleOoh.enabled ? '✓ Activa' : '✗')}
      {row('Seguimiento', w.ruleFollowup.enabled ? `✓ ${w.ruleFollowup.minutes} min` : '✗')}
      {row('Crear lead auto', w.actionCreateLead ? '✓' : '✗')}
      {row('Guardar datos', w.actionSaveData ? `✓ ${w.actionSaveDataFields.join(', ')}` : '✗')}
      {w.teams.some(t=>(t.keywords||[]).length>0) && row('Asig. por sucursal', '✓ Automático')}
    </div>
  );
}

// ── Main Wizard Component ────────────────────────────────────────────────────

function OnboardingWizardPanel({ onSwitchToAI, obToken }) {
  const stored = () => { try { return JSON.parse(localStorage.getItem('ob_wizard')||'null'); } catch { return null; } };
  const [w, setW] = React.useState({ ...WIZARD_EMPTY, ...(stored() || {}) });
  const [step, setStep] = React.useState(+localStorage.getItem('ob_wizard_step')||0);
  const [phase, setPhase] = React.useState('wizard'); // wizard | running | done
  const [steps, setSteps] = React.useState([]);
  const [result, setResult] = React.useState(null);
  const [error, setError] = React.useState('');

  const save = (next) => { setW(next); localStorage.setItem('ob_wizard', JSON.stringify(next)); };
  const set = (k, v) => save({ ...w, [k]: v });
  const goStep = (n) => { setStep(n); localStorage.setItem('ob_wizard_step', n); };
  const reset = () => { save(WIZARD_EMPTY); goStep(0); setPhase('wizard'); setSteps([]); setResult(null); setError(''); localStorage.removeItem('ob_wizard'); };

  const execute = async () => {
    const plan = buildPlanFromWizard(w);
    setPhase('running'); setSteps([]); setResult(null); setError('');
    try {
      const res = obToken
        ? await fetch(`/onboarding/${obToken}/run`, { method:'POST', headers:{'Content-Type':'application/json'}, body:JSON.stringify({plan}) })
        : await apiFetch('/api/onboarding/execute', { method:'POST', headers:{'Content-Type':'application/json'}, body:JSON.stringify({plan}) });
      const reader = res.body.getReader(); const decoder = new TextDecoder(); let buf='';
      while(true) {
        const {done,value} = await reader.read(); if(done) break;
        buf += decoder.decode(value,{stream:true});
        const lines = buf.split('\n'); buf = lines.pop()||'';
        for(const line of lines) {
          if(!line.startsWith('data:')) continue;
          try {
            const evt = JSON.parse(line.slice(5).trim());
            if(evt.type==='step') setSteps(prev=>{ const idx=prev.findIndex(s=>s.step===evt.step); return idx>=0?prev.map((s,i)=>i===idx?evt:s):[...prev,evt]; });
            else if(evt.type==='complete') { setResult(evt.result); setPhase('done'); }
            else if(evt.type==='error') { setError(evt.message); setPhase('done'); }
          } catch {}
        }
      }
    } catch(e) { setError('Error: '+e.message); setPhase('done'); }
  };

  // ── Running / Done ──
  if (phase !== 'wizard') return (
    <div style={S.page}>
      <div style={{ fontSize:22, fontWeight:800, marginBottom:4 }}>{phase==='running'?'⏳ Configurando...':'✅ ¡Listo!'}</div>
      <div style={{ ...S.pageSubtitle, marginBottom:24 }}>{phase==='running'?'No cierres esta ventana.':'Tu cuenta fue configurada exitosamente.'}</div>
      <div style={{ maxWidth:620 }}>
        <div style={{ background:'var(--surface)', border:'1px solid var(--border)', borderRadius:12, padding:'16px 18px', marginBottom:16 }}>
          {steps.length===0&&phase==='running'&&<div style={{fontSize:13,color:'var(--muted)'}}>Iniciando...</div>}
          {steps.map((s,i)=>(
            <div key={i} style={{display:'flex',alignItems:'center',gap:10,padding:'8px 0',borderBottom:i<steps.length-1?'1px solid var(--border)':'none'}}>
              <span style={{fontSize:18,width:24,textAlign:'center'}}>{s.status==='running'?'⏳':s.status==='done'?'✅':'❌'}</span>
              <div style={{flex:1}}>
                <div style={{fontSize:13,fontWeight:600}}>{EXEC_STEP_ICONS[s.step]||'⚙️'} {s.label}</div>
                {s.detail&&<div style={{fontSize:11,color:'var(--muted)',marginTop:2}}>{s.detail}</div>}
              </div>
            </div>
          ))}
        </div>
        {result?.phoneToConnect&&(
          <div style={{background:'var(--warning-light,#FEF3C7)',border:'1px solid var(--warning,#92400E)',borderRadius:12,padding:'14px 18px',marginBottom:16}}>
            <div style={{fontWeight:700,fontSize:14,marginBottom:4}}>📞 Conectar el número (manual)</div>
            <div style={{fontSize:13,color:'var(--ink-2)'}}>Acordate de dar de alta el número <b>{result.phoneToConnect}</b> en Pipochat y conectarlo a este tenant.</div>
          </div>
        )}
        {result?.operatorsCreated?.length>0&&(
          <div style={{background:'var(--surface)',border:'1px solid var(--border)',borderRadius:12,padding:'16px 18px',marginBottom:16}}>
            <div style={{fontWeight:700,fontSize:14,marginBottom:12}}>🔑 Credenciales temporales</div>
            <div style={{fontSize:12,color:'var(--warning)',marginBottom:10}}>⚠️ Guardá estas contraseñas — no se podrán ver de nuevo.</div>
            <table style={{width:'100%',borderCollapse:'collapse',fontSize:13}}>
              <thead><tr style={{borderBottom:'2px solid var(--border)'}}>
                <th style={{textAlign:'left',padding:'6px 8px'}}>Nombre</th>
                <th style={{textAlign:'left',padding:'6px 8px'}}>Email</th>
                <th style={{textAlign:'left',padding:'6px 8px'}}>Contraseña temporal</th>
              </tr></thead>
              <tbody>{result.operatorsCreated.map((op,i)=>(
                <tr key={i} style={{borderBottom:'1px solid var(--border)'}}>
                  <td style={{padding:'6px 8px'}}>{op.name}</td>
                  <td style={{padding:'6px 8px',color:'var(--muted)'}}>{op.email}</td>
                  <td style={{padding:'6px 8px',fontFamily:'monospace',fontWeight:700,color:'var(--primary)'}}>{op.tempPassword}</td>
                </tr>
              ))}</tbody>
            </table>
          </div>
        )}
        {error&&<div style={{color:'var(--danger)',fontSize:13,marginBottom:12}}>{error}</div>}
        {phase==='done'&&<button onClick={reset} style={{padding:'8px 20px',borderRadius:8,border:'1px solid var(--border)',background:'transparent',cursor:'pointer',color:'var(--text)'}}>← Nueva configuración</button>}
      </div>
    </div>
  );

  // ── Wizard steps ──
  const stepProps = { w, set };
  const stepContent = [
    <StepBusiness {...stepProps} />,
    <StepOperators {...stepProps} />,
    <StepTeams {...stepProps} />,
    <StepPipeline {...stepProps} />,
    <StepTags {...stepProps} />,
    <StepAgent {...stepProps} />,
    <StepKnowledge {...stepProps} />,
    <StepRules {...stepProps} />,
    <StepReview w={w} />,
  ];
  const stepTitles = [
    ['🏢 Tu negocio', 'Contanos sobre la empresa'],
    ['👤 Operadores', 'Quiénes van a usar Pipochat'],
    ['👥 Equipos', 'Cómo se agrupan los operadores'],
    ['📊 Pipeline de ventas', 'Las etapas del proceso comercial'],
    ['🏷️ Etiquetas', 'Para clasificar contactos automáticamente'],
    ['🤖 Agente AI', 'Cómo va a responder el asistente'],
    ['📚 Base de conocimiento', 'Lo que el agente necesita saber'],
    ['⚡ Reglas y acciones', 'Qué hace el agente automáticamente'],
    ['✅ Revisar y ejecutar', 'Confirmá la configuración'],
  ];
  const isLastStep = step === WIZARD_STEPS.length - 1;
  const canNext = step === 0 ? w.businessName.trim().length > 0 : true;

  return (
    <div style={S.page}>
      <div style={S.pageHeader}>
        <div>
          <div style={{ fontSize:22, fontWeight:800, marginBottom:4 }}>🚀 Configuración guiada</div>
          <div style={S.pageSubtitle}>Completá cada paso para dejar tu cuenta 100% configurada.</div>
        </div>
        {onSwitchToAI && (
          <button onClick={onSwitchToAI} style={{ fontSize:12, padding:'6px 14px', borderRadius:8, border:'1px solid var(--border)', background:'transparent', cursor:'pointer', color:'var(--muted)' }}>
            ✨ Modo descripción libre
          </button>
        )}
      </div>
      <WizardChrome step={step} total={WIZARD_STEPS.length}
        title={stepTitles[step][0]} subtitle={stepTitles[step][1]}
        onBack={()=>step===0?(onSwitchToAI ? onSwitchToAI() : null):goStep(step-1)}
        onNext={isLastStep ? execute : ()=>goStep(step+1)}
        nextLabel={isLastStep ? '🚀 Ejecutar configuración' : 'Siguiente →'}
        nextDisabled={!canNext}>
        {stepContent[step]}
      </WizardChrome>
    </div>
  );
}

function OnboardingAIPanel({ onSwitchToWizard }) {
  const [phase, setPhase] = useState(() => localStorage.getItem('ob_phase') || 'input');
  const [prompt, setPrompt] = useState(() => localStorage.getItem('ob_prompt') || '');
  const [plan, setPlan] = useState(() => { try { return JSON.parse(localStorage.getItem('ob_plan') || 'null'); } catch { return null; } });
  const [loading, setLoading] = useState(false);
  const [steps, setSteps] = useState([]);
  const [result, setResult] = useState(null);
  const [error, setError] = useState('');

  const savePrompt = (v) => { setPrompt(v); localStorage.setItem('ob_prompt', v); };
  const savePlan   = (v) => { setPlan(v);   localStorage.setItem('ob_plan', JSON.stringify(v)); };
  const savePhase  = (v) => { setPhase(v);  localStorage.setItem('ob_phase', v); };

  const generatePlan = async () => {
    if (!prompt.trim()) return;
    setLoading(true); setError('');
    try {
      const res = await apiFetch('/api/onboarding/plan', {
        method: 'POST', headers: {'Content-Type':'application/json'}, body: JSON.stringify({ prompt })
      });
      const data = await res.json();
      if (data.error) { setError(data.error); setLoading(false); return; }
      savePlan(data);
      savePhase('plan');
    } catch(e) { setError('Error generando el plan. Intentá de nuevo.'); }
    setLoading(false);
  };

  const executePlan = async () => {
    savePhase('running');
    setSteps([]);
    setResult(null);

    try {
      const res = await apiFetch('/api/onboarding/execute', {
        method: 'POST', headers: {'Content-Type':'application/json'}, body: JSON.stringify({ plan })
      });

      const reader = res.body.getReader();
      const decoder = new TextDecoder();
      let buf = '';

      while (true) {
        const { done, value } = await reader.read();
        if (done) break;
        buf += decoder.decode(value, { stream: true });
        const lines = buf.split('\n');
        buf = lines.pop() || '';
        for (const line of lines) {
          if (!line.startsWith('data:')) continue;
          try {
            const evt = JSON.parse(line.slice(5).trim());
            if (evt.type === 'step') {
              setSteps(prev => {
                const idx = prev.findIndex(s => s.step === evt.step);
                return idx >= 0 ? prev.map((s,i) => i===idx ? evt : s) : [...prev, evt];
              });
            } else if (evt.type === 'complete') {
              setResult(evt.result);
              savePhase('done');
            } else if (evt.type === 'error') {
              setError(evt.message);
              setPhase('done');
            }
          } catch {}
        }
      }
    } catch(e) { setError('Error ejecutando el plan: ' + e.message); savePhase('done'); }
  };

  const reset = () => {
    savePhase('input'); savePlan(null); setSteps([]); setResult(null); setError('');
    localStorage.removeItem('ob_plan');
  };

  // ── Styles ──
  const card = { background:'var(--surface)', border:'1px solid var(--border)', borderRadius:12, padding:'16px 18px', marginBottom:10 };

  // ── Phase: input ──
  if (phase === 'input') return (
    <div style={S.page}>
      <div style={S.pageHeader}>
        <div>
          <div style={{ fontSize:22, fontWeight:800, marginBottom:4 }}>🚀 Onboarding AI</div>
          <div style={S.pageSubtitle}>Describí tu negocio y la AI configura todo automáticamente — operadores, equipos, pipeline, reglas y agente.</div>
        </div>
        <button onClick={onSwitchToWizard} style={{ fontSize:12, padding:'6px 14px', borderRadius:8, border:'1px solid var(--border)', background:'transparent', cursor:'pointer', color:'var(--muted)' }}>
          📋 Usar asistente paso a paso
        </button>
      </div>

      <div style={{ width:'100%' }}>
        <div style={{ marginBottom:12 }}>
          <textarea
            value={prompt} onChange={e => savePrompt(e.target.value)}
            style={{ width:'100%', minHeight:160, padding:'12px 14px', borderRadius:10, border:'1px solid var(--border)',
              background:'var(--surface)', color:'var(--text)', fontSize:14, resize:'vertical', lineHeight:1.6,
              fontFamily:'inherit', outline:'none', boxSizing:'border-box' }}
            placeholder="Describí tu empresa: rubro, productos o servicios, operadores (nombre y email), horario de atención, cualquier detalle que quieras que el agente AI conozca..."
          />
        </div>

        {error && <div style={{ color:'var(--danger)', fontSize:13, marginBottom:10 }}>{error}</div>}

        <div style={{ display:'flex', gap:10, marginBottom:24 }}>
          <button onClick={generatePlan} disabled={!prompt.trim() || loading}
            style={{ padding:'10px 24px', borderRadius:9, border:'none', background:'var(--primary)', color:'#fff',
              fontWeight:700, fontSize:14, cursor:'pointer', opacity: (!prompt.trim()||loading) ? 0.5 : 1 }}>
            {loading ? '⏳ Generando plan...' : '✨ Generar plan de configuración'}
          </button>
        </div>

        <div style={{ fontSize:12, color:'var(--muted)', marginBottom:8, fontWeight:600 }}>Ejemplos para probar:</div>
        <div style={{ display:'flex', flexDirection:'column', gap:6 }}>
          {ONBOARDING_EXAMPLES.map((ex, i) => (
            <button key={i} onClick={() => savePrompt(ex)}
              style={{ textAlign:'left', padding:'10px 14px', borderRadius:9, border:'1px solid var(--border)',
                background:'var(--bg)', color:'var(--muted)', fontSize:12, cursor:'pointer', lineHeight:1.5 }}>
              {ex.slice(0, 120)}...
            </button>
          ))}
        </div>
      </div>
    </div>
  );

  // ── Phase: plan review ──
  if (phase === 'plan' && plan) return (
    <div style={S.page}>
      <div style={S.pageHeader}>
        <div>
          <div style={{ fontSize:22, fontWeight:800, marginBottom:4 }}>🚀 Onboarding AI — Plan</div>
          <div style={S.pageSubtitle}>Revisá qué va a crear la AI. Podés volver atrás si querés ajustar la descripción.</div>
        </div>
        <div style={{ display:'flex', gap:8 }}>
          <button onClick={reset} style={{ padding:'8px 16px', borderRadius:8, border:'1px solid var(--border)', background:'transparent', cursor:'pointer', color:'var(--text)' }}>← Editar</button>
          <button onClick={executePlan} style={{ padding:'8px 20px', borderRadius:8, border:'none', background:'var(--primary)', color:'#fff', fontWeight:700, cursor:'pointer' }}>🚀 Ejecutar todo</button>
        </div>
      </div>

      <div style={{ width:'100%' }}>
        {plan.businessSummary && (
          <div style={{ ...card, background:'var(--primary-light)', border:'1px solid var(--primary)', marginBottom:16 }}>
            <div style={{ fontSize:12, color:'var(--primary)', fontWeight:700, marginBottom:4 }}>RESUMEN DEL NEGOCIO</div>
            <div style={{ fontSize:14, color:'var(--text)' }}>{plan.businessSummary}</div>
          </div>
        )}

        {plan.operators?.length > 0 && (
          <div style={card}>
            <div style={{ fontWeight:700, fontSize:14, marginBottom:10 }}>👤 Operadores ({plan.operators.length})</div>
            {plan.operators.map((op, i) => (
              <div key={i} style={{ fontSize:13, color:'var(--muted)', marginBottom:4 }}>
                {op.firstName} {op.lastName} · <span style={{ color:'var(--text)' }}>{op.email}</span> · {op.role}
              </div>
            ))}
          </div>
        )}

        {plan.teams?.length > 0 && (
          <div style={card}>
            <div style={{ fontWeight:700, fontSize:14, marginBottom:10 }}>👥 Equipos ({plan.teams.length})</div>
            {plan.teams.map((t, i) => (
              <div key={i} style={{ fontSize:13, color:'var(--muted)', marginBottom:4 }}>
                <b style={{ color:'var(--text)' }}>{t.title}</b> · Líder: {t.leaderEmail}
                {t.memberEmails?.length > 0 && ` · Miembros: ${t.memberEmails.join(', ')}`}
              </div>
            ))}
          </div>
        )}

        {plan.pipeline && (
          <div style={card}>
            <div style={{ fontWeight:700, fontSize:14, marginBottom:10 }}>📊 Pipeline: {plan.pipeline.title}</div>
            <div style={{ display:'flex', gap:6, flexWrap:'wrap' }}>
              {plan.pipeline.stages.map((s, i) => (
                <span key={i} style={{ fontSize:12, background:'var(--bg)', border:'1px solid var(--border)', padding:'3px 10px', borderRadius:20 }}>
                  {i+1}. {s}
                </span>
              ))}
            </div>
          </div>
        )}

        {plan.tags?.length > 0 && (
          <div style={card}>
            <div style={{ fontWeight:700, fontSize:14, marginBottom:10 }}>🏷️ Etiquetas ({plan.tags.length})</div>
            <div style={{ display:'flex', gap:6, flexWrap:'wrap' }}>
              {plan.tags.map((t, i) => (
                <span key={i} style={{ fontSize:12, background:'var(--primary-light)', color:'var(--primary)', padding:'3px 10px', borderRadius:20 }}>{t}</span>
              ))}
            </div>
          </div>
        )}

        {plan.agent && (
          <div style={card}>
            <div style={{ fontWeight:700, fontSize:14, marginBottom:6 }}>🤖 Agente AI: {plan.agent.name}</div>
            <div style={{ fontSize:12, color:'var(--muted)', marginBottom:6 }}>
              Idioma: {plan.agent.language} · Horario: {plan.agent.scheduleStart}:00 — {plan.agent.scheduleEnd}:00
            </div>
            <div style={{ fontSize:12, color:'var(--muted)', background:'var(--bg)', padding:'8px 10px', borderRadius:8, maxHeight:80, overflow:'hidden' }}>
              {plan.agent.instructions?.slice(0, 200)}...
            </div>
          </div>
        )}

        <div style={card}>
          <div style={{ fontWeight:700, fontSize:14, marginBottom:8 }}>⚙️ Reglas automáticas</div>
          {plan.rules?.welcome?.enabled && <div style={{ fontSize:13, color:'var(--muted)', marginBottom:4 }}>👋 Bienvenida al primer mensaje</div>}
          {plan.rules?.outOfHours?.enabled && <div style={{ fontSize:13, color:'var(--muted)', marginBottom:4 }}>🌙 Respuesta fuera de horario</div>}
          {plan.rules?.followUp?.enabled && <div style={{ fontSize:13, color:'var(--muted)', marginBottom:4 }}>💬 Seguimiento a los {plan.rules.followUp.minutes} min sin respuesta</div>}
        </div>

        {/* Bottom action bar */}
        <div style={{ display:'flex', gap:8, justifyContent:'flex-end', paddingTop:8, paddingBottom:24 }}>
          <button onClick={reset} style={{ padding:'10px 18px', borderRadius:8, border:'1px solid var(--border)', background:'transparent', cursor:'pointer', color:'var(--text)', fontWeight:500 }}>← Editar descripción</button>
          <button onClick={executePlan} style={{ padding:'10px 24px', borderRadius:8, border:'none', background:'var(--primary)', color:'#fff', fontWeight:700, fontSize:14, cursor:'pointer' }}>🚀 Ejecutar todo</button>
        </div>
      </div>
    </div>
  );

  // ── Phase: running / done ──
  return (
    <div style={S.page}>
      <div style={{ fontSize:22, fontWeight:800, marginBottom:4 }}>
        {phase === 'running' ? '⏳ Configurando tu cuenta...' : '✅ Configuración completada'}
      </div>
      <div style={S.pageSubtitle}>
        {phase === 'running' ? 'No cierres esta ventana mientras se ejecuta el proceso.' : 'Tu cuenta fue configurada automáticamente.'}
      </div>

      <div style={{ maxWidth:620, marginTop:24 }}>
        {/* Steps progress */}
        <div style={{ ...card, marginBottom:16 }}>
          {steps.length === 0 && phase === 'running' && (
            <div style={{ fontSize:13, color:'var(--muted)' }}>Iniciando...</div>
          )}
          {steps.map((s, i) => (
            <div key={i} style={{ display:'flex', alignItems:'center', gap:10, padding:'8px 0', borderBottom: i < steps.length-1 ? '1px solid var(--border)' : 'none' }}>
              <span style={{ fontSize:18, width:24, textAlign:'center' }}>
                {s.status === 'running' ? '⏳' : s.status === 'done' ? '✅' : '❌'}
              </span>
              <div style={{ flex:1 }}>
                <div style={{ fontSize:13, fontWeight:600 }}>{STEP_ICONS[s.step] || '⚙️'} {s.label}</div>
                {s.detail && <div style={{ fontSize:11, color:'var(--muted)', marginTop:2 }}>{s.detail}</div>}
              </div>
            </div>
          ))}
        </div>

        {/* Credentials table */}
        {result?.operatorsCreated?.length > 0 && (
          <div style={{ ...card, marginBottom:16 }}>
            <div style={{ fontWeight:700, fontSize:14, marginBottom:12 }}>🔑 Credenciales de acceso para los operadores</div>
            <div style={{ fontSize:12, color:'var(--muted)', marginBottom:10 }}>
              Compartí estas credenciales con cada operador para que puedan ingresar a Pipochat.
            </div>
            <table style={{ width:'100%', borderCollapse:'collapse', fontSize:13 }}>
              <thead>
                <tr style={{ borderBottom:'2px solid var(--border)' }}>
                  <th style={{ textAlign:'left', padding:'6px 8px', fontWeight:600 }}>Nombre</th>
                  <th style={{ textAlign:'left', padding:'6px 8px', fontWeight:600 }}>Email</th>
                  <th style={{ textAlign:'left', padding:'6px 8px', fontWeight:600 }}>Contraseña temporal</th>
                </tr>
              </thead>
              <tbody>
                {result.operatorsCreated.map((op, i) => (
                  <tr key={i} style={{ borderBottom:'1px solid var(--border)' }}>
                    <td style={{ padding:'6px 8px' }}>{op.name}</td>
                    <td style={{ padding:'6px 8px', color:'var(--muted)' }}>{op.email}</td>
                    <td style={{ padding:'6px 8px', fontFamily:'monospace', fontWeight:700, color:'var(--primary)' }}>{op.tempPassword}</td>
                  </tr>
                ))}
              </tbody>
            </table>
            <div style={{ fontSize:11, color:'var(--warning)', marginTop:10 }}>
              ⚠️ Guardá estas contraseñas. No se podrán ver después de cerrar esta pantalla.
            </div>
          </div>
        )}

        {/* Summary */}
        {result && (
          <div style={card}>
            <div style={{ fontWeight:700, fontSize:14, marginBottom:10 }}>📋 Resumen</div>
            <div style={{ fontSize:13, color:'var(--muted)', display:'flex', flexDirection:'column', gap:4 }}>
              {result.operatorsCreated?.length > 0 && <div>✅ {result.operatorsCreated.length} operador(es) creado(s)</div>}
              {result.teamsCreated?.length > 0      && <div>✅ {result.teamsCreated.length} equipo(s) creado(s)</div>}
              {result.pipelineCreated               && <div>✅ Pipeline "{result.pipelineCreated.name}" con {result.pipelineCreated.stages.length} etapas</div>}
              {result.tagsCreated?.length > 0       && <div>✅ {result.tagsCreated.length} etiqueta(s): {result.tagsCreated.join(', ')}</div>}
              {result.agentConfigured               && <div>✅ Agente AI configurado</div>}
              {result.kbLoaded                      && <div>✅ Base de conocimiento cargada</div>}
              {result.rulesCreated?.length > 0      && <div>✅ Reglas: {result.rulesCreated.join(', ')}</div>}
              {result.errors?.length > 0            && result.errors.map((e,i) => <div key={i} style={{ color:'var(--danger)' }}>⚠️ {e}</div>)}
            </div>
          </div>
        )}

        {error && <div style={{ color:'var(--danger)', fontSize:13, marginTop:10 }}>{error}</div>}

        {phase === 'done' && (
          <button onClick={reset} style={{ marginTop:16, padding:'8px 20px', borderRadius:8, border:'1px solid var(--border)', background:'transparent', cursor:'pointer', color:'var(--text)' }}>
            ← Nueva configuración
          </button>
        )}
      </div>
    </div>
  );
}

// ─── OnboardingPanel (mode switcher) ─────────────────────────────────────────
function OnboardingPanel() {
  const [mode, setMode] = React.useState(() => localStorage.getItem('ob_mode') || 'wizard');
  const [link, setLink] = React.useState(null);
  const [genErr, setGenErr] = React.useState('');
  const [copied, setCopied] = React.useState(false);
  const switchTo = (m) => { setMode(m); localStorage.setItem('ob_mode', m); };
  const genLink = async () => {
    setGenErr(''); setCopied(false);
    try {
      const r = await apiFetch('/api/onboarding/link', { method:'POST' }).then(x=>x.json());
      if (r.url) setLink(r); else setGenErr(r.error || 'No se pudo generar el link');
    } catch(e) { setGenErr(e.message); }
  };
  return (
    <div>
      <div style={{ maxWidth:780, margin:'0 auto', padding:'10px 16px 0', display:'flex', justifyContent:'flex-end' }}>
        <button onClick={genLink} style={{ fontSize:13, padding:'8px 14px', borderRadius:10, border:'1px solid var(--border)', background:'transparent', cursor:'pointer', color:'var(--text)' }}>🔗 Compartir wizard con el cliente</button>
      </div>
      {link && (
        <div style={{ maxWidth:780, margin:'10px auto 0', padding:'14px 18px', background:'var(--green-light,#EBF3EF)', border:'1px solid var(--green-mid,#B8D4C8)', borderRadius:12 }}>
          <div style={{ fontWeight:700, fontSize:14, marginBottom:4 }}>Link de onboarding (solo wizard)</div>
          <div style={{ fontSize:12.5, color:'var(--ink-2)', marginBottom:10 }}>Mandáselo al cliente: abre solo el formulario de configuración (sin login ni menú). Vence el {new Date(link.expiresAt).toLocaleDateString('es-AR')}.</div>
          <div style={{ display:'flex', gap:8, alignItems:'center' }}>
            <code style={{ flex:1, fontSize:12, background:'var(--surface)', border:'1px solid var(--border)', borderRadius:8, padding:'8px 10px', wordBreak:'break-all' }}>{link.url}</code>
            <button onClick={()=>{ navigator.clipboard?.writeText(link.url); setCopied(true); setTimeout(()=>setCopied(false),2000); }} style={{ fontSize:13, padding:'8px 14px', borderRadius:8, border:'none', background:'var(--green)', color:'#fff', cursor:'pointer', whiteSpace:'nowrap' }}>{copied ? '✓ Copiado' : 'Copiar'}</button>
          </div>
        </div>
      )}
      {genErr && <div style={{ maxWidth:780, margin:'8px auto 0', color:'var(--danger)', fontSize:13 }}>{genErr}</div>}
      {mode === 'ai'
        ? <OnboardingAIPanel onSwitchToWizard={() => switchTo('wizard')} />
        : <OnboardingWizardPanel onSwitchToAI={() => switchTo('ai')} />}
    </div>
  );
}

// ─── IntegrationCard ─────────────────────────────────────────────────────────
function IntegrationCard({ icon, title, description, enabled, onToggle, children, webhookUrl, badge }) {
  return (
    <div style={{ ...S.card, border: enabled ? '1.5px solid var(--green-mid)' : '1px solid var(--border)' }}>
      <div style={{ display:'flex', alignItems:'flex-start', gap:14 }}>
        <div style={{ fontSize:26, width:44, height:44, display:'flex', alignItems:'center', justifyContent:'center', borderRadius:12, background:'var(--green-light)', flexShrink:0 }}>{icon}</div>
        <div style={{ flex:1 }}>
          <div style={{ display:'flex', alignItems:'center', gap:10, marginBottom:4, flexWrap:'wrap' }}>
            <div style={{ fontSize:15, fontWeight:700, color:'var(--ink)' }}>{title}</div>
            <Toggle on={enabled} onChange={onToggle} />
            {enabled && <span style={{ fontSize:11, fontWeight:600, color:'var(--green)', background:'var(--green-light)', padding:'2px 8px', borderRadius:99 }}>Activa</span>}
            {badge}
          </div>
          <div style={{ fontSize:13, color:'var(--ink-3)', lineHeight:1.6 }}>{description}</div>
        </div>
      </div>
      {enabled && (
        <div style={{ marginTop:20, paddingTop:18, borderTop:'1px solid var(--border-soft)', display:'flex', flexDirection:'column', gap:16 }}>
          {children}
          {webhookUrl && (
            <div style={{ background:'var(--cream)', border:'1px solid var(--border-soft)', borderRadius:10, padding:'10px 14px' }}>
              <div style={{ fontSize:11, fontWeight:700, color:'var(--ink-4)', textTransform:'uppercase', letterSpacing:.7, marginBottom:4 }}>Webhook URL (configurar en Meta)</div>
              <code style={{ fontSize:12, color:'var(--green-hover)', wordBreak:'break-all' }}>{webhookUrl}</code>
            </div>
          )}
        </div>
      )}
    </div>
  );
}

// ─── Meta helpers ─────────────────────────────────────────────────────────────
function useMeta(connection) {
  const [accounts,   setAccounts]   = useState([]);
  const [pixels,     setPixels]     = useState([]);
  const [pages,      setPages]      = useState([]);
  const [businesses, setBusinesses] = useState([]);
  const [loading,    setLoading]    = useState(false);

  const connected = connection?.connected;

  useEffect(() => {
    if (!connected) { setAccounts([]); setPixels([]); setPages([]); setBusinesses([]); return; }
    setLoading(true);
    // Sequential to avoid hitting Meta's rate limit with 3 simultaneous requests
    (async () => {
      try {
        const [acData, pgData] = await Promise.all([
          apiFetch('/api/meta/accounts').then(r => r.json()).catch(() => ({})),
          apiFetch('/api/meta/pages').then(r => r.json()).catch(() => ({})),
        ]);
        setAccounts(acData.accounts || []);
        setPages(pgData.pages || []);
        // businesses last — less critical, load after accounts+pages
        const bizData = await apiFetch('/api/meta/businesses').then(r => r.json()).catch(() => ({}));
        setBusinesses(bizData.businesses || []);
      } finally {
        setLoading(false);
      }
    })();
  }, [connected]);

  const loadBMAccounts = (businessId) => {
    setLoading(true);
    if (!businessId) {
      // No BM selected — reload personal accounts
      apiFetch('/api/meta/accounts').then(r => r.json())
        .then(d => setAccounts(d.accounts || []))
        .catch(() => {})
        .finally(() => setLoading(false));
      return;
    }
    // BM selected — replace with BM-only accounts
    apiFetch(`/api/meta/bm-accounts?businessId=${businessId}`).then(r => r.json())
      .then(d => setAccounts(d.accounts || []))
      .catch(() => {})
      .finally(() => setLoading(false));
  };

  const loadBMPages = (businessId) => {
    setLoading(true);
    if (!businessId) {
      // No BM selected — reload personal pages
      apiFetch('/api/meta/pages').then(r => r.json())
        .then(d => setPages(d.pages || []))
        .catch(() => {})
        .finally(() => setLoading(false));
      return;
    }
    // BM selected — replace with BM-only pages
    apiFetch(`/api/meta/bm-pages?businessId=${businessId}`).then(r => r.json())
      .then(d => setPages(d.pages || []))
      .catch(() => {})
      .finally(() => setLoading(false));
  };

  const loadPixels = (adAccountId) => {
    if (!adAccountId) { setPixels([]); return; }
    apiFetch(`/api/meta/pixels?adAccountId=${adAccountId}`).then(r => r.json()).then(d => setPixels(d.pixels || [])).catch(() => {});
  };

  const loadForms = (pageId, businessId) => {
    if (!pageId) return Promise.resolve([]);
    const qs = businessId ? `&businessId=${businessId}` : '';
    return apiFetch(`/api/meta/forms?pageId=${pageId}${qs}`).then(r => r.json()).then(d => d.forms || []).catch(() => []);
  };

  return { accounts, pixels, pages, businesses, loading, loadPixels, loadForms, loadBMAccounts, loadBMPages };
}

function FacebookConnectSection({ connection, onConnected, onDisconnected }) {
  const [connecting, setConnecting] = useState(false);

  const connect = async () => {
    setConnecting(true);
    try {
      const r = await apiFetch('/api/meta/auth-url');
      const { url, error } = await r.json();
      if (error) { alert('Error: ' + error); setConnecting(false); return; }
      const popup = window.open(url, 'meta-oauth', 'width=640,height=720,left=200,top=80,scrollbars=yes');
      const handler = (e) => {
        if (e.data?.type === 'meta-connected') {
          window.removeEventListener('message', handler);
          setConnecting(false);
          onConnected();
        }
      };
      window.addEventListener('message', handler);
      const timer = setInterval(() => {
        if (popup?.closed) { clearInterval(timer); window.removeEventListener('message', handler); setConnecting(false); }
      }, 800);
    } catch { setConnecting(false); }
  };

  const disconnect = async () => {
    await apiFetch('/api/meta/connection', { method: 'DELETE' });
    onDisconnected();
  };

  if (connection?.connected) {
    const connDate = connection.connectedAt ? new Date(connection.connectedAt).toLocaleDateString('es-AR') : '';
    const expDate  = connection.expiresAt   ? new Date(connection.expiresAt).toLocaleDateString('es-AR') : '';
    return (
      <div style={{ display:'flex', alignItems:'center', gap:14, padding:'12px 16px', background:'var(--green-light)', borderRadius:12, border:'1px solid var(--green-mid)' }}>
        <div style={{ width:36, height:36, borderRadius:'50%', background:'#1877F2', display:'flex', alignItems:'center', justifyContent:'center', fontSize:20, flexShrink:0 }}>f</div>
        <div style={{ flex:1 }}>
          <div style={{ fontWeight:600, fontSize:13, color:'var(--green-hover)' }}>✓ Conectado como <strong>{connection.userName}</strong></div>
          <div style={{ fontSize:11, color:'var(--ink-4)', marginTop:2 }}>
            {connDate && `Conectado el ${connDate}`}{expDate && ` · Expira ${expDate}`}
          </div>
        </div>
        <button style={{ ...S.dangerBtn, fontSize:12, padding:'6px 14px' }} onClick={disconnect}>Desconectar</button>
      </div>
    );
  }

  return (
    <div style={{ display:'flex', alignItems:'center', gap:14, padding:'12px 16px', background:'var(--cream)', borderRadius:12, border:'1.5px dashed var(--border)' }}>
      <div style={{ width:36, height:36, borderRadius:'50%', background:'#1877F2', display:'flex', alignItems:'center', justifyContent:'center', fontSize:20, color:'#fff', fontWeight:700, flexShrink:0 }}>f</div>
      <div style={{ flex:1 }}>
        <div style={{ fontWeight:600, fontSize:13, color:'var(--ink)' }}>Cuenta de Facebook no conectada</div>
        <div style={{ fontSize:12, color:'var(--ink-4)', marginTop:2 }}>Necesitás conectar una cuenta para configurar las integraciones de Meta.</div>
      </div>
      <button style={{ ...S.btnPrimary, background:'#1877F2', boxShadow:'none', fontSize:13 }}
        onClick={connect} disabled={connecting}>
        {connecting ? 'Abriendo…' : '🔗 Conectar con Facebook'}
      </button>
    </div>
  );
}

function MetaSelectField({ label, value, items, onChange, placeholder, loading }) {
  return (
    <div style={S.col}>
      <label style={S.label}>{label}</label>
      {loading
        ? <div style={{ ...S.input, color:'var(--ink-4)', fontSize:12 }}>Cargando…</div>
        : items.length > 0
          ? (
            <select style={S.select} value={value || ''} onChange={e => onChange(e.target.value, items.find(i => i.id === e.target.value))}>
              <option value="">{placeholder}</option>
              {items.map(i => <option key={i.id} value={i.id}>{i.name}</option>)}
            </select>
          )
          : <input style={{ ...S.input, color:'var(--ink-4)' }} placeholder="Conectar Facebook primero" disabled />
      }
    </div>
  );
}

// ─── Tokko Test Button ────────────────────────────────────────────────────────
function TokkoTestButton() {
  const [testing, setTesting] = useState(false);
  const [result,  setResult]  = useState(null);

  const runTest = async () => {
    setTesting(true); setResult(null);
    const data = await apiFetch('/api/debug/tokko-test', { method: 'POST' })
      .then(r => r.json()).catch(e => ({ success: false, error: e.message }));
    setResult(data);
    setTesting(false);
  };

  return (
    <div style={{ borderTop:'1px solid var(--border-soft)', paddingTop:14 }}>
      <div style={{ display:'flex', alignItems:'center', gap:12, flexWrap:'wrap' }}>
        <button style={{ ...S.outlineBtn }} onClick={runTest} disabled={testing}>
          {testing ? '⏳ Enviando…' : '🧪 Enviar contacto de prueba a Tokko'}
        </button>
        {result && (
          result.success
            ? <span style={{ fontSize:13, color:'#16a34a', fontWeight:600 }}>
                ✅ Enviado correctamente{result.contactId ? ` — ID Tokko: ${result.contactId}` : ''}
              </span>
            : <span style={{ fontSize:13, color:'var(--danger)', fontWeight:600 }}>
                ❌ {result.error}
              </span>
        )}
      </div>
      {result?.success && (
        <div style={{ fontSize:12, color:'var(--ink-4)', marginTop:6 }}>
          Buscá en Tokko el contacto <strong>"LoopLead Test"</strong> con email <strong>test@looplead.com</strong> y etiqueta <strong>TEST_LOOPLEAD</strong>.
        </div>
      )}
    </div>
  );
}

// ─── Tokko Labels Editor ──────────────────────────────────────────────────────
function TokkoLabelsEditor({ labels, onChange }) {
  const [newVal, setNewVal] = useState('');

  const add = () => {
    const v = newVal.trim();
    if (!v) return;
    onChange([...labels, { id: Date.now().toString(), value: v, applyWhen: 'always' }]);
    setNewVal('');
  };

  const remove = (id) => onChange(labels.filter(l => l.id !== id));
  const updateLabel = (id, patch) => onChange(labels.map(l => l.id === id ? { ...l, ...patch } : l));

  return (
    <div style={{ display:'flex', flexDirection:'column', gap:8 }}>
      <label style={S.label}>Etiquetas globales para Tokko</label>
      <div style={{ fontSize:12, color:'var(--ink-4)', marginBottom:2 }}>
        Se envían al crear el contacto en Tokko. Definí el origen para cada una.
      </div>
      {labels.map(l => (
        <div key={l.id} style={{ display:'flex', gap:8, alignItems:'center' }}>
          <input style={{ ...S.input, flex:1 }} value={l.value}
            onChange={e => updateLabel(l.id, { value: e.target.value })}
            placeholder="Ej: Lead WhatsApp" />
          <select style={{ ...S.select, width:190 }} value={l.applyWhen}
            onChange={e => updateLabel(l.id, { applyWhen: e.target.value })}>
            <option value="always">Siempre (cualquier origen)</option>
            <option value="lead_ads_only">Solo Lead Ads</option>
            <option value="whatsapp_only">Solo WhatsApp</option>
          </select>
          <button style={S.ghostBtn} onClick={() => remove(l.id)}>✕</button>
        </div>
      ))}
      <div style={{ display:'flex', gap:8 }}>
        <input style={{ ...S.input, flex:1 }} value={newVal} onChange={e => setNewVal(e.target.value)}
          onKeyDown={e => e.key === 'Enter' && add()}
          placeholder="Nueva etiqueta (Enter para agregar)" />
        <button style={S.saveBtn} onClick={add}>+ Agregar</button>
      </div>
    </div>
  );
}

// ─── Mini chip tag input (for per-form labels) ────────────────────────────────
function FormLabelInput({ labels = [], onChange }) {
  const [val, setVal] = useState('');
  const add = () => {
    const v = val.trim();
    if (!v || labels.includes(v)) return;
    onChange([...labels, v]);
    setVal('');
  };
  return (
    <div style={{ display:'flex', flexWrap:'wrap', gap:5, alignItems:'center', marginTop:5, paddingLeft:24 }}>
      {labels.map(l => (
        <span key={l} style={{ display:'inline-flex', alignItems:'center', gap:4, fontSize:11, background:'var(--green-light)', color:'var(--green-hover)', padding:'2px 8px', borderRadius:99, border:'1px solid var(--green-mid)', fontWeight:500 }}>
          {l}
          <button onClick={() => onChange(labels.filter(x => x !== l))}
            style={{ background:'none', border:'none', cursor:'pointer', color:'var(--green)', fontSize:12, lineHeight:1, padding:0, marginLeft:2 }}>✕</button>
        </span>
      ))}
      <div style={{ display:'flex', gap:4, alignItems:'center' }}>
        <input value={val} onChange={e => setVal(e.target.value)}
          onKeyDown={e => e.key === 'Enter' && add()}
          placeholder="+ etiqueta"
          style={{ border:'1px solid var(--border)', borderRadius:6, fontSize:11, padding:'2px 7px', width:110, outline:'none', background:'var(--white)' }} />
        {val.trim() && (
          <button onClick={add}
            style={{ fontSize:11, padding:'2px 8px', borderRadius:6, background:'var(--green)', color:'#fff', border:'none', cursor:'pointer' }}>
            OK
          </button>
        )}
      </div>
    </div>
  );
}

// ─── CAPI Rules Editor ────────────────────────────────────────────────────────
function CAPIRulesEditor({ rules, onChange }) {
  const { pipelines, tags } = usePipochat();
  const EVENTS = ['Lead','Contact','Purchase','Schedule','SubmitApplication','ViewContent','InitiateCheckout'];

  const addRule = () => onChange([...rules, { id: Date.now().toString(), event: 'Lead', trigger: 'always' }]);
  const removeRule = (id) => onChange(rules.filter(r => r.id !== id));
  const updateRule = (id, patch) => onChange(rules.map(r => r.id === id ? { ...r, ...patch } : r));

  return (
    <div style={{ display:'flex', flexDirection:'column', gap:10 }}>
      <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between' }}>
        <label style={S.label}>Reglas de eventos</label>
        <button style={{ ...S.outlineBtn, fontSize:12, padding:'5px 12px' }} onClick={addRule}>+ Nueva regla</button>
      </div>
      <div style={{ fontSize:12, color:'var(--ink-4)' }}>Definí cuándo enviar cada evento a Meta. Podés combinar múltiples reglas.</div>
      {rules.length === 0 && (
        <div style={{ textAlign:'center', padding:'20px', color:'var(--ink-4)', fontSize:13, background:'var(--cream)', borderRadius:10, border:'1px dashed var(--border)' }}>
          Sin reglas. Hacé clic en "+ Nueva regla" para agregar.
        </div>
      )}
      {rules.map(rule => (
        <div key={rule.id} style={{ background:'var(--cream)', border:'1px solid var(--border)', borderRadius:10, padding:'12px 14px', display:'flex', flexDirection:'column', gap:10 }}>
          <div style={{ display:'flex', gap:8, alignItems:'center' }}>
            <div style={{ flex:1 }}>
              <label style={S.label}>Evento Meta</label>
              <select style={S.select} value={rule.event} onChange={e => updateRule(rule.id, { event: e.target.value })}>
                {EVENTS.map(ev => <option key={ev} value={ev}>{ev}</option>)}
              </select>
            </div>
            <div style={{ flex:1 }}>
              <label style={S.label}>Disparador</label>
              <select style={S.select} value={rule.trigger} onChange={e => updateRule(rule.id, { trigger: e.target.value, tagId: undefined, tagName: undefined, pipelineId: undefined, stageId: undefined })}>
                <option value="always">Siempre (cualquier conversación)</option>
                <option value="tag_added">Cuando se agrega una etiqueta</option>
                <option value="pipeline_stage">Cuando llega a una etapa del pipeline</option>
              </select>
            </div>
            <button style={{ ...S.ghostBtn, marginTop:18 }} onClick={() => removeRule(rule.id)}>✕</button>
          </div>

          {rule.trigger === 'tag_added' && (
            <div>
              <label style={S.label}>Etiqueta</label>
              <select style={S.select} value={rule.tagId || ''} onChange={e => {
                const t = tags.find(t => t._id === e.target.value);
                updateRule(rule.id, { tagId: e.target.value, tagName: t?.name });
              }}>
                <option value="">— Seleccioná una etiqueta —</option>
                {rule.tagId && !tags.some(t => t._id === rule.tagId) && (
                  <option value={rule.tagId}>{rule.tagName || "(etiqueta seleccionada)"}</option>
                )}
                {tags.map(t => <option key={t._id} value={t._id}>{t.name}</option>)}
              </select>
            </div>
          )}

          {rule.trigger === 'pipeline_stage' && (
            <div style={S.row}>
              <div style={S.col}>
                <label style={S.label}>Pipeline</label>
                <select style={S.select} value={rule.pipelineId || ''} onChange={e => {
                  const p = pipelines.find(p => p._id === e.target.value);
                  updateRule(rule.id, { pipelineId: e.target.value, pipelineName: p?.title || p?.name, stageId: undefined });
                }}>
                  <option value="">— Seleccioná un pipeline —</option>
                  {pipelines.map(p => <option key={p._id} value={p._id}>{p.title || p.name}</option>)}
                </select>
              </div>
              <div style={S.col}>
                <label style={S.label}>Etapa</label>
                <select style={S.select} value={rule.stageId || ''} onChange={e => {
                  const pipeline = pipelines.find(p => p._id === rule.pipelineId);
                  const stage = pipeline?.stages?.find(s => s._id === e.target.value);
                  updateRule(rule.id, { stageId: e.target.value, stageName: stage?.displayName || stage?.name });
                }}>
                  <option value="">— Seleccioná una etapa —</option>
                  {(pipelines.find(p => p._id === rule.pipelineId)?.stages || []).map(s => (
                    <option key={s._id} value={s._id}>{s.displayName || s.name}</option>
                  ))}
                </select>
              </div>
            </div>
          )}
        </div>
      ))}
    </div>
  );
}

// ─── IntegracionesPanel ───────────────────────────────────────────────────────
function GoogleCalendarCard({ gc, onPatch }) {
  const [cals,    setCals]    = useState(null);
  const [loading, setLoading] = useState(false);
  const [syncRes, setSyncRes] = useState(null);
  const [tid,     setTid]     = useState('');

  useEffect(() => {
    apiFetch('/api/auth/me').then(r => r.json()).then(d => setTid(d.tenantId || '')).catch(() => {});
  }, []);

  const loadCalendars = async () => {
    setLoading(true);
    try {
      const r = await apiFetch('/api/integrations/google-calendar/calendars');
      const d = await r.json();
      setCals(d.calendars || []);
    } catch { setCals([]); }
    setLoading(false);
  };

  const disconnect = async () => {
    if (!confirm('¿Desconectar Google Calendar?')) return;
    await apiFetch('/api/integrations/google-calendar', { method: 'DELETE' });
    onPatch({ connected: false, email: undefined, accessToken: undefined, refreshToken: undefined });
  };

  const saveSetting = async (patch2) => {
    onPatch(patch2);
    await apiFetch('/api/integrations/google-calendar/settings', {
      method: 'PUT', headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ ...gc, ...patch2 }),
    });
  };

  const syncNow = async () => {
    setSyncRes(null); setLoading(true);
    try {
      const r = await apiFetch('/api/integrations/google-calendar/sync-now', { method: 'POST' });
      const d = await r.json();
      setSyncRes(d);
    } catch (err) {
      setSyncRes({ error: err.message || 'Error al sincronizar' });
    } finally {
      setLoading(false);
    }
  };

  return (
    <div style={{ ...S.card, marginBottom: 20 }}>
      <div style={{ display:'flex', alignItems:'flex-start', justifyContent:'space-between', gap:12, flexWrap:'wrap' }}>
        <div style={{ display:'flex', alignItems:'center', gap:12 }}>
          <div style={{ width:44, height:44, borderRadius:10, background:'#EEF2FF', display:'flex', alignItems:'center', justifyContent:'center', fontSize:22, flexShrink:0 }}>📅</div>
          <div>
            <div style={{ fontWeight:700, fontSize:15 }}>Google Calendar</div>
            <div style={{ fontSize:12, color:'var(--ink-3)', marginTop:2 }}>Sync bidireccional: reservas de Pipochat ↔ Google Calendar.</div>
          </div>
        </div>
        {gc.connected
          ? <div style={{ display:'flex', alignItems:'center', gap:8, flexShrink:0 }}>
              <span style={{ fontSize:12, color:'#16a34a', fontWeight:600 }}>✓ {gc.email || 'Conectado'}</span>
              <button onClick={disconnect} style={{ fontSize:12, color:'var(--danger)', background:'var(--danger-light)', border:'none', borderRadius:6, padding:'4px 10px', cursor:'pointer' }}>Desconectar</button>
            </div>
          : <button onClick={async () => {
                let id = tid;
                if (!id) {
                  try { const d = await apiFetch('/api/auth/me').then(r => r.json()); id = d.tenantId; }
                  catch {}
                }
                if (id) window.location.href = `/api/integrations/google-calendar/authorize?tid=${id}`;
              }} style={{ ...S.saveBtn, fontSize:13, display:'inline-flex', alignItems:'center', gap:6, flexShrink:0 }}>
              🔗 Conectar Google
            </button>
        }
      </div>

      {gc.connected && (
        <div style={{ marginTop:16, display:'flex', flexDirection:'column', gap:12 }}>
          <div style={{ display:'flex', gap:16, flexWrap:'wrap' }}>
            <label style={{ display:'flex', alignItems:'center', gap:7, fontSize:13, cursor:'pointer' }}>
              <input type="checkbox" checked={!!gc.syncPipochatToGoogle}
                onChange={e => saveSetting({ syncPipochatToGoogle: e.target.checked })} />
              <span>Pipochat → Google <span style={{ color:'var(--ink-4)', fontSize:11 }}>(reservas como eventos)</span></span>
            </label>
            <label style={{ display:'flex', alignItems:'center', gap:7, fontSize:13, cursor:'pointer' }}>
              <input type="checkbox" checked={!!gc.syncGoogleToPipochat}
                onChange={e => saveSetting({ syncGoogleToPipochat: e.target.checked })} />
              <span>Google → Pipochat <span style={{ color:'var(--ink-4)', fontSize:11 }}>(bloquear disponibilidad)</span></span>
            </label>
          </div>

          <div style={{ display:'flex', gap:8, alignItems:'flex-end', flexWrap:'wrap' }}>
            <div style={{ flex:1, minWidth:200 }}>
              <div style={{ fontSize:11, color:'var(--ink-4)', marginBottom:4 }}>Calendario destino</div>
              {cals
                ? <select style={S.select} value={gc.selectedCalendarId || 'primary'}
                    onChange={e => { const c = cals.find(x => x.id === e.target.value); saveSetting({ selectedCalendarId: e.target.value, selectedCalendarName: c?.summary }); }}>
                    {cals.map(c => <option key={c.id} value={c.id}>{c.summary}{c.primary ? ' (principal)' : ''}</option>)}
                  </select>
                : <div style={{ fontSize:13, color:'var(--ink-3)', padding:'6px 0' }}>{gc.selectedCalendarName || gc.selectedCalendarId || 'principal'}</div>
              }
            </div>
            <button style={S.outlineBtn} onClick={loadCalendars} disabled={loading}>
              {cals ? '↺ Recargar' : '📋 Ver calendarios'}
            </button>
          </div>

          <div style={{ display:'flex', gap:8, alignItems:'center', flexWrap:'wrap' }}>
            <button style={S.outlineBtn} onClick={syncNow} disabled={loading}>
              {loading ? '⏳…' : '↺ Sincronizar ahora'}
            </button>
            {gc.lastSyncAt && <span style={{ fontSize:11, color:'var(--ink-4)' }}>Última sync: {new Date(gc.lastSyncAt).toLocaleString('es-AR')}</span>}
            {syncRes && (syncRes.error
              ? <span style={{ fontSize:12, color:'var(--danger)' }}>❌ {syncRes.error}</span>
              : <span style={{ fontSize:12, color:'#16a34a' }}>
                  ✅ {syncRes.bookingsSynced || 0} reservas + {syncRes.activitiesSynced || 0} actividades → Google
                  {(syncRes.errors||[]).length > 0 && <span style={{ color:'#92400e' }}> · ⚠ {syncRes.errors[0]}</span>}
                </span>
            )}
          </div>
        </div>
      )}
    </div>
  );
}

// ─── Handoff inteligente ──────────────────────────────────────────────────────

function HandoffPanel() {
  const [cfg,    setCfg]    = useState(null);
  const [saving, setSaving] = useState(false);
  const [msg,    setMsg]    = useState('');
  const [testConvId, setTestConvId] = useState('');
  const [testing,    setTesting]    = useState(false);
  const [testRes,    setTestRes]    = useState(null);

  useEffect(() => {
    apiFetch('/api/handoff/config').then(r=>r.json()).then(setCfg).catch(()=>{});
  }, []);

  const save = async () => {
    setSaving(true); setMsg('');
    try {
      const r = await apiFetch('/api/handoff/config', { method:'PUT', headers:{'Content-Type':'application/json'}, body: JSON.stringify(cfg) });
      setCfg(await r.json()); setMsg('✓ Guardado');
    } catch { setMsg('❌ Error'); }
    setSaving(false); setTimeout(()=>setMsg(''), 3000);
  };

  const testHandoff = async () => {
    if (!testConvId.trim()) return;
    setTesting(true); setTestRes(null);
    try {
      const r = await apiFetch('/api/handoff/trigger', { method:'POST', headers:{'Content-Type':'application/json'}, body: JSON.stringify({ conversationId: testConvId, contactName: 'Test Lead' }) });
      setTestRes(await r.json());
    } catch(e) { setTestRes({ error: e.message }); }
    finally { setTesting(false); }
  };

  if (!cfg) return <div style={{ padding:28, color:'var(--ink-3)' }}>Cargando…</div>;

  return (
    <div style={{ ...S.editor }}>
      <div style={{ fontWeight:700, fontSize:20, marginBottom:6 }}>🤝 Handoff Inteligente</div>
      <div style={{ fontSize:13, color:'var(--ink-3)', marginBottom:24 }}>Claude genera un resumen del lead y lo manda al asesor humano por WhatsApp</div>

      <div style={{ ...S.card, marginBottom:16 }}>
        {/* How it works info */}
        <div style={{ fontSize:13, background:'#f0fdf4', border:'1px solid #86efac', borderRadius:8, padding:'10px 14px', marginBottom:16, lineHeight:1.7 }}>
          <strong>¿Cómo funciona?</strong><br/>
          Se dispara desde una <strong>Regla de conversación</strong> (acción "Handoff a humano") o manualmente vía API.<br/>
          Claude lee el historial y genera: nombre, interés, presupuesto, disponibilidad, urgencia.<br/>
          El resumen llega al asesor por WhatsApp y el bot se pausa.
        </div>

        <label style={{ display:'flex', alignItems:'center', gap:8, fontSize:13, marginBottom:16, cursor:'pointer' }}>
          <input type="checkbox" checked={cfg.enabled} onChange={e=>setCfg(c=>({...c,enabled:e.target.checked}))} />
          <span><strong>Activo</strong> — permitir handoffs desde reglas de conversación</span>
        </label>

        <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr', gap:12, marginBottom:14 }}>
          <div>
            <label style={{ fontSize:12, fontWeight:600, display:'block', marginBottom:4 }}>WhatsApp del asesor (destino del resumen)</label>
            <input value={cfg.agentPhone||''} onChange={e=>setCfg(c=>({...c,agentPhone:e.target.value}))}
              placeholder="5491112345678"
              style={{ width:'100%', padding:'8px 10px', borderRadius:8, border:'1px solid var(--border)', fontSize:13, boxSizing:'border-box' }} />
          </div>
          <div>
            <label style={{ fontSize:12, fontWeight:600, display:'block', marginBottom:4 }}>Nombre del asesor (referencia)</label>
            <input value={cfg.agentPhoneLabel||''} onChange={e=>setCfg(c=>({...c,agentPhoneLabel:e.target.value}))}
              placeholder="Ej: Juan Vendedor"
              style={{ width:'100%', padding:'8px 10px', borderRadius:8, border:'1px solid var(--border)', fontSize:13, boxSizing:'border-box' }} />
          </div>
        </div>

        <div style={{ display:'flex', gap:20, marginBottom:14 }}>
          <label style={{ display:'flex', alignItems:'center', gap:8, fontSize:13, cursor:'pointer' }}>
            <input type="checkbox" checked={cfg.pauseBot} onChange={e=>setCfg(c=>({...c,pauseBot:e.target.checked}))} />
            Pausar bot después del handoff
          </label>
          <label style={{ display:'flex', alignItems:'center', gap:8, fontSize:13, cursor:'pointer' }}>
            <input type="checkbox" checked={cfg.notifyContact} onChange={e=>setCfg(c=>({...c,notifyContact:e.target.checked}))} />
            Avisar al contacto
          </label>
        </div>

        {cfg.notifyContact && (
          <div style={{ ...S.card, background:'var(--bg)', marginBottom:14, padding:'14px 16px' }}>
            <label style={{ fontSize:12, fontWeight:600, display:'block', marginBottom:8 }}>Tipo de mensaje al contacto</label>
            <div style={{ display:'flex', gap:10, marginBottom:12 }}>
              {[['false','✍️ Texto libre (solo 24hs)'],['true','📋 Template aprobado (siempre)']].map(([val,label])=>(
                <label key={val} style={{ display:'flex', alignItems:'center', gap:6, fontSize:12, cursor:'pointer',
                  background: String(!!cfg.contactUseTemplate)===val ? 'var(--green-light)' : 'var(--white)',
                  border:'1px solid var(--border)', borderRadius:8, padding:'6px 12px', userSelect:'none', flex:1 }}>
                  <input type="radio" checked={String(!!cfg.contactUseTemplate)===val}
                    onChange={()=>setCfg(c=>({...c,contactUseTemplate:val==='true'}))} style={{margin:0}} />
                  {label}
                </label>
              ))}
            </div>
            <div style={{ fontSize:11, color:'var(--warning)', background:'var(--warning-light)', borderRadius:6, padding:'6px 10px', marginBottom:10 }}>
              ⚠️ El handoff suele ocurrir después de un silencio largo — la ventana de 24hs probablemente esté cerrada. Recomendamos usar template aprobado.
            </div>
            {cfg.contactUseTemplate ? (
              <TemplateSelector
                value={cfg.contactTemplateId||''}
                varMapping={cfg.contactTemplateVars||{}}
                onChange={v=>setCfg(c=>({...c,contactTemplateId:v}))}
                onVarChange={(slot,v)=>setCfg(c=>({...c,contactTemplateVars:{...c.contactTemplateVars,[slot]:v}}))}
              />
            ) : (
              <input value={cfg.contactMessage||''} onChange={e=>setCfg(c=>({...c,contactMessage:e.target.value}))}
                placeholder='Ej: "¡Perfecto! Un asesor te contacta en breve."'
                style={{ width:'100%', padding:'8px 10px', borderRadius:8, border:'1px solid var(--border)', fontSize:13, boxSizing:'border-box' }} />
            )}
          </div>
        )}

        <div style={{ marginBottom:16 }}>
          <label style={{ fontSize:12, fontWeight:600, display:'block', marginBottom:4 }}>Instrucciones extra para Claude (opcional)</label>
          <textarea value={cfg.systemExtra||''} onChange={e=>setCfg(c=>({...c,systemExtra:e.target.value}))} rows={2}
            placeholder='Ej: "Siempre mencioná el nombre del proyecto de interés. Indicá el próximo paso sugerido."'
            style={{ width:'100%', padding:'8px 10px', borderRadius:8, border:'1px solid var(--border)', fontSize:13, resize:'vertical', boxSizing:'border-box' }} />
        </div>

        <div style={{ display:'flex', gap:8, alignItems:'center' }}>
          <button onClick={save} disabled={saving} style={{ ...S.saveBtn }}>
            {saving ? 'Guardando…' : 'Guardar configuración'}
          </button>
          {msg && <span style={{ fontSize:12, color: msg.startsWith('✓') ? '#16a34a' : 'var(--danger)' }}>{msg}</span>}
        </div>
      </div>

      {/* Test handoff */}
      <div style={{ ...S.card }}>
        <div style={{ fontWeight:600, fontSize:14, marginBottom:10 }}>🧪 Probar handoff manualmente</div>
        <div style={{ fontSize:12, color:'var(--ink-3)', marginBottom:10 }}>
          Ingresá un Conversation ID de Pipochat para testear el resumen sin esperar una regla.
        </div>
        <div style={{ display:'flex', gap:8 }}>
          <input value={testConvId} onChange={e=>setTestConvId(e.target.value)}
            placeholder="ID de conversación Pipochat"
            style={{ flex:1, padding:'8px 10px', borderRadius:8, border:'1px solid var(--border)', fontSize:13 }} />
          <button onClick={testHandoff} disabled={testing || !testConvId} style={{ ...S.outlineBtn }}>
            {testing ? '⏳…' : '▶ Probar'}
          </button>
        </div>
        {testRes && (
          <div style={{ marginTop:12, fontSize:12, padding:'10px 12px', borderRadius:8,
            background: testRes.error ? 'var(--danger-light)' : '#f0fdf4',
            border: `1px solid ${testRes.error ? 'var(--danger)' : '#86efac'}`,
            whiteSpace: 'pre-wrap' }}>
            {testRes.error ? `❌ ${testRes.error}` : `✅ Enviado: ${testRes.sent ? 'Sí' : 'No (asesor no encontrado)'}\nBot pausado: ${testRes.paused ? 'Sí' : 'No'}\n\n📋 Resumen:\n${testRes.summary}`}
          </div>
        )}
      </div>
    </div>
  );
}

// ─── Lead Scoring ─────────────────────────────────────────────────────────────

const SCORE_COLORS = {
  'caliente': { bg:'#fef2f2', border:'#fca5a5', text:'#b91c1c', dot:'#ef4444' },
  'tibio':    { bg:'#fffbeb', border:'#fcd34d', text:'#92400e', dot:'#f59e0b' },
  'frío':     { bg:'#f8fafc', border:'#cbd5e1', text:'#475569', dot:'#94a3b8' },
};

function ScoreBar({ score }) {
  const pct = (score / 10) * 100;
  const color = score >= 7 ? '#ef4444' : score >= 4 ? '#f59e0b' : '#94a3b8';
  return (
    <div style={{ display:'flex', alignItems:'center', gap:8 }}>
      <div style={{ flex:1, height:6, background:'#e5e7eb', borderRadius:3, overflow:'hidden' }}>
        <div style={{ width:`${pct}%`, height:'100%', background:color, borderRadius:3, transition:'width .3s' }} />
      </div>
      <span style={{ fontSize:13, fontWeight:700, color, minWidth:32 }}>{score}/10</span>
    </div>
  );
}

function ScoringPanel() {
  const [cfg,     setCfg]     = useState(null);
  const [scores,  setScores]  = useState(null);
  const [saving,  setSaving]  = useState(false);
  const [msg,     setMsg]     = useState('');
  const [testConvId, setTestConvId] = useState('');
  const [testContact, setTestContact] = useState('');
  const [testing, setTesting] = useState(false);
  const [testRes, setTestRes] = useState(null);

  const load = () => {
    apiFetch('/api/scoring/config').then(r=>r.json()).then(setCfg).catch(()=>{});
    apiFetch('/api/scoring/scores').then(r=>r.json()).then(d=>setScores(d.scores || [])).catch(()=>setScores([]));
  };
  useEffect(load, []);

  const save = async () => {
    setSaving(true); setMsg('');
    try {
      const r = await apiFetch('/api/scoring/config', { method:'PUT', headers:{'Content-Type':'application/json'}, body: JSON.stringify(cfg) });
      setCfg(await r.json()); setMsg('✓ Guardado');
    } catch { setMsg('❌ Error'); }
    setSaving(false); setTimeout(()=>setMsg(''), 3000);
  };

  const scoreNow = async () => {
    if (!testConvId.trim()) return;
    setTesting(true); setTestRes(null);
    try {
      const r = await apiFetch('/api/scoring/score', { method:'POST', headers:{'Content-Type':'application/json'}, body: JSON.stringify({ conversationId: testConvId, contactName: testContact || 'Lead' }) });
      const d = await r.json();
      setTestRes(d);
      load(); // refresh scores list
    } catch(e) { setTestRes({ error: e.message }); }
    finally { setTesting(false); }
  };

  if (!cfg) return <div style={{ padding:28, color:'var(--ink-3)' }}>Cargando…</div>;

  return (
    <div style={{ ...S.editor }}>
      <div style={{ fontWeight:700, fontSize:20, marginBottom:6 }}>⭐ Lead Scoring</div>
      <div style={{ fontSize:13, color:'var(--ink-3)', marginBottom:24 }}>Claude lee cada conversación y asigna un puntaje 1-10 según intención, presupuesto y urgencia</div>

      <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr', gap:16, marginBottom:20 }}>
        {/* Config card */}
        <div style={{ ...S.card }}>
          <div style={{ fontWeight:600, fontSize:14, marginBottom:14 }}>Configuración</div>
          <label style={{ display:'flex', alignItems:'center', gap:8, fontSize:13, marginBottom:10, cursor:'pointer' }}>
            <input type="checkbox" checked={cfg.enabled} onChange={e=>setCfg(c=>({...c,enabled:e.target.checked}))} />
            <strong>Scoring activo</strong>
          </label>
          <label style={{ display:'flex', alignItems:'center', gap:8, fontSize:13, marginBottom:14, cursor:'pointer' }}>
            <input type="checkbox" checked={cfg.autoScore} onChange={e=>setCfg(c=>({...c,autoScore:e.target.checked}))} />
            Auto-puntuar en cada mensaje
          </label>
          <div style={{ display:'flex', gap:10, marginBottom:14 }}>
            <div style={{ flex:1 }}>
              <label style={{ fontSize:11, fontWeight:600, display:'block', marginBottom:4, color:'var(--danger)' }}>🔥 Caliente ≥</label>
              <input type="number" min="1" max="10" value={cfg.hotThreshold} onChange={e=>setCfg(c=>({...c,hotThreshold:+e.target.value}))}
                style={{ width:'100%', padding:'6px 8px', borderRadius:6, border:'1px solid var(--border)', fontSize:13, textAlign:'center' }} />
            </div>
            <div style={{ flex:1 }}>
              <label style={{ fontSize:11, fontWeight:600, display:'block', marginBottom:4, color:'#92400e' }}>🟡 Tibio ≥</label>
              <input type="number" min="1" max="10" value={cfg.warmThreshold} onChange={e=>setCfg(c=>({...c,warmThreshold:+e.target.value}))}
                style={{ width:'100%', padding:'6px 8px', borderRadius:6, border:'1px solid var(--border)', fontSize:13, textAlign:'center' }} />
            </div>
          </div>

          <label style={{ display:'flex', alignItems:'center', gap:8, fontSize:13, marginBottom:8, cursor:'pointer' }}>
            <input type="checkbox" checked={cfg.notifyOnHot} onChange={e=>setCfg(c=>({...c,notifyOnHot:e.target.checked}))} />
            Notificar cuando un lead se vuelve caliente
          </label>
          {cfg.notifyOnHot && (
            <input value={cfg.notifyPhone||''} onChange={e=>setCfg(c=>({...c,notifyPhone:e.target.value}))}
              placeholder="WhatsApp ej: 5491112345678"
              style={{ width:'100%', padding:'7px 10px', borderRadius:8, border:'1px solid var(--border)', fontSize:13, marginBottom:10, boxSizing:'border-box' }} />
          )}

          <div style={{ display:'flex', gap:8, alignItems:'center' }}>
            <button onClick={save} disabled={saving} style={{ ...S.saveBtn, fontSize:13 }}>
              {saving ? 'Guardando…' : 'Guardar'}
            </button>
            {msg && <span style={{ fontSize:12, color: msg.startsWith('✓') ? '#16a34a' : 'var(--danger)' }}>{msg}</span>}
          </div>
        </div>

        {/* Test card */}
        <div style={{ ...S.card }}>
          <div style={{ fontWeight:600, fontSize:14, marginBottom:12 }}>🧪 Puntuar manualmente</div>
          <label style={{ fontSize:12, fontWeight:600, display:'block', marginBottom:4 }}>Conversation ID</label>
          <input value={testConvId} onChange={e=>setTestConvId(e.target.value)}
            placeholder="ID de conversación Pipochat"
            style={{ width:'100%', padding:'7px 10px', borderRadius:8, border:'1px solid var(--border)', fontSize:13, marginBottom:8, boxSizing:'border-box' }} />
          <label style={{ fontSize:12, fontWeight:600, display:'block', marginBottom:4 }}>Nombre del contacto</label>
          <input value={testContact} onChange={e=>setTestContact(e.target.value)}
            placeholder="Ej: Martín García"
            style={{ width:'100%', padding:'7px 10px', borderRadius:8, border:'1px solid var(--border)', fontSize:13, marginBottom:10, boxSizing:'border-box' }} />
          <button onClick={scoreNow} disabled={testing || !testConvId} style={{ ...S.outlineBtn, width:'100%' }}>
            {testing ? '⏳ Analizando…' : '⭐ Puntuar ahora'}
          </button>
          {testRes && (
            <div style={{ marginTop:12, fontSize:13, padding:'10px 12px', borderRadius:8,
              background: testRes.error ? 'var(--danger-light)' : '#f0fdf4',
              border: `1px solid ${testRes.error ? 'var(--danger)' : '#86efac'}` }}>
              {testRes.error ? `❌ ${testRes.error}` : (
                <>
                  <div style={{ fontWeight:700, marginBottom:4 }}>{testRes.score}/10 — {testRes.label}</div>
                  <div style={{ color:'var(--ink-2)' }}>{testRes.reasoning}</div>
                </>
              )}
            </div>
          )}
        </div>
      </div>

      {/* Scores list */}
      <div style={{ fontWeight:700, fontSize:15, marginBottom:12 }}>📋 Scores recientes</div>
      {!scores && <div style={{ color:'var(--ink-3)', fontSize:13 }}>Cargando…</div>}
      {scores && scores.length === 0 && (
        <div style={{ ...S.card, textAlign:'center', padding:32, color:'var(--ink-3)' }}>
          <div style={{ fontSize:28, marginBottom:8 }}>⭐</div>
          <strong>Sin scores todavía</strong><br/>
          <span style={{ fontSize:13 }}>Usá el panel de prueba o la acción en reglas para puntuar leads</span>
        </div>
      )}
      {scores && scores.map(s => {
        const colors = SCORE_COLORS[s.label] || SCORE_COLORS['frío'];
        return (
          <div key={s.convId} style={{ ...S.card, marginBottom:10, border:`1px solid ${colors.border}`, background: colors.bg }}>
            <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between', marginBottom:8 }}>
              <div style={{ display:'flex', alignItems:'center', gap:10 }}>
                <span style={{ fontSize:20, lineHeight:1 }}>
                  {s.label === 'caliente' ? '🔥' : s.label === 'tibio' ? '🟡' : '❄️'}
                </span>
                <div>
                  <div style={{ fontWeight:600, fontSize:14 }}>{s.contactName || 'Lead'}</div>
                  <div style={{ fontSize:11, color:'var(--ink-4)' }}>{new Date(s.scoredAt).toLocaleString('es-AR')}</div>
                </div>
              </div>
              <span style={{ fontSize:12, padding:'3px 10px', borderRadius:20, fontWeight:700,
                background: colors.bg, color: colors.text, border:`1px solid ${colors.border}` }}>
                {s.label}
              </span>
            </div>
            <ScoreBar score={s.score} />
            <div style={{ fontSize:12, color:'var(--ink-2)', marginTop:8 }}>{s.reasoning}</div>
          </div>
        );
      })}
    </div>
  );
}

// ─── Proactive Agent ──────────────────────────────────────────────────────────

const PROACTIVE_DEFAULTS = {
  name: 'Follow-up leads silenciosos',
  enabled: false,
  silenceValue: 24,
  silenceUnit: 'hours',
  pipelineId: '',
  pipelineName: '',
  stageId: '',
  stageName: '',
  maxAttempts: 2,
  cooldownHours: 24,
  systemPromptExtra: '',
  useTemplate: false,
  templateId: '',
  templateVarMapping: {},
};

function ProactiveModal({ rule, onClose, onSaved }) {
  const { pipelines, connected } = usePipochat();
  const [form, setForm] = useState(rule ? { ...rule } : { ...PROACTIVE_DEFAULTS });
  const [saving, setSaving] = useState(false);
  const [err, setErr] = useState('');
  const set = (k, v) => setForm(f => ({ ...f, [k]: v }));

  const selectedPipeline = pipelines.find(p => p._id === form.pipelineId);
  const stages = selectedPipeline?.stages || [];

  const save = async () => {
    if (!form.name.trim()) return setErr('El nombre es requerido');
    if (!form.silenceValue || form.silenceValue < 1) return setErr('El tiempo debe ser mayor a 0');
    setSaving(true); setErr('');
    try {
      const url    = rule ? `/api/proactive-rules/${rule.id}` : '/api/proactive-rules';
      const method = rule ? 'PUT' : 'POST';
      const res  = await apiFetch(url, { method, headers: {'Content-Type':'application/json'}, body: JSON.stringify(form) });
      const data = await res.json();
      if (data.error) { setErr(data.error); setSaving(false); return; }
      onSaved(data);
    } catch(e) { setErr(e.message); setSaving(false); }
  };

  const silenceUnits = [['minutes','minutos'],['hours','horas'],['days','días']];

  return (
    <div style={{ position:'fixed', inset:0, background:'rgba(0,0,0,.45)', zIndex:1000, display:'flex', alignItems:'center', justifyContent:'center' }}
      onClick={e=>{ if(e.target===e.currentTarget) onClose(); }}>
      <div style={{ background:'var(--white)', borderRadius:16, padding:28, width:'100%', maxWidth:560, maxHeight:'90vh', overflowY:'auto', boxShadow:'var(--shadow-xl)' }}>
        <div style={{ fontWeight:700, fontSize:17, marginBottom:20 }}>{rule ? 'Editar regla' : '🤖 Nueva regla agentic'}</div>

        {/* Name + enabled */}
        <div style={{ display:'flex', gap:12, marginBottom:16, alignItems:'flex-end' }}>
          <div style={{ flex:1 }}>
            <label style={{ fontSize:12, fontWeight:600, display:'block', marginBottom:4 }}>Nombre</label>
            <input value={form.name} onChange={e=>set('name',e.target.value)}
              style={{ width:'100%', padding:'8px 10px', borderRadius:8, border:'1px solid var(--border)', fontSize:13 }} />
          </div>
          <label style={{ display:'flex', alignItems:'center', gap:6, fontSize:13, cursor:'pointer', paddingBottom:8 }}>
            <input type="checkbox" checked={form.enabled} onChange={e=>set('enabled',e.target.checked)} />
            Activa
          </label>
        </div>

        {/* Silence threshold */}
        <div style={{ ...S.card, background:'var(--green-light)', border:'1px solid var(--green-mid)', marginBottom:16 }}>
          <div style={{ fontSize:13, fontWeight:600, marginBottom:10 }}>⏱️ Disparar cuando el contacto lleva...</div>
          <div style={{ display:'flex', gap:8, alignItems:'center' }}>
            <input type="number" min="1" value={form.silenceValue} onChange={e=>set('silenceValue',+e.target.value)}
              style={{ width:80, padding:'8px 10px', borderRadius:8, border:'1px solid var(--border)', fontSize:13, textAlign:'center' }} />
            <select value={form.silenceUnit} onChange={e=>set('silenceUnit',e.target.value)}
              style={{ padding:'8px 10px', borderRadius:8, border:'1px solid var(--border)', fontSize:13, flex:1 }}>
              {silenceUnits.map(([v,l])=><option key={v} value={v}>{l} sin responder al bot</option>)}
            </select>
          </div>
        </div>

        {/* Scope filters */}
        <div style={{ marginBottom:16 }}>
          <label style={{ fontSize:12, fontWeight:600, display:'block', marginBottom:6 }}>Filtro por pipeline (opcional)</label>
          <select value={form.pipelineId||''} onChange={e=>{
            const p = pipelines.find(x=>x._id===e.target.value);
            set('pipelineId', e.target.value);
            set('pipelineName', p?.name||'');
            set('stageId',''); set('stageName','');
          }} style={{ width:'100%', padding:'8px 10px', borderRadius:8, border:'1px solid var(--border)', fontSize:13, marginBottom:8 }}>
            <option value=''>— Todos los pipelines —</option>
            {pipelines.map(p=><option key={p._id} value={p._id}>{p.name}</option>)}
          </select>
          {form.pipelineId && stages.length > 0 && (
            <>
              <label style={{ fontSize:12, fontWeight:600, display:'block', marginBottom:4 }}>Filtro por etapa (opcional)</label>
              <select value={form.stageId||''} onChange={e=>{
                const s = stages.find(x=>x._id===e.target.value);
                set('stageId', e.target.value);
                set('stageName', s?.name||'');
              }} style={{ width:'100%', padding:'8px 10px', borderRadius:8, border:'1px solid var(--border)', fontSize:13 }}>
                <option value=''>— Todas las etapas —</option>
                {stages.map(s=><option key={s._id} value={s._id}>{s.name}</option>)}
              </select>
            </>
          )}
        </div>

        {/* Limits */}
        <div style={{ display:'flex', gap:12, marginBottom:16 }}>
          <div style={{ flex:1 }}>
            <label style={{ fontSize:12, fontWeight:600, display:'block', marginBottom:4 }}>Máx. intentos por conv.</label>
            <input type="number" min="1" max="5" value={form.maxAttempts} onChange={e=>set('maxAttempts',+e.target.value)}
              style={{ width:'100%', padding:'8px 10px', borderRadius:8, border:'1px solid var(--border)', fontSize:13 }} />
            <div style={{ fontSize:11, color:'var(--ink-4)', marginTop:3 }}>Después no vuelve a escribir</div>
          </div>
          <div style={{ flex:1 }}>
            <label style={{ fontSize:12, fontWeight:600, display:'block', marginBottom:4 }}>Cooldown entre intentos (hs)</label>
            <input type="number" min="1" value={form.cooldownHours} onChange={e=>set('cooldownHours',+e.target.value)}
              style={{ width:'100%', padding:'8px 10px', borderRadius:8, border:'1px solid var(--border)', fontSize:13 }} />
            <div style={{ fontSize:11, color:'var(--ink-4)', marginTop:3 }}>Mínimo entre mensajes</div>
          </div>
        </div>

        {/* System prompt extra */}
        <div style={{ marginBottom:16 }}>
          <label style={{ fontSize:12, fontWeight:600, display:'block', marginBottom:4 }}>Instrucciones extra para Claude (opcional)</label>
          <textarea value={form.systemPromptExtra||''} onChange={e=>set('systemPromptExtra',e.target.value)} rows={2}
            placeholder='Ej: "Mencioná siempre el nombre del proyecto Oslo. Tono informal."'
            style={{ width:'100%', padding:'8px 10px', borderRadius:8, border:'1px solid var(--border)', fontSize:13, resize:'vertical', boxSizing:'border-box' }} />
        </div>

        {/* 24h fallback */}
        <div style={{ ...S.card, marginBottom:16 }}>
          <div style={{ fontSize:13, fontWeight:600, marginBottom:8 }}>📋 Fuera de la ventana de 24hs</div>
          <div style={{ fontSize:12, color:'var(--ink-3)', marginBottom:10 }}>
            Si el contacto no escribió en las últimas 24hs, WhatsApp solo permite enviar templates aprobados.
          </div>
          <label style={{ display:'flex', alignItems:'center', gap:8, fontSize:13, cursor:'pointer', marginBottom: form.useTemplate ? 12 : 0 }}>
            <input type="checkbox" checked={form.useTemplate||false} onChange={e=>set('useTemplate',e.target.checked)} />
            Usar template aprobado como fallback
          </label>
          {form.useTemplate && (
            <TemplateSelector
              value={form.templateId||''}
              varMapping={form.templateVarMapping||{}}
              onChange={v=>set('templateId',v)}
              onVarChange={(slot,v)=>set('templateVarMapping',{...form.templateVarMapping,[slot]:v})}
            />
          )}
        </div>

        {err && <div style={{ color:'var(--danger)', fontSize:13, marginBottom:12 }}>{err}</div>}
        <div style={{ display:'flex', gap:10 }}>
          <button onClick={save} disabled={saving} style={{ ...S.saveBtn }}>
            {saving ? 'Guardando…' : rule ? 'Guardar cambios' : 'Crear regla'}
          </button>
          <button onClick={onClose} style={{ ...S.outlineBtn }}>Cancelar</button>
        </div>
      </div>
    </div>
  );
}

function LearningPanel() {
  const [agents, setAgents]   = useState([]);
  const [agentId, setAgentId] = useState('');
  const [config, setConfig]   = useState({ enabled:false });
  const [suggestions, setSuggestions] = useState([]);
  const [learnings, setLearnings]     = useState([]);
  const [scanning, setScanning] = useState(false);
  const [edits, setEdits]       = useState({});  // id -> texto editado
  const [busy, setBusy]         = useState('');   // id en proceso
  const [msg, setMsg]           = useState('');

  // Cargar agentes (elige el primero por defecto)
  useEffect(() => {
    api.list().then(list => {
      const arr = Array.isArray(list) ? list : (list?.agents || []);
      setAgents(arr);
      if (arr.length && !agentId) setAgentId(arr[0].id);
    }).catch(() => {});
  }, []);

  const loadSuggestions = (aid) => apiFetch('/api/learning-suggestions?status=pending')
    .then(r=>r.json()).then(d => { setSuggestions(d.suggestions||[]); setConfig(d.config||{enabled:false}); }).catch(()=>{});
  const loadLearnings = (aid) => aid && apiFetch(`/api/learnings?agentId=${encodeURIComponent(aid)}`)
    .then(r=>r.json()).then(d => setLearnings(d.learnings||[])).catch(()=>{});

  useEffect(() => { if (agentId) { loadSuggestions(agentId); loadLearnings(agentId); } }, [agentId]);

  const toggleAuto = async () => {
    const next = !config.enabled;
    setConfig(c => ({ ...c, enabled: next }));
    await apiFetch('/api/learning-config', { method:'PUT', headers:{'Content-Type':'application/json'}, body: JSON.stringify({ enabled: next, agentId }) }).catch(()=>{});
  };

  const scan = async () => {
    if (!agentId) return;
    setScanning(true); setMsg('');
    try {
      const r = await apiFetch('/api/learning-suggestions/scan', { method:'POST', headers:{'Content-Type':'application/json'}, body: JSON.stringify({ agentId }) }).then(r=>r.json());
      if (r.error) setMsg('⚠️ ' + r.error);
      else { setMsg(`Escaneé ${r.scanned||0} conversaciones · ${r.found||0} sugerencia(s) nueva(s).`); loadSuggestions(agentId); }
    } catch { setMsg('⚠️ Error al escanear'); }
    setScanning(false);
  };

  const approve = async (s) => {
    setBusy(s.id);
    await apiFetch(`/api/learning-suggestions/${s.id}/approve`, { method:'POST', headers:{'Content-Type':'application/json'}, body: JSON.stringify({ answer: edits[s.id] }) }).catch(()=>{});
    setSuggestions(list => list.filter(x => x.id !== s.id));
    loadLearnings(agentId); setBusy('');
  };
  const reject = async (s) => {
    setBusy(s.id);
    await apiFetch(`/api/learning-suggestions/${s.id}/reject`, { method:'POST' }).catch(()=>{});
    setSuggestions(list => list.filter(x => x.id !== s.id)); setBusy('');
  };
  const delLearning = async (id) => {
    await apiFetch(`/api/learnings/${id}`, { method:'DELETE' }).catch(()=>{});
    setLearnings(list => list.filter(l => l.id !== id));
  };

  const catColor = (c) => ({
    objecion:'#f59e0b', precio:'#ef4444', faq:'#3b82f6', tono:'#a855f7', proceso:'#10b981', producto:'#06b6d4',
  }[c] || 'var(--ink-4)');
  const fmt = (iso) => { try { return new Date(iso).toLocaleString('es-AR', { day:'2-digit', month:'2-digit', hour:'2-digit', minute:'2-digit' }); } catch { return ''; } };

  return (
    <div style={{ ...S.editor }}>
      <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between', marginBottom:16, gap:12, flexWrap:'wrap' }}>
        <div>
          <div style={{ fontWeight:700, fontSize:20 }}>🧠 Aprendizaje</div>
          <div style={{ fontSize:13, color:'var(--ink-3)', marginTop:4, maxWidth:640 }}>
            El sistema lee cómo respondió el vendedor humano y propone aprendizajes. Vos los aprobás de a uno —
            lo aprobado se le suma al agente como corrección de máxima prioridad. Nunca aprende solo.
          </div>
        </div>
        <div style={{ display:'flex', gap:8, alignItems:'center', flexWrap:'wrap' }}>
          {agents.length > 1 && (
            <select value={agentId} onChange={e=>setAgentId(e.target.value)} style={{ padding:'8px 10px', borderRadius:10, border:'1px solid var(--border)', background:'var(--bg)', color:'var(--text)', fontSize:13 }}>
              {agents.map(a => <option key={a.id} value={a.id}>{a.name || a.id}</option>)}
            </select>
          )}
          <button onClick={scan} disabled={scanning || !agentId} style={{ padding:'8px 14px', borderRadius:10, border:'none', background:'var(--green)', color:'#fff', fontSize:13, cursor: scanning?'default':'pointer', fontWeight:600, opacity: scanning?0.7:1 }}>
            {scanning ? '⏳ Escaneando…' : '🔍 Escanear ahora'}
          </button>
        </div>
      </div>

      {/* Toggle aprendizaje automático */}
      <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between', gap:12, background:'var(--surface-2, var(--green-light))', border:'1px solid var(--border-soft)', borderRadius:12, padding:'12px 16px', marginBottom:18 }}>
        <div>
          <div style={{ fontWeight:600, fontSize:13.5 }}>Aprendizaje automático</div>
          <div style={{ fontSize:12, color:'var(--ink-3)', marginTop:2 }}>Cuando está activo, revisa las respuestas del humano cada 6 horas y junta nuevas sugerencias acá.</div>
        </div>
        <button onClick={toggleAuto} style={{ flexShrink:0, width:48, height:26, borderRadius:13, border:'none', cursor:'pointer', background: config.enabled ? 'var(--green)' : 'var(--border)', position:'relative', transition:'background .15s' }}>
          <span style={{ position:'absolute', top:3, left: config.enabled?25:3, width:20, height:20, borderRadius:'50%', background:'#fff', transition:'left .15s' }} />
        </button>
      </div>

      {msg && <div style={{ fontSize:12.5, color:'var(--ink-2)', marginBottom:14, background:'var(--border-soft)', padding:'8px 12px', borderRadius:8 }}>{msg}</div>}

      {/* Sugerencias pendientes */}
      <div style={{ fontWeight:700, fontSize:14, marginBottom:10 }}>Sugerencias para revisar {suggestions.length ? `(${suggestions.length})` : ''}</div>
      {suggestions.length === 0 && (
        <div style={{ fontSize:13, color:'var(--ink-3)', marginBottom:20, padding:'14px 0' }}>
          No hay sugerencias pendientes. Tocá <b>Escanear ahora</b> para revisar las últimas respuestas del vendedor.
        </div>
      )}
      {suggestions.map(s => (
        <div key={s.id} style={{ border:'1px solid var(--border-soft)', borderRadius:12, padding:14, marginBottom:12, background:'var(--bg)' }}>
          <div style={{ display:'flex', alignItems:'center', gap:8, marginBottom:8, flexWrap:'wrap' }}>
            <span style={{ fontSize:10.5, fontWeight:700, textTransform:'uppercase', letterSpacing:.5, color:'#fff', background:catColor(s.category), padding:'2px 8px', borderRadius:6 }}>{s.category}</span>
            {(() => { const g = !s.scope || String(s.scope).toLowerCase() === 'general'; return (
              <span title={g ? 'Aplica a todos los proyectos' : 'Específico de este proyecto — no se aplica a otros'} style={{ fontSize:10.5, fontWeight:700, color: g ? 'var(--ink-3)' : '#fff', background: g ? 'var(--border-soft)' : '#0ea5e9', border: g ? '1px solid var(--border)' : 'none', padding:'2px 8px', borderRadius:6 }}>{g ? '🌐 General' : `🏢 ${s.scope}`}</span>
            ); })()}
            {s.sourceContact && <span style={{ fontSize:11.5, color:'var(--ink-4)' }}>de {s.sourceContact}</span>}
            <span style={{ fontSize:11, color:'var(--ink-4)', marginLeft:'auto' }}>{fmt(s.ts)}</span>
          </div>
          {s.question && <div style={{ fontSize:12.5, color:'var(--ink-3)', marginBottom:8 }}><b>Situación:</b> {s.question}</div>}
          <div style={{ fontSize:12, color:'var(--ink-4)', marginBottom:4 }}>Aprendizaje (editable):</div>
          <textarea
            defaultValue={s.answer}
            onChange={e => setEdits(m => ({ ...m, [s.id]: e.target.value }))}
            style={{ width:'100%', minHeight:64, padding:'9px 11px', borderRadius:9, border:'1px solid var(--border)', background:'var(--bg)', color:'var(--text)', fontSize:13, lineHeight:1.5, resize:'vertical', boxSizing:'border-box', fontFamily:'inherit' }} />
          <div style={{ display:'flex', gap:8, marginTop:10 }}>
            <button onClick={()=>approve(s)} disabled={busy===s.id} style={{ padding:'7px 16px', borderRadius:9, border:'none', background:'var(--green)', color:'#fff', fontSize:12.5, cursor:'pointer', fontWeight:600 }}>✓ Aprobar</button>
            <button onClick={()=>reject(s)} disabled={busy===s.id} style={{ padding:'7px 16px', borderRadius:9, border:'1px solid var(--border)', background:'transparent', color:'var(--ink-2)', fontSize:12.5, cursor:'pointer' }}>✕ Descartar</button>
          </div>
        </div>
      ))}

      {/* Aprendizajes activos */}
      <div style={{ fontWeight:700, fontSize:14, margin:'24px 0 10px' }}>Lo que ya aprendió {learnings.length ? `(${learnings.length})` : ''}</div>
      {learnings.length === 0 && <div style={{ fontSize:13, color:'var(--ink-3)' }}>Todavía no hay aprendizajes aprobados para este agente.</div>}
      {learnings.map(l => (
        <div key={l.id} style={{ display:'flex', alignItems:'flex-start', gap:10, border:'1px solid var(--border-soft)', borderRadius:10, padding:'10px 12px', marginBottom:8, background:'var(--bg)' }}>
          <div style={{ flex:1, fontSize:13, color:'var(--ink-2)', lineHeight:1.45 }}>{l.correction}</div>
          <button onClick={()=>delLearning(l.id)} title="Quitar" style={{ flexShrink:0, padding:'4px 9px', borderRadius:7, border:'1px solid var(--border)', background:'transparent', color:'var(--danger)', fontSize:12, cursor:'pointer' }}>✕</button>
        </div>
      ))}
    </div>
  );
}

function AssignmentLogPanel() {
  const [data, setData] = useState(null);
  const [shareUrl, setShareUrl] = useState('');
  const [copied, setCopied] = useState(false);
  const load = () => apiFetch('/api/assignment-log').then(r=>r.json()).then(setData).catch(()=>setData({ log:[], counts:{}, names:{} }));
  useEffect(() => { load(); }, []);

  const getShareLink = () => apiFetch('/api/logs/share-link').then(r=>r.json()).then(d => {
    if (!d.url) return;
    setShareUrl(d.url);
    if (navigator.clipboard) navigator.clipboard.writeText(d.url).then(() => { setCopied(true); setTimeout(() => setCopied(false), 2500); }).catch(()=>{});
  }).catch(()=>{});

  if (!data) return <div style={{ ...S.editor }}>Cargando…</div>;

  const nameOf = (id) => (data.names && data.names[id]) || id || '—';

  // Reparto SEPARADO calculado desde el LOG real: conversaciones nuevas (asignación
  // inicial, motor conv-rules) vs reasignaciones por timeout (op-timeout).
  const distFor = (kind) => {
    const d = {};
    (data.log || []).forEach(e => {
      if (!e.picked) return;
      const isReassign = e.engine === 'op-timeout';
      if (kind === 'new' && isReassign) return;
      if (kind === 'reassign' && !isReassign) return;
      d[e.picked] = (d[e.picked] || 0) + 1;
    });
    const rows = Object.entries(d).sort((a, b) => b[1] - a[1]);
    return { rows, max: rows.length ? rows[0][1] : 0, total: rows.reduce((s, [, n]) => s + n, 0) };
  };
  const nuevas = distFor('new');
  const reasig = distFor('reassign');
  const renderBars = (dd) => dd.rows.length === 0
    ? <div style={{ fontSize:13, color:'var(--ink-3)', marginBottom:16 }}>Sin datos todavía.</div>
    : dd.rows.map(([op, n]) => (
        <div key={op} style={{ display:'flex', alignItems:'center', gap:10, marginBottom:7 }}>
          <div style={{ width:160, fontSize:13, color:'var(--ink-2)', overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap' }}>{nameOf(op)}</div>
          <div style={{ flex:1, background:'var(--border-soft)', borderRadius:6, height:18, overflow:'hidden' }}>
            <div style={{ width:(dd.max ? Math.round(n/dd.max*100) : 0)+'%', background:'var(--green)', height:'100%' }} />
          </div>
          <div style={{ width:90, textAlign:'right', fontSize:12.5, color:'var(--ink-2)' }}>{n} ({dd.total ? Math.round(n/dd.total*100) : 0}%)</div>
        </div>
      ));

  const fmt = (iso) => { try { return new Date(iso).toLocaleString('es-AR', { day:'2-digit', month:'2-digit', hour:'2-digit', minute:'2-digit' }); } catch { return iso; } };
  const th = { textAlign:'left', fontSize:11, fontWeight:700, color:'var(--ink-4)', textTransform:'uppercase', letterSpacing:.5, padding:'6px 10px' };
  const td = { fontSize:12.5, color:'var(--ink-2)', padding:'7px 10px', borderTop:'1px solid var(--border-soft)' };

  return (
    <div style={{ ...S.editor }}>
      <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between', marginBottom:20, gap:12, flexWrap:'wrap' }}>
        <div>
          <div style={{ fontWeight:700, fontSize:20 }}>🎯 Logs de asignación</div>
          <div style={{ fontSize:13, color:'var(--ink-3)', marginTop:4, maxWidth:600 }}>Reparto equitativo por conteo (elige siempre al operador online con menos asignaciones). Las conversaciones NUEVAS y las reasignaciones por timeout se reparten por separado.</div>
        </div>
        <div style={{ display:'flex', gap:8, alignItems:'center' }}>
          <button onClick={getShareLink} style={{ padding:'8px 14px', borderRadius:10, border:'none', background:'var(--green)', color:'#fff', fontSize:13, cursor:'pointer', fontWeight:600 }}>🔗 {copied ? '¡Copiado!' : 'Compartir link en vivo'}</button>
          <button onClick={load} style={{ padding:'8px 14px', borderRadius:10, border:'1px solid var(--border)', background:'transparent', color:'var(--text)', fontSize:13, cursor:'pointer' }}>↻ Actualizar</button>
        </div>
      </div>
      {shareUrl && (
        <div style={{ display:'flex', alignItems:'center', gap:10, background:'var(--green-light)', border:'1px solid var(--green-mid)', borderRadius:10, padding:'10px 14px', marginBottom:18, flexWrap:'wrap' }}>
          <span style={{ fontSize:12.5, color:'var(--green-hover)', fontWeight:600 }}>Link de solo lectura (en vivo) para tu cliente:</span>
          <a href={shareUrl} target="_blank" style={{ fontSize:12.5, color:'var(--green)', wordBreak:'break-all' }}>{shareUrl}</a>
          <span style={{ fontSize:11.5, color:'var(--ink-4)' }}>— muestra solo este log, no el agente.</span>
        </div>
      )}

      <div style={{ fontWeight:700, fontSize:14, marginBottom:10 }}>🆕 Conversaciones nuevas {nuevas.total ? `(${nuevas.total})` : ''}</div>
      {renderBars(nuevas)}

      <div style={{ fontWeight:700, fontSize:14, margin:'22px 0 10px' }}>⏱️ Reasignaciones por timeout {reasig.total ? `(${reasig.total})` : ''}</div>
      {renderBars(reasig)}

      <div style={{ fontWeight:700, fontSize:14, margin:'24px 0 10px' }}>Últimas asignaciones</div>
      <div style={{ overflowX:'auto' }}>
        <table style={{ borderCollapse:'collapse', width:'100%', minWidth:620 }}>
          <thead><tr>
            <th style={th}>Fecha</th><th style={th}>Motor</th><th style={th}>Regla</th><th style={th}>Operador</th><th style={th}>Online</th><th style={th}>Método</th>
          </tr></thead>
          <tbody>
            {(data.log || []).map((e, i) => (
              <tr key={i}>
                <td style={td}>{fmt(e.at)}</td>
                <td style={td}>{e.engine === 'op-timeout' ? '⏱️ reasignación' : '⚡ asignación'}</td>
                <td style={td}>{e.rule}</td>
                <td style={{ ...td, fontWeight:600, color: e.picked ? 'var(--ink)' : 'var(--danger)' }}>{e.picked ? nameOf(e.picked) : 'sin elegible'}</td>
                <td style={td}>{e.online}/{e.candidates}</td>
                <td style={td}>{e.method}</td>
              </tr>
            ))}
            {(!data.log || data.log.length === 0) && <tr><td style={td} colSpan={6}>Sin registros todavía.</td></tr>}
          </tbody>
        </table>
      </div>
    </div>
  );
}

function ContextualTagsPanel() {
  const { tags } = usePipochat();
  const [cfg, setCfg]       = useState(null);
  const [saving, setSaving] = useState(false);
  const [saved, setSaved]   = useState(false);

  useEffect(() => {
    apiFetch('/api/contextual-tags').then(r=>r.json()).then(d=>setCfg({ enabled: !!d.enabled, tags: Array.isArray(d.tags)?d.tags:[] })).catch(()=>setCfg({ enabled:false, tags:[] }));
  }, []);

  const inp = { padding:'8px 10px', borderRadius:8, border:'1px solid var(--border)', background:'var(--bg)', color:'var(--text)', fontSize:13, width:'100%', boxSizing:'border-box' };
  const lbl = { fontSize:12, color:'var(--ink-3)', display:'block', marginBottom:4 };

  if (!cfg) return <div style={{ ...S.editor }}>Cargando…</div>;

  const upd    = (patch)    => setCfg(c => ({ ...c, ...patch }));
  const updTag = (i, patch) => setCfg(c => ({ ...c, tags: c.tags.map((t,j)=>j===i?{...t,...patch}:t) }));
  const addTag = ()         => setCfg(c => ({ ...c, tags: [...(c.tags||[]), { name:'', tagId:'', description:'' }] }));
  const delTag = (i)        => setCfg(c => ({ ...c, tags: c.tags.filter((_,j)=>j!==i) }));

  const save = async () => {
    setSaving(true); setSaved(false);
    try {
      const r = await apiFetch('/api/contextual-tags', { method:'PUT', headers:{'Content-Type':'application/json'}, body: JSON.stringify(cfg) });
      const out = await r.json();
      setCfg({ enabled: !!out.enabled, tags: Array.isArray(out.tags)?out.tags:[] });
      setSaved(true); setTimeout(()=>setSaved(false), 2500);
    } catch(e) { alert('Error al guardar: '+e.message); }
    finally { setSaving(false); }
  };

  return (
    <div style={{ ...S.editor }}>
      <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between', marginBottom:20, gap:12, flexWrap:'wrap' }}>
        <div>
          <div style={{ fontWeight:700, fontSize:20 }}>🏷️ Etiquetado contextual (IA)</div>
          <div style={{ fontSize:13, color:'var(--ink-3)', marginTop:4, maxWidth:560 }}>La IA lee cada conversación y aplica estas etiquetas al contacto cuando detecta la señal — incluso cuando la atiende un operador. Sirve para que el equipo identifique al lead y para segmentar el seguimiento.</div>
        </div>
        <button onClick={save} disabled={saving} style={{ padding:'9px 18px', borderRadius:10, border:'none', background:'var(--green)', color:'#fff', fontWeight:600, fontSize:14, cursor:'pointer', whiteSpace:'nowrap' }}>
          {saving ? 'Guardando…' : saved ? '✓ Guardado' : 'Guardar cambios'}
        </button>
      </div>

      <label style={{ display:'flex', alignItems:'center', gap:10, marginBottom:20, cursor:'pointer' }}>
        <input type="checkbox" checked={!!cfg.enabled} onChange={e=>upd({ enabled: e.target.checked })} />
        <span style={{ fontWeight:600 }}>Activar etiquetado contextual</span>
      </label>

      {(cfg.tags||[]).length === 0 && (
        <div style={{ fontSize:13, color:'var(--ink-3)', padding:'16px 0' }}>Todavía no hay etiquetas configuradas. Agregá una abajo.</div>
      )}

      {(cfg.tags||[]).map((t, i) => (
        <div key={i} style={{ border:'1px solid var(--border)', borderRadius:12, padding:16, marginBottom:14, background:'var(--surface)' }}>
          <div style={{ display:'flex', gap:12, alignItems:'flex-end', flexWrap:'wrap' }}>
            <div style={{ flex:'1 1 220px' }}>
              <span style={lbl}>Etiqueta a aplicar</span>
              <select style={inp} value={t.tagId||''} onChange={e=>{ const tg=(tags||[]).find(x=>x._id===e.target.value); updTag(i, { tagId:e.target.value, name: tg ? tg.name : t.name }); }}>
                <option value="">— Elegí una etiqueta —</option>
                {(tags||[]).map(tg => <option key={tg._id} value={tg._id}>{tg.name}</option>)}
              </select>
            </div>
            <button onClick={()=>delTag(i)} style={{ padding:'8px 14px', borderRadius:8, border:'1px solid var(--border)', background:'transparent', color:'var(--danger)', fontSize:13, cursor:'pointer' }}>Eliminar</button>
          </div>
          <div style={{ marginTop:12 }}>
            <span style={lbl}>¿Cuándo aplicarla? (describilo natural — la IA lo usa para decidir)</span>
            <textarea style={{ ...inp, minHeight:62, resize:'vertical' }} value={t.description||''} onChange={e=>updTag(i, { description: e.target.value })} placeholder="Ej: El cliente pide coordinar una visita o ir a ver una propiedad en persona." />
          </div>
        </div>
      ))}

      <button onClick={addTag} style={{ padding:'9px 16px', borderRadius:10, border:'1px dashed var(--border)', background:'transparent', color:'var(--text)', fontSize:13, cursor:'pointer', marginTop:4 }}>+ Agregar etiqueta</button>
    </div>
  );
}

function ProactivePanel() {
  const [rules,     setRules]     = useState(null);
  const [showModal, setShowModal] = useState(false);
  const [editing,   setEditing]   = useState(null);
  const [testing,   setTesting]   = useState(false);
  const [testRes,   setTestRes]   = useState(null);

  const load = () => apiFetch('/api/proactive-rules').then(r=>r.json()).then(setRules).catch(()=>setRules([]));
  useEffect(()=>{ load(); }, []);

  const handleSave = (rule) => {
    setRules(prev => {
      if (!prev) return [rule];
      const idx = prev.findIndex(r=>r.id===rule.id);
      return idx>=0 ? prev.map((r,i)=>i===idx?rule:r) : [...prev, rule];
    });
    setShowModal(false); setEditing(null);
  };

  const del = async (id) => {
    if (!confirm('¿Eliminar esta regla?')) return;
    await apiFetch(`/api/proactive-rules/${id}`, { method:'DELETE' });
    setRules(prev=>prev.filter(r=>r.id!==id));
  };

  const toggle = async (rule) => {
    const updated = { ...rule, enabled: !rule.enabled };
    await apiFetch(`/api/proactive-rules/${rule.id}`, { method:'PUT', headers:{'Content-Type':'application/json'}, body:JSON.stringify(updated) });
    setRules(prev=>prev.map(r=>r.id===rule.id?updated:r));
  };

  const testNow = async () => {
    setTesting(true); setTestRes(null);
    try {
      const r = await apiFetch('/api/proactive-rules/test-now', { method:'POST' });
      setTestRes(await r.json());
    } catch(e) { setTestRes({ error: e.message }); }
    finally { setTesting(false); }
  };

  const silenceLabel = (r) => `${r.silenceValue} ${r.silenceUnit === 'hours' ? 'hs' : r.silenceUnit === 'days' ? (r.silenceValue===1?'día':'días') : 'min'}`;

  return (
    <div style={{ ...S.editor }}>
      <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between', marginBottom:24 }}>
        <div>
          <div style={{ fontWeight:700, fontSize:20 }}>🤖 Agente Proactivo</div>
          <div style={{ fontSize:13, color:'var(--ink-3)', marginTop:4 }}>Claude detecta leads silenciosos y les escribe un mensaje personalizado</div>
        </div>
        <div style={{ display:'flex', gap:8 }}>
          <button onClick={testNow} disabled={testing} style={{ ...S.outlineBtn, fontSize:13 }}>
            {testing ? '⏳ Verificando…' : '▶ Probar ahora'}
          </button>
          <button onClick={()=>{ setEditing(null); setShowModal(true); }} style={{ ...S.saveBtn, fontSize:13 }}>
            + Nueva regla
          </button>
        </div>
      </div>

      {/* How it works */}
      <div style={{ ...S.card, background:'#f0fdf4', border:'1px solid #86efac', marginBottom:20, fontSize:13 }}>
        <div style={{ fontWeight:600, marginBottom:8 }}>¿Cómo funciona?</div>
        <div style={{ color:'var(--ink-2)', lineHeight:1.7 }}>
          Cada 10 minutos el agente revisa las conversaciones abiertas donde <strong>el bot mandó el último mensaje</strong> y el contacto no respondió en el tiempo configurado.<br/>
          Claude lee el historial de la conversación y genera un <strong>mensaje de seguimiento personalizado</strong> — no un template genérico.<br/>
          Si la ventana de 24hs está cerrada, usa el template aprobado como fallback.
        </div>
      </div>

      {testRes && (
        <div style={{ ...S.card, marginBottom:16,
          background: testRes.error ? 'var(--danger-light)' : '#f0fdf4',
          borderColor: testRes.error ? 'var(--danger)' : '#86efac', fontSize:13 }}>
          {testRes.error
            ? `❌ ${testRes.error}`
            : `✅ ${testRes.sent} mensaje${testRes.sent!==1?'s':''} enviado${testRes.sent!==1?'s':''} · ${testRes.skipped} conversación${testRes.skipped!==1?'es':''} salteada${testRes.skipped!==1?'s':''}${testRes.errors?.length>0?` · ⚠ ${testRes.errors[0]}`:''}`
          }
        </div>
      )}

      {!rules && <div style={{ color:'var(--ink-3)', fontSize:13 }}>Cargando…</div>}

      {rules && rules.length === 0 && (
        <div style={{ ...S.card, textAlign:'center', padding:40, color:'var(--ink-3)' }}>
          <div style={{ fontSize:32, marginBottom:12 }}>🤖</div>
          <strong>Sin reglas configuradas</strong><br/>
          <span style={{ fontSize:13 }}>Creá una para que Claude empiece a hacer seguimiento automático</span>
        </div>
      )}

      {rules && rules.map(rule => (
        <div key={rule.id} style={{ ...S.card, marginBottom:12, opacity: rule.enabled ? 1 : 0.6 }}>
          <div style={{ display:'flex', alignItems:'flex-start', justifyContent:'space-between', gap:12 }}>
            <div style={{ flex:1 }}>
              <div style={{ display:'flex', alignItems:'center', gap:8, marginBottom:6 }}>
                <span style={{ fontWeight:600, fontSize:15 }}>{rule.name}</span>
                <span style={{ fontSize:11, padding:'2px 8px', borderRadius:20,
                  background: rule.enabled ? '#dcfce7' : '#f3f4f6',
                  color: rule.enabled ? '#16a34a' : '#6b7280' }}>
                  {rule.enabled ? 'Activa' : 'Pausada'}
                </span>
              </div>
              <div style={{ fontSize:12, color:'var(--ink-3)', display:'flex', flexWrap:'wrap', gap:12 }}>
                <span>⏱️ Silencio &gt; {silenceLabel(rule)}</span>
                <span>🔁 Máx {rule.maxAttempts} intento{rule.maxAttempts!==1?'s':''} · cada {rule.cooldownHours}hs</span>
                {rule.pipelineName && <span>📌 {rule.pipelineName}{rule.stageName ? ` › ${rule.stageName}` : ''}</span>}
                {rule.useTemplate && rule.templateId && <span>📋 Template fallback activo</span>}
              </div>
              {rule.systemPromptExtra && (
                <div style={{ fontSize:12, color:'var(--ink-4)', marginTop:4, fontStyle:'italic' }}>
                  "{rule.systemPromptExtra}"
                </div>
              )}
            </div>
            <div style={{ display:'flex', gap:6, flexShrink:0 }}>
              <button onClick={()=>toggle(rule)} style={{ ...S.outlineBtn, fontSize:12, padding:'4px 10px' }}>
                {rule.enabled ? '⏸ Pausar' : '▶ Activar'}
              </button>
              <button onClick={()=>{ setEditing(rule); setShowModal(true); }} style={{ ...S.outlineBtn, fontSize:12, padding:'4px 10px' }}>
                ✏️ Editar
              </button>
              <button onClick={()=>del(rule.id)} style={{ fontSize:12, padding:'4px 10px', background:'var(--danger-light)', color:'var(--danger)', border:'none', borderRadius:8, cursor:'pointer' }}>
                🗑
              </button>
            </div>
          </div>
        </div>
      ))}

      {showModal && (
        <ProactiveModal rule={editing} onClose={()=>{ setShowModal(false); setEditing(null); }} onSaved={handleSave} />
      )}
    </div>
  );
}

// ─── WhatsApp Reminders ────────────────────────────────────────────────────────

const REMINDER_DEFAULTS = {
  name: 'Recordatorio reunión',
  enabled: true,
  offsetValue: 24,
  offsetUnit: 'hours',
  sources: ['booking', 'activity'],
  activityTypes: [],
  sendToContact: true,
  sendToAgent: false,
  agentPhone: '',
  messageTemplate: 'Hola {name}, te recordamos tu reunión "{title}" el {date} a las {time}. ¡Te esperamos! 🗓️',
};

function TemplateSelector({ value, varMapping, onChange, onVarChange }) {
  const [templates, setTemplates] = useState(null);
  const [selected,  setSelected]  = useState(null);

  useEffect(() => {
    apiFetch('/api/pipochat/templates').then(r=>r.json()).then(d => {
      const rows = Array.isArray(d) ? d : (Array.isArray(d.templates) ? d.templates : []);
      setTemplates(rows);
      if (value) setSelected(rows.find(t=>t._id===value) || null);
    }).catch(()=>setTemplates([]));
  }, []);

  const pick = (t) => {
    setSelected(t);
    onChange(t?._id || '');
  };

  // Extract {{N}} variables from template body
  const extractVars = (tpl) => {
    if (!tpl) return [];
    try {
      const body = (typeof tpl.body === 'string' ? tpl.body : '')
        || (tpl.components?.find(c=>c.type==='BODY')?.text || '')
        || (typeof tpl.content === 'string' ? tpl.content : '')
        || '';
      const matches = [...body.matchAll(/\{\{(\d+)\}\}/g)];
      return [...new Set(matches.map(m=>m[1]))].sort();
    } catch(e) { return []; }
  };

  const VAR_OPTIONS = ['{name}','{date}','{time}','{title}','(texto fijo)'];

  if (!templates) return <div style={{fontSize:12,color:'var(--ink-3)'}}>Cargando templates…</div>;
  if (templates.length === 0) return <div style={{fontSize:12,color:'var(--danger)'}}>No hay templates aprobados en tu cuenta</div>;

  const vars = extractVars(selected);
  const bodyText = selected ? (selected.body || selected.components?.find(c=>c.type==='BODY')?.text || selected.content || '') : '';

  return (
    <div>
      <select value={value||''} onChange={e=>pick(templates.find(t=>t._id===e.target.value)||null)}
        style={{width:'100%',padding:'8px 10px',borderRadius:8,border:'1px solid var(--border)',fontSize:13,marginBottom:8,boxSizing:'border-box'}}>
        <option value=''>— Seleccioná un template —</option>
        {templates.map(t=><option key={t._id} value={t._id}>{t.name || t.title || t._id} {t.status ? `(${t.status})` : ''}</option>)}
      </select>
      {bodyText && <div style={{fontSize:12,background:'var(--bg)',border:'1px solid var(--border)',borderRadius:8,padding:'8px 10px',marginBottom:8,color:'var(--ink-2)',whiteSpace:'pre-wrap'}}>{bodyText}</div>}
      {vars.length > 0 && (
        <div style={{marginTop:4}}>
          <div style={{fontSize:12,fontWeight:600,marginBottom:6}}>Mapeo de variables</div>
          {vars.map(slot=>(
            <div key={slot} style={{display:'flex',alignItems:'center',gap:8,marginBottom:6}}>
              <span style={{fontSize:13,fontFamily:'monospace',background:'var(--bg)',padding:'2px 8px',borderRadius:6,border:'1px solid var(--border)',minWidth:32,textAlign:'center'}}>{'{{'+slot+'}}'}</span>
              <select value={varMapping?.[slot]||''} onChange={e=>onVarChange(slot,e.target.value)}
                style={{padding:'6px 8px',borderRadius:6,border:'1px solid var(--border)',fontSize:13,flex:1}}>
                <option value=''>— elegir —</option>
                {VAR_OPTIONS.map(v=><option key={v} value={v}>{v}</option>)}
              </select>
            </div>
          ))}
        </div>
      )}
    </div>
  );
}

function ReminderModal({ rule, onClose, onSaved }) {
  const [form, setForm] = useState(rule ? { ...rule } : { ...REMINDER_DEFAULTS });
  const [saving, setSaving] = useState(false);
  const [err, setErr] = useState('');
  const set = (k, v) => setForm(f => ({ ...f, [k]: v }));
  const toggleSource = (s) => set('sources', form.sources.includes(s) ? form.sources.filter(x=>x!==s) : [...form.sources, s]);

  const save = async () => {
    if (!form.name.trim()) return setErr('El nombre es requerido');
    if (!form.messageTemplate.trim()) return setErr('El mensaje es requerido');
    if (form.sendToAgent && !form.agentPhone.trim()) return setErr('Ingresá el teléfono del agente');
    setSaving(true); setErr('');
    try {
      const url    = rule ? `/api/reminders/${rule.id}` : '/api/reminders';
      const method = rule ? 'PUT' : 'POST';
      const res = await apiFetch(url, { method, headers: {'Content-Type':'application/json'}, body: JSON.stringify(form) });
      const data = await res.json();
      if (data.error) { setErr(data.error); setSaving(false); return; }
      onSaved(data);
    } catch (e) { setErr(e.message); setSaving(false); }
  };

  return (
    <div style={{ position:'fixed', inset:0, background:'rgba(0,0,0,.45)', display:'flex', alignItems:'center', justifyContent:'center', zIndex:1000 }}>
      <div style={{ background:'var(--surface)', borderRadius:16, padding:28, width:520, maxHeight:'90vh', overflowY:'auto', boxShadow:'0 20px 60px rgba(0,0,0,.25)' }}>
        <div style={{ fontWeight:700, fontSize:17, marginBottom:20 }}>{rule ? 'Editar recordatorio' : 'Nuevo recordatorio'}</div>

        <label style={{ fontSize:13, fontWeight:600, display:'block', marginBottom:4 }}>Nombre</label>
        <input value={form.name} onChange={e=>set('name',e.target.value)}
          style={{ width:'100%', padding:'8px 10px', borderRadius:8, border:'1px solid var(--border)', fontSize:13, marginBottom:14, boxSizing:'border-box' }} />

        <div style={{ display:'flex', gap:10, marginBottom:14 }}>
          <div style={{ flex:1 }}>
            <label style={{ fontSize:13, fontWeight:600, display:'block', marginBottom:4 }}>Tiempo antes</label>
            <input type="number" min={1} value={form.offsetValue} onChange={e=>set('offsetValue', parseInt(e.target.value)||1)}
              style={{ width:'100%', padding:'8px 10px', borderRadius:8, border:'1px solid var(--border)', fontSize:13, boxSizing:'border-box' }} />
          </div>
          <div style={{ flex:1 }}>
            <label style={{ fontSize:13, fontWeight:600, display:'block', marginBottom:4 }}>Unidad</label>
            <select value={form.offsetUnit} onChange={e=>set('offsetUnit',e.target.value)}
              style={{ width:'100%', padding:'8px 10px', borderRadius:8, border:'1px solid var(--border)', fontSize:13, boxSizing:'border-box' }}>
              <option value="hours">Horas</option>
              <option value="days">Días</option>
            </select>
          </div>
        </div>

        <label style={{ fontSize:13, fontWeight:600, display:'block', marginBottom:6 }}>Origen de eventos</label>
        <div style={{ display:'flex', gap:10, marginBottom:14 }}>
          {[['booking','📅 Booking (Meeting Scheduler)'],['activity','🤝 Actividad CRM']].map(([s,label])=>(
            <label key={s} style={{ display:'flex', alignItems:'center', gap:6, fontSize:13, cursor:'pointer',
              background: form.sources.includes(s) ? 'var(--accent-light)' : 'var(--bg)', border:'1px solid var(--border)',
              borderRadius:8, padding:'6px 12px', userSelect:'none' }}>
              <input type="checkbox" checked={form.sources.includes(s)} onChange={()=>toggleSource(s)} style={{ margin:0 }} />
              {label}
            </label>
          ))}
        </div>

        {form.sources.includes('activity') && (
          <>
            <label style={{ fontSize:13, fontWeight:600, display:'block', marginBottom:4 }}>Tipos de actividad (vacío = todos)</label>
            <input value={form.activityTypes.join(', ')} placeholder="Meeting, Call, ..."
              onChange={e=>set('activityTypes', e.target.value.split(',').map(s=>s.trim()).filter(Boolean))}
              style={{ width:'100%', padding:'8px 10px', borderRadius:8, border:'1px solid var(--border)', fontSize:13, marginBottom:14, boxSizing:'border-box' }} />
          </>
        )}

        <label style={{ fontSize:13, fontWeight:600, display:'block', marginBottom:6 }}>Enviar a</label>
        <div style={{ display:'flex', flexDirection:'column', gap:8, marginBottom:14 }}>
          <label style={{ display:'flex', alignItems:'center', gap:8, fontSize:13, cursor:'pointer' }}>
            <input type="checkbox" checked={form.sendToContact} onChange={e=>set('sendToContact',e.target.checked)} />
            Contacto del lead (WhatsApp del interesado)
          </label>
          <label style={{ display:'flex', alignItems:'center', gap:8, fontSize:13, cursor:'pointer' }}>
            <input type="checkbox" checked={form.sendToAgent} onChange={e=>set('sendToAgent',e.target.checked)} />
            Agente / número fijo
          </label>
          {form.sendToAgent && (
            <input value={form.agentPhone} onChange={e=>set('agentPhone',e.target.value)}
              placeholder="Ej: 5491112345678"
              style={{ padding:'8px 10px', borderRadius:8, border:'1px solid var(--border)', fontSize:13, marginLeft:24 }} />
          )}
        </div>

        <label style={{ fontSize:13, fontWeight:600, display:'block', marginBottom:6 }}>Tipo de mensaje</label>
        <div style={{ display:'flex', gap:10, marginBottom:12 }}>
          {[['false','✍️ Texto libre (solo 24hs)'],['true','📋 Template aprobado (siempre)']].map(([val,label])=>(
            <label key={val} style={{ display:'flex', alignItems:'center', gap:6, fontSize:13, cursor:'pointer',
              background: String(!!form.useTemplate)===val ? 'var(--accent-light)' : 'var(--bg)',
              border:'1px solid var(--border)', borderRadius:8, padding:'6px 12px', userSelect:'none', flex:1 }}>
              <input type="radio" checked={String(!!form.useTemplate)===val}
                onChange={()=>set('useTemplate', val==='true')} style={{margin:0}} />
              {label}
            </label>
          ))}
        </div>

        {form.useTemplate ? (
          <TemplateSelector
            value={form.templateId||''}
            varMapping={form.templateVarMapping||{}}
            onChange={v=>set('templateId',v)}
            onVarChange={(slot,v)=>set('templateVarMapping',{...form.templateVarMapping,[slot]:v})}
          />
        ) : (
          <>
            <label style={{ fontSize:13, fontWeight:600, display:'block', marginBottom:4 }}>Mensaje</label>
            <div style={{ fontSize:11, color:'var(--ink-3)', marginBottom:6 }}>
              Variables: <code>{'{name}'}</code> <code>{'{date}'}</code> <code>{'{time}'}</code> <code>{'{title}'}</code>
            </div>
            <textarea value={form.messageTemplate} onChange={e=>set('messageTemplate',e.target.value)} rows={4}
              style={{ width:'100%', padding:'8px 10px', borderRadius:8, border:'1px solid var(--border)', fontSize:13, resize:'vertical', boxSizing:'border-box' }} />
          </>
        )}

        {err && <div style={{ color:'var(--danger)', fontSize:13, marginBottom:12 }}>❌ {err}</div>}

        <div style={{ display:'flex', gap:10, justifyContent:'flex-end' }}>
          <button onClick={onClose} style={{ ...S.outlineBtn }}>Cancelar</button>
          <button onClick={save} disabled={saving} style={{ ...S.saveBtn }}>
            {saving ? 'Guardando…' : (rule ? 'Guardar cambios' : 'Crear recordatorio')}
          </button>
        </div>
      </div>
    </div>
  );
}

function RemindersPanel() {
  const [rules,    setRules]    = useState(null);
  const [showModal,setShowModal]= useState(false);
  const [editing,  setEditing]  = useState(null);
  const [testing,  setTesting]  = useState(false);
  const [testRes,  setTestRes]  = useState(null);

  // Booking confirmation state
  const [confirm,    setConfirm]    = useState(null);
  const [savingConf, setSavingConf] = useState(false);
  const [confMsg,    setConfMsg]    = useState('');
  const [testingConf,setTestingConf]= useState(false);
  const [testConfRes,setTestConfRes]= useState(null);

  const loadConfirm = () => apiFetch('/api/reminders/booking-confirmation').then(r=>r.json()).then(setConfirm).catch(()=>{});

  const saveConfirm = async () => {
    setSavingConf(true); setConfMsg('');
    try {
      const res = await apiFetch('/api/reminders/booking-confirmation', {
        method:'PUT', headers:{'Content-Type':'application/json'}, body: JSON.stringify(confirm),
      });
      const d = await res.json();
      setConfirm(d); setConfMsg('✓ Guardado');
    } catch { setConfMsg('❌ Error'); }
    setSavingConf(false);
    setTimeout(()=>setConfMsg(''), 3000);
  };

  const testConfirmNow = async () => {
    setTestingConf(true); setTestConfRes(null);
    try {
      const r = await apiFetch('/api/reminders/booking-confirmation/test-now', { method:'POST' });
      setTestConfRes(await r.json());
    } catch(e) { setTestConfRes({ error: e.message }); }
    finally { setTestingConf(false); }
  };

  const load = () => apiFetch('/api/reminders').then(r=>r.json()).then(setRules).catch(()=>setRules([]));
  useEffect(()=>{ load(); loadConfirm(); },[]);

  const handleSave = (rule) => {
    setRules(prev => {
      if (!prev) return [rule];
      const idx = prev.findIndex(r=>r.id===rule.id);
      return idx>=0 ? prev.map((r,i)=>i===idx?rule:r) : [...prev, rule];
    });
    setShowModal(false); setEditing(null);
  };

  const del = async (id) => {
    if (!confirm('¿Eliminar este recordatorio?')) return;
    await apiFetch(`/api/reminders/${id}`, { method:'DELETE' });
    setRules(prev=>prev.filter(r=>r.id!==id));
  };

  const toggle = async (rule) => {
    const updated = { ...rule, enabled: !rule.enabled };
    await apiFetch(`/api/reminders/${rule.id}`, { method:'PUT', headers:{'Content-Type':'application/json'}, body:JSON.stringify(updated) });
    setRules(prev=>prev.map(r=>r.id===rule.id?updated:r));
  };

  const testNow = async () => {
    setTesting(true); setTestRes(null);
    try {
      const r = await apiFetch('/api/reminders/test-now', { method:'POST' });
      const d = await r.json();
      setTestRes(d);
    } catch(e) { setTestRes({ error: e.message }); }
    finally { setTesting(false); }
  };

  const offsetLabel = (r) => `${r.offsetValue} ${r.offsetUnit === 'hours' ? (r.offsetValue===1?'hora':'horas') : (r.offsetValue===1?'día':'días')} antes`;

  return (
    <div style={{ ...S.editor }}>
      <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between', marginBottom:24 }}>
        <div>
          <div style={{ fontWeight:700, fontSize:20 }}>🔔 Recordatorios WhatsApp</div>
          <div style={{ fontSize:13, color:'var(--ink-3)', marginTop:4 }}>Enviá mensajes automáticos antes de reuniones o actividades agendadas</div>
        </div>
        <div style={{ display:'flex', gap:8 }}>
          <button onClick={testNow} disabled={testing} style={{ ...S.outlineBtn, fontSize:13 }}>
            {testing ? '⏳ Verificando…' : '▶ Probar ahora'}
          </button>
          <button onClick={()=>{ setEditing(null); setShowModal(true); }} style={{ ...S.saveBtn, fontSize:13 }}>
            + Nuevo recordatorio
          </button>
        </div>
      </div>

      {testRes && (
        <div style={{ ...S.card, marginBottom:16, background: testRes.error ? 'var(--danger-light)' : '#f0fdf4',
          borderColor: testRes.error ? 'var(--danger)' : '#86efac', fontSize:13 }}>
          {testRes.error
            ? `❌ ${testRes.error}`
            : `✅ ${testRes.sent} recordatorio${testRes.sent!==1?'s':''} enviado${testRes.sent!==1?'s':''}${testRes.errors?.length>0 ? ` · ⚠ ${testRes.errors[0]}` : ''}`
          }
        </div>
      )}

      {/* Booking Confirmation Card */}
      {confirm && (
        <div style={{ ...S.card, marginBottom:20 }}>
          <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between', marginBottom:14 }}>
            <div>
              <div style={{ fontWeight:700, fontSize:15 }}>✅ Confirmación de booking</div>
              <div style={{ fontSize:12, color:'var(--ink-3)', marginTop:2 }}>Se envía automáticamente cuando alguien agenda por el Meeting Scheduler</div>
            </div>
            <div style={{ display:'flex', alignItems:'center', gap:8 }}>
              <label style={{ display:'flex', alignItems:'center', gap:6, fontSize:13, cursor:'pointer' }}>
                <input type="checkbox" checked={confirm.enabled} onChange={e=>setConfirm(c=>({...c,enabled:e.target.checked}))} />
                Activo
              </label>
            </div>
          </div>

          <label style={{ fontSize:13, fontWeight:600, display:'block', marginBottom:6 }}>Tipo de mensaje</label>
          <div style={{ display:'flex', gap:10, marginBottom:12 }}>
            {[['false','✍️ Texto libre (solo 24hs)'],['true','📋 Template aprobado (siempre)']].map(([val,label])=>(
              <label key={val} style={{ display:'flex', alignItems:'center', gap:6, fontSize:12, cursor:'pointer',
                background: String(!!confirm.useTemplate)===val ? 'var(--accent-light)' : 'var(--bg)',
                border:'1px solid var(--border)', borderRadius:8, padding:'5px 10px', userSelect:'none', flex:1 }}>
                <input type="radio" checked={String(!!confirm.useTemplate)===val}
                  onChange={()=>setConfirm(c=>({...c,useTemplate:val==='true'}))} style={{margin:0}} />
                {label}
              </label>
            ))}
          </div>

          {confirm.useTemplate ? (
            <TemplateSelector
              value={confirm.templateId||''}
              varMapping={confirm.templateVarMapping||{}}
              onChange={v=>setConfirm(c=>({...c,templateId:v}))}
              onVarChange={(slot,v)=>setConfirm(c=>({...c,templateVarMapping:{...c.templateVarMapping,[slot]:v}}))}
            />
          ) : (
            <>
              <label style={{ fontSize:13, fontWeight:600, display:'block', marginBottom:4 }}>Mensaje de confirmación</label>
              <div style={{ fontSize:11, color:'var(--ink-3)', marginBottom:6 }}>
                Variables: <code>{'{name}'}</code> <code>{'{date}'}</code> <code>{'{time}'}</code>
              </div>
              <textarea value={confirm.messageTemplate} onChange={e=>setConfirm(c=>({...c,messageTemplate:e.target.value}))} rows={3}
                style={{ width:'100%', padding:'8px 10px', borderRadius:8, border:'1px solid var(--border)', fontSize:13, resize:'vertical', boxSizing:'border-box' }} />
            </>
          )}

          <div style={{ display:'flex', flexDirection:'column', gap:8, marginBottom:14 }}>
            <label style={{ display:'flex', alignItems:'center', gap:8, fontSize:13, cursor:'pointer' }}>
              <input type="checkbox" checked={confirm.sendToContact} onChange={e=>setConfirm(c=>({...c,sendToContact:e.target.checked}))} />
              Enviar al contacto (quien hizo el booking)
            </label>
            <label style={{ display:'flex', alignItems:'center', gap:8, fontSize:13, cursor:'pointer' }}>
              <input type="checkbox" checked={confirm.sendToAgent} onChange={e=>setConfirm(c=>({...c,sendToAgent:e.target.checked}))} />
              Notificarme a mí (número fijo)
            </label>
            {confirm.sendToAgent && (
              <input value={confirm.agentPhone||''} onChange={e=>setConfirm(c=>({...c,agentPhone:e.target.value}))}
                placeholder="Ej: 5491112345678"
                style={{ padding:'8px 10px', borderRadius:8, border:'1px solid var(--border)', fontSize:13, marginLeft:24, width:220 }} />
            )}
          </div>

          {testConfRes && (
            <div style={{ fontSize:12, marginBottom:10, color: testConfRes.error ? 'var(--danger)' : '#16a34a' }}>
              {testConfRes.error ? `❌ ${testConfRes.error}` : `✅ ${testConfRes.sent} confirmación${testConfRes.sent!==1?'es':''} enviada${testConfRes.sent!==1?'s':''}`}
            </div>
          )}

          <div style={{ display:'flex', gap:8, alignItems:'center' }}>
            <button onClick={saveConfirm} disabled={savingConf} style={{ ...S.saveBtn, fontSize:13 }}>
              {savingConf ? 'Guardando…' : 'Guardar'}
            </button>
            <button onClick={testConfirmNow} disabled={testingConf} style={{ ...S.outlineBtn, fontSize:13 }}>
              {testingConf ? '⏳…' : '▶ Probar ahora'}
            </button>
            {confMsg && <span style={{ fontSize:12, color: confMsg.startsWith('✓') ? '#16a34a' : 'var(--danger)' }}>{confMsg}</span>}
          </div>
        </div>
      )}

      <div style={{ fontWeight:700, fontSize:15, marginBottom:12, marginTop:8 }}>⏰ Recordatorios programados</div>

      {!rules && <div style={{ color:'var(--ink-3)', fontSize:13 }}>Cargando…</div>}
      {rules && rules.length === 0 && (
        <div style={{ ...S.card, textAlign:'center', padding:40, color:'var(--ink-3)' }}>
          <div style={{ fontSize:32, marginBottom:12 }}>🔔</div>
          <strong>Sin recordatorios configurados</strong><br/>
          <span style={{ fontSize:13 }}>Creá uno para empezar a enviar avisos automáticos por WhatsApp</span>
        </div>
      )}

      {rules && rules.map(rule => (
        <div key={rule.id} style={{ ...S.card, marginBottom:12, opacity: rule.enabled ? 1 : 0.6 }}>
          <div style={{ display:'flex', alignItems:'flex-start', justifyContent:'space-between', gap:12 }}>
            <div style={{ flex:1 }}>
              <div style={{ display:'flex', alignItems:'center', gap:8, marginBottom:4 }}>
                <span style={{ fontWeight:600, fontSize:15 }}>{rule.name}</span>
                <span style={{ fontSize:11, padding:'2px 8px', borderRadius:20,
                  background: rule.enabled ? '#dcfce7' : '#f3f4f6',
                  color: rule.enabled ? '#16a34a' : '#6b7280' }}>
                  {rule.enabled ? 'Activo' : 'Pausado'}
                </span>
              </div>
              <div style={{ fontSize:12, color:'var(--ink-3)', display:'flex', flexWrap:'wrap', gap:12 }}>
                <span>⏰ {offsetLabel(rule)}</span>
                <span>📌 {rule.sources.map(s=>s==='booking'?'Bookings':'Actividades CRM').join(' + ')}</span>
                <span>📤 {[rule.sendToContact&&'Contacto', rule.sendToAgent&&`Agente (${rule.agentPhone})`].filter(Boolean).join(' + ') || '—'}</span>
              </div>
              <div style={{ fontSize:12, color:'var(--ink-4)', marginTop:6, fontStyle:'italic', whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis', maxWidth:460 }}>
                "{rule.messageTemplate}"
              </div>
            </div>
            <div style={{ display:'flex', gap:6, flexShrink:0 }}>
              <button onClick={()=>toggle(rule)} style={{ ...S.outlineBtn, fontSize:12, padding:'4px 10px' }}>
                {rule.enabled ? '⏸ Pausar' : '▶ Activar'}
              </button>
              <button onClick={()=>{ setEditing(rule); setShowModal(true); }} style={{ ...S.outlineBtn, fontSize:12, padding:'4px 10px' }}>
                ✏️ Editar
              </button>
              <button onClick={()=>del(rule.id)} style={{ fontSize:12, padding:'4px 10px', background:'var(--danger-light)', color:'var(--danger)', border:'none', borderRadius:8, cursor:'pointer' }}>
                🗑
              </button>
            </div>
          </div>
        </div>
      ))}

      {showModal && (
        <ReminderModal rule={editing} onClose={()=>{ setShowModal(false); setEditing(null); }} onSaved={handleSave} />
      )}
    </div>
  );
}

// ─── FormConfigSection ────────────────────────────────────────────────────────
function FormConfigSection({ f, cfg, patch, patchFormSheets, setSheetsModal, sheetsConnected }) {
  const formLabels   = cfg.metaLeadAds?.formLabels?.[f.id] || [];
  const fSheetsCfg   = cfg.metaLeadAds?.formSheetsConfig?.[f.id];
  const sendToTokko  = cfg.metaLeadAds?.sendToTokko;

  return (
    <div style={{ borderTop:'1px solid var(--border-soft)', padding:'12px 14px', display:'flex', flexDirection:'column', gap:10, background:'var(--white)' }}>

      {sendToTokko && (<>
        <div>
          <div style={{ fontSize:11, fontWeight:600, color:'var(--ink-3)', marginBottom:4 }}>Etiquetas Tokko</div>
          <FormLabelInput labels={formLabels} onChange={newLabels => {
            patch('metaLeadAds', { formLabels: { ...(cfg.metaLeadAds?.formLabels||{}), [f.id]: newLabels } });
          }} />
        </div>
        <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr', gap:8 }}>
          <div>
            <div style={{ fontSize:11, fontWeight:600, color:'var(--ink-3)', marginBottom:4 }}>Asesor (email)</div>
            <input style={{ border:'1px solid var(--border)', borderRadius:8, padding:'7px 10px', fontSize:12, width:'100%', outline:'none', background:'var(--white)' }}
              value={cfg.metaLeadAds?.formAdvisorEmail?.[f.id] || ''}
              onChange={e => patch('metaLeadAds', { formAdvisorEmail: { ...(cfg.metaLeadAds?.formAdvisorEmail||{}), [f.id]: e.target.value } })}
              placeholder="asesor@empresa.com" />
          </div>
          <div>
            <div style={{ fontSize:11, fontWeight:600, color:'var(--ink-3)', marginBottom:4 }}>Emprendimiento</div>
            <div style={{ display:'flex', gap:4 }}>
              <input style={{ border:'1px solid var(--border)', borderRadius:8, padding:'7px 6px', fontSize:12, width:60, outline:'none', background:'var(--white)', flexShrink:0 }}
                value={cfg.metaLeadAds?.formDevelopmentId?.[f.id] || ''}
                onChange={e => patch('metaLeadAds', { formDevelopmentId: { ...(cfg.metaLeadAds?.formDevelopmentId||{}), [f.id]: e.target.value } })}
                placeholder="ID" />
              <input style={{ border:'1px solid var(--border)', borderRadius:8, padding:'7px 10px', fontSize:12, width:'100%', outline:'none', background:'var(--white)' }}
                value={cfg.metaLeadAds?.formDevelopmentName?.[f.id] || ''}
                onChange={e => patch('metaLeadAds', { formDevelopmentName: { ...(cfg.metaLeadAds?.formDevelopmentName||{}), [f.id]: e.target.value } })}
                placeholder="Nombre" />
            </div>
          </div>
        </div>
      </>)}

      {sheetsConnected && (
        <div style={{ borderTop: sendToTokko ? '1px solid var(--border-soft)' : 'none', paddingTop: sendToTokko ? 10 : 0 }}>
          <div style={{ display:'flex', alignItems:'center', gap:8, marginBottom:8 }}>
            <GSIcon size={14} />
            <div style={{ fontSize:11, fontWeight:700, color:'var(--ink-2)' }}>Google Sheets</div>
            <div onClick={() => patchFormSheets(f.id, { enabled: !(fSheetsCfg?.enabled) })}
              style={{ width:32, height:17, borderRadius:10, background: fSheetsCfg?.enabled ? 'var(--green)' : 'var(--border)', cursor:'pointer', position:'relative', flexShrink:0, transition:'background .2s', marginLeft:'auto' }}>
              <div style={{ position:'absolute', top:2, left: fSheetsCfg?.enabled ? 16 : 2, width:13, height:13, borderRadius:'50%', background:'#fff', transition:'left .2s' }} />
            </div>
          </div>
          {fSheetsCfg?.enabled !== false && (
            <div style={{ display:'flex', flexDirection:'column', gap:6 }}>
              <input style={{ border:'1px solid var(--border)', borderRadius:8, padding:'7px 10px', fontSize:12, width:'100%', outline:'none', background:'var(--white)' }}
                value={fSheetsCfg?.spreadsheetId || ''}
                onChange={e => patchFormSheets(f.id, { spreadsheetId: e.target.value })}
                onBlur={e => {
                  if (!e.target.value.trim()) return;
                  // Persist URL to server so it survives page reloads
                  apiFetch('/api/meta-lead-ads/sheets/save-url', {
                    method: 'POST', headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify({ formId: f.id, spreadsheetId: e.target.value.trim(), sheetName: fSheetsCfg?.sheetName || '' }),
                  }).catch(() => {});
                }}
                placeholder="URL de la planilla de Google Sheets" />
              <div style={{ display:'flex', gap:4 }}>
                <input style={{ border:'1px solid var(--border)', borderRadius:8, padding:'7px 10px', fontSize:12, width:140, outline:'none', background:'var(--white)', flexShrink:0 }}
                  value={fSheetsCfg?.sheetName || ''}
                  onChange={e => patchFormSheets(f.id, { sheetName: e.target.value })}
                  onBlur={e => {
                    if (!fSheetsCfg?.spreadsheetId) return;
                    apiFetch('/api/meta-lead-ads/sheets/save-url', {
                      method: 'POST', headers: { 'Content-Type': 'application/json' },
                      body: JSON.stringify({ formId: f.id, spreadsheetId: fSheetsCfg.spreadsheetId, sheetName: e.target.value.trim() }),
                    }).catch(() => {});
                  }}
                  placeholder="Nombre de hoja (ej: Hoja1)" />
                <button
                  onClick={() => setSheetsModal({ formId: f.id, formName: f.name, spreadsheetId: fSheetsCfg?.spreadsheetId || '', sheetName: fSheetsCfg?.sheetName || '' })}
                  disabled={!fSheetsCfg?.spreadsheetId}
                  style={{ flex:1, padding:'7px 10px', borderRadius:7, border:'1px solid var(--border)', background: fSheetsCfg?.spreadsheetId ? 'var(--green)' : 'var(--border)', color: fSheetsCfg?.spreadsheetId ? '#fff' : 'var(--ink-4)', fontWeight:600, fontSize:11, cursor: fSheetsCfg?.spreadsheetId ? 'pointer' : 'default', whiteSpace:'nowrap' }}>
                  {fSheetsCfg?.knownHeaders?.length > 0 ? '↻ Remapear' : '🗂 Columnas'}
                </button>
              </div>
              {fSheetsCfg?.knownHeaders?.length > 0 && (
                <div style={{ fontSize:11, color:'var(--ink-3)' }}>
                  ✓ {fSheetsCfg.knownHeaders.length} col.: {fSheetsCfg.knownHeaders.slice(0,4).join(', ')}{fSheetsCfg.knownHeaders.length > 4 ? '…' : ''}
                </div>
              )}
            </div>
          )}
        </div>
      )}
    </div>
  );
}

// ─── SheetsColumnMappingModal ─────────────────────────────────────────────────
function SheetsColumnMappingModal({ formId, formName, spreadsheetId, sheetName, onClose, onSaved }) {
  const [phase, setPhase]         = useState('detecting'); // detecting | mapping | saving | done | error
  const [data, setData]           = useState(null);
  const [items, setItems]         = useState([]);          // editable mapping rows
  const [statics, setStatics]     = useState([]);          // [{ column, value }] fixed-value columns
  const [error, setError]         = useState('');

  React.useEffect(() => { detect(); }, []);

  async function detect() {
    setPhase('detecting'); setError('');
    try {
      const res = await apiFetch('/api/meta-lead-ads/sheets/detect', {
        method: 'POST', headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ formId, spreadsheetId, sheetName }),
      });
      let d = null; try { d = await res.json(); } catch { /* respuesta no-JSON (502/504) */ }
      if (!res.ok || !d) { setPhase('error'); setError((d && d.error) || `El servidor no respondió bien (${res.status || 'sin respuesta'}). Reintentá en unos segundos.`); return; }
      if (d.error) { setPhase('error'); setError(d.error); return; }
      setData(d);
      setItems((d.mapping || []).map(m => ({
        field: m.field,
        header: m.matchedHeader || m.field,
        columnIndex: m.matchedIndex,
        isNew: m.isNew,
        skip: false,
      })));
      setStatics(Object.entries(d.staticFields || {}).map(([column, value]) => ({ column, value: String(value) })));
      setPhase('mapping');
    } catch { setPhase('error'); setError('Error al conectar con el servidor'); }
  }

  async function save() {
    setPhase('saving'); setError('');
    try {
      const staticFields = {};
      statics.forEach(s => { const c = (s.column || '').trim(); if (c) staticFields[c] = s.value || ''; });
      const res = await apiFetch('/api/meta-lead-ads/sheets/save', {
        method: 'POST', headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ formId, spreadsheetId, sheetName, mapping: items, staticFields, writeHeaders: true, enabled: true }),
      });
      let d = null; try { d = await res.json(); } catch { /* no-JSON */ }
      if (!res.ok || !d) { setPhase('error'); setError((d && d.error) || `El servidor no respondió bien (${res.status || 'sin respuesta'}). Reintentá.`); return; }
      if (d.error) { setPhase('error'); setError(d.error); return; }
      setPhase('done');
      onSaved && onSaved(d);
    } catch { setPhase('error'); setError('No se pudo guardar. Revisá tu conexión y reintentá.'); }
  }

  const newCount  = items.filter(i => i.isNew && !i.skip).length;
  const skipCount = items.filter(i => i.skip).length;
  const headers   = data?.headers || [];

  return (
    <div style={{ position:'fixed', inset:0, zIndex:1000, background:'rgba(0,0,0,.45)', display:'flex', alignItems:'center', justifyContent:'center' }}>
      <div style={{ background:'var(--surface)', borderRadius:16, width:'100%', maxWidth:520, maxHeight:'85vh', display:'flex', flexDirection:'column', boxShadow:'var(--shadow-xl)' }}>
        {/* Header */}
        <div style={{ padding:'18px 20px 12px', borderBottom:'1px solid var(--border-soft)' }}>
          <div style={{ display:'flex', alignItems:'center', gap:10 }}>
            <GSIcon size={22} />
            <div style={{ flex:1 }}>
              <div style={{ fontSize:15, fontWeight:700, color:'var(--ink)' }}>Mapear columnas</div>
              <div style={{ fontSize:12, color:'var(--ink-3)', marginTop:1 }}>{formName} → {sheetName || 'Hoja1'}</div>
            </div>
            <button onClick={onClose} style={{ background:'none', border:'none', fontSize:18, cursor:'pointer', color:'var(--ink-3)' }}>✕</button>
          </div>
        </div>

        {/* Body */}
        <div style={{ flex:1, overflowY:'auto', padding:'16px 20px' }}>
          {phase === 'detecting' && (
            <div style={{ textAlign:'center', padding:'32px 0', color:'var(--ink-3)', fontSize:13 }}>
              🔍 Leyendo encabezados de la planilla…
            </div>
          )}
          {phase === 'error' && (
            <div>
              <div style={{ color:'var(--danger)', fontSize:13, marginBottom:12 }}>❌ {error}</div>
              <button onClick={detect} style={{ padding:'6px 14px', borderRadius:7, border:'1px solid var(--border)', background:'var(--surface)', cursor:'pointer', fontSize:13 }}>Reintentar</button>
            </div>
          )}
          {(phase === 'mapping' || phase === 'saving') && (
            <>
              {headers.length > 0 ? (
                <div style={{ fontSize:12, color:'var(--ink-3)', marginBottom:12 }}>
                  📋 Planilla con {headers.length} columnas existentes.
                  {newCount > 0 && <span style={{ color:'#b45309', fontWeight:600 }}> Se agregarán {newCount} columnas nuevas.</span>}
                </div>
              ) : (
                <div style={{ fontSize:12, color:'var(--ink-3)', marginBottom:12 }}>
                  📋 Planilla vacía — se crearán todos los encabezados automáticamente.
                </div>
              )}

              {items.map((item, idx) => (
                <div key={item.field} style={{ display:'flex', alignItems:'center', gap:8, marginBottom:8, padding:'8px 10px', borderRadius:8, background: item.skip ? 'var(--cream-mid)' : (item.isNew ? '#fffbeb' : 'var(--green-light)'), border: `1px solid ${item.skip ? 'var(--border)' : (item.isNew ? '#fde68a' : 'var(--green-mid)')}` }}>
                  {/* Field badge */}
                  <div style={{ fontSize:11, fontWeight:600, color:'var(--ink-2)', background:'var(--white)', border:'1px solid var(--border)', borderRadius:5, padding:'2px 7px', flexShrink:0, maxWidth:160, overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap' }}>
                    {item.field}
                  </div>
                  <div style={{ color:'var(--ink-4)', fontSize:12, flexShrink:0 }}>→</div>

                  {/* Column target */}
                  {item.skip ? (
                    <div style={{ flex:1, fontSize:12, color:'var(--ink-4)', fontStyle:'italic' }}>omitir</div>
                  ) : (
                    <select value={item.isNew ? '__new__' : String(item.columnIndex)}
                      onChange={e => {
                        const val = e.target.value;
                        setItems(prev => prev.map((it, i) => i !== idx ? it : {
                          ...it,
                          columnIndex: val === '__new__' ? null : Number(val),
                          matchedHeader: val === '__new__' ? null : headers[Number(val)],
                          isNew: val === '__new__',
                          header: val === '__new__' ? it.field : headers[Number(val)],
                        }));
                      }}
                      style={{ flex:1, fontSize:12, padding:'4px 6px', borderRadius:6, border:'1px solid var(--border)', background:'var(--white)' }}>
                      {!item.isNew && <option value={String(item.columnIndex)}>{headers[item.columnIndex] || '—'} (columna {item.columnIndex + 1})</option>}
                      <option value="__new__">+ Nueva columna: {item.field}</option>
                      {headers.map((h, i) => (
                        (item.isNew || i !== item.columnIndex) && <option key={i} value={String(i)}>{h} (col. {i + 1})</option>
                      ))}
                    </select>
                  )}

                  {/* Status badge */}
                  {!item.skip && (
                    <span style={{ fontSize:10, fontWeight:700, color: item.isNew ? '#92400e' : '#166534', background: item.isNew ? '#fef3c7' : '#dcfce7', borderRadius:4, padding:'2px 5px', flexShrink:0 }}>
                      {item.isNew ? 'nueva' : '✓ coincide'}
                    </span>
                  )}

                  {/* Skip toggle */}
                  <button onClick={() => setItems(prev => prev.map((it, i) => i !== idx ? it : { ...it, skip: !it.skip }))}
                    style={{ background:'none', border:'none', cursor:'pointer', color:'var(--ink-4)', fontSize:13, padding:'0 2px', flexShrink:0 }}
                    title={item.skip ? 'Incluir' : 'Omitir'}>
                    {item.skip ? '↩' : '✕'}
                  </button>
                </div>
              ))}

              {skipCount > 0 && <div style={{ fontSize:11, color:'var(--ink-4)', marginTop:4 }}>{skipCount} campo(s) omitido(s) — no se enviarán a la planilla.</div>}

              {/* Valores fijos */}
              <div style={{ marginTop:16, paddingTop:14, borderTop:'1px solid var(--border-soft)' }}>
                <div style={{ fontSize:12.5, fontWeight:700, color:'var(--ink)', marginBottom:2 }}>📌 Valores fijos</div>
                <div style={{ fontSize:11.5, color:'var(--ink-4)', marginBottom:8, lineHeight:1.5 }}>
                  Columnas con un valor que elegís vos (no vienen del formulario). Ej: <b>Proyecto</b> = <b>Ginevra</b>. Se agregan a cada lead.
                </div>
                {statics.map((s, i) => {
                  const isCustom = s._custom || (s.column && headers.length > 0 && !headers.includes(s.column));
                  return (
                  <div key={i} style={{ display:'flex', alignItems:'center', gap:6, marginBottom:6 }}>
                    {(headers.length > 0 && !isCustom) ? (
                      <select value={s.column}
                        onChange={e => {
                          const v = e.target.value;
                          setStatics(prev => prev.map((x, j) => j !== i ? x : (v === '__new__' ? { ...x, column:'', _custom:true } : { ...x, column:v, _custom:false })));
                        }}
                        style={{ flex:1, fontSize:12, padding:'5px 8px', borderRadius:6, border:'1px solid var(--border)', background:'var(--white)' }}>
                        <option value="">— Elegí columna —</option>
                        {headers.map((h, k) => <option key={k} value={h}>{h}</option>)}
                        <option value="__new__">➕ Nueva columna…</option>
                      </select>
                    ) : (
                      <input value={s.column} autoFocus onChange={e => setStatics(prev => prev.map((x, j) => j !== i ? x : { ...x, column: e.target.value }))}
                        placeholder="Nombre de columna nueva"
                        style={{ flex:1, fontSize:12, padding:'5px 8px', borderRadius:6, border:'1px solid var(--border)', background:'var(--white)' }} />
                    )}
                    <span style={{ color:'var(--ink-4)', fontSize:12, flexShrink:0 }}>=</span>
                    <input value={s.value} onChange={e => setStatics(prev => prev.map((x, j) => j !== i ? x : { ...x, value: e.target.value }))}
                      placeholder="Valor (ej: Ginevra)"
                      style={{ flex:1, fontSize:12, padding:'5px 8px', borderRadius:6, border:'1px solid var(--border)', background:'var(--white)' }} />
                    <button onClick={() => setStatics(prev => prev.filter((_, j) => j !== i))}
                      style={{ background:'none', border:'none', cursor:'pointer', color:'var(--ink-4)', fontSize:13, flexShrink:0 }} title="Quitar">✕</button>
                  </div>
                  );
                })}
                <button onClick={() => setStatics(prev => [...prev, { column:'', value:'' }])}
                  style={{ fontSize:12, color:'var(--green)', background:'none', border:'1px dashed var(--green-mid)', borderRadius:6, padding:'5px 10px', cursor:'pointer', marginTop:2 }}>
                  + Agregar valor fijo
                </button>
              </div>
            </>
          )}
          {phase === 'done' && (
            <div style={{ textAlign:'center', padding:'24px 0' }}>
              <div style={{ fontSize:32, marginBottom:8 }}>✅</div>
              <div style={{ fontSize:14, fontWeight:600, color:'var(--ink)' }}>¡Configuración guardada!</div>
              <div style={{ fontSize:12, color:'var(--ink-3)', marginTop:4 }}>Los próximos leads se enviarán automáticamente a la planilla.</div>
            </div>
          )}
        </div>

        {/* Footer */}
        {(phase === 'mapping' || phase === 'saving') && (
          <div style={{ padding:'12px 20px', borderTop:'1px solid var(--border-soft)', display:'flex', justifyContent:'flex-end', gap:8 }}>
            <button onClick={onClose} style={{ padding:'8px 16px', borderRadius:8, border:'1px solid var(--border)', background:'transparent', color:'var(--ink-3)', fontWeight:600, fontSize:13, cursor:'pointer' }}>Cancelar</button>
            <button onClick={save} disabled={phase === 'saving'}
              style={{ padding:'8px 20px', borderRadius:8, border:'none', background:'var(--green)', color:'#fff', fontWeight:700, fontSize:13, cursor:'pointer', opacity: phase === 'saving' ? .6 : 1 }}>
              {phase === 'saving' ? 'Guardando…' : `Confirmar${newCount > 0 ? ` y agregar ${newCount} columna${newCount > 1 ? 's' : ''}` : ''}`}
            </button>
          </div>
        )}
        {phase === 'done' && (
          <div style={{ padding:'12px 20px', borderTop:'1px solid var(--border-soft)', display:'flex', justifyContent:'center' }}>
            <button onClick={onClose} style={{ padding:'8px 24px', borderRadius:8, border:'none', background:'var(--green)', color:'#fff', fontWeight:700, fontSize:13, cursor:'pointer' }}>Cerrar</button>
          </div>
        )}
      </div>
    </div>
  );
}

function CopilotPanel() {
  const [msgs, setMsgs] = useState([{ role:'assistant', content:'¡Hola! Soy tu Copiloto de configuración 🤖\n\nPedime lo que necesites en castellano y lo configuro. Por ejemplo:\n• "Creá la etiqueta Lead Caliente en rojo"\n• "Cambiá las instrucciones del agente para que sea más formal"\n• "Agregá el número 549… a los de prueba"\n• "Armá un flow con campos: zona (dropdown: Palermo, Belgrano), ambientes (1,2,3) y nombre"\n• "Mostrame la config actual"\n\nAntes de hacer cosas importantes (publicar un flow, crear operadores) te voy a pedir confirmación.' }]);
  const [input, setInput] = useState('');
  const [busy, setBusy]   = useState(false);
  const [pending, setPending] = useState(null); // acciones propuestas a confirmar
  const [showLog, setShowLog] = useState(false);
  const [logEntries, setLogEntries] = useState([]);
  const loadLog = async () => {
    try { const r = await apiFetch('/api/copilot/log?limit=200'); const d = await r.json(); setLogEntries(d.log || []); } catch { setLogEntries([]); }
    setShowLog(true);
  };
  const scrollRef = React.useRef(null);
  const fileRef = React.useRef(null);
  React.useEffect(() => { if (scrollRef.current) scrollRef.current.scrollTop = scrollRef.current.scrollHeight; }, [msgs, busy, pending]);

  const confirmPending = async () => {
    if (!pending || !pending.length) return;
    const actions = pending.map(p => ({ tool: p.tool, input: p.input }));
    setMsgs(m => [...m, { role:'user', content:'✅ Confirmar' }]);
    setPending(null); setBusy(true);
    try {
      const r = await apiFetch('/api/copilot/execute', { method:'POST', headers:{'Content-Type':'application/json'}, body: JSON.stringify({ actions }) });
      const d = await r.json();
      const lines = (d.results || []).map(x => {
        const okMark = x.result?.error ? '❌' : '✅';
        return `${okMark} ${x.summary}${x.result?.error ? ' — ' + x.result.error : ''}`;
      });
      setMsgs(m => [...m, { role:'assistant', content: (lines.length ? 'Aplicado:\n' + lines.join('\n') : (d.error ? '❌ ' + d.error : 'Listo.')) }]);
    } catch (e) { setMsgs(m => [...m, { role:'assistant', content:'❌ Error aplicando las acciones.' }]); }
    setBusy(false);
  };
  const cancelPending = () => { setPending(null); setMsgs(m => [...m, { role:'assistant', content:'❌ Acciones canceladas.' }]); };

  const uploadFile = async (file) => {
    if (!file) return;
    setBusy(true);
    setMsgs(m => [...m, { role:'assistant', content:`📎 Subiendo "${file.name}"…` }]);
    try {
      const fd = new FormData(); fd.append('file', file);
      const r = await apiFetch('/api/media/upload', { method:'POST', body: fd });
      const d = await r.json();
      if (d.success) setMsgs(m => [...m, { role:'assistant', content:`✅ Archivo subido: **${d.filename}** (url: ${d.url}). Decime qué hago con él (ej. "usalo en el flow X" o "que el agente lo envíe cuando…").` }]);
      else setMsgs(m => [...m, { role:'assistant', content:'❌ ' + (d.error || 'No se pudo subir (formatos: jpg, png, pdf, mp4, mov, máx 25MB).') }]);
    } catch (e) { setMsgs(m => [...m, { role:'assistant', content:'❌ Error subiendo el archivo.' }]); }
    setBusy(false);
  };

  const send = async () => {
    const text = input.trim();
    if (!text || busy) return;
    const next = [...msgs, { role:'user', content:text }];
    setMsgs(next); setInput(''); setBusy(true); setPending(null);
    try {
      // Anthropic requiere arrancar con 'user' → descartamos el saludo inicial
      const firstUser = next.findIndex(m => m.role === 'user');
      const payload = next.slice(firstUser).map(m => ({ role: m.role, content: m.content }));
      const r = await apiFetch('/api/copilot/chat', { method:'POST', headers:{'Content-Type':'application/json'}, body: JSON.stringify({ messages: payload }) });
      const d = await r.json();
      setMsgs(m => [...m, { role:'assistant', content: d.reply || ('❌ ' + (d.error || 'Error')) }]);
      setPending(d.pendingActions && d.pendingActions.length ? d.pendingActions : null);
    } catch (e) { setMsgs(m => [...m, { role:'assistant', content:'❌ Error de conexión con el copiloto.' }]); }
    setBusy(false);
  };

  return (
    <div style={{ ...S.editor, display:'flex', flexDirection:'column', height:'calc(100vh - 40px)' }}>
      <div style={{ ...S.pageHeader, display:'flex', justifyContent:'space-between', alignItems:'flex-start' }}>
        <div>
          <div style={S.pageTitle}>🤖 Copiloto</div>
          <div style={S.pageSubtitle}>Configurá todo escribiendo en castellano. El copiloto ejecuta los cambios sobre tu cuenta.</div>
        </div>
        <button style={{ background:'var(--white)', border:'1px solid var(--border)', borderRadius:10, padding:'8px 14px', fontSize:13, fontWeight:600, color:'var(--ink-2)', cursor:'pointer', flexShrink:0 }}
          onClick={() => showLog ? setShowLog(false) : loadLog()}>{showLog ? '← Volver al chat' : '📜 Historial'}</button>
      </div>
      {showLog && (
        <div style={{ flex:1, overflowY:'auto', padding:'12px 4px', display:'flex', flexDirection:'column', gap:10 }}>
          {logEntries.length === 0 && <div style={{ color:'var(--ink-3)', fontSize:13, padding:12 }}>Todavía no hay actividad registrada. Pedile algo al copiloto y va a quedar acá.</div>}
          {logEntries.map((e, i) => (
            <div key={i} style={{ border:'1px solid var(--border)', borderRadius:12, padding:'10px 14px', background:'var(--white)', fontSize:13 }}>
              <div style={{ fontSize:11, color:'var(--ink-3)', marginBottom:4 }}>{(() => { try { return new Date(e.ts).toLocaleString('es-AR'); } catch { return e.ts; } })()}</div>
              {e.request && e.request !== '(confirmación de acciones)' && <div style={{ marginBottom:4 }}><b>Pediste:</b> {String(e.request).slice(0,400)}</div>}
              {e.reply && <div style={{ marginBottom:4, color:'var(--ink-2)' }}><b>Respuesta:</b> {String(e.reply).slice(0,400)}</div>}
              {(e.executed||[]).filter(x => x && x.summary).map((x,j) => <div key={'e'+j} style={{ fontSize:12, color: x.ok===false ? 'var(--red,#c0392b)' : 'var(--ink-2)' }}>{x.ok===false ? '❌' : '✅'} {x.summary}{x.error ? (' — ' + x.error) : ''}</div>)}
              {(e.proposed||[]).map((x,j) => <div key={'p'+j} style={{ fontSize:12, color:'var(--ink-3)' }}>📝 propuesto: {x.summary}</div>)}
              {(e.confirmed||[]).map((x,j) => <div key={'c'+j} style={{ fontSize:12, color: x.ok===false ? 'var(--red,#c0392b)' : 'var(--ink-2)' }}>{x.ok===false ? '❌' : '✅'} confirmado: {x.summary}{x.error ? (' — ' + x.error) : ''}</div>)}
            </div>
          ))}
        </div>
      )}
      {!showLog && (<React.Fragment>
      <div ref={scrollRef} style={{ flex:1, overflowY:'auto', display:'flex', flexDirection:'column', gap:12, padding:'12px 4px' }}>
        {msgs.map((m, i) => (
          <div key={i} style={{ alignSelf: m.role === 'user' ? 'flex-end' : 'flex-start', maxWidth:'80%', background: m.role === 'user' ? 'var(--green)' : 'var(--white)', color: m.role === 'user' ? '#fff' : 'var(--ink)', border: m.role === 'user' ? 'none' : '1px solid var(--border)', borderRadius:14, padding:'10px 14px', fontSize:14, whiteSpace:'pre-wrap', lineHeight:1.5, boxShadow:'var(--shadow-sm)' }}>
            {m.content}
            {m.actions && m.actions.length > 0 && (
              <div style={{ marginTop:8, fontSize:11, opacity:.7, borderTop:'1px solid var(--border-soft)', paddingTop:6 }}>
                {m.actions.map((a,j) => <div key={j}>⚙️ {a.tool}{a.result?.ok ? ' ✓' : (a.result?.error ? ' ✗' : '')}</div>)}
              </div>
            )}
          </div>
        ))}
        {busy && <div style={{ alignSelf:'flex-start', color:'var(--ink-3)', fontSize:13, padding:'4px 8px' }}>⏳ El copiloto está trabajando…</div>}
      </div>
      {pending && pending.length > 0 && (
        <div style={{ border:'1.5px solid var(--green-mid, #B8D4C8)', background:'var(--green-light,#EBF3EF)', borderRadius:14, padding:'14px 16px', marginBottom:10 }}>
          <div style={{ fontWeight:700, fontSize:13, marginBottom:8, color:'var(--ink)' }}>⚠️ Estas acciones se van a aplicar — confirmá:</div>
          {pending.map((p, i) => <div key={i} style={{ fontSize:13, marginBottom:5, color:'var(--ink-2)' }}>{p.summary}</div>)}
          <div style={{ display:'flex', gap:8, marginTop:12 }}>
            <button style={S.saveBtn} onClick={confirmPending} disabled={busy}>✅ Confirmar y aplicar</button>
            <button style={{ background:'var(--white)', border:'1px solid var(--border)', borderRadius:10, padding:'8px 16px', fontSize:13, fontWeight:600, color:'var(--ink-2)' }} onClick={cancelPending} disabled={busy}>Cancelar</button>
          </div>
        </div>
      )}
      <div style={{ display:'flex', gap:8, paddingTop:10, borderTop:'1px solid var(--border)', alignItems:'flex-end' }}>
        <input ref={fileRef} type="file" accept=".jpg,.jpeg,.png,.gif,.webp,.pdf,.mp4,.mov,.webm" style={{ display:'none' }}
          onChange={e => { const f = e.target.files?.[0]; if (f) uploadFile(f); e.target.value=''; }} />
        <button style={{ ...S.input, width:46, minHeight:46, display:'flex', alignItems:'center', justifyContent:'center', fontSize:20, cursor:'pointer', flexShrink:0 }} title="Subir imagen o archivo" onClick={() => fileRef.current && fileRef.current.click()} disabled={busy}>📎</button>
        <textarea style={{ ...S.input, flex:1, resize:'none', minHeight:46, maxHeight:120 }} value={input} onChange={e => setInput(e.target.value)}
          onKeyDown={e => { if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); send(); } }}
          placeholder="Escribí lo que necesitás configurar… (Enter para enviar, Shift+Enter para salto de línea)" disabled={busy} />
        <button style={S.saveBtn} onClick={send} disabled={busy || !input.trim()}>Enviar</button>
      </div>
      </React.Fragment>)}
    </div>
  );
}

function TestNumbersCard() {
  const [nums, setNums]   = useState([]);
  const [phone, setPhone] = useState('');
  const [busy, setBusy]   = useState(false);
  const load = () => apiFetch('/api/test-numbers').then(r => r.json()).then(d => setNums(d.numbers || [])).catch(() => {});
  useEffect(() => { load(); }, []);
  const add = async () => {
    const p = phone.replace(/\D/g, '');
    if (p.length < 8) return;
    setBusy(true);
    try { const r = await apiFetch('/api/test-numbers', { method:'POST', headers:{'Content-Type':'application/json'}, body: JSON.stringify({ phone: p }) }); const d = await r.json(); if (d.numbers) setNums(d.numbers); setPhone(''); } catch {}
    setBusy(false);
  };
  const del = async (p) => { try { const r = await apiFetch('/api/test-numbers/' + encodeURIComponent(p), { method:'DELETE' }); const d = await r.json(); if (d.numbers) setNums(d.numbers); } catch {} };
  return (
    <div style={{ background:'var(--card,#fff)', border:'1px solid var(--border,#e5e7eb)', borderRadius:14, padding:'18px 20px', marginBottom:20 }}>
      <div style={{ fontSize:15, fontWeight:700, marginBottom:4 }}>🧪 Números de prueba</div>
      <div style={{ fontSize:13, color:'var(--ink-3,#666)', marginBottom:14 }}>Para estos números la IA <b>siempre responde</b> (ignora pausas de humano/coexistence) y el flow se vuelve a disparar. Ideal para testear cualquier agente sin que se frene. No afecta a contactos reales.</div>
      <div style={{ display:'flex', gap:8, marginBottom:12 }}>
        <input style={{ ...S.input, flex:1 }} value={phone} onChange={e => setPhone(e.target.value)} placeholder="Ej: 5491144491195 (con código de país)" onKeyDown={e => e.key === 'Enter' && add()} />
        <button style={S.saveBtn} onClick={add} disabled={busy || phone.replace(/\D/g,'').length < 8}>Agregar</button>
      </div>
      {nums.length === 0 ? <div style={{ fontSize:13, color:'var(--ink-3,#888)' }}>Sin números de prueba.</div> :
        <div style={{ display:'flex', flexWrap:'wrap', gap:8 }}>
          {nums.map(n => (
            <span key={n} style={{ display:'inline-flex', alignItems:'center', gap:8, background:'var(--chip,#f3f4f6)', borderRadius:20, padding:'6px 12px', fontSize:13, fontWeight:600 }}>
              📱 {n}
              <span onClick={() => del(n)} title="Quitar" style={{ cursor:'pointer', color:'#d33', fontWeight:800, fontSize:15, lineHeight:1 }}>×</span>
            </span>
          ))}
        </div>
      }
    </div>
  );
}

function IntegracionesPanel() {
  const [cfg, setCfg]         = useState(null);
  const [saving, setSaving]   = useState(false);
  const [msg, setMsg]         = useState('');
  const [sheetsModal, setSheetsModal] = useState(null); // { formId, formName, spreadsheetId, sheetName }

  const reloadCfg = () => apiFetch('/api/integrations').then(r => r.json()).then(setCfg).catch(() => {});

  useEffect(() => { reloadCfg(); }, []);

  const meta = useMeta(cfg?.metaConnection);

  const sheetsConnected = !!(cfg?.googleSheets?.connected && cfg?.googleSheets?.refreshToken);

  // Helper: patch a single form's sheets config in local state
  const patchFormSheets = (formId, val) => setCfg(prev => ({
    ...prev,
    metaLeadAds: {
      ...prev.metaLeadAds,
      formSheetsConfig: {
        ...(prev.metaLeadAds?.formSheetsConfig || {}),
        [formId]: { spreadsheetId: '', sheetName: '', enabled: false, columnMapping: {}, knownHeaders: [], ...(prev.metaLeadAds?.formSheetsConfig?.[formId] || {}), ...val },
      },
    },
  }));

  // When businesses are loaded, auto-apply BM filter if one is already saved
  useEffect(() => {
    if (!cfg || meta.businesses.length === 0) return;
    if (cfg.metaCapi?.businessId)     meta.loadBMAccounts(cfg.metaCapi.businessId);
  }, [meta.businesses.length]);

  // Cargar los pixels de la cuenta publicitaria YA GUARDADA al abrir la página. Sin esto,
  // el campo "Pixel" queda vacío y muestra "Conectar Facebook primero" aunque FB esté
  // conectado, porque loadPixels solo corría al CAMBIAR la cuenta (onChange), no al montar.
  useEffect(() => {
    if (cfg?.metaConnection?.connected && cfg?.metaCapi?.adAccountId) {
      meta.loadPixels(cfg.metaCapi.adAccountId);
    }
  }, [cfg?.metaConnection?.connected, cfg?.metaCapi?.adAccountId]);

  const save = async () => {
    if (!cfg) return;
    setSaving(true); setMsg('');
    try {
      const res = await apiFetch('/api/integrations', {
        method: 'PUT', headers: {'Content-Type':'application/json'}, body: JSON.stringify(cfg),
      });
      const data = await res.json();
      if (data.error) { setMsg('❌ ' + data.error); }
      else { setCfg(data); setMsg('✓ Guardado'); }
    } catch { setMsg('❌ Error al guardar'); }
    setSaving(false);
    setTimeout(() => setMsg(''), 3000);
  };

  const patch = (key, val) => setCfg(prev => ({ ...prev, [key]: { ...prev[key], ...val } }));

  if (!cfg) return <div style={S.editor}><div style={{ color:'var(--ink-3)', fontSize:13 }}>Cargando…</div></div>;

  const origin  = window.location.origin;
  const conn    = cfg.metaConnection;

  return (
    <div style={{ ...S.editor }}>
      <div style={S.pageHeader}>
        <div>
          <div style={S.pageTitle}>🔌 Integraciones</div>
          <div style={S.pageSubtitle}>Conectá Looplead con plataformas externas para automatizar el flujo de leads y conversiones.</div>
        </div>
        <div style={{ display:'flex', alignItems:'center', gap:12, flexShrink:0 }}>
          {msg && <span style={{ fontSize:13, color: msg.startsWith('✓') ? 'var(--green)' : 'var(--danger)', fontWeight:600 }}>{msg}</span>}
          <button style={S.saveBtn} onClick={save} disabled={saving}>{saving ? 'Guardando…' : 'Guardar cambios'}</button>
        </div>
      </div>

      <TestNumbersCard />

      {/* ── Tokko CRM ─────────────────────────────────────────────────────── */}
      <IntegrationCard
        icon="🏠" title="Tokko CRM"
        description="Enviá contactos automáticamente a Tokko Broker cuando llega un lead por WhatsApp o Lead Ads."
        enabled={cfg.tokko.enabled} onToggle={v => patch('tokko', { enabled: v })}
      >
        <div style={S.row}>
          <div style={S.col}>
            <label style={S.label}>API URL</label>
            <input style={S.input} value={cfg.tokko.apiUrl}
              onChange={e => patch('tokko', { apiUrl: e.target.value })}
              placeholder="https://tokkobroker.com/api/v1/" />
          </div>
          <div style={S.col}>
            <label style={S.label}>API Key</label>
            <input style={S.input} type="password" value={cfg.tokko.apiKey}
              onChange={e => patch('tokko', { apiKey: e.target.value })}
              placeholder="Tu API Key de Tokko" />
          </div>
        </div>
        <TokkoLabelsEditor
          labels={cfg.tokko.labels || []}
          onChange={labels => patch('tokko', { labels })}
        />

        {/* ── WhatsApp settings ──────────────────────────────────────────── */}
        <div style={{ borderTop:'1px solid var(--border-soft)', paddingTop:16, display:'flex', flexDirection:'column', gap:12 }}>
          <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between' }}>
            <div>
              <div style={{ fontWeight:600, fontSize:13, color:'var(--ink)' }}>Contactos de WhatsApp</div>
              <div style={{ fontSize:12, color:'var(--ink-4)', marginTop:2 }}>Enviá automáticamente a Tokko cuando entra un contacto nuevo por WhatsApp.</div>
            </div>
            <Toggle on={cfg.tokko.whatsapp?.enabled} onChange={v => patch('tokko', { whatsapp: { ...(cfg.tokko.whatsapp||{}), enabled: v } })} />
          </div>

          {cfg.tokko.whatsapp?.enabled && (
            <div style={{ display:'flex', flexDirection:'column', gap:10, paddingLeft:0 }}>

              {/* Delay */}
              <div style={{ display:'flex', alignItems:'center', gap:10 }}>
                <label style={{ ...S.label, marginBottom:0, whiteSpace:'nowrap' }}>Esperar antes de enviar</label>
                <div style={{ display:'flex', alignItems:'center', gap:6 }}>
                  <input
                    type="number" min="0" max="10080"
                    style={{ ...S.input, width:80, textAlign:'center' }}
                    value={cfg.tokko.whatsapp?.delayMinutes ?? 0}
                    onChange={e => patch('tokko', { whatsapp: { ...(cfg.tokko.whatsapp||{}), delayMinutes: Math.max(0, parseInt(e.target.value)||0) } })}
                  />
                  <span style={{ fontSize:13, color:'var(--ink-3)' }}>minutos</span>
                  {(cfg.tokko.whatsapp?.delayMinutes||0) >= 60 && (
                    <span style={{ fontSize:12, color:'var(--ink-4)' }}>
                      ({Math.floor((cfg.tokko.whatsapp?.delayMinutes||0)/60)}h {(cfg.tokko.whatsapp?.delayMinutes||0)%60}m)
                    </span>
                  )}
                </div>
                <span style={{ fontSize:11, color:'var(--ink-4)' }}>0 = en el primer mensaje</span>
              </div>

              {/* Options */}
              <div style={{ display:'flex', flexDirection:'column', gap:8 }}>
                <label style={{ ...S.label, marginBottom:0 }}>Incluir al enviar</label>
                {[
                  { key:'sendSummary',    label:'Resumen IA de la conversación', hint:'Claude genera un resumen de los últimos mensajes' },
                  { key:'sendTags',       label:'Etiquetas de Pipochat',          hint:'Las etiquetas del contacto en el momento del envío' },
                  { key:'sendAttributes', label:'Atributos del contacto',         hint:'Campaña, adset, ad y otros atributos guardados' },
                ].map(({ key, label, hint }) => (
                  <label key={key} style={{ display:'flex', alignItems:'flex-start', gap:8, cursor:'pointer' }}>
                    <input type="checkbox"
                      checked={!!(cfg.tokko.whatsapp?.[key])}
                      onChange={e => patch('tokko', { whatsapp: { ...(cfg.tokko.whatsapp||{}), [key]: e.target.checked } })}
                      style={{ marginTop:2 }}
                    />
                    <div>
                      <div style={{ fontSize:13, color:'var(--ink-2)', fontWeight:500 }}>{label}</div>
                      <div style={{ fontSize:11, color:'var(--ink-4)' }}>{hint}</div>
                    </div>
                  </label>
                ))}
              </div>
            </div>
          )}
        </div>

        <div style={{ fontSize:12, color:'var(--ink-4)', background:'var(--warning-light)', border:'1px solid #FCD34D', borderRadius:8, padding:'8px 12px' }}>
          💡 Se envía a Tokko cuando el agente ejecuta <strong>Crear oportunidad de venta</strong>, por Lead Ads con "Enviar a Tokko" activo, o automáticamente al entrar un contacto de WhatsApp.
        </div>

        {/* ── Test de conexión ──────────────────────────────────────────────── */}
        <TokkoTestButton />
      </IntegrationCard>

      {/* ── Meta — shared connection ───────────────────────────────────────── */}
      <div style={S.card}>
        <div style={{ display:'flex', alignItems:'center', gap:8, marginBottom:14 }}>
          <div style={{ fontSize:22 }}>f</div>
          <div style={{ fontSize:14, fontWeight:700, color:'var(--ink)' }}>Cuenta de Meta (Facebook)</div>
          <div style={{ fontSize:11, color:'var(--ink-4)', marginLeft:4 }}>— compartida por todas las integraciones de Meta</div>
        </div>
        <FacebookConnectSection
          connection={conn}
          onConnected={reloadCfg}
          onDisconnected={() => setCfg(prev => ({ ...prev, metaConnection: { connected: false } }))}
        />
      </div>

      {/* ── Meta Conversions API ───────────────────────────────────────────── */}
      <IntegrationCard
        icon="📊" title="Meta Conversions API"
        description="Enviá eventos de conversión a Meta basándose en reglas personalizadas: etiquetas, etapas del pipeline, o siempre."
        enabled={cfg.metaCapi.enabled} onToggle={v => patch('metaCapi', { enabled: v })}
        badge={!conn?.connected && cfg.metaCapi.enabled && <span style={{ fontSize:11, color:'#92400E', background:'#FEF3C7', padding:'2px 8px', borderRadius:99 }}>⚠ Conectar Facebook</span>}
      >
        {!conn?.connected
          ? <div style={{ color:'var(--ink-4)', fontSize:13, textAlign:'center', padding:'12px 0' }}>Conectá tu cuenta de Facebook para configurar esta integración.</div>
          : (
            <>
              {meta.businesses.length > 0 && (
                <MetaSelectField label="Business Manager (opcional)" value={cfg.metaCapi.businessId} items={meta.businesses} loading={false}
                  placeholder="— Cargar cuentas del BM —"
                  onChange={(id) => { patch('metaCapi', { businessId: id, adAccountId: '', adAccountName: '', pixelId: '', pixelName: '' }); meta.loadBMAccounts(id); meta.loadPixels(null); }} />
              )}
              <div style={S.row}>
                <MetaSelectField label="Cuenta publicitaria" value={cfg.metaCapi.adAccountId} items={meta.accounts} loading={meta.loading}
                  placeholder="— Seleccioná una cuenta —"
                  onChange={(id, item) => { patch('metaCapi', { adAccountId: id, adAccountName: item?.name }); meta.loadPixels(id); }} />
                <MetaSelectField label="Pixel" value={cfg.metaCapi.pixelId} items={meta.pixels} loading={false}
                  placeholder="— Seleccioná un pixel —"
                  onChange={(id, item) => patch('metaCapi', { pixelId: id, pixelName: item?.name })} />
              </div>
              <CAPIRulesEditor
                rules={cfg.metaCapi.rules || []}
                onChange={rules => patch('metaCapi', { rules })}
              />
            </>
          )
        }
      </IntegrationCard>

      {/* ── Google Calendar ────────────────────────────────────────────────── */}
      <GoogleCalendarCard gc={cfg.googleCalendar || {}} onPatch={v => patch('googleCalendar', v)} />

      {/* ── Meta Lead Ads ──────────────────────────────────────────────────── */}
      <IntegrationCard
        icon="📋" title="Meta Lead Ads"
        description="Recibí contactos de tus formularios de Lead Ads directamente en Pipochat y activá el agente automáticamente."
        enabled={cfg.metaLeadAds.enabled} onToggle={v => patch('metaLeadAds', { enabled: v })}
        webhookUrl={`${origin}/api/meta/lead-ads`}
        badge={!conn?.connected && cfg.metaLeadAds.enabled && <span style={{ fontSize:11, color:'#92400E', background:'#FEF3C7', padding:'2px 8px', borderRadius:99 }}>⚠ Conectar Facebook</span>}
      >
        {!conn?.connected
          ? <div style={{ color:'var(--ink-4)', fontSize:13, textAlign:'center', padding:'12px 0' }}>Conectá tu cuenta de Facebook para configurar esta integración.</div>
          : (
            <>
              <LeadAdsConfig cfg={cfg} patch={patch} meta={meta} sheetsConnected={sheetsConnected} patchFormSheets={patchFormSheets} setSheetsModal={setSheetsModal} />
              <div style={{ display:'flex', alignItems:'center', gap:10 }}>
                <Toggle on={cfg.metaLeadAds.sendToTokko} onChange={v => patch('metaLeadAds', { sendToTokko: v })} />
                <span style={{ fontSize:13, color:'var(--ink-2)' }}>Enviar automáticamente a <strong>Tokko CRM</strong> con las etiquetas definidas</span>
              </div>
            </>
          )
        }
      </IntegrationCard>

      {/* Meta Campaign Tracking card removed — CTWA tracking is automatic via Pipochat webhook */}

      {/* Google Sheets column mapping modal */}
      {sheetsModal && (
        <SheetsColumnMappingModal
          formId={sheetsModal.formId}
          formName={sheetsModal.formName}
          spreadsheetId={sheetsModal.spreadsheetId}
          sheetName={sheetsModal.sheetName}
          onClose={() => setSheetsModal(null)}
          onSaved={d => {
            patchFormSheets(sheetsModal.formId, d.config);
            setSheetsModal(null);
          }}
        />
      )}
    </div>
  );
}

// ─── LeadAdsActionsEditor ─────────────────────────────────────────────────────
function LeadAdsActionsEditor({ actions, inboxes, forms = [], onChange }) {
  const TEMPLATE_VARS = ['{{nombre}}', '{{apellido}}', '{{telefono}}', '{{email}}'];
  const formId  = f => String(f.id || f.formId || f._id || '');
  const formName = f => f.name || f.title || formId(f);

  const addAction = () => {
    onChange([...actions, {
      type: 'whatsapp_message',
      enabled: true,
      inboxId: '',
      inboxName: '',
      messageTemplate: 'Hola {{nombre}}, gracias por tu consulta. Te contactamos a la brevedad.',
      delayMinutes: 0,
    }]);
  };

  const updateAction = (i, update) => {
    const next = actions.map((a, idx) => idx === i ? { ...a, ...update } : a);
    onChange(next);
  };

  const removeAction = (i) => onChange(actions.filter((_, idx) => idx !== i));

  return (
    <div style={{ marginTop:16 }}>
      <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between', marginBottom:8 }}>
        <label style={{ ...S.label, marginBottom:0 }}>⚡ Acciones automáticas</label>
        <button style={S.outlineBtn} onClick={addAction}>+ Agregar acción</button>
      </div>

      {actions.length === 0 && (
        <div style={{ fontSize:12, color:'var(--ink-4)', background:'var(--cream)', borderRadius:8, padding:'10px 14px' }}>
          Sin acciones. Podés enviar un WhatsApp automático cuando ingrese un lead del formulario.
        </div>
      )}

      {actions.map((action, i) => (
        <div key={i} style={{ border:'1px solid var(--border)', borderRadius:10, padding:'14px', marginBottom:10, background: action.enabled ? 'var(--white)' : 'var(--cream)' }}>
          <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between', marginBottom:12 }}>
            <div style={{ display:'flex', alignItems:'center', gap:8 }}>
              <Toggle on={action.enabled} onChange={v => updateAction(i, { enabled: v })} />
              <span style={{ fontSize:13, fontWeight:600 }}>
                {action.type === 'whatsapp_template' ? `📋 Template${action.templateName ? ` "${action.templateName}"` : ''}` : '💬 Mensaje libre'}
                {action.condition?.field && action.condition?.equals && (
                  <span style={{ fontSize:11, fontWeight:500, color:'var(--ink-4)', marginLeft:6 }}>· si {action.condition.field}={action.condition.equals}</span>
                )}
              </span>
            </div>
            <button style={{ background:'none', border:'none', color:'var(--ink-4)', cursor:'pointer', fontSize:16, padding:'0 4px' }}
              onClick={() => removeAction(i)}>✕</button>
          </div>

          {/* Tipo de envío */}
          <div style={S.row}>
            <div style={S.col}>
              <label style={S.label}>Tipo de envío</label>
              <select style={S.input} value={action.type === 'whatsapp_template' ? 'template' : 'libre'}
                onChange={e => updateAction(i, { type: e.target.value === 'template' ? 'whatsapp_template' : 'whatsapp_message' })}>
                <option value="libre">💬 Mensaje libre (ventana 24h abierta)</option>
                <option value="template">📋 Template de Meta (recomendado para Lead Ads)</option>
              </select>
            </div>
            <div style={S.col}>
              <label style={S.label}>Demora (minutos)</label>
              <input style={S.input} type="number" min="0" max="60"
                value={action.delayMinutes}
                onChange={e => updateAction(i, { delayMinutes: Number(e.target.value) })}
                placeholder="0 = inmediato" />
            </div>
          </div>

          {/* Formulario + condición opcional */}
          <div style={{ background:'var(--cream)', border:'1px dashed var(--border)', borderRadius:8, padding:'10px 12px', marginTop:4 }}>
            <label style={{ ...S.label, marginBottom:6 }}>🎯 Disparar solo en (opcional)</label>
            <div style={{ ...S.col, marginBottom:8 }}>
              <select style={S.input} value={action.formId || ''}
                onChange={e => updateAction(i, { formId: e.target.value })}>
                <option value="">Todos los formularios</option>
                {forms.map(f => (<option key={formId(f)} value={formId(f)}>{formName(f)}</option>))}
              </select>
            </div>
            <div style={S.row}>
              <div style={S.col}>
                <input style={S.input} value={action.condition?.field || ''}
                  onChange={e => updateAction(i, { condition: { ...(action.condition||{}), field: e.target.value } })}
                  placeholder="Campo del form (ej: ambientes)" />
              </div>
              <div style={S.col}>
                <input style={S.input} value={action.condition?.equals || ''}
                  onChange={e => updateAction(i, { condition: { ...(action.condition||{}), equals: e.target.value } })}
                  placeholder="Valor (ej: 3 ambientes)" />
              </div>
            </div>
            <div style={{ fontSize:11, color:'var(--ink-4)', marginTop:4 }}>Dejá vacío para disparar siempre. Ej: campo <code>ambientes</code> = <code>3 ambientes</code> → un template; otra acción con <code>4 ambientes</code> → otro.</div>
          </div>

          {action.type === 'whatsapp_template' ? (
            <div style={{ marginTop:10 }}>
              <div style={S.row}>
                <div style={S.col}>
                  <label style={S.label}>Nombre del template (Meta)</label>
                  <input style={S.input} value={action.templateName || ''}
                    onChange={e => updateAction(i, { templateName: e.target.value.trim() })}
                    placeholder="ej: black_nunez_3amb" />
                </div>
                <div style={S.col}>
                  <label style={S.label}>Línea de WhatsApp</label>
                  <select style={S.input} value={action.inboxId}
                    onChange={e => { const item = inboxes.find(x => x._id === e.target.value); updateAction(i, { inboxId: e.target.value, inboxName: item?.name || '' }); }}>
                    <option value="">— (opcional) —</option>
                    {inboxes.map(inbox => (<option key={inbox._id} value={inbox._id}>{inbox.name}</option>))}
                  </select>
                </div>
              </div>
              <div style={{ fontSize:11, color:'var(--ink-4)', marginTop:6 }}>El template debe estar <strong>aprobado en Meta</strong> y en idioma <code>es_AR</code>. Las variables del cuerpo (ej. {'{{name}}'}) se completan <strong>automáticamente</strong> con los datos del contacto — no hace falta cargarlas.</div>
            </div>
          ) : (
            <div style={{ ...S.col, marginTop:10 }}>
              <label style={S.label}>Línea de WhatsApp</label>
              <select style={S.input} value={action.inboxId}
                onChange={e => { const item = inboxes.find(x => x._id === e.target.value); updateAction(i, { inboxId: e.target.value, inboxName: item?.name || '' }); }}>
                <option value="">— Seleccioná una línea —</option>
                {inboxes.map(inbox => (<option key={inbox._id} value={inbox._id}>{inbox.name}</option>))}
              </select>
              <label style={{ ...S.label, marginTop:10 }}>Mensaje</label>
              <textarea style={{ ...S.input, height:80, resize:'vertical', fontFamily:'inherit', fontSize:13 }}
                value={action.messageTemplate}
                onChange={e => updateAction(i, { messageTemplate: e.target.value })}
                placeholder="Hola {{nombre}}, gracias por tu consulta…" />
              <div style={{ display:'flex', gap:6, flexWrap:'wrap', marginTop:6 }}>
                {TEMPLATE_VARS.map(v => (
                  <button key={v} style={{ fontSize:11, background:'var(--cream)', border:'1px solid var(--border)', borderRadius:6, padding:'2px 8px', cursor:'pointer', fontFamily:'monospace' }}
                    onClick={() => updateAction(i, { messageTemplate: action.messageTemplate + v })}>
                    {v}
                  </button>
                ))}
                <span style={{ fontSize:11, color:'var(--ink-4)', alignSelf:'center' }}>clic para insertar variable</span>
              </div>
            </div>
          )}
        </div>
      ))}
    </div>
  );
}

function LeadAdsConfig({ cfg, patch, meta, sheetsConnected, patchFormSheets, setSheetsModal }) {
  const [forms, setForms] = useState([]);
  const [loadingForms, setLoadingForms] = useState(false);
  const [formSearch, setFormSearch] = useState('');
  const [formsOpen, setFormsOpen] = useState(false);
  const [expandedForms, setExpandedForms] = useState({});
  const [tokkoLog, setTokkoLog] = useState(null);
  const [loadingTokkoLog, setLoadingTokkoLog] = useState(false);
  // Extra pages state
  const [extraPageForms, setExtraPageForms] = useState({});       // pageId → Form[]
  const [loadingExtraForms, setLoadingExtraForms] = useState({}); // pageId → bool
  const { inboxes } = usePipochat();
  const [subStatus, setSubStatus] = useState(null); // null | { subscribed, fields } | 'loading' | 'subscribing'

  const checkSubscription = async () => {
    setSubStatus('loading');
    const d = await apiFetch('/api/meta/subscribe-page').then(r => r.json()).catch(() => null);
    setSubStatus(d);
  };

  const doSubscribe = async () => {
    setSubStatus('subscribing');
    const d = await apiFetch('/api/meta/subscribe-page', { method: 'POST' }).then(r => r.json()).catch(e => ({ error: e.message }));
    if (d.ok) { setSubStatus({ subscribed: true, fields: ['leadgen'] }); }
    else { setSubStatus({ subscribed: false, fields: [], error: d.error }); }
  };

  const loadTokkoLog = async () => {
    setLoadingTokkoLog(true);
    const d = await apiFetch('/api/lead-ads/tokko-log').then(r => r.json()).catch(() => ({ entries: [] }));
    setTokkoLog(d.entries || []);
    setLoadingTokkoLog(false);
  };

  useEffect(() => { if (cfg.metaLeadAds.pageId) checkSubscription(); }, [cfg.metaLeadAds.pageId]);

  // Bulk import state
  const [bulkResult,       setBulkResult]       = useState(null);
  const [bulkLoading,      setBulkLoading]      = useState(false);
  const [sendWhatsapp,     setSendWhatsapp]      = useState(false);
  const [testMode,         setTestMode]          = useState(false);
  const [previewLoading,   setPreviewLoading]    = useState(false);
  const [previewData,      setPreviewData]       = useState(null);   // { forms: [{formId, formName, leads:[]}] }
  const [selectedLeadIds,  setSelectedLeadIds]   = useState(new Set());
  // Pipochat contact test
  const [pipoTestLoading,  setPipoTestLoading]   = useState(false);
  const [pipoTestResult,   setPipoTestResult]    = useState(null);
  // Pipochat API key update
  const [showApiKeyForm,   setShowApiKeyForm]    = useState(false);
  const [newApiKey,        setNewApiKey]         = useState('');
  const [apiKeyLoading,    setApiKeyLoading]     = useState(false);
  const [apiKeyResult,     setApiKeyResult]      = useState(null);

  const loadPreview = async () => {
    setPreviewLoading(true); setPreviewData(null); setSelectedLeadIds(new Set());
    const data = await apiFetch('/api/meta/leadads-preview')
      .then(r => r.json()).catch(e => ({ error: e.message }));
    setPreviewData(data);
    // Pre-select all leads
    if (data?.forms) {
      // Pre-select only leads NOT already sent
      const newIds = new Set(data.forms.flatMap(f => f.leads.filter(l => !l.alreadySent).map(l => l.id)));
      setSelectedLeadIds(newIds);
    }
    setPreviewLoading(false);
  };

  const toggleLead = (id) => setSelectedLeadIds(prev => {
    const next = new Set(prev);
    next.has(id) ? next.delete(id) : next.add(id);
    return next;
  });

  const toggleAll = (leads) => {
    const allIds = leads.map(l => l.id);
    const allSelected = allIds.every(id => selectedLeadIds.has(id));
    setSelectedLeadIds(prev => {
      const next = new Set(prev);
      allIds.forEach(id => allSelected ? next.delete(id) : next.add(id));
      return next;
    });
  };

  const runBulkSend = async () => {
    const ids = previewData ? [...selectedLeadIds] : null;
    const count = ids ? ids.length : (cfg.metaLeadAds.formIds||[]).length;
    const confirmMsg = testMode
      ? `¿Probar con 1 solo lead (modo test)?`
      : ids
        ? `¿Enviar ${ids.length} lead${ids.length !== 1 ? 's' : ''} seleccionado${ids.length !== 1 ? 's' : ''}?`
        : `¿Enviar todos los leads acumulados de ${count} formulario${count !== 1 ? 's' : ''}?`;
    if (!confirm(confirmMsg)) return;
    setBulkLoading(true); setBulkResult(null);
    const data = await apiFetch('/api/meta/leadads-bulk-send', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ sendWhatsapp, testMode, selectedLeadIds: ids }),
    }).then(r => r.json()).catch(e => ({ error: e.message }));
    setBulkResult(data);
    setBulkLoading(false);
    if (!data.error) { setPreviewData(null); setSelectedLeadIds(new Set()); }
  };

  const runPipoTest = async () => {
    setPipoTestLoading(true); setPipoTestResult(null);
    const data = await apiFetch('/api/debug/pipochat-contact-test', { method: 'POST' })
      .then(r => r.json()).catch(e => ({ success: false, error: e.message }));
    setPipoTestResult(data);
    setPipoTestLoading(false);
    // Auto-show API key form only if createContact (the critical step) fails with 401
    if (!data.success && data.step === 'createContact' && data.error?.includes('401')) setShowApiKeyForm(true);
  };

  const saveApiKey = async () => {
    if (!newApiKey.trim()) return;
    setApiKeyLoading(true); setApiKeyResult(null);
    const data = await apiFetch('/api/auth/api-token', {
      method: 'PATCH',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ pipochatApiToken: newApiKey.trim() }),
    }).then(r => r.json()).catch(e => ({ error: e.message }));
    setApiKeyResult(data);
    setApiKeyLoading(false);
    if (data.success) {
      setNewApiKey('');
      setShowApiKeyForm(false);
      setPipoTestResult(null); // reset so user re-tests
    }
  };

  const loadForms = async (pageId, businessId) => {
    if (!pageId) return;
    setLoadingForms(true);
    const f = await meta.loadForms(pageId, businessId || cfg.metaLeadAds.businessId);
    setForms(f);
    setLoadingForms(false);
  };

  // When businesses list is ready and a BM is already saved in config,
  // load BM-filtered pages immediately instead of showing all personal pages
  useEffect(() => {
    if (meta.businesses.length > 0 && cfg.metaLeadAds.businessId) {
      meta.loadBMPages(cfg.metaLeadAds.businessId);
    }
  }, [meta.businesses.length]);

  useEffect(() => {
    if (cfg.metaLeadAds.pageId) loadForms(cfg.metaLeadAds.pageId, cfg.metaLeadAds.businessId);
  }, [cfg.metaLeadAds.pageId]);

  // Extra pages helpers
  const loadExtraPageForms = async (pageId) => {
    if (!pageId || extraPageForms[pageId]) return;
    setLoadingExtraForms(prev => ({ ...prev, [pageId]: true }));
    const f = await meta.loadForms(pageId, cfg.metaLeadAds.businessId);
    setExtraPageForms(prev => ({ ...prev, [pageId]: f }));
    setLoadingExtraForms(prev => ({ ...prev, [pageId]: false }));
  };

  // Load forms for extra pages already saved in config
  useEffect(() => {
    for (const ep of (cfg.metaLeadAds.extraPages || [])) {
      if (ep.pageId) loadExtraPageForms(ep.pageId);
    }
  }, []);

  const addExtraPage = () => {
    const cur = cfg.metaLeadAds.extraPages || [];
    patch('metaLeadAds', { extraPages: [...cur, { pageId: '', pageName: '', pageAccessToken: '', formIds: [] }] });
  };

  const removeExtraPage = (idx) => {
    const cur = cfg.metaLeadAds.extraPages || [];
    patch('metaLeadAds', { extraPages: cur.filter((_, i) => i !== idx) });
  };

  const patchExtraPage = (idx, changes) => {
    const cur = [...(cfg.metaLeadAds.extraPages || [])];
    cur[idx] = { ...cur[idx], ...changes };
    patch('metaLeadAds', { extraPages: cur });
  };

  // Pages available for extra selection (exclude already-chosen ones)
  const usedPageIds = [
    cfg.metaLeadAds.pageId,
    ...(cfg.metaLeadAds.extraPages || []).map(ep => ep.pageId),
  ].filter(Boolean);
  const availablePages = (idx) => meta.pages.filter(p =>
    !usedPageIds.includes(p.id) || (cfg.metaLeadAds.extraPages || [])[idx]?.pageId === p.id
  );

  return (
    <>
      {meta.businesses.length > 0 && (
        <MetaSelectField label="Business Manager (opcional)" value={cfg.metaLeadAds.businessId} items={meta.businesses} loading={false}
          placeholder="— Cargar páginas del BM —"
          onChange={(id) => { patch('metaLeadAds', { businessId: id, pageId: '', pageName: '', pageAccessToken: '', formIds: [] }); meta.loadBMPages(id); setForms([]); }} />
      )}
      <div style={S.row}>
        <MetaSelectField label="Página de Facebook" value={cfg.metaLeadAds.pageId} items={meta.pages} loading={meta.loading}
          placeholder="— Seleccioná una página —"
          onChange={(id, item) => { patch('metaLeadAds', { pageId: id, pageName: item?.name, pageAccessToken: item?.access_token, formIds: [] }); loadForms(id, cfg.metaLeadAds.businessId); }} />
        <div style={S.col}>
          <label style={S.label}>Verify Token</label>
          <input style={S.input} value={cfg.metaLeadAds.verifyToken}
            onChange={e => patch('metaLeadAds', { verifyToken: e.target.value })}
            placeholder="Token de verificación del webhook" />
        </div>
      </div>

      {cfg.metaLeadAds.pageId && (() => {
        const loading = subStatus === 'loading' || subStatus === 'subscribing';
        const subscribed = subStatus?.subscribed;
        const err = subStatus?.error;
        return (
          <div style={{ display:'flex', alignItems:'center', gap:10, padding:'8px 12px', borderRadius:8,
            background: subscribed ? '#f0fdf4' : '#fff7ed',
            border: `1px solid ${subscribed ? '#86efac' : '#fdba74'}` }}>
            <span style={{ fontSize:16 }}>{loading ? '⏳' : subscribed ? '✅' : '⚠️'}</span>
            <div style={{ flex:1, fontSize:13 }}>
              {loading ? (subStatus==='subscribing' ? 'Suscribiendo...' : 'Verificando suscripción...') :
               subscribed ? 'Webhook de leads activo — Meta enviará leads en tiempo real' :
               err ? `Error: ${err}` : 'Webhook no suscrito — los leads NO llegarán automáticamente'}
            </div>
            {!loading && !subscribed && (
              <button onClick={doSubscribe}
                style={{ fontSize:12, padding:'5px 14px', borderRadius:7, border:'none',
                  background:'#f97316', color:'#fff', fontWeight:700, cursor:'pointer', whiteSpace:'nowrap' }}>
                Activar webhook
              </button>
            )}
            {!loading && subscribed && (
              <button onClick={checkSubscription}
                style={{ fontSize:11, padding:'4px 10px', borderRadius:6, border:'1px solid #86efac',
                  background:'transparent', color:'#15803d', cursor:'pointer' }}>
                Verificar
              </button>
            )}
          </div>
        );
      })()}

      {cfg.metaLeadAds.pageId && (() => {
        const selIds = cfg.metaLeadAds.formIds || [];
        const selectedForms   = forms.filter(f =>  selIds.includes(f.id));
        const unselectedForms = forms.filter(f => !selIds.includes(f.id));
        const showConfig = cfg.metaLeadAds.sendToTokko || sheetsConnected;

        return (
          <div>
            <label style={{ ...S.label, marginBottom:6 }}>
              FORMULARIOS {loadingForms && <span style={{ fontWeight:400, color:'var(--ink-4)' }}>(cargando…)</span>}
            </label>

            {/* ── Formularios activos ── */}
            {selectedForms.length > 0 && (
              <div style={{ display:'flex', flexDirection:'column', gap:6, marginBottom:8 }}>
                {selectedForms.map(f => {
                  const expanded = expandedForms[f.id] ?? false;
                  return (
                    <div key={f.id} style={{ borderRadius:10, border:'1px solid var(--green-mid)', background:'var(--green-light)', overflow:'hidden' }}>
                      <div style={{ display:'flex', alignItems:'center', gap:8, padding:'9px 12px' }}>
                        <div style={{ width:7, height:7, borderRadius:'50%', background:'var(--green)', flexShrink:0 }} />
                        <span style={{ fontSize:13, fontWeight:600, color:'var(--ink-2)', flex:1, overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap' }}>
                          {f.name}
                        </span>
                        {showConfig && (
                          <button onClick={() => setExpandedForms(p => ({ ...p, [f.id]: !expanded }))}
                            style={{ fontSize:11, padding:'4px 10px', borderRadius:6, border:'1px solid var(--border)', background: expanded ? 'var(--green)' : 'var(--white)', color: expanded ? '#fff' : 'var(--ink-2)', cursor:'pointer', flexShrink:0, fontWeight:500, transition:'all .15s' }}>
                            {expanded ? '▲ Cerrar' : '⚙ Configurar'}
                          </button>
                        )}
                        <button onClick={() => {
                          const newIds = selIds.filter(x => x !== f.id);
                          const newLabels = { ...(cfg.metaLeadAds.formLabels || {}) };
                          delete newLabels[f.id];
                          patch('metaLeadAds', { formIds: newIds, formLabels: newLabels });
                          setExpandedForms(p => { const n = {...p}; delete n[f.id]; return n; });
                        }}
                          style={{ width:24, height:24, borderRadius:6, border:'1px solid var(--border)', background:'var(--white)', color:'var(--ink-4)', cursor:'pointer', fontSize:13, flexShrink:0, display:'flex', alignItems:'center', justifyContent:'center', lineHeight:1 }}>
                          ✕
                        </button>
                      </div>
                      {showConfig && expanded && <FormConfigSection f={f} cfg={cfg} patch={patch} patchFormSheets={patchFormSheets} setSheetsModal={setSheetsModal} sheetsConnected={sheetsConnected} />}
                    </div>
                  );
                })}
              </div>
            )}

            {/* ── Agregar formularios ── */}
            {unselectedForms.length > 0 && (
              <div>
                <button onClick={() => setFormsOpen(o => !o)}
                  style={{ display:'flex', alignItems:'center', gap:8, width:'100%', padding:'8px 12px', borderRadius:8, border:'1px dashed var(--border)', background:'transparent', cursor:'pointer', color:'var(--ink-3)', fontSize:12, textAlign:'left', transition:'border-color .15s' }}>
                  <span style={{ fontSize:16, color:'var(--green)', fontWeight:700, lineHeight:1 }}>{formsOpen ? '−' : '+'}</span>
                  <span>{formsOpen ? 'Ocultar lista' : `Agregar formulario (${unselectedForms.length} disponibles)`}</span>
                </button>

                {formsOpen && (
                  <div style={{ marginTop:6, border:'1px solid var(--border)', borderRadius:10, overflow:'hidden' }}>
                    {forms.length > 5 && (
                      <div style={{ padding:'8px 10px', borderBottom:'1px solid var(--border-soft)', background:'var(--cream)' }}>
                        <input
                          style={{ ...S.input, fontSize:12, margin:0 }}
                          placeholder="🔍 Buscar por nombre o ID…"
                          value={formSearch}
                          onChange={e => setFormSearch(e.target.value)}
                        />
                      </div>
                    )}
                    <div style={{ maxHeight:260, overflowY:'auto' }}>
                      {unselectedForms.filter(f => {
                        if (!formSearch.trim()) return true;
                        const q = formSearch.toLowerCase();
                        return f.name?.toLowerCase().includes(q) || f.id?.includes(q);
                      }).map((f, i, arr) => (
                        <button key={f.id}
                          onClick={() => {
                            const newNames = { ...(cfg.metaLeadAds.formNames || {}), [f.id]: f.name };
                            patch('metaLeadAds', { formIds: [...selIds, f.id], formNames: newNames });
                          }}
                          style={{ display:'flex', alignItems:'center', gap:8, width:'100%', padding:'9px 14px', border:'none', borderBottom: i < arr.length - 1 ? '1px solid var(--border-soft)' : 'none', background:'var(--white)', cursor:'pointer', textAlign:'left', fontSize:13, color:'var(--ink-2)', transition:'background .1s' }}
                          onMouseEnter={e => e.currentTarget.style.background='var(--cream)'}
                          onMouseLeave={e => e.currentTarget.style.background='var(--white)'}>
                          <span style={{ color:'var(--green)', fontSize:15, fontWeight:700, lineHeight:1, flexShrink:0 }}>+</span>
                          <span style={{ flex:1, overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap' }}>{f.name}</span>
                          <span style={{ fontSize:10, color:'var(--ink-4)', fontFamily:'monospace', flexShrink:0 }}>{f.id.slice(-8)}</span>
                        </button>
                      ))}
                    </div>
                  </div>
                )}
              </div>
            )}

            {!loadingForms && forms.length === 0 && (
              <div style={{ fontSize:12, color:'var(--ink-4)', padding:'6px 0' }}>No se encontraron formularios para esta página.</div>
            )}
            <div style={{ fontSize:11, color:'var(--ink-4)', marginTop:6 }}>Sin selección = acepta todos los formularios de la página.</div>
          </div>
        );
      })()}

      {/* ── Páginas adicionales de Facebook ─────────────────────────────── */}
      {(cfg.metaLeadAds.extraPages || []).map((ep, idx) => (
        <div key={idx} style={{ border: '1px solid var(--border)', borderRadius: 10, padding: '12px 14px', marginTop: 4, background: '#fafafa' }}>
          <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 10 }}>
            <span style={{ fontWeight: 700, fontSize: 13, color: 'var(--ink-2)' }}>📄 Página adicional {idx + 1}</span>
            <button onClick={() => removeExtraPage(idx)}
              style={{ fontSize: 11, padding: '3px 10px', borderRadius: 6, border: '1px solid #fca5a5', background: '#fff1f2', color: '#dc2626', cursor: 'pointer', fontWeight: 600 }}>
              ✕ Eliminar
            </button>
          </div>
          <MetaSelectField
            label="Página de Facebook"
            value={ep.pageId}
            items={availablePages(idx)}
            loading={meta.loading}
            placeholder="— Seleccioná una página —"
            onChange={(id, item) => {
              patchExtraPage(idx, { pageId: id, pageName: item?.name, pageAccessToken: item?.access_token, formIds: [] });
              if (id) loadExtraPageForms(id);
            }}
          />
          {ep.pageId && (
            <div style={{ marginTop: 8 }}>
              <label style={S.label}>Formularios {loadingExtraForms[ep.pageId] && '(cargando…)'}</label>
              {(extraPageForms[ep.pageId] || []).length > 0
                ? (
                  <div style={{ display: 'flex', flexDirection: 'column', gap: 4, marginTop: 4 }}>
                    {(extraPageForms[ep.pageId] || []).map(f => {
                      const sel = (ep.formIds || []).includes(f.id);
                      const formLabels = ep.formLabels?.[f.id] || [];
                      const fSheetsCfg = cfg.metaLeadAds?.formSheetsConfig?.[f.id];
                      return (
                        <div key={f.id} style={{ borderRadius: 8, background: sel ? 'var(--green-light)' : 'transparent', border: sel ? '1px solid var(--green-mid)' : '1px solid transparent', padding: sel ? '6px 10px 8px' : '2px 6px' }}>
                          <label style={{ display: 'flex', alignItems: 'center', gap: 8, cursor: 'pointer', fontSize: 13, color: 'var(--ink-2)' }}>
                            <input type="checkbox" checked={sel} onChange={e => {
                              const cur = ep.formIds || [];
                              const newIds = e.target.checked ? [...cur, f.id] : cur.filter(x => x !== f.id);
                              const newNames = { ...(ep.formNames || {}), [f.id]: f.name };
                              const newFormLabels = { ...(ep.formLabels || {}) };
                              if (!e.target.checked) delete newFormLabels[f.id];
                              patchExtraPage(idx, { formIds: newIds, formNames: newNames, formLabels: newFormLabels });
                            }} />
                            <span style={{ flex: 1 }}>{f.name}</span>
                            <span style={{ fontSize: 11, color: 'var(--ink-4)' }}>({f.id})</span>
                          </label>
                          {sel && cfg.metaLeadAds.sendToTokko && (
                            <div style={{ paddingLeft: 24, marginTop: 6, display: 'flex', flexDirection: 'column', gap: 6 }}>
                              <div>
                                <div style={{ fontSize: 11, color: 'var(--ink-3)', marginBottom: 2 }}>Etiquetas Tokko:</div>
                                <FormLabelInput labels={formLabels} onChange={newLabels => {
                                  patchExtraPage(idx, { formLabels: { ...(ep.formLabels || {}), [f.id]: newLabels } });
                                }} />
                              </div>
                              <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 6 }}>
                                <div>
                                  <div style={{ fontSize: 11, color: 'var(--ink-3)', marginBottom: 2 }}>Asesor (email)</div>
                                  <input style={{ ...S.input, fontSize: 12 }}
                                    value={ep.formAdvisorEmail?.[f.id] || ''}
                                    onChange={e => patchExtraPage(idx, { formAdvisorEmail: { ...(ep.formAdvisorEmail || {}), [f.id]: e.target.value } })}
                                    placeholder="asesor@empresa.com" />
                                </div>
                                <div>
                                  <div style={{ fontSize: 11, color: 'var(--ink-3)', marginBottom: 2 }}>Emprendimiento</div>
                                  <div style={{ display: 'flex', gap: 4 }}>
                                    <input style={{ ...S.input, width: 64, fontSize: 12, flexShrink: 0 }}
                                      value={ep.formDevelopmentId?.[f.id] || ''}
                                      onChange={e => patchExtraPage(idx, { formDevelopmentId: { ...(ep.formDevelopmentId || {}), [f.id]: e.target.value } })}
                                      placeholder="ID" />
                                    <input style={{ ...S.input, fontSize: 12 }}
                                      value={ep.formDevelopmentName?.[f.id] || ''}
                                      onChange={e => patchExtraPage(idx, { formDevelopmentName: { ...(ep.formDevelopmentName || {}), [f.id]: e.target.value } })}
                                      placeholder="Nombre" />
                                  </div>
                                </div>
                              </div>
                            </div>
                          )}
                          {sel && sheetsConnected && (
                            <div style={{ paddingLeft: 24, marginTop: 8 }}>
                              <div style={{ display:'flex', alignItems:'center', gap:8, marginBottom:8 }}>
                                <GSIcon size={14} />
                                <div style={{ fontSize:11, fontWeight:700, color:'var(--ink-2)' }}>Google Sheets</div>
                                <div onClick={() => patchFormSheets(f.id, { enabled: !(fSheetsCfg?.enabled) })}
                                  style={{ width:32, height:17, borderRadius:10, background: fSheetsCfg?.enabled ? 'var(--green)' : 'var(--border)', cursor:'pointer', position:'relative', flexShrink:0, transition:'background .2s', marginLeft:'auto' }}>
                                  <div style={{ position:'absolute', top:2, left: fSheetsCfg?.enabled ? 16 : 2, width:13, height:13, borderRadius:'50%', background:'#fff', transition:'left .2s' }} />
                                </div>
                              </div>
                              {fSheetsCfg?.enabled && (
                                <div style={{ display:'flex', flexDirection:'column', gap:6 }}>
                                  <input style={{ border:'1px solid var(--border)', borderRadius:8, padding:'7px 10px', fontSize:12, width:'100%', outline:'none', background:'var(--white)' }}
                                    value={fSheetsCfg?.spreadsheetId || ''}
                                    onChange={e => patchFormSheets(f.id, { spreadsheetId: e.target.value })}
                                    onBlur={e => { if (!e.target.value.trim()) return; apiFetch('/api/meta-lead-ads/sheets/save-url', { method:'POST', headers:{'Content-Type':'application/json'}, body: JSON.stringify({ formId: f.id, spreadsheetId: e.target.value.trim(), sheetName: fSheetsCfg?.sheetName || '' }) }).catch(()=>{}); }}
                                    placeholder="URL de la planilla de Google Sheets" />
                                  <div style={{ display:'flex', gap:4 }}>
                                    <input style={{ border:'1px solid var(--border)', borderRadius:8, padding:'7px 10px', fontSize:12, width:140, outline:'none', background:'var(--white)', flexShrink:0 }}
                                      value={fSheetsCfg?.sheetName || ''}
                                      onChange={e => patchFormSheets(f.id, { sheetName: e.target.value })}
                                      onBlur={e => { if (!fSheetsCfg?.spreadsheetId) return; apiFetch('/api/meta-lead-ads/sheets/save-url', { method:'POST', headers:{'Content-Type':'application/json'}, body: JSON.stringify({ formId: f.id, spreadsheetId: fSheetsCfg.spreadsheetId, sheetName: e.target.value.trim() }) }).catch(()=>{}); }}
                                      placeholder="Hoja (ej: Hoja1)" />
                                    <button onClick={() => setSheetsModal({ formId: f.id, formName: f.name, spreadsheetId: fSheetsCfg?.spreadsheetId || '', sheetName: fSheetsCfg?.sheetName || '' })}
                                      disabled={!fSheetsCfg?.spreadsheetId}
                                      style={{ flex:1, padding:'7px 10px', borderRadius:7, border:'1px solid var(--border)', background: fSheetsCfg?.spreadsheetId ? 'var(--green)' : 'var(--border)', color: fSheetsCfg?.spreadsheetId ? '#fff' : 'var(--ink-4)', fontWeight:600, fontSize:11, cursor: fSheetsCfg?.spreadsheetId ? 'pointer' : 'default', whiteSpace:'nowrap' }}>
                                      {fSheetsCfg?.knownHeaders?.length > 0 ? '↻ Remapear' : '🗂 Columnas'}
                                    </button>
                                  </div>
                                </div>
                              )}
                            </div>
                          )}
                        </div>
                      );
                    })}
                  </div>
                )
                : !loadingExtraForms[ep.pageId] && (
                  <div style={{ fontSize: 12, color: 'var(--ink-4)', marginTop: 4 }}>No se encontraron formularios para esta página.</div>
                )
              }
            </div>
          )}
        </div>
      ))}

      {/* Botón agregar página */}
      {cfg.metaLeadAds.pageId && (
        <button onClick={addExtraPage}
          style={{ fontSize: 12, padding: '6px 14px', borderRadius: 8, border: '1px dashed var(--border)', background: 'transparent', color: 'var(--ink-3)', cursor: 'pointer', marginTop: 2, display: 'flex', alignItems: 'center', gap: 6 }}>
          + Agregar otra página de Facebook
        </button>
      )}

      {/* ── Bulk import leads acumulados ─────────────────────────────────── */}
      {(cfg.metaLeadAds.formIds || []).length > 0 && (
        <div style={{ background:'#f8fafc', border:'1px solid var(--border)', borderRadius:12, padding:'14px 16px', marginTop:4 }}>
          <div style={{ fontWeight:700, fontSize:13, marginBottom:6 }}>📥 Enviar leads acumulados</div>
          <div style={{ fontSize:12, color:'var(--ink-4)', marginBottom:12 }}>
            Trae todos los leads existentes en los <strong>{(cfg.metaLeadAds.formIds||[]).length} formularios seleccionados</strong> y los procesa:
            crea contactos en Pipochat{cfg.metaLeadAds.sendToTokko ? ' y los envía a Tokko CRM' : ''}.
          </div>

          {/* Pipochat connection test */}
          <div style={{ marginBottom:12 }}>
            <div style={{ display:'flex', alignItems:'center', gap:12, flexWrap:'wrap' }}>
              <button style={{ ...S.outlineBtn, fontSize:12 }} onClick={runPipoTest} disabled={pipoTestLoading}>
                {pipoTestLoading ? '⏳…' : '🧪 Probar conexión Pipochat'}
              </button>
              {pipoTestResult && (
                pipoTestResult.success
                  ? <span style={{ fontSize:12, color:'#16a34a', fontWeight:600 }} title={(pipoTestResult.steps||[]).join('\n')}>
                      ✅ {pipoTestResult.message}
                    </span>
                  : <span style={{ fontSize:12, color:'var(--danger)', fontWeight:600 }}>
                      ❌ {pipoTestResult.step}: error en createContact
                      <button onClick={() => setShowApiKeyForm(v => !v)}
                        style={{ marginLeft:8, fontSize:11, color:'#2563eb', background:'none', border:'none', cursor:'pointer', textDecoration:'underline' }}>
                        {showApiKeyForm ? 'cerrar' : 'actualizar API Key'}
                      </button>
                    </span>
              )}
            </div>

            {/* API key update form — shown on 401 error */}
            {showApiKeyForm && (
              <div style={{ marginTop:10, background:'#fffbeb', border:'1px solid #fbbf24', borderRadius:8, padding:'12px 14px' }}>
                <div style={{ fontSize:12, fontWeight:600, marginBottom:6, color:'#92400e' }}>
                  🔑 Actualizar API Key de Pipochat (X-Secret-Key)
                </div>
                <div style={{ fontSize:11, color:'var(--ink-4)', marginBottom:8 }}>
                  Encontrala en Pipochat → Configuración → Integraciones → API Key
                </div>
                <div style={{ display:'flex', gap:8, alignItems:'center' }}>
                  <input
                    type="password"
                    placeholder="Pegá la nueva API Key acá…"
                    value={newApiKey}
                    onChange={e => setNewApiKey(e.target.value)}
                    onKeyDown={e => e.key === 'Enter' && saveApiKey()}
                    style={{ ...S.input, flex:1, fontSize:12, fontFamily:'monospace' }}
                  />
                  <button
                    style={{ ...S.saveBtn, fontSize:12, padding:'6px 14px', background: apiKeyLoading ? 'var(--ink-3)' : '#2563eb' }}
                    onClick={saveApiKey}
                    disabled={apiKeyLoading || !newApiKey.trim()}
                  >
                    {apiKeyLoading ? '⏳…' : 'Guardar'}
                  </button>
                </div>
                {apiKeyResult && (
                  <div style={{ marginTop:8, fontSize:12, color: apiKeyResult.success ? '#16a34a' : 'var(--danger)', fontWeight:600 }}>
                    {apiKeyResult.success ? `✅ ${apiKeyResult.message}` : `❌ ${apiKeyResult.error}`}
                  </div>
                )}
              </div>
            )}
          </div>

          <label style={{ display:'flex', alignItems:'center', gap:8, fontSize:13, marginBottom:8, cursor:'pointer' }}>
            <input type="checkbox" checked={sendWhatsapp} onChange={e => setSendWhatsapp(e.target.checked)} />
            <span>Enviar también mensajes de WhatsApp automáticos</span>
            <span style={{ fontSize:11, color:'var(--ink-4)' }}>(por defecto se omiten para leads viejos)</span>
          </label>

          <label style={{ display:'flex', alignItems:'center', gap:8, fontSize:13, marginBottom:12, cursor:'pointer' }}>
            <input type="checkbox" checked={testMode} onChange={e => setTestMode(e.target.checked)} />
            <span style={{ fontWeight: testMode ? 600 : 400 }}>Modo test — procesar solo 1 lead</span>
            <span style={{ fontSize:11, color: testMode ? '#92400e' : 'var(--ink-4)' }}>
              {testMode ? '⚠️ solo el 1er lead del 1er formulario' : '(para verificar antes de enviar todos)'}
            </span>
          </label>

          <div style={{ display:'flex', gap:8, flexWrap:'wrap', marginBottom:8 }}>
            <button
              style={{ ...S.saveBtn, background: previewLoading ? 'var(--ink-3)' : '#0369a1', flex:'0 0 auto' }}
              onClick={loadPreview}
              disabled={previewLoading || bulkLoading}
            >
              {previewLoading ? '⏳ Cargando…' : '👁️ Ver leads antes de enviar'}
            </button>
            <button
              style={{ ...S.saveBtn, background: bulkLoading ? 'var(--ink-3)' : testMode ? '#92400e' : '#6d28d9', flex:'0 0 auto' }}
              onClick={runBulkSend}
              disabled={bulkLoading || (previewData && selectedLeadIds.size === 0)}
            >
              {bulkLoading ? '⏳ Procesando…' : testMode ? '🧪 Probar con 1 lead' : previewData ? `📥 Enviar ${selectedLeadIds.size} seleccionados` : '📥 Enviar todos los leads'}
            </button>
          </div>

          {/* Preview table */}
          {previewData && !previewData.error && (
            <div style={{ marginBottom:12 }}>
              {previewData.forms.map(form => (
                <div key={form.formId} style={{ marginBottom:12 }}>
                  <div style={{ display:'flex', alignItems:'center', gap:10, marginBottom:6 }}>
                    <span style={{ fontWeight:600, fontSize:13 }}>{form.formName}</span>
                    <span style={{ fontSize:12, color:'var(--ink-4)' }}>{form.leads.length} leads</span>
                    <button
                      onClick={() => toggleAll(form.leads)}
                      style={{ fontSize:11, padding:'2px 8px', borderRadius:4, border:'1px solid var(--ink-5)', background:'var(--surface)', cursor:'pointer' }}
                    >
                      {form.leads.every(l => selectedLeadIds.has(l.id)) ? 'Deseleccionar todos' : 'Seleccionar todos'}
                    </button>
                  </div>
                  <div style={{ border:'1px solid var(--ink-6)', borderRadius:8, overflow:'hidden', fontSize:12 }}>
                    <div style={{ display:'grid', gridTemplateColumns:'32px 1fr 1fr 1fr 100px', background:'var(--ink-7)', padding:'6px 10px', fontWeight:600, color:'var(--ink-2)', gap:8 }}>
                      <span></span><span>Nombre</span><span>Teléfono</span><span>Email</span><span>Fecha</span>
                    </div>
                    {form.leads.length === 0 && (
                      <div style={{ padding:'10px 12px', color:'var(--ink-4)' }}>Sin leads</div>
                    )}
                    {form.leads.map((lead, i) => (
                      <div
                        key={lead.id}
                        onClick={() => toggleLead(lead.id)}
                        style={{ display:'grid', gridTemplateColumns:'32px 1fr 1fr 1fr 100px', padding:'6px 10px', gap:8, cursor:'pointer', background: i % 2 === 0 ? 'var(--surface)' : 'var(--ink-7)', alignItems:'center', opacity: selectedLeadIds.has(lead.id) ? 1 : 0.45 }}
                      >
                        <input type="checkbox" checked={selectedLeadIds.has(lead.id)} onChange={() => toggleLead(lead.id)} onClick={e => e.stopPropagation()} />
                        <span style={{ fontWeight:500, overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap', display:'flex', alignItems:'center', gap:5 }}>
                          {lead.name}
                          {lead.alreadySent && <span style={{ fontSize:10, background:'#dcfce7', color:'#166534', borderRadius:4, padding:'1px 5px', fontWeight:600, flexShrink:0 }}>Ya enviado</span>}
                        </span>
                        <span style={{ color:'var(--ink-3)', overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap' }}>{lead.phone || '—'}</span>
                        <span style={{ color:'var(--ink-4)', overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap' }}>{lead.email || '—'}</span>
                        <span style={{ color:'var(--ink-4)' }}>{lead.created_time ? new Date(lead.created_time).toLocaleDateString('es-AR') : '—'}</span>
                      </div>
                    ))}
                  </div>
                </div>
              ))}
              <div style={{ fontSize:12, color:'var(--ink-4)', marginTop:4 }}>
                {selectedLeadIds.size} de {previewData.forms.reduce((s, f) => s + f.leads.length, 0)} leads seleccionados
              </div>
            </div>
          )}

          {bulkLoading && (
            <div style={{ fontSize:12, color:'var(--ink-3)', marginTop:10 }}>
              Esto puede tardar unos minutos dependiendo de la cantidad de leads…
            </div>
          )}

          {bulkResult && (
            <div style={{ marginTop:14 }}>
              {bulkResult.error ? (
                <div style={{ color:'var(--danger)', background:'var(--danger-light)', borderRadius:8, padding:'10px 14px', fontSize:13 }}>
                  ❌ {bulkResult.error}
                </div>
              ) : (
                <>
                  {/* counters */}
                  <div style={{ display:'flex', gap:10, flexWrap:'wrap', marginBottom:12 }}>
                    {[
                      { label:'Total leads',         value: bulkResult.totalLeads,        color:'var(--ink-2)' },
                      { label:'💬 Pipochat OK',      value: bulkResult.totalPipochatOk ?? bulkResult.totalOk,   color:'#16a34a' },
                      { label:'💬 Pipochat error',   value: bulkResult.totalPipochatErr ?? bulkResult.totalErrors, color:'var(--danger)' },
                      { label:'⚠️ Omitidos',         value: bulkResult.totalSkip,         color:'#92400e' },
                      ...(bulkResult.totalTokkoOk != null ? [
                        { label:'🏠 Tokko OK',       value: bulkResult.totalTokkoOk,      color:'#16a34a' },
                        { label:'🏠 Tokko error',    value: bulkResult.totalTokkoErr,     color:'var(--danger)' },
                      ] : []),
                    ].map(({ label, value, color }) => (
                      <div key={label} style={{ textAlign:'center', background:'var(--white)', border:'1px solid var(--border)', borderRadius:8, padding:'8px 14px', minWidth:70 }}>
                        <div style={{ fontSize:20, fontWeight:700, color }}>{value}</div>
                        <div style={{ fontSize:10, color:'var(--ink-4)', marginTop:2 }}>{label}</div>
                      </div>
                    ))}
                  </div>

                  {/* per-form details */}
                  {(bulkResult.forms || []).map(f => (
                    <details key={f.formId} style={{ marginBottom:8, background:'var(--white)', border:'1px solid var(--border)', borderRadius:8 }}>
                      <summary style={{ padding:'8px 12px', fontSize:13, cursor:'pointer', fontWeight:600 }}>
                        {f.formName}
                        <span style={{ fontWeight:400, color:'var(--ink-4)', marginLeft:8 }}>
                          {f.total} leads · 💬 {f.pipochatOk ?? f.ok}✅{(f.pipochatErrors ?? f.errors) > 0 ? ` ${f.pipochatErrors ?? f.errors}❌` : ''}{f.skipped > 0 ? ` ${f.skipped}⚠️` : ''}
                          {f.tokkoOk != null ? ` · 🏠 ${f.tokkoOk}✅${f.tokkoErrors > 0 ? ` ${f.tokkoErrors}❌` : ''}` : ''}
                        </span>
                      </summary>
                      <div style={{ padding:'0 12px 10px', maxHeight:300, overflowY:'auto' }}>
                        <div style={{ display:'grid', gridTemplateColumns:'1fr auto auto auto', gap:'2px 10px', fontSize:12, color:'var(--ink-4)', padding:'4px 0 6px', borderBottom:'1px solid var(--border)', fontWeight:600 }}>
                          <span>Nombre</span><span>Teléfono</span><span>Pipochat</span><span>Tokko</span>
                        </div>
                        {(f.details || []).map((d, i) => {
                          const pipochatIcon = d.pipochat === 'created' ? '✅ nuevo'
                            : d.pipochat === 'found'   ? '✅ exist.'
                            : d.pipochat === 'error'   ? '❌'
                            : d.status === 'ok'        ? '✅'
                            : d.status === 'skipped'   ? '⚠️' : '❌';
                          const pipochatTitle = d.pipochatError || (d.pipochatId ? `ID: ${d.pipochatId}` : '');
                          const tokkoIcon = d.tokko === 'ok' ? '✅' : d.tokko === 'error' ? '❌' : '—';
                          const tokkoTitle = d.tokko === 'error' ? (d.error || 'Error desconocido') : d.tokkoId ? `ID: ${d.tokkoId}` : '';
                          const nameTitle = d.rawFields?.length
                            ? `${d.name}\n\nCampos del formulario:\n${d.rawFields.join(', ')}`
                            : d.name;
                          return (
                            <div key={i} style={{ display:'grid', gridTemplateColumns:'1fr auto auto auto', gap:'2px 10px', fontSize:12, padding:'4px 0', borderBottom:'1px solid var(--border)', alignItems:'center' }}>
                              <span style={{ color: d.pipochat === 'error' ? 'var(--danger)' : d.name === 'Sin nombre' ? 'var(--warning)' : 'var(--ink-2)', overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap', cursor: d.rawFields?.length ? 'help' : 'default' }} title={nameTitle}>{d.name}{d.rawFields?.length ? ' ⓘ' : ''}</span>
                              <span style={{ color:'var(--ink-4)', fontFamily:'monospace', fontSize:11 }}>{d.phone || '—'}</span>
                              <span title={pipochatTitle} style={{ cursor: pipochatTitle ? 'help' : 'default', color: d.pipochat === 'error' ? 'var(--danger)' : d.pipochat === 'found' ? '#2563eb' : 'inherit', fontSize:11 }}>
                                {pipochatIcon}
                              </span>
                              <span title={tokkoTitle} style={{ cursor: tokkoTitle ? 'help' : 'default', color: d.tokko === 'error' ? 'var(--danger)' : 'inherit' }}>
                                {tokkoIcon}
                              </span>
                            </div>
                          );
                        })}
                      </div>
                    </details>
                  ))}
                </>
              )}
            </div>
          )}
        </div>
      )}

      {/* ── Acciones automáticas ──────────────────────────────────────────── */}
      <LeadAdsActionsEditor
        actions={cfg.metaLeadAds.actions || []}
        inboxes={inboxes}
        forms={forms}
        onChange={actions => patch('metaLeadAds', { actions })}
      />

      {/* ── Log de leads enviados a Tokko ─────────────────────────────────── */}
      <div style={{ marginTop:8, border:'1px solid var(--border)', borderRadius:10, overflow:'hidden' }}>
        <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between', padding:'10px 14px', background:'var(--cream-mid)', borderBottom: tokkoLog ? '1px solid var(--border)' : 'none' }}>
          <span style={{ fontWeight:700, fontSize:13 }}>🏠 Log de leads enviados a Tokko</span>
          <button onClick={loadTokkoLog} disabled={loadingTokkoLog}
            style={{ fontSize:12, padding:'3px 12px', borderRadius:6, border:'1px solid var(--border)', background:'var(--white)', cursor:'pointer', color:'var(--ink-2)' }}>
            {loadingTokkoLog ? 'Cargando…' : tokkoLog ? '↺ Actualizar' : 'Ver log'}
          </button>
        </div>
        {tokkoLog && (
          tokkoLog.length === 0
            ? <div style={{ padding:'12px 14px', fontSize:13, color:'var(--ink-4)' }}>No hay registros todavía.</div>
            : <div style={{ maxHeight:320, overflowY:'auto' }}>
                <div style={{ display:'grid', gridTemplateColumns:'130px 1fr auto auto auto', gap:'0 10px', fontSize:11, fontWeight:600, color:'var(--ink-4)', padding:'6px 14px', borderBottom:'1px solid var(--border)', background:'var(--cream-mid)', position:'sticky', top:0 }}>
                  <span>Fecha</span><span>Nombre</span><span>Teléfono</span><span>Formulario</span><span>Estado</span>
                </div>
                {tokkoLog.map((e, i) => {
                  const dt = new Date(e.ts);
                  const dateStr = dt.toLocaleDateString('es-AR', { day:'2-digit', month:'2-digit', year:'2-digit' }) + ' ' + dt.toLocaleTimeString('es-AR', { hour:'2-digit', minute:'2-digit' });
                  return (
                    <div key={i} style={{ display:'grid', gridTemplateColumns:'130px 1fr auto auto auto', gap:'0 10px', fontSize:12, padding:'5px 14px', borderBottom:'1px solid var(--border-soft)', alignItems:'center', background: i%2===0 ? 'var(--white)' : 'transparent' }}>
                      <span style={{ fontSize:11, color:'var(--ink-4)', fontFamily:'monospace' }}>{dateStr}</span>
                      <span style={{ overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap' }} title={e.name}>{e.name}</span>
                      <span style={{ color:'var(--ink-4)', fontFamily:'monospace', fontSize:11 }}>{e.phone || '—'}</span>
                      <span style={{ color:'var(--ink-3)', overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap', maxWidth:140 }} title={e.formName}>{e.formName || '—'}</span>
                      <span title={e.error || (e.tokkoId ? `ID: ${e.tokkoId}` : '')} style={{ cursor: e.error||e.tokkoId ? 'help' : 'default', color: e.status==='ok' ? 'var(--success)' : 'var(--danger)' }}>
                        {e.status==='ok' ? `✅ ${e.tokkoId||''}` : `❌`}
                      </span>
                    </div>
                  );
                })}
              </div>
        )}
      </div>
    </>
  );
}

// ─── PropertyPanel ────────────────────────────────────────────────────────────
function PropertyPanel() {
  const [properties, setProperties] = React.useState([]);
  const [meta,       setMeta]       = React.useState(null);
  const [total,      setTotal]      = React.useState(0);
  const [loading,    setLoading]    = React.useState(false);
  const [syncing,    setSyncing]    = React.useState(false);
  const [syncResult, setSyncResult] = React.useState(null);
  const [selected,   setSelected]   = React.useState(null); // property detail modal
  const [page,       setPage]       = React.useState(0);

  // Template send flow
  const [sendModal,  setSendModal]  = React.useState(null); // property to send as template
  const [templates,  setTemplates]  = React.useState([]);
  const [tplLoading, setTplLoading] = React.useState(false);
  const [selTpl,     setSelTpl]     = React.useState(null); // selected template
  const [tplVars,    setTplVars]    = React.useState({});   // variable overrides
  const [sendPhone,  setSendPhone]  = React.useState('');
  const [sending,    setSending]    = React.useState(false);
  const [sendResult, setSendResult] = React.useState(null);
  const PAGE = 20;

  // Filters
  const [q,         setQ]         = React.useState('');
  const [tipo,      setTipo]      = React.useState('');
  const [operacion, setOperacion] = React.useState('');
  const [barrio,    setBarrio]    = React.useState('');

  // Map property fields to template variable names automatically
  const propertyToVars = (prop, tpl) => {
    if (!tpl?.variables) return {};
    const vars = {};
    const fieldMap = {
      titulo: prop.titulo, title: prop.titulo,
      tipo_propiedad: prop.tipo, tipo: prop.tipo,
      operacion: prop.operacion || '', operation: prop.operacion || '',
      ambientes: prop.ambientes ? String(prop.ambientes) + ' ambientes' : '',
      dormitorios: prop.dormitorios ? String(prop.dormitorios) + ' dormitorios' : '',
      precio: prop.precio_str || '',
      price: prop.precio_str || '',
      direccion: prop.direccion || '', address: prop.direccion || '',
      barrio: prop.barrio || '',
      ciudad: prop.ciudad || '',
      m2: prop.m2_cubiertos ? prop.m2_cubiertos + ' m²' : '',
      descripcion: prop.descripcion_corta || '',
      link: prop.link_tokko || '',
      url: prop.link_tokko || '',
    };
    for (const v of (tpl.variables || [])) {
      const key = (v.name || v.key || '').toLowerCase();
      vars[v.name || v.key] = fieldMap[key] || '';
    }
    return vars;
  };

  const openSendModal = async (prop) => {
    setSendModal(prop); setSelTpl(null); setTplVars({}); setSendPhone(''); setSendResult(null);
    setTplLoading(true);
    try {
      const r = await apiFetch('/api/pipochat/templates');
      const data = await r.json().catch(() => ({ templates: [] }));
      setTemplates(Array.isArray(data.templates) ? data.templates : Array.isArray(data) ? data : []);
    } catch (e) {
      setTemplates([]);
    }
    setTplLoading(false);
  };

  const selectTemplate = (tpl) => {
    setSelTpl(tpl);
    setTplVars(propertyToVars(sendModal, tpl));
  };

  const sendTemplate = async () => {
    if (!selTpl || !sendPhone.trim()) return;
    setSending(true); setSendResult(null);
    const data = await apiFetch('/api/pipochat/send-template', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        phone: sendPhone.trim(),
        templateId: selTpl.id || selTpl._id,
        variables: tplVars,
        imageUrl: sendModal?.imagen_principal || undefined,
        propertyId: sendModal?.id ? String(sendModal.id) : undefined,
      }),
    }).then(r => r.json()).catch(e => ({ error: e.message }));
    setSendResult(data);
    setSending(false);
  };

  const load = async (p = 0) => {
    setLoading(true);
    const params = new URLSearchParams({ limit: PAGE, offset: p * PAGE });
    if (q)         params.set('q', q);
    if (tipo)      params.set('tipo', tipo);
    if (operacion) params.set('operacion', operacion);
    if (barrio)    params.set('barrio', barrio);
    const data = await apiFetch(`/api/properties?${params}`).then(r => r.json()).catch(() => ({ items: [], total: 0 }));
    setProperties(data.items || []);
    setTotal(data.total || 0);
    setPage(p);
    setLoading(false);
  };

  const loadMeta = async () => {
    const data = await apiFetch('/api/properties/meta').then(r => r.json()).catch(() => null);
    setMeta(data);
  };

  React.useEffect(() => { load(0); loadMeta(); }, []);

  const sync = async () => {
    setSyncing(true); setSyncResult(null);
    const data = await apiFetch('/api/properties/sync', { method: 'POST' }).then(r => r.json()).catch(e => ({ error: e.message }));
    setSyncResult(data);
    setSyncing(false);
    if (!data.error) { load(0); loadMeta(); }
  };

  const search = (e) => { e.preventDefault(); load(0); };

  const fmtPrice = (p) => p.precio_str || '—';
  const fmtLocation = (p) => [p.barrio, p.ciudad].filter(Boolean).join(', ') || p.direccion || '—';
  const fmtRooms = (p) => p.ambientes ? `${p.ambientes} amb.` : '';

  return (
    <div style={S.editor}>
      <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between', marginBottom:20 }}>
        <div>
          <div style={S.pageTitle}>🏠 Propiedades</div>
          {meta && (
            <div style={{ fontSize:12, color:'var(--ink-4)', marginTop:2 }}>
              {meta.total} propiedades
              {meta.lastSync && ` · última sync: ${new Date(meta.lastSync).toLocaleString('es-AR')}`}
            </div>
          )}
        </div>
        <button style={{ ...S.saveBtn, display:'flex', alignItems:'center', gap:6 }} onClick={sync} disabled={syncing}>
          {syncing ? '⏳ Sincronizando…' : '🔄 Sincronizar desde Tokko'}
        </button>
      </div>

      {/* Sync result */}
      {syncResult && (
        <div style={{ ...S.card, marginBottom:16, background: syncResult.error ? 'var(--danger-light)' : '#f0fdf4', borderColor: syncResult.error ? 'var(--danger)' : '#86efac' }}>
          {syncResult.error ? (
            <div style={{ color:'var(--danger)', fontSize:13 }}>❌ {syncResult.error}</div>
          ) : (
            <div style={{ fontSize:13, color:'#166534' }}>
              ✅ Sincronización completada — <strong>{syncResult.synced}</strong> propiedades importadas
              {syncResult.durationMs && ` en ${(syncResult.durationMs/1000).toFixed(1)}s`}
              {syncResult.errors?.length > 0 && (
                <div style={{ marginTop:6, color:'#92400e', fontSize:12 }}>
                  ⚠️ {syncResult.errors.length} error{syncResult.errors.length>1?'es':''}:
                  <ul style={{ margin:'4px 0 0 16px', padding:0 }}>
                    {syncResult.errors.map((e,i) => <li key={i}>{e}</li>)}
                  </ul>
                </div>
              )}
            </div>
          )}
        </div>
      )}

      {/* Filters */}
      <form onSubmit={search} style={{ ...S.card, marginBottom:16, display:'flex', gap:8, flexWrap:'wrap', alignItems:'flex-end' }}>
        <div style={S.col}>
          <label style={S.label}>Buscar</label>
          <input style={{ ...S.input, minWidth:200 }} value={q} onChange={e => setQ(e.target.value)} placeholder="título, barrio, dirección…" />
        </div>
        <div style={S.col}>
          <label style={S.label}>Tipo</label>
          <select style={S.input} value={tipo} onChange={e => setTipo(e.target.value)}>
            <option value="">Todos</option>
            <option>Departamento</option><option>Casa</option><option>PH</option>
            <option>Oficina</option><option>Local</option><option>Terreno</option><option>Cochera</option>
          </select>
        </div>
        <div style={S.col}>
          <label style={S.label}>Operación</label>
          <select style={S.input} value={operacion} onChange={e => setOperacion(e.target.value)}>
            <option value="">Todas</option>
            <option>Venta</option><option>Alquiler</option><option>Alquiler Temporario</option>
          </select>
        </div>
        <div style={S.col}>
          <label style={S.label}>Barrio / Ciudad</label>
          <input style={S.input} value={barrio} onChange={e => setBarrio(e.target.value)} placeholder="ej: Palermo" />
        </div>
        <button type="submit" style={{ ...S.saveBtn, whiteSpace:'nowrap' }}>Buscar</button>
        {(q||tipo||operacion||barrio) && (
          <button type="button" style={{ ...S.outlineBtn }} onClick={() => { setQ(''); setTipo(''); setOperacion(''); setBarrio(''); setTimeout(() => load(0), 50); }}>Limpiar</button>
        )}
      </form>

      {/* Grid */}
      {loading ? (
        <div style={{ textAlign:'center', padding:40, color:'var(--ink-4)' }}>Cargando propiedades…</div>
      ) : properties.length === 0 ? (
        <div style={{ ...S.card, textAlign:'center', padding:40, color:'var(--ink-4)' }}>
          {total === 0 && !q && !tipo && !operacion && !barrio
            ? <div><div style={{ fontSize:32, marginBottom:12 }}>🏠</div><strong>Sin propiedades cargadas</strong><br/><span style={{ fontSize:13 }}>Hacé clic en "Sincronizar desde Tokko" para importar el catálogo.</span></div>
            : 'No se encontraron propiedades con esos filtros.'
          }
        </div>
      ) : (
        <>
          <div style={{ fontSize:12, color:'var(--ink-4)', marginBottom:10 }}>
            {total} resultado{total !== 1 ? 's' : ''} · página {page+1}/{Math.ceil(total/PAGE)}
          </div>
          <div style={{ display:'grid', gridTemplateColumns:'repeat(auto-fill, minmax(280px, 1fr))', gap:14 }}>
            {properties.map(p => (
              <div key={p.id} onClick={() => setSelected(p)}
                style={{ background:'var(--white)', border:'1px solid var(--border)', borderRadius:12, overflow:'hidden', cursor:'pointer', transition:'box-shadow .15s, transform .15s' }}
                onMouseEnter={e => { e.currentTarget.style.boxShadow = 'var(--shadow-md)'; e.currentTarget.style.transform = 'translateY(-2px)'; }}
                onMouseLeave={e => { e.currentTarget.style.boxShadow = ''; e.currentTarget.style.transform = ''; }}>
                {/* Image */}
                <div style={{ width:'100%', height:160, background:'var(--cream)', position:'relative', overflow:'hidden' }}>
                  {p.imagen_principal ? (
                    <img src={p.imagen_principal} alt={p.titulo} style={{ width:'100%', height:'100%', objectFit:'cover' }} onError={e => { e.target.style.display='none'; }} />
                  ) : (
                    <div style={{ width:'100%', height:'100%', display:'flex', alignItems:'center', justifyContent:'center', fontSize:40 }}>🏠</div>
                  )}
                  {p.destacada && <span style={{ position:'absolute', top:8, left:8, background:'#f59e0b', color:'#fff', fontSize:10, fontWeight:700, padding:'2px 8px', borderRadius:99 }}>⭐ DESTACADA</span>}
                  <span style={{ position:'absolute', top:8, right:8, background:'rgba(0,0,0,.55)', color:'#fff', fontSize:10, fontWeight:600, padding:'2px 8px', borderRadius:99 }}>{p.operacion}</span>
                </div>
                {/* Info */}
                <div style={{ padding:'12px 14px' }}>
                  <div style={{ fontSize:12, color:'var(--ink-4)', marginBottom:4, display:'flex', gap:6 }}>
                    <span>{p.tipo}</span>
                    {fmtRooms(p) && <><span>·</span><span>{fmtRooms(p)}</span></>}
                    {p.m2_cubiertos && <><span>·</span><span>{p.m2_cubiertos} m²</span></>}
                  </div>
                  <div style={{ fontSize:13, fontWeight:600, color:'var(--ink)', lineHeight:1.3, marginBottom:6, display:'-webkit-box', WebkitLineClamp:2, WebkitBoxOrient:'vertical', overflow:'hidden' }}>
                    {p.titulo}
                  </div>
                  <div style={{ fontSize:12, color:'var(--ink-3)', marginBottom:8 }}>📍 {fmtLocation(p)}</div>
                  <div style={{ fontSize:15, fontWeight:700, color:'var(--green)' }}>{fmtPrice(p)}</div>
                </div>
              </div>
            ))}
          </div>
          {/* Pagination */}
          {total > PAGE && (
            <div style={{ display:'flex', justifyContent:'center', gap:8, marginTop:20 }}>
              <button style={S.outlineBtn} disabled={page === 0} onClick={() => load(page-1)}>← Anterior</button>
              <span style={{ fontSize:13, color:'var(--ink-3)', alignSelf:'center' }}>Pág {page+1} / {Math.ceil(total/PAGE)}</span>
              <button style={S.outlineBtn} disabled={(page+1)*PAGE >= total} onClick={() => load(page+1)}>Siguiente →</button>
            </div>
          )}
        </>
      )}

      {/* ── Send as Template modal ────────────────────────────────────────── */}
      {sendModal && (
        <div style={{ position:'fixed', inset:0, background:'rgba(0,0,0,.5)', zIndex:9999, display:'flex', alignItems:'center', justifyContent:'center', padding:20 }}
          onClick={() => setSendModal(null)}>
          <div style={{ background:'var(--white)', borderRadius:16, maxWidth:680, width:'100%', maxHeight:'92vh', overflow:'auto', boxShadow:'0 20px 60px rgba(0,0,0,.3)' }}
            onClick={e => e.stopPropagation()}>
            <div style={{ padding:24 }}>
              <div style={{ display:'flex', justifyContent:'space-between', alignItems:'center', marginBottom:20 }}>
                <div>
                  <div style={{ fontWeight:700, fontSize:16 }}>📤 Enviar propiedad como template</div>
                  <div style={{ fontSize:12, color:'var(--ink-4)', marginTop:2 }}>{sendModal.titulo}</div>
                </div>
                <button type="button" onClick={() => setSendModal(null)} style={{ background:'none', border:'none', fontSize:22, cursor:'pointer', color:'var(--ink-4)' }}>✕</button>
              </div>

              {/* Step 1: Pick template */}
              <div style={{ marginBottom:20 }}>
                <div style={{ fontSize:13, fontWeight:600, color:'var(--ink-2)', marginBottom:10 }}>1. Seleccioná un template de WhatsApp</div>
                {tplLoading ? (
                  <div style={{ fontSize:13, color:'var(--ink-4)' }}>Cargando templates…</div>
                ) : templates.length === 0 ? (
                  <div style={{ fontSize:13, color:'var(--ink-4)', background:'var(--cream)', borderRadius:8, padding:'10px 14px' }}>
                    Sin templates disponibles. Creá uno en Pipochat primero.
                  </div>
                ) : (
                  <div style={{ display:'flex', flexDirection:'column', gap:6, maxHeight:220, overflowY:'auto' }}>
                    {templates.filter(t => t.status === 'approved' || t.status === 'APPROVED' || !t.status).map(t => (
                      <div key={t.id || t._id} onClick={() => selectTemplate(t)}
                        style={{ border:`2px solid ${selTpl?.id === t.id || selTpl?._id === t._id ? '#7c3aed' : 'var(--border)'}`,
                          borderRadius:8, padding:'10px 14px', cursor:'pointer',
                          background: selTpl?.id === t.id || selTpl?._id === t._id ? '#faf5ff' : 'var(--white)' }}>
                        <div style={{ display:'flex', justifyContent:'space-between', alignItems:'center' }}>
                          <span style={{ fontSize:13, fontWeight:600, color:'var(--ink)', fontFamily:'monospace' }}>{t.name}</span>
                          <span style={{ fontSize:11, background: t.status === 'approved' || t.status === 'APPROVED' ? '#d1fae5' : '#fef3c7',
                            color: t.status === 'approved' || t.status === 'APPROVED' ? '#166534' : '#92400e',
                            padding:'1px 8px', borderRadius:99, fontWeight:500 }}>{t.status || 'activo'}</span>
                        </div>
                        {t.body && <div style={{ fontSize:11, color:'var(--ink-4)', marginTop:4, lineHeight:1.4 }}>{t.body.slice(0, 120)}</div>}
                      </div>
                    ))}
                  </div>
                )}
              </div>

              {/* Step 2: Variables auto-filled */}
              {selTpl && (
                <div style={{ marginBottom:20 }}>
                  <div style={{ fontSize:13, fontWeight:600, color:'var(--ink-2)', marginBottom:10 }}>
                    2. Variables del template
                    <span style={{ fontSize:11, fontWeight:400, color:'var(--ink-4)', marginLeft:8 }}>auto-completadas desde la propiedad</span>
                  </div>
                  <div style={{ display:'flex', flexDirection:'column', gap:8 }}>
                    {(selTpl.variables || []).map(v => {
                      const key = v.name || v.key;
                      return (
                        <div key={key} style={{ display:'flex', gap:8, alignItems:'center' }}>
                          <label style={{ ...S.label, minWidth:120, margin:0, fontFamily:'monospace' }}>{key}</label>
                          <input style={{ ...S.input, flex:1 }}
                            value={tplVars[key] || ''}
                            onChange={e => setTplVars(p => ({ ...p, [key]: e.target.value }))}
                            placeholder={`Valor para ${key}`} />
                        </div>
                      );
                    })}
                    {/* Fallback: no variables defined but template likely has {{1}}, {{2}} */}
                    {(!selTpl.variables || selTpl.variables.length === 0) && (
                      <div style={{ fontSize:12, color:'var(--ink-4)', background:'var(--cream)', borderRadius:8, padding:'10px 14px' }}>
                        Este template no tiene variables definidas o se envía sin variables.
                      </div>
                    )}
                  </div>
                  {/* Image preview */}
                  {sendModal.imagen_principal && (
                    <div style={{ marginTop:10, fontSize:12, color:'var(--ink-3)', display:'flex', alignItems:'center', gap:8 }}>
                      <img src={sendModal.imagen_principal} alt="" style={{ width:48, height:36, objectFit:'cover', borderRadius:6 }} />
                      <span>Imagen de la propiedad incluida automáticamente</span>
                    </div>
                  )}
                </div>
              )}

              {/* Step 3: Contact phone */}
              {selTpl && (
                <div style={{ marginBottom:20 }}>
                  <div style={{ fontSize:13, fontWeight:600, color:'var(--ink-2)', marginBottom:10 }}>3. Teléfono del destinatario</div>
                  <input style={{ ...S.input, width:'100%' }}
                    value={sendPhone} onChange={e => setSendPhone(e.target.value)}
                    placeholder="Ej: 5491112345678" />
                </div>
              )}

              {/* Send button */}
              {selTpl && (
                <div style={{ display:'flex', gap:10, alignItems:'center' }}>
                  <button type="button" style={{ ...S.saveBtn, background:'#7c3aed', opacity: (!sendPhone.trim() || sending) ? .6 : 1 }}
                    onClick={sendTemplate} disabled={!sendPhone.trim() || sending}>
                    {sending ? 'Enviando…' : '📤 Enviar template'}
                  </button>
                  {sendResult && (
                    sendResult.error
                      ? <span style={{ fontSize:13, color:'var(--danger)' }}>❌ {sendResult.error}</span>
                      : <span style={{ fontSize:13, color:'#166534' }}>✅ Enviado correctamente</span>
                  )}
                </div>
              )}
            </div>
          </div>
        </div>
      )}

      {/* Detail modal */}
      {selected && (
        <div style={{ position:'fixed', inset:0, background:'rgba(0,0,0,.5)', zIndex:9999, display:'flex', alignItems:'center', justifyContent:'center', padding:20 }}
          onClick={() => setSelected(null)}>
          <div style={{ background:'var(--white)', borderRadius:16, maxWidth:720, width:'100%', maxHeight:'90vh', overflow:'auto', boxShadow:'0 20px 60px rgba(0,0,0,.3)' }}
            onClick={e => e.stopPropagation()}>
            {/* Modal header image */}
            {selected.imagen_principal && (
              <div style={{ width:'100%', height:260, overflow:'hidden', borderRadius:'16px 16px 0 0' }}>
                <img src={selected.imagen_principal} alt={selected.titulo} style={{ width:'100%', height:'100%', objectFit:'cover' }} />
              </div>
            )}
            <div style={{ padding:24 }}>
              <div style={{ display:'flex', justifyContent:'space-between', alignItems:'flex-start', marginBottom:16 }}>
                <div style={{ flex:1 }}>
                  <div style={{ display:'flex', gap:8, marginBottom:8, flexWrap:'wrap' }}>
                    <span style={{ background:'var(--green)', color:'#fff', fontSize:11, fontWeight:600, padding:'2px 10px', borderRadius:99 }}>{selected.operacion}</span>
                    <span style={{ background:'var(--cream-dark)', fontSize:11, fontWeight:500, padding:'2px 10px', borderRadius:99 }}>{selected.tipo}</span>
                    {selected.destacada && <span style={{ background:'#fef3c7', color:'#92400e', fontSize:11, fontWeight:600, padding:'2px 10px', borderRadius:99 }}>⭐ Destacada</span>}
                  </div>
                  <div style={{ fontSize:18, fontWeight:700, color:'var(--ink)', marginBottom:4 }}>{selected.titulo}</div>
                  <div style={{ fontSize:13, color:'var(--ink-3)' }}>📍 {[selected.direccion, selected.barrio, selected.ciudad, selected.provincia].filter(Boolean).join(', ')}</div>
                </div>
                <button onClick={() => setSelected(null)} style={{ background:'none', border:'none', fontSize:22, cursor:'pointer', color:'var(--ink-4)', padding:4 }}>✕</button>
              </div>

              {/* Price */}
              <div style={{ fontSize:24, fontWeight:700, color:'var(--green)', marginBottom:16 }}>
                {selected.precio_str || '—'}
                {selected.expensas && <span style={{ fontSize:13, color:'var(--ink-3)', fontWeight:400, marginLeft:10 }}>+ exp. {selected.moneda_expensas} {selected.expensas?.toLocaleString('es-AR')}</span>}
              </div>

              {/* Stats grid */}
              <div style={{ display:'grid', gridTemplateColumns:'repeat(auto-fill, minmax(130px, 1fr))', gap:10, marginBottom:18 }}>
                {[
                  selected.ambientes   && { icon:'🚪', label:'Ambientes',  val: selected.ambientes },
                  selected.dormitorios && { icon:'🛏️', label:'Dormitorios', val: selected.dormitorios },
                  selected.banos       && { icon:'🚿', label:'Baños',       val: selected.banos },
                  selected.m2_cubiertos && { icon:'📐', label:'M² cubiertos', val: `${selected.m2_cubiertos} m²` },
                  selected.m2_totales  && { icon:'📏', label:'M² totales',  val: `${selected.m2_totales} m²` },
                ].filter(Boolean).map((s, i) => (
                  <div key={i} style={{ background:'var(--cream)', borderRadius:10, padding:'10px 14px', textAlign:'center' }}>
                    <div style={{ fontSize:20 }}>{s.icon}</div>
                    <div style={{ fontSize:13, fontWeight:600, color:'var(--ink)' }}>{s.val}</div>
                    <div style={{ fontSize:11, color:'var(--ink-4)' }}>{s.label}</div>
                  </div>
                ))}
              </div>

              {/* Description */}
              {selected.descripcion_corta && (
                <div style={{ fontSize:13, color:'var(--ink-2)', lineHeight:1.6, marginBottom:18, background:'var(--cream)', borderRadius:10, padding:'12px 14px' }}>
                  {selected.descripcion_corta}
                </div>
              )}

              {/* Planos */}
              {selected.planos?.length > 0 && (
                <div style={{ marginBottom:18 }}>
                  <div style={{ fontSize:12, fontWeight:600, color:'var(--ink-3)', marginBottom:8 }}>PLANOS ({selected.planos.length})</div>
                  <div style={{ display:'flex', gap:8, flexWrap:'wrap' }}>
                    {selected.planos.map((url, i) => (
                      <a key={i} href={url} target="_blank" rel="noreferrer"
                        style={{ display:'block', width:80, height:80, borderRadius:8, overflow:'hidden', border:'1px solid var(--border)' }}>
                        <img src={url} alt={`Plano ${i+1}`} style={{ width:'100%', height:'100%', objectFit:'cover' }} />
                      </a>
                    ))}
                  </div>
                </div>
              )}

              {/* Gallery */}
              {selected.imagenes?.length > 1 && (
                <div style={{ marginBottom:18 }}>
                  <div style={{ fontSize:12, fontWeight:600, color:'var(--ink-3)', marginBottom:8 }}>GALERÍA ({selected.imagenes.length} fotos)</div>
                  <div style={{ display:'flex', gap:6, overflowX:'auto', paddingBottom:4 }}>
                    {selected.imagenes.slice(0,10).map((url, i) => (
                      <a key={i} href={url} target="_blank" rel="noreferrer" style={{ flexShrink:0 }}>
                        <img src={url} alt={`Foto ${i+1}`} style={{ width:80, height:60, objectFit:'cover', borderRadius:6, border:'1px solid var(--border)' }} />
                      </a>
                    ))}
                  </div>
                </div>
              )}

              {/* Actions */}
              <div style={{ display:'flex', gap:10, flexWrap:'wrap' }}>
                <button type="button" style={{ ...S.saveBtn, background:'#7c3aed', display:'flex', alignItems:'center', gap:6 }}
                  onClick={() => { const p = selected; setSelected(null); openSendModal(p); }}>
                  📤 Enviar como template
                </button>
                {selected.link_tokko && (
                  <a href={selected.link_tokko} target="_blank" rel="noreferrer"
                    style={{ ...S.saveBtn, textDecoration:'none', display:'inline-flex', alignItems:'center', gap:6 }}>
                    🔗 Ver en Tokko
                  </a>
                )}
                {selected.imagen_principal && (
                  <button style={S.outlineBtn} onClick={() => navigator.clipboard?.writeText(selected.imagen_principal)}>
                    📋 Copiar URL imagen
                  </button>
                )}
                {selected.link_tokko && (
                  <button style={S.outlineBtn} onClick={() => navigator.clipboard?.writeText(selected.link_tokko)}>
                    📋 Copiar link
                  </button>
                )}
              </div>

              <div style={{ marginTop:16, fontSize:11, color:'var(--ink-4)', fontFamily:'monospace' }}>
                ID Tokko: {selected.id} · Sync: {selected.syncedAt ? new Date(selected.syncedAt).toLocaleString('es-AR') : '—'}
              </div>
            </div>
          </div>
        </div>
      )}
    </div>
  );
}

// ─── ContactsTablePanel ────────────────────────────────────────────────────────
// Log de actividad por contacto (piloto Land Ventures). Datos calculados por un indexador
// en background — ver src/contact-stats.ts. "conversationsStarted"/"assignmentCount"/
// "totalMessages" solo son exactos DE ACÁ PARA ADELANTE (Pipochat no tiene API de historial),
// por eso siempre se muestra "Datos desde {trackingSince}" — no ocultar esa limitación.
function fmtRelativeTime(iso) {
  if (!iso) return '—';
  const diffMs = Date.now() - new Date(iso).getTime();
  const min = Math.floor(diffMs / 60000);
  if (min < 1) return 'recién';
  if (min < 60) return `hace ${min}m`;
  const hr = Math.floor(min / 60);
  if (hr < 24) return `hace ${hr}h`;
  const d = Math.floor(hr / 24);
  return `hace ${d}d`;
}

function ContactBulkModal({ action, onClose, onSubmit, submitting }) {
  const { pipelines, tags, users, templates } = usePipochat();
  const [tagIds, setTagIds]         = useState([]);
  const [pipelineId, setPipelineId] = useState('');
  const [stageId, setStageId]       = useState('');
  const [message, setMessage]       = useState('');
  const [templateId, setTemplateId] = useState('');
  const [operatorId, setOperatorId] = useState('');

  const stages = (pipelines.find(p => p._id === pipelineId)?.stages) || [];

  const titles = {
    tag: '🏷️ Etiquetar contactos',
    move_stage: '➡️ Mover de etapa',
    send_message: '💬 Enviar mensaje',
    send_template: '📨 Enviar plantilla',
    assign_operator: '👤 Asignar operador',
    export_webhook: '🔗 Enviar a CRM externo',
  };

  const canSubmit =
    (action === 'tag' && tagIds.length > 0) ||
    (action === 'move_stage' && pipelineId && stageId) ||
    (action === 'send_message' && message.trim()) ||
    (action === 'send_template' && templateId) ||
    (action === 'assign_operator' && operatorId) ||
    (action === 'export_webhook');

  const buildPayload = () => {
    if (action === 'tag') return { tagIds, mode: 'add' };
    if (action === 'move_stage') return { pipelineId, stageId };
    if (action === 'send_message') return { message };
    if (action === 'send_template') return { templateId };
    if (action === 'assign_operator') return { operatorId };
    return {};
  };

  return (
    <div style={{ position:'fixed', inset:0, background:'rgba(0,0,0,.5)', zIndex:9999, display:'flex', alignItems:'center', justifyContent:'center', padding:20 }} onClick={onClose}>
      <div style={{ background:'var(--white)', borderRadius:16, maxWidth:480, width:'100%', maxHeight:'88vh', overflow:'auto', boxShadow:'0 20px 60px rgba(0,0,0,.3)', padding:24 }} onClick={e => e.stopPropagation()}>
        <div style={{ display:'flex', justifyContent:'space-between', alignItems:'center', marginBottom:18 }}>
          <div style={{ fontWeight:700, fontSize:16 }}>{titles[action]}</div>
          <button type="button" onClick={onClose} style={{ background:'none', border:'none', fontSize:22, cursor:'pointer', color:'var(--ink-4)' }}>✕</button>
        </div>

        {action === 'tag' && (
          <div style={{ display:'flex', flexDirection:'column', gap:6, maxHeight:280, overflowY:'auto' }}>
            {tags.map(t => (
              <label key={t._id} style={{ display:'flex', alignItems:'center', gap:8, fontSize:13, cursor:'pointer' }}>
                <input type="checkbox" checked={tagIds.includes(t._id)}
                  onChange={e => setTagIds(ids => e.target.checked ? [...ids, t._id] : ids.filter(x => x !== t._id))} />
                {t.name}
              </label>
            ))}
          </div>
        )}

        {action === 'move_stage' && (
          <div style={{ display:'flex', flexDirection:'column', gap:12 }}>
            <div style={S.col}>
              <label style={S.label}>Pipeline</label>
              <select style={S.select} value={pipelineId} onChange={e => { setPipelineId(e.target.value); setStageId(''); }}>
                <option value="">— Elegí un pipeline —</option>
                {pipelines.map(p => <option key={p._id} value={p._id}>{p.title || p.name}</option>)}
              </select>
            </div>
            <div style={S.col}>
              <label style={S.label}>Etapa destino</label>
              <select style={S.select} value={stageId} onChange={e => setStageId(e.target.value)} disabled={!pipelineId}>
                <option value="">— Elegí una etapa —</option>
                {stages.map(s => <option key={s._id} value={s._id}>{s.displayName || s.name}</option>)}
              </select>
            </div>
          </div>
        )}

        {action === 'send_message' && (
          <div style={S.col}>
            <label style={S.label}>Mensaje</label>
            <textarea style={{ ...S.input, minHeight:100, resize:'vertical' }} value={message} onChange={e => setMessage(e.target.value)} placeholder="Escribí el mensaje…" />
          </div>
        )}

        {action === 'send_template' && (
          <div style={S.col}>
            <label style={S.label}>Plantilla</label>
            <select style={S.select} value={templateId} onChange={e => setTemplateId(e.target.value)}>
              <option value="">— Elegí una plantilla —</option>
              {templates.map(t => <option key={t.id || t._id} value={t.id || t._id}>{t.name}</option>)}
            </select>
          </div>
        )}

        {action === 'assign_operator' && (
          <div style={S.col}>
            <label style={S.label}>Operador</label>
            <select style={S.select} value={operatorId} onChange={e => setOperatorId(e.target.value)}>
              <option value="">— Elegí un operador —</option>
              {users.map(u => <option key={u._id} value={u._id}>{u.fullName || u.name || u.email}</option>)}
            </select>
          </div>
        )}

        {action === 'export_webhook' && (
          <div style={{ fontSize:13, color:'var(--ink-3)' }}>
            Se van a enviar los datos de los contactos seleccionados a cualquier webhook de este tenant suscripto al evento <code>contact.export</code> (configurable en la sección Webhooks).
          </div>
        )}

        <div style={{ display:'flex', gap:8, justifyContent:'flex-end', marginTop:20 }}>
          <button type="button" style={S.outlineBtn} onClick={onClose}>Cancelar</button>
          <button type="button" style={{ ...S.saveBtn, opacity: canSubmit && !submitting ? 1 : .5 }} disabled={!canSubmit || submitting} onClick={() => onSubmit(buildPayload())}>
            {submitting ? 'Aplicando…' : 'Aplicar'}
          </button>
        </div>
      </div>
    </div>
  );
}

function ContactsTablePanel({ onOpenDetail }) {
  const { pipelines, tags } = usePipochat();
  const [contacts, setContacts]   = useState([]);
  const [total, setTotal]         = useState(0);
  const [meta, setMeta]           = useState({ trackingSince: null, lastIndexedAt: null });
  const [loading, setLoading]     = useState(false);
  const [notEnabled, setNotEnabled] = useState(false);
  const [page, setPage]           = useState(0);
  const PAGE = 50;

  const [q, setQ]               = useState('');
  const [tagFilter, setTagFilter]     = useState('');
  const [sortBy, setSortBy]     = useState('lastMessageAt');
  const [sortDir, setSortDir]   = useState('desc');

  const [selectedIds, setSelectedIds] = useState(new Set());
  const [bulkAction, setBulkAction]   = useState(null);
  const [bulkSubmitting, setBulkSubmitting] = useState(false);
  const [bulkResult, setBulkResult]   = useState(null);
  const [reindexing, setReindexing]   = useState(false);

  const load = async (p = 0) => {
    setLoading(true);
    const params = new URLSearchParams({ limit: PAGE, offset: p * PAGE, sortBy, sortDir });
    if (q) params.set('q', q);
    if (tagFilter) params.set('tag', tagFilter);
    const res = await apiFetch(`/api/contacts/stats?${params}`);
    if (res.status === 503) { setNotEnabled(true); setLoading(false); return; }
    const data = await res.json().catch(() => ({ items: [], total: 0 }));
    setNotEnabled(false);
    setContacts(data.items || []);
    setTotal(data.total || 0);
    setMeta({ trackingSince: data.trackingSince, lastIndexedAt: data.lastIndexedAt });
    setPage(p);
    setLoading(false);
  };

  useEffect(() => { load(0); }, [sortBy, sortDir]);

  const search = (e) => { e.preventDefault(); load(0); };

  const toggleSelect = (id) => setSelectedIds(prev => {
    const next = new Set(prev);
    next.has(id) ? next.delete(id) : next.add(id);
    return next;
  });
  const toggleSelectAll = () => setSelectedIds(prev =>
    prev.size === contacts.length ? new Set() : new Set(contacts.map(c => c.contactId))
  );

  const reindex = async () => {
    setReindexing(true);
    await apiFetch('/api/contacts/stats/reindex', { method: 'POST' }).then(r => r.json()).catch(() => null);
    await load(page);
    setReindexing(false);
  };

  const runBulkAction = async (payload) => {
    setBulkSubmitting(true);
    const data = await apiFetch('/api/contacts/bulk-action', {
      method: 'POST', headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ contactIds: Array.from(selectedIds), action: bulkAction, payload }),
    }).then(r => r.json()).catch(e => ({ error: e.message }));
    setBulkSubmitting(false);
    setBulkAction(null);
    if (data.error) { setBulkResult({ ok: false, msg: data.error }); }
    else {
      setBulkResult({ ok: true, msg: `${data.succeeded.length} de ${data.succeeded.length + data.failed.length} contactos actualizados${data.failed.length ? `, ${data.failed.length} fallaron` : ''}.` });
      setSelectedIds(new Set());
      load(page);
    }
    setTimeout(() => setBulkResult(null), 7000);
  };

  if (notEnabled) {
    return (
      <div style={S.editor}>
        <div style={S.pageTitle}>📇 Contactos</div>
        <div style={{ ...S.card, marginTop:16, textAlign:'center', padding:40, color:'var(--ink-4)' }}>
          <div style={{ fontSize:32, marginBottom:12 }}>📇</div>
          <strong>Todavía no está habilitado para este tenant.</strong>
          <div style={{ fontSize:13, marginTop:6 }}>Es una función en piloto — pedile a soporte que la active.</div>
        </div>
      </div>
    );
  }

  return (
    <div style={S.editor}>
      <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between', marginBottom:4 }}>
        <div>
          <div style={S.pageTitle}>📇 Contactos</div>
          <div style={{ fontSize:12, color:'var(--ink-4)', marginTop:2 }}>
            Datos desde {meta.trackingSince ? new Date(meta.trackingSince).toLocaleDateString('es-AR') : '—'} · Actualizado {meta.lastIndexedAt ? fmtRelativeTime(meta.lastIndexedAt) : '—'}
          </div>
        </div>
        <button style={{ ...S.outlineBtn, display:'flex', alignItems:'center', gap:6 }} onClick={reindex} disabled={reindexing}>
          {reindexing ? '⏳ Actualizando…' : '🔄 Actualizar ahora'}
        </button>
      </div>

      {bulkResult && (
        <div style={{ ...S.card, marginTop:16, background: bulkResult.ok ? '#f0fdf4' : 'var(--danger-light)', borderColor: bulkResult.ok ? '#86efac' : 'var(--danger)' }}>
          <div style={{ fontSize:13, color: bulkResult.ok ? '#166534' : 'var(--danger)' }}>{bulkResult.ok ? '✅' : '❌'} {bulkResult.msg}</div>
        </div>
      )}

      <form onSubmit={search} style={{ ...S.card, marginTop:16, display:'flex', gap:8, flexWrap:'wrap', alignItems:'flex-end' }}>
        <div style={S.col}>
          <label style={S.label}>Buscar</label>
          <input style={{ ...S.input, minWidth:200 }} value={q} onChange={e => setQ(e.target.value)} placeholder="nombre o teléfono…" />
        </div>
        <div style={S.col}>
          <label style={S.label}>Etiqueta</label>
          <select style={S.select} value={tagFilter} onChange={e => setTagFilter(e.target.value)}>
            <option value="">Todas</option>
            {tags.map(t => <option key={t._id} value={t._id}>{t.name}</option>)}
          </select>
        </div>
        <div style={S.col}>
          <label style={S.label}>Ordenar por</label>
          <select style={S.select} value={sortBy} onChange={e => setSortBy(e.target.value)}>
            <option value="lastMessageAt">Última actividad</option>
            <option value="totalMessages">Mensajes totales</option>
            <option value="tagCount">Cantidad de etiquetas</option>
            <option value="assignmentCount">Reasignaciones</option>
            <option value="conversationsStarted">Conversaciones iniciadas</option>
          </select>
        </div>
        <button type="submit" style={S.saveBtn}>Buscar</button>
      </form>

      {selectedIds.size > 0 && (
        <div style={{ ...S.card, marginTop:14, display:'flex', alignItems:'center', gap:10, flexWrap:'wrap', background:'#eff6ff', borderColor:'#bfdbfe' }}>
          <span style={{ fontSize:13, fontWeight:600 }}>{selectedIds.size} seleccionado{selectedIds.size > 1 ? 's' : ''}</span>
          <button style={S.outlineBtn} onClick={() => setBulkAction('tag')}>🏷️ Etiquetar</button>
          <button style={S.outlineBtn} onClick={() => setBulkAction('move_stage')}>➡️ Mover etapa</button>
          <button style={S.outlineBtn} onClick={() => setBulkAction('send_message')}>💬 Mensaje</button>
          <button style={S.outlineBtn} onClick={() => setBulkAction('send_template')}>📨 Plantilla</button>
          <button style={S.outlineBtn} onClick={() => setBulkAction('assign_operator')}>👤 Asignar</button>
          <button style={S.outlineBtn} onClick={() => setBulkAction('export_webhook')}>🔗 Enviar a CRM</button>
          <button style={{ ...S.ghostBtn, fontSize:13, color:'var(--ink-4)' }} onClick={() => setSelectedIds(new Set())}>Cancelar</button>
        </div>
      )}

      {loading ? (
        <div style={{ textAlign:'center', padding:40, color:'var(--ink-4)' }}>Cargando contactos…</div>
      ) : contacts.length === 0 ? (
        <div style={{ ...S.card, marginTop:16, textAlign:'center', padding:40, color:'var(--ink-4)' }}>Sin contactos indexados todavía.</div>
      ) : (
        <>
          <div style={{ fontSize:12, color:'var(--ink-4)', margin:'14px 0 6px' }}>{total} contacto{total !== 1 ? 's' : ''} · página {page+1}/{Math.ceil(total/PAGE) || 1}</div>
          <div style={{ ...S.card, padding:0, overflowX:'auto' }}>
            <table style={{ width:'100%', borderCollapse:'collapse', fontSize:13 }}>
              <thead>
                <tr style={{ borderBottom:'1px solid var(--border)', textAlign:'left' }}>
                  <th style={{ padding:'10px 12px' }}><input type="checkbox" checked={selectedIds.size === contacts.length && contacts.length > 0} onChange={toggleSelectAll} /></th>
                  <th style={{ padding:'10px 12px' }}>Nombre / Teléfono</th>
                  <th style={{ padding:'10px 12px' }}>Conversaciones</th>
                  <th style={{ padding:'10px 12px' }}>Reasignaciones</th>
                  <th style={{ padding:'10px 12px' }}>Etiquetas</th>
                  <th style={{ padding:'10px 12px' }}>Mensajes</th>
                  <th style={{ padding:'10px 12px' }}>Lead / Etapa</th>
                  <th style={{ padding:'10px 12px' }}>Última actividad</th>
                </tr>
              </thead>
              <tbody>
                {contacts.map(c => (
                  <tr key={c.contactId} style={{ borderBottom:'1px solid var(--border-soft)', cursor:'pointer' }}
                    onMouseEnter={e => e.currentTarget.style.background = 'var(--cream)'}
                    onMouseLeave={e => e.currentTarget.style.background = ''}>
                    <td style={{ padding:'10px 12px' }} onClick={e => e.stopPropagation()}>
                      <input type="checkbox" checked={selectedIds.has(c.contactId)} onChange={() => toggleSelect(c.contactId)} />
                    </td>
                    <td style={{ padding:'10px 12px' }} onClick={() => onOpenDetail(c.contactId)}>
                      <div style={{ fontWeight:600 }}>{c.name || '(sin nombre)'}</div>
                      <div style={{ fontSize:11, color:'var(--ink-4)' }}>{c.phone}</div>
                    </td>
                    <td style={{ padding:'10px 12px' }} onClick={() => onOpenDetail(c.contactId)}>{c.conversationsStarted}</td>
                    <td style={{ padding:'10px 12px' }} onClick={() => onOpenDetail(c.contactId)}>{c.assignmentCount}</td>
                    <td style={{ padding:'10px 12px' }} onClick={() => onOpenDetail(c.contactId)}>{c.tagCount}</td>
                    <td style={{ padding:'10px 12px' }} onClick={() => onOpenDetail(c.contactId)}>{c.totalMessages}</td>
                    <td style={{ padding:'10px 12px' }} onClick={() => onOpenDetail(c.contactId)}>
                      {c.currentStage ? <span>{c.currentStage.pipelineName} · {c.currentStage.stageName}</span> : <span style={{ color:'var(--ink-4)' }}>Sin lead</span>}
                    </td>
                    <td style={{ padding:'10px 12px' }} onClick={() => onOpenDetail(c.contactId)}>
                      {fmtRelativeTime(c.lastMessageAt)}
                      {c.lastMessageFromContact && <span style={{ marginLeft:6, fontSize:10, fontWeight:700, color:'#b45309', background:'#fef3c7', padding:'1px 6px', borderRadius:99 }}>sin responder</span>}
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
          {total > PAGE && (
            <div style={{ display:'flex', justifyContent:'center', gap:8, marginTop:20 }}>
              <button style={S.outlineBtn} disabled={page === 0} onClick={() => load(page-1)}>← Anterior</button>
              <span style={{ fontSize:13, color:'var(--ink-3)', alignSelf:'center' }}>Pág {page+1} / {Math.ceil(total/PAGE)}</span>
              <button style={S.outlineBtn} disabled={(page+1)*PAGE >= total} onClick={() => load(page+1)}>Siguiente →</button>
            </div>
          )}
        </>
      )}

      {bulkAction && (
        <ContactBulkModal action={bulkAction} submitting={bulkSubmitting} onClose={() => setBulkAction(null)} onSubmit={runBulkAction} />
      )}
    </div>
  );
}

// ─── ContactDetailPanel ─────────────────────────────────────────────────────────
function ContactDetailPanel({ contactId, onBack }) {
  const [data, setData]     = useState(null);
  const [loading, setLoading] = useState(true);
  const [notFound, setNotFound] = useState(false);

  useEffect(() => {
    setLoading(true); setNotFound(false);
    apiFetch(`/api/contacts/${contactId}/stats`).then(async r => {
      if (r.status === 404) { setNotFound(true); setLoading(false); return; }
      const d = await r.json().catch(() => null);
      setData(d);
      setLoading(false);
    });
  }, [contactId]);

  if (loading) return <div style={S.editor}><div style={{ textAlign:'center', padding:40, color:'var(--ink-4)' }}>Cargando…</div></div>;
  if (notFound || !data) return (
    <div style={S.editor}>
      <button style={S.outlineBtn} onClick={onBack}>← Volver</button>
      <div style={{ ...S.card, marginTop:16, textAlign:'center', padding:40, color:'var(--ink-4)' }}>Contacto no indexado todavía.</div>
    </div>
  );

  const metric = (label, value) => (
    <div style={{ ...S.card, textAlign:'center', padding:'14px 10px' }}>
      <div style={{ fontSize:22, fontWeight:800, color:'var(--green)' }}>{value}</div>
      <div style={{ fontSize:11, color:'var(--ink-4)', marginTop:4 }}>{label}</div>
    </div>
  );

  return (
    <div style={S.editor}>
      <button style={S.outlineBtn} onClick={onBack}>← Volver a Contactos</button>

      <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between', marginTop:16 }}>
        <div>
          <div style={S.pageTitle}>{data.name || '(sin nombre)'}</div>
          <div style={{ fontSize:13, color:'var(--ink-4)', marginTop:2 }}>{data.phone}</div>
        </div>
        <div style={{ fontSize:12, color:'var(--ink-4)', textAlign:'right' }}>
          Datos desde {new Date(data.trackingSince).toLocaleDateString('es-AR')}<br/>
          {data.lastMessageFromContact && <span style={{ fontWeight:700, color:'#b45309' }}>Sin responder desde {fmtRelativeTime(data.noReplySince)}</span>}
        </div>
      </div>

      <div style={{ display:'grid', gridTemplateColumns:'repeat(auto-fit, minmax(130px, 1fr))', gap:12, marginTop:16 }}>
        {metric('Conversaciones iniciadas', data.conversationsStarted)}
        {metric('Reasignaciones', data.assignmentCount)}
        {metric('Etiquetas', data.tagCount)}
        {metric('Mensajes totales', data.totalMessages)}
      </div>

      <div style={{ ...S.card, marginTop:16 }}>
        <div style={{ fontWeight:700, fontSize:14, marginBottom:10 }}>🏷️ Etiquetas</div>
        {data.tagNames?.length
          ? <div style={{ display:'flex', gap:6, flexWrap:'wrap' }}>{data.tagNames.map((n,i) => <span key={i} style={{ fontSize:12, background:'var(--cream)', padding:'3px 10px', borderRadius:99 }}>{n}</span>)}</div>
          : <div style={{ fontSize:13, color:'var(--ink-4)' }}>Sin etiquetas.</div>}
      </div>

      <div style={{ ...S.card, marginTop:16 }}>
        <div style={{ fontWeight:700, fontSize:14, marginBottom:10 }}>📋 Atributos personalizados</div>
        {Object.keys(data.attributes || {}).length
          ? <div style={{ display:'flex', flexDirection:'column', gap:6 }}>{Object.entries(data.attributes).map(([k,v]) => (
              <div key={k} style={{ display:'flex', gap:8, fontSize:13 }}><span style={{ color:'var(--ink-4)', minWidth:140 }}>{k}</span><span>{v}</span></div>
            ))}</div>
          : <div style={{ fontSize:13, color:'var(--ink-4)' }}>Sin atributos guardados.</div>}
      </div>

      <div style={{ ...S.card, marginTop:16 }}>
        <div style={{ fontWeight:700, fontSize:14, marginBottom:10 }}>🎯 Lead vinculado</div>
        {data.currentStage
          ? <div style={{ fontSize:13 }}>{data.currentStage.pipelineName} → <strong>{data.currentStage.stageName}</strong></div>
          : <div style={{ fontSize:13, color:'var(--ink-4)' }}>Sin lead vinculado.</div>}
      </div>

      <div style={{ ...S.card, marginTop:16 }}>
        <div style={{ fontWeight:700, fontSize:14, marginBottom:10 }}>📝 Notas</div>
        {data.notes?.pipochat?.length > 0 && (
          <div style={{ marginBottom:12 }}>
            <div style={{ fontSize:11, fontWeight:700, color:'var(--ink-4)', textTransform:'uppercase', marginBottom:6 }}>Notas del lead (Pipochat)</div>
            {data.notes.pipochat.map((n,i) => <div key={i} style={{ fontSize:13, padding:'6px 0', borderBottom:'1px solid var(--border-soft)' }}>{n.notes}</div>)}
          </div>
        )}
        <div style={{ fontSize:11, fontWeight:700, color:'var(--ink-4)', textTransform:'uppercase', marginBottom:6 }}>Notas internas (LoopLead)</div>
        {data.notes?.internal?.length > 0
          ? data.notes.internal.map((n,i) => <div key={i} style={{ fontSize:13, padding:'6px 0', borderBottom:'1px solid var(--border-soft)' }}>{n.text} <span style={{ color:'var(--ink-4)', fontSize:11 }}>— {n.author}</span></div>)
          : <div style={{ fontSize:13, color:'var(--ink-4)' }}>Sin notas internas.</div>}
      </div>
    </div>
  );
}

// ─── DebugPanel ───────────────────────────────────────────────────────────────
function DebugPanel() {
  const [events,       setEvents]      = useState([]);
  const [loading,      setLoading]     = useState(false);
  const [selected,     setSelected]    = useState(null);
  const [adId,         setAdId]        = useState('');
  const [testResult,   setTestResult]  = useState(null);
  const [testing,      setTesting]     = useState(false);
  const [autoRefresh,  setAutoRefresh] = useState(false);
  const [whCheck,      setWhCheck]     = useState(null);

  // Lead Ads test tool state
  const [laFormId,     setLaFormId]    = useState('');
  const [laLeads,      setLaLeads]     = useState(null);
  const [laTesting,    setLaTesting]   = useState(false);

  // Coexistence: human-paused conversations
  const [pausedConvs,  setPausedConvs] = useState(null);
  const [pausedLoading, setPausedLoading] = useState(false);

  // CTWA re-process state
  const [rpPhone,      setRpPhone]     = useState('');
  const [rpAdId,       setRpAdId]      = useState('');
  const [rpResult,     setRpResult]    = useState(null);
  const [rpLoading,    setRpLoading]   = useState(false);

  const load = async () => {
    setLoading(true);
    const data = await apiFetch('/api/debug/events').then(r => r.json()).catch(() => ({ events: [] }));
    setEvents(data.events || []);
    setLoading(false);
  };

  const loadPausedConvs = async () => {
    setPausedLoading(true);
    const data = await apiFetch('/api/debug/human-active').then(r => r.json()).catch(() => ({ paused: [] }));
    setPausedConvs(data.paused || []);
    setPausedLoading(false);
  };

  const reEnableAI = async (conversationId) => {
    await apiFetch(`/api/debug/human-active/${conversationId}`, { method: 'DELETE' }).catch(() => {});
    loadPausedConvs();
  };

  useEffect(() => {
    load();
    apiFetch('/api/debug/webhook-check').then(r => r.json()).then(setWhCheck).catch(() => {});
    loadPausedConvs();
  }, []);
  useEffect(() => {
    if (!autoRefresh) return;
    const t = setInterval(load, 3000);
    return () => clearInterval(t);
  }, [autoRefresh]);

  const testLeadAds = async () => {
    if (!laFormId.trim()) return;
    setLaTesting(true); setLaLeads(null);
    const data = await apiFetch(`/api/debug/leadads-test?formId=${laFormId.trim()}&limit=5`)
      .then(r => r.json()).catch(e => ({ error: e.message }));
    setLaLeads(data);
    setLaTesting(false);
  };

  const testCtwa = async () => {
    if (!adId.trim()) return;
    setTesting(true); setTestResult(null);
    const data = await apiFetch('/api/debug/ctwa-test', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ adId: adId.trim() }),
    }).then(r => r.json()).catch(e => ({ error: e.message }));
    setTestResult(data);
    setTesting(false);
  };

  const reprocessCtwa = async () => {
    if (!rpPhone.trim()) return;
    setRpLoading(true); setRpResult(null);
    const val = rpPhone.trim();
    // If it looks like a MongoDB ObjectId (24 hex chars) treat it as contactId, otherwise phone
    const isObjectId = /^[0-9a-f]{24}$/i.test(val);
    const data = await apiFetch('/api/debug/ctwa-reprocess', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        ...(isObjectId ? { contactId: val } : { phone: val }),
        adId: rpAdId.trim() || undefined,
      }),
    }).then(r => r.json()).catch(e => ({ error: e.message }));
    setRpResult(data);
    setRpLoading(false);
  };

  const eventColor = (evt) => {
    const hasReferral = evt.summary?.referral;
    if (hasReferral) return '#d1fae5';
    if (evt.event === 'newContactMessageReceived') return '#eff6ff';
    return 'var(--white)';
  };

  return (
    <div style={S.editor}>
      <div style={S.pageTitle}>🔍 Debug Webhooks</div>

      {/* ── Webhook health check ────────────────────────────────────────────── */}
      {whCheck && (
        <div style={{ ...S.card, marginBottom:20, borderColor: whCheck.mismatch ? 'var(--danger)' : whCheck.ok ? '#86efac' : 'var(--border)', background: whCheck.mismatch ? '#fef2f2' : whCheck.ok ? '#f0fdf4' : 'var(--white)' }}>
          <div style={{ display:'flex', alignItems:'flex-start', gap:12 }}>
            <div style={{ fontSize:22, lineHeight:1 }}>{whCheck.mismatch ? '❌' : whCheck.ok ? '✅' : '⏳'}</div>
            <div style={{ flex:1 }}>
              <div style={{ fontWeight:700, fontSize:14, marginBottom:4 }}>
                {whCheck.mismatch ? 'Webhook mal configurado' : whCheck.ok ? 'Webhook OK' : 'Sin eventos aún'}
              </div>
              <div style={{ fontSize:13, color:'var(--ink-2)', marginBottom:8 }}>{whCheck.hint}</div>
              <div style={{ display:'flex', alignItems:'center', gap:8, background:'rgba(0,0,0,.04)', borderRadius:8, padding:'6px 12px' }}>
                <span style={{ fontSize:11, color:'var(--ink-3)' }}>URL correcta para este tenant:</span>
                <code style={{ fontSize:12, fontFamily:'monospace', flex:1 }}>{whCheck.webhookUrl}</code>
                <button style={S.outlineBtn} onClick={() => navigator.clipboard?.writeText(whCheck.webhookUrl)}>Copiar</button>
              </div>
              {whCheck.lastEventAt && (
                <div style={{ fontSize:11, color:'var(--ink-4)', marginTop:6 }}>
                  Último evento: {new Date(whCheck.lastEventAt).toLocaleString('es-AR')}
                  {whCheck.pipochatAccount && ` — cuenta Pipochat: ${whCheck.pipochatAccount}`}
                </div>
              )}
            </div>
          </div>
        </div>
      )}

      {/* ── Coexistence: human-paused conversations ─────────────────────── */}
      <div style={{ ...S.card, marginBottom:20 }}>
        <div style={{ display:'flex', justifyContent:'space-between', alignItems:'center', marginBottom:4 }}>
          <div style={{ fontWeight:700, fontSize:14 }}>🤝 Coexistencia — Agente pausado</div>
          <button style={S.outlineBtn} onClick={loadPausedConvs} disabled={pausedLoading}>
            {pausedLoading ? 'Cargando…' : '↺ Actualizar'}
          </button>
        </div>
        <div style={{ fontSize:12, color:'var(--ink-4)', marginBottom:14 }}>
          Conversaciones donde el operador respondió desde WhatsApp nativo. El agente de IA está pausado
          hasta que expire (8 h) o lo reactives manualmente.
        </div>

        {pausedConvs === null ? (
          <div style={{ fontSize:13, color:'var(--ink-4)' }}>Cargando…</div>
        ) : pausedConvs.length === 0 ? (
          <div style={{ fontSize:13, color:'#16a34a', background:'#f0fdf4', borderRadius:8, padding:'10px 14px' }}>
            ✅ Ninguna conversación pausada — el agente de IA responde normalmente en todas.
          </div>
        ) : (
          <div style={{ display:'flex', flexDirection:'column', gap:8 }}>
            {pausedConvs.map(c => (
              <div key={c.conversationId} style={{
                background:'#fff7ed', border:'1px solid #fed7aa', borderRadius:8,
                padding:'10px 14px', display:'flex', alignItems:'center', justifyContent:'space-between', gap:12,
              }}>
                <div style={{ flex:1, minWidth:0 }}>
                  <div style={{ fontSize:12, fontWeight:600, color:'#9a3412', marginBottom:2 }}>
                    🧑 Operador activo
                  </div>
                  <code style={{ fontSize:12, fontFamily:'monospace', color:'var(--ink-2)', wordBreak:'break-all' }}>
                    {c.conversationId}
                  </code>
                  <div style={{ fontSize:11, color:'var(--ink-4)', marginTop:3 }}>
                    Pausado: {new Date(c.activatedAt).toLocaleString('es-AR')} —
                    expira: {new Date(c.expiresAt).toLocaleString('es-AR')}
                  </div>
                </div>
                <button
                  style={{ ...S.saveBtn, background:'#16a34a', whiteSpace:'nowrap', fontSize:12, padding:'6px 12px' }}
                  onClick={() => reEnableAI(c.conversationId)}
                >
                  Reactivar IA
                </button>
              </div>
            ))}
          </div>
        )}
      </div>

      {/* ── Lead Ads Test Tool ─────────────────────────────────────────────── */}
      <div style={{ ...S.card, marginBottom:20 }}>
        <div style={{ fontWeight:700, fontSize:14, marginBottom:4 }}>📋 Probar leads de formulario</div>
        <div style={{ fontSize:12, color:'var(--ink-4)', marginBottom:14 }}>
          Ingresá el ID de un formulario de Lead Ads para ver los últimos 5 leads recibidos y verificar qué campos trae.
        </div>
        <div style={{ display:'flex', gap:8, alignItems:'flex-end' }}>
          <div style={S.col}>
            <label style={S.label}>Form ID</label>
            <input style={{ ...S.input, fontFamily:'monospace', fontSize:13 }}
              value={laFormId} onChange={e => setLaFormId(e.target.value)}
              onKeyDown={e => e.key === 'Enter' && testLeadAds()}
              placeholder="Ej: 1234567890123456" />
          </div>
          <button style={{ ...S.saveBtn, whiteSpace:'nowrap' }} onClick={testLeadAds} disabled={!laFormId.trim() || laTesting}>
            {laTesting ? 'Cargando…' : 'Ver leads'}
          </button>
        </div>

        {laLeads && (
          <div style={{ marginTop:14 }}>
            {laLeads.error ? (
              <div style={{ color:'var(--danger)', fontSize:13, background:'var(--danger-light)', borderRadius:8, padding:'10px 14px' }}>
                ❌ {laLeads.error}
              </div>
            ) : laLeads.leads?.length === 0 ? (
              <div style={{ color:'#92400E', background:'#fef3c7', borderRadius:8, padding:'10px 14px', fontSize:13 }}>
                Sin leads aún en este formulario.
              </div>
            ) : (
              <div style={{ display:'flex', flexDirection:'column', gap:8 }}>
                <div style={{ fontSize:12, color:'var(--ink-3)', fontWeight:600 }}>{laLeads.total} LEADS — mostrando últimos {laLeads.leads?.length}</div>
                {(laLeads.leads || []).map((lead, i) => (
                  <div key={lead.id} style={{ background:'var(--cream)', borderRadius:8, padding:'10px 14px', border:'1px solid var(--border)' }}>
                    <div style={{ fontSize:11, color:'var(--ink-4)', marginBottom:6, fontFamily:'monospace' }}>
                      {new Date(lead.created_time).toLocaleString('es-AR')} — ID: {lead.id}
                    </div>
                    {Object.entries(lead.fields || {}).map(([k, v]) => (
                      <div key={k} style={{ display:'flex', gap:8, fontSize:12, padding:'2px 0' }}>
                        <span style={{ fontFamily:'monospace', color:'var(--ink-3)', minWidth:160 }}>{k}</span>
                        <span style={{ color:'var(--ink)', fontWeight:500 }}>{String(v)}</span>
                      </div>
                    ))}
                  </div>
                ))}
              </div>
            )}
          </div>
        )}

        <div style={{ marginTop:14, fontSize:12, color:'var(--ink-4)', background:'var(--cream)', borderRadius:8, padding:'10px 14px' }}>
          <strong>¿Dónde encontrar el Form ID?</strong><br/>
          En Meta Ads Manager → tu campaña de Lead Ads → el formulario. También aparece en la sección de Formularios dentro de Lead Ads en Integraciones.
        </div>
      </div>

      {/* ── CTWA Test Tool ─────────────────────────────────────────────────── */}
      <div style={{ ...S.card, marginBottom:20 }}>
        <div style={{ fontWeight:700, fontSize:14, marginBottom:4 }}>🧪 Probar tracking de Click-to-WhatsApp</div>
        <div style={{ fontSize:12, color:'var(--ink-4)', marginBottom:14 }}>
          Ingresá un Ad ID de Facebook para verificar que los datos de campaña se van a resolver correctamente cuando llegue un clic real.
        </div>
        <div style={{ display:'flex', gap:8, alignItems:'flex-end' }}>
          <div style={S.col}>
            <label style={S.label}>Ad ID de Facebook</label>
            <input style={{ ...S.input, fontFamily:'monospace', fontSize:13 }}
              value={adId} onChange={e => setAdId(e.target.value)}
              onKeyDown={e => e.key === 'Enter' && testCtwa()}
              placeholder="Ej: 23856315813500" />
          </div>
          <button style={{ ...S.saveBtn, whiteSpace:'nowrap' }} onClick={testCtwa} disabled={!adId.trim() || testing}>
            {testing ? 'Resolviendo…' : 'Probar Ad ID'}
          </button>
        </div>

        {testResult && (
          <div style={{ marginTop:14 }}>
            {testResult.error ? (
              <div style={{ color:'var(--danger)', fontSize:13, background:'var(--danger-light)', borderRadius:8, padding:'10px 14px' }}>
                ❌ {testResult.error}
              </div>
            ) : (
              <div style={{ display:'flex', flexDirection:'column', gap:10 }}>
                <div style={{ fontSize:13, color: testResult.resolved ? '#166534' : '#92400E',
                  background: testResult.resolved ? '#d1fae5' : '#fef3c7', borderRadius:8, padding:'10px 14px' }}>
                  {testResult.hint}
                </div>
                {testResult.resolved && (
                  <div style={{ background:'var(--cream)', borderRadius:8, padding:'12px 14px', border:'1px solid var(--border)' }}>
                    <div style={{ fontSize:12, fontWeight:600, color:'var(--ink-3)', marginBottom:8 }}>ATRIBUTOS QUE SE GUARDARÁN EN EL CONTACTO</div>
                    {Object.entries(testResult.attrs || {}).map(([k, v]) => (
                      <div key={k} style={{ display:'flex', gap:8, fontSize:13, padding:'3px 0', borderBottom:'1px solid var(--border-soft)' }}>
                        <span style={{ fontFamily:'monospace', color:'var(--ink-3)', minWidth:140 }}>{k}</span>
                        <span style={{ color:'var(--ink)', fontWeight:500 }}>{String(v)}</span>
                      </div>
                    ))}
                  </div>
                )}
              </div>
            )}
          </div>
        )}

        <div style={{ marginTop:14, fontSize:12, color:'var(--ink-4)', background:'var(--cream)', borderRadius:8, padding:'10px 14px' }}>
          <strong>¿Cómo encontrar el Ad ID?</strong><br/>
          En Meta Ads Manager → seleccioná el anuncio → mirá la URL o usá la columna "ID del anuncio". También aparece en la pestaña Inspeccionar de cualquier evento de CTWA.
        </div>
      </div>

      {/* ── CTWA Re-process ─────────────────────────────────────────────────── */}
      <div style={{ ...S.card, marginBottom:20 }}>
        <div style={{ fontWeight:700, fontSize:14, marginBottom:4 }}>🔄 Re-procesar CTWA de contacto existente</div>
        <div style={{ fontSize:12, color:'var(--ink-4)', marginBottom:14 }}>
          Para contactos que llegaron antes de configurar el webhook CTWA. Pegá el <strong>ID de la conversación</strong> (desde la URL de Pipochat)
          o el teléfono. El Ad ID lo podés sacar del campo <code style={{ fontFamily:'monospace' }}>ctwa_source_id</code> del contacto.
        </div>
        <div style={{ display:'flex', gap:8, alignItems:'flex-end', flexWrap:'wrap' }}>
          <div style={S.col}>
            <label style={S.label}>ID de conversación, contacto o teléfono</label>
            <input style={{ ...S.input, fontFamily:'monospace', fontSize:13 }}
              value={rpPhone} onChange={e => setRpPhone(e.target.value)}
              onKeyDown={e => e.key === 'Enter' && reprocessCtwa()}
              placeholder="ID de la URL de Pipochat o 5491112345678" />
          </div>
          <div style={S.col}>
            <label style={S.label}>Ad ID (ctwa_source_id)</label>
            <input style={{ ...S.input, fontFamily:'monospace', fontSize:13 }}
              value={rpAdId} onChange={e => setRpAdId(e.target.value)}
              onKeyDown={e => e.key === 'Enter' && reprocessCtwa()}
              placeholder="Ej: 23856315813500" />
          </div>
          <button style={{ ...S.saveBtn, whiteSpace:'nowrap' }} onClick={reprocessCtwa} disabled={!rpPhone.trim() || rpLoading}>
            {rpLoading ? 'Procesando…' : '🔄 Re-procesar'}
          </button>
        </div>

        {rpResult && (
          <div style={{ marginTop:14 }}>
            {rpResult.error ? (
              <div style={{ color:'var(--danger)', fontSize:13, background:'var(--danger-light)', borderRadius:8, padding:'10px 14px' }}>
                ❌ {rpResult.error}
              </div>
            ) : (
              <div style={{ display:'flex', flexDirection:'column', gap:10 }}>
                <div style={{ fontSize:13, color:'#166534', background:'#d1fae5', borderRadius:8, padding:'10px 14px' }}>
                  ✅ {rpResult.message || 'Atributos guardados correctamente en el contacto.'}
                </div>
                {rpResult.attrs && (
                  <div style={{ background:'var(--cream)', borderRadius:8, padding:'12px 14px', border:'1px solid var(--border)' }}>
                    <div style={{ fontSize:12, fontWeight:600, color:'var(--ink-3)', marginBottom:8 }}>ATRIBUTOS GUARDADOS</div>
                    {Object.entries(rpResult.attrs).map(([k, v]) => (
                      <div key={k} style={{ display:'flex', gap:8, fontSize:13, padding:'3px 0', borderBottom:'1px solid var(--border-soft)' }}>
                        <span style={{ fontFamily:'monospace', color:'var(--ink-3)', minWidth:180 }}>{k}</span>
                        <span style={{ color:'var(--ink)', fontWeight:500 }}>{String(v)}</span>
                      </div>
                    ))}
                  </div>
                )}
                {rpResult.contactId && (
                  <div style={{ fontSize:11, color:'var(--ink-4)', fontFamily:'monospace' }}>
                    Contact ID: {rpResult.contactId}
                  </div>
                )}
              </div>
            )}
          </div>
        )}
      </div>

      {/* ── Event Viewer ───────────────────────────────────────────────────── */}
      <div style={{ ...S.card }}>
        <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between', marginBottom:14 }}>
          <div>
            <div style={{ fontWeight:700, fontSize:14 }}>Últimos eventos de webhook</div>
            <div style={{ fontSize:12, color:'var(--ink-4)', marginTop:2 }}>
              {events.length} eventos — <span style={{ background:'#d1fae5', padding:'1px 6px', borderRadius:4, fontSize:11 }}>verde = tiene datos CTWA</span>
            </div>
          </div>
          <div style={{ display:'flex', gap:8, alignItems:'center' }}>
            <label style={{ display:'flex', alignItems:'center', gap:5, fontSize:12, color:'var(--ink-3)', cursor:'pointer' }}>
              <input type="checkbox" checked={autoRefresh} onChange={e => setAutoRefresh(e.target.checked)} />
              Auto-refresh (3s)
            </label>
            <button style={S.outlineBtn} onClick={load} disabled={loading}>{loading ? '…' : '↺ Actualizar'}</button>
          </div>
        </div>

        {events.length === 0 && !loading && (
          <div style={{ textAlign:'center', padding:30, color:'var(--ink-4)', fontSize:13 }}>
            Sin eventos aún. Los mensajes de WhatsApp aparecerán aquí en tiempo real.
          </div>
        )}

        <div style={{ display:'flex', flexDirection:'column', gap:4 }}>
          {events.map((evt, i) => (
            <div key={i}
              style={{ borderRadius:8, border:'1px solid var(--border)', background: eventColor(evt), cursor:'pointer', overflow:'hidden' }}
              onClick={() => setSelected(selected === i ? null : i)}>
              <div style={{ display:'flex', gap:10, alignItems:'center', padding:'8px 12px' }}>
                <span style={{ fontSize:11, color:'var(--ink-4)', fontFamily:'monospace', whiteSpace:'nowrap' }}>
                  {new Date(evt.ts).toLocaleTimeString('es-AR')}
                </span>
                <span style={{ fontSize:11, background: evt.event === 'newContactMessageReceived' ? '#dbeafe' : 'var(--cream-dark)',
                  padding:'1px 7px', borderRadius:99, fontWeight:500, color:'var(--ink-2)' }}>
                  {evt.event}
                </span>
                <span style={{ fontSize:12, color:'var(--ink)', fontWeight:500, flex:1 }}>
                  {evt.summary?.contactName || '—'} {evt.summary?.contactPhone ? `(${evt.summary.contactPhone})` : ''}
                </span>
                {evt.summary?.referral && (
                  <span style={{ fontSize:11, background:'#d1fae5', color:'#166534', padding:'1px 8px', borderRadius:99, fontWeight:600 }}>
                    📣 CTWA ad={evt.summary.referral.source_id}
                  </span>
                )}
                <span style={{ fontSize:11, color:'var(--ink-4)' }}>{selected === i ? '▲' : '▼'}</span>
              </div>
              {selected === i && (
                <pre style={{ margin:0, padding:'10px 14px', fontSize:11, borderTop:'1px solid var(--border)', background:'rgba(0,0,0,.03)', overflowX:'auto', maxHeight:320, color:'var(--ink-2)' }}>
                  {JSON.stringify(evt.rawBody, null, 2)}
                </pre>
              )}
            </div>
          ))}
        </div>
      </div>
    </div>
  );
}

// ─── HomePanel (Dashboard) ────────────────────────────────────────────────────
function HomePanel() {
  const [data, setData]       = useState(null);
  const [loading, setLoading] = useState(true);

  const load = () => {
    setLoading(true);
    apiFetch('/api/dashboard').then(r => r.json())
      .then(d => { setData(d); setLoading(false); })
      .catch(() => setLoading(false));
  };

  useEffect(() => { load(); }, []);

  if (loading) return (
    <div style={{ ...S.editor, alignItems:'center', justifyContent:'center' }}>
      <div style={{ color:'var(--ink-3)', fontSize:14 }}>Cargando dashboard…</div>
    </div>
  );

  const hour = new Date().getHours();
  const greeting = hour < 12 ? 'Buenos días' : hour < 18 ? 'Buenas tardes' : 'Buenas noches';
  const { metrics = {}, hotLeads = [], agents = [], automations = {}, costUsd = 0, costToday = 0 } = data || {};

  const card = (icon, value, label, sub, accent) => (
    <div style={{
      background:'var(--surface)', border:'1px solid var(--border-color)',
      borderRadius:16, padding:'20px 22px', flex:1, minWidth:150,
      borderTop: accent ? `3px solid ${accent}` : '3px solid transparent',
    }}>
      <div style={{ fontSize:22, marginBottom:8 }}>{icon}</div>
      <div style={{ fontSize:30, fontWeight:800, color: accent || 'var(--ink)', lineHeight:1 }}>{value ?? 0}</div>
      <div style={{ fontSize:13, fontWeight:600, color:'var(--ink)', marginTop:6 }}>{label}</div>
      {sub && <div style={{ fontSize:12, color:'var(--ink-3)', marginTop:2 }}>{sub}</div>}
    </div>
  );

  const sectionCard = ({ title, children }) => (
    <div style={{ background:'var(--surface)', border:'1px solid var(--border-color)', borderRadius:16, padding:'20px 22px' }}>
      <div style={{ fontSize:14, fontWeight:700, color:'var(--ink)', marginBottom:16 }}>{title}</div>
      {children}
    </div>
  );

  const totalActive = Object.values(automations).reduce((acc, a) => acc + (a?.active || 0), 0);
  const SCORE_C = { caliente: '#B91C1C', tibio: '#92400E', frío: '#1D4ED8' };
  const SCORE_BG = { caliente: '#FEE2E2', tibio: '#FEF3C7', frío: '#EFF6FF' };
  const SCORE_EMOJI = { caliente: '🔥', tibio: '🟡', frío: '❄️' };

  const automationRows = [
    { key: 'convRules', icon: '⚡', label: 'Reglas de conversación' },
    { key: 'noReply',   icon: '💤', label: 'Sin respuesta' },
    { key: 'nurturing', icon: '🌱', label: 'Nurturing' },
    { key: 'proactive', icon: '🤖', label: 'Agente Proactivo' },
  ];

  return (
    <div style={{ ...S.editor, gap:22, overflowY:'auto', paddingBottom:40 }}>

      {/* Header */}
      <div style={{ display:'flex', justifyContent:'space-between', alignItems:'flex-start', flexWrap:'wrap', gap:12 }}>
        <div>
          <div style={{ fontSize:22, fontWeight:800, color:'var(--ink)' }}>{greeting} 👋</div>
          <div style={{ fontSize:13, color:'var(--ink-3)', marginTop:3 }}>
            {new Date().toLocaleDateString('es-AR', { weekday:'long', day:'numeric', month:'long', year:'numeric' })}
          </div>
        </div>
        <button onClick={load} style={{
          display:'flex', alignItems:'center', gap:6, padding:'8px 16px',
          background:'var(--surface)', border:'1px solid var(--border-color)', borderRadius:10,
          fontSize:13, fontWeight:500, color:'var(--ink-3)', cursor:'pointer',
          transition:'all .15s',
        }}>↻ Actualizar</button>
      </div>

      {/* KPI cards */}
      <div style={{ display:'flex', gap:14, flexWrap:'wrap' }}>
        {card('🤖', metrics.ai_replies,    'Respuestas IA',    'mensajes enviados',  '#3A6351')}
        {card('👤', metrics.leads_created, 'Leads creados',    'registrados en CRM', '#7C3AED')}
        {card('🔥', hotLeads.length,       'Leads calientes',  'score ≥ 7',          '#B91C1C')}
        {card('🤝', metrics.handoffs,      'Handoffs',         'transferidos al asesor', '#1D4ED8')}
      </div>

      {/* Second row */}
      <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr', gap:14 }}>

        {/* Hot leads */}
        {React.createElement(sectionCard, { title: `🔥 Leads calientes (${hotLeads.length})` },
          hotLeads.length === 0 ? (
            <div style={{ fontSize:13, color:'var(--ink-3)', textAlign:'center', padding:'20px 0' }}>
              Aún no hay leads calientes.<br/>
              <span style={{ fontSize:12 }}>Activá Lead Scoring para empezar a puntuar.</span>
            </div>
          ) : (
            <div style={{ display:'flex', flexDirection:'column', gap:10 }}>
              {hotLeads.map(l => (
                <div key={l.convId} style={{
                  display:'flex', alignItems:'flex-start', gap:12,
                  padding:'10px 12px', background:'var(--bg)', borderRadius:10,
                  border:'1px solid var(--border-soft)',
                }}>
                  <div style={{
                    width:36, height:36, borderRadius:10, flexShrink:0,
                    background: SCORE_BG[l.label] || '#F3F4F6',
                    display:'flex', alignItems:'center', justifyContent:'center',
                    fontSize:18,
                  }}>{SCORE_EMOJI[l.label] || '⭐'}</div>
                  <div style={{ flex:1, minWidth:0 }}>
                    <div style={{ display:'flex', alignItems:'center', gap:8, flexWrap:'wrap' }}>
                      <span style={{ fontSize:13, fontWeight:700, color:'var(--ink)' }}>{l.contactName}</span>
                      <span style={{
                        fontSize:11, fontWeight:700, padding:'2px 8px', borderRadius:99,
                        background: SCORE_BG[l.label], color: SCORE_C[l.label],
                      }}>{l.score}/10</span>
                    </div>
                    <div style={{ fontSize:12, color:'var(--ink-3)', marginTop:3, overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap' }}>
                      {l.reasoning}
                    </div>
                    <div style={{ fontSize:11, color:'var(--ink-4)', marginTop:2 }}>
                      {l.scoredAt ? new Date(l.scoredAt).toLocaleDateString('es-AR', { day:'numeric', month:'short', hour:'2-digit', minute:'2-digit' }) : ''}
                    </div>
                  </div>
                </div>
              ))}
            </div>
          )
        )}

        {/* Right column: automations + agents */}
        <div style={{ display:'flex', flexDirection:'column', gap:14 }}>

          {/* Automations health */}
          {React.createElement(sectionCard, { title: `⚡ Automatizaciones activas (${totalActive})` },
            <div style={{ display:'flex', flexDirection:'column', gap:8 }}>
              {automationRows.map(({ key, icon, label }) => {
                const a = automations[key] || { total: 0, active: 0 };
                const allActive = a.active === a.total && a.total > 0;
                const noneActive = a.active === 0;
                return (
                  <div key={key} style={{ display:'flex', alignItems:'center', gap:10 }}>
                    <span style={{ fontSize:16, width:22, textAlign:'center' }}>{icon}</span>
                    <span style={{ flex:1, fontSize:13, color:'var(--ink-2)' }}>{label}</span>
                    <span style={{
                      fontSize:11, fontWeight:600, padding:'2px 10px', borderRadius:99,
                      background: noneActive ? '#F3F4F6' : allActive ? '#DCFCE7' : '#FEF3C7',
                      color: noneActive ? '#6B7280' : allActive ? '#15803D' : '#92400E',
                    }}>
                      {a.active > 0 ? `${a.active} activa${a.active > 1 ? 's' : ''}` : 'Sin reglas'}
                    </span>
                  </div>
                );
              })}
            </div>
          )}

          {/* Agents */}
          {React.createElement(sectionCard, { title: `🤖 Agentes (${agents.length})` },
            agents.length === 0 ? (
              <div style={{ fontSize:13, color:'var(--ink-3)' }}>No hay agentes configurados.</div>
            ) : (
              <div style={{ display:'flex', flexDirection:'column', gap:8 }}>
                {agents.map(a => (
                  <div key={a.id} style={{ display:'flex', alignItems:'center', gap:10 }}>
                    <div style={{
                      width:8, height:8, borderRadius:'50%', flexShrink:0,
                      background: a.enabled ? '#22C55E' : '#D1D5DB',
                    }} />
                    <span style={{ flex:1, fontSize:13, color:'var(--ink-2)', overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap' }}>{a.name}</span>
                    <span style={{ fontSize:11, color:'var(--ink-4)' }}>{a.type || 'General'}</span>
                  </div>
                ))}
              </div>
            )
          )}

          {/* Cost */}
          <div style={{
            background:'var(--surface)', border:'1px solid var(--border-color)',
            borderRadius:16, padding:'16px 22px',
            display:'flex', alignItems:'center', justifyContent:'space-between',
          }}>
            <div>
              <div style={{ fontSize:13, fontWeight:600, color:'var(--ink)' }}>💰 Costo IA acumulado</div>
              <div style={{ fontSize:12, color:'var(--ink-3)', marginTop:2 }}>Tokens Claude procesados</div>
            </div>
            <div style={{ textAlign:'right' }}>
              <div style={{ fontSize:20, fontWeight:800, color:'var(--green)' }}>
                ${(costUsd || 0).toFixed(2)}
              </div>
              <div style={{ fontSize:12, color:'var(--ink-3)', marginTop:2 }}>Hoy: <b style={{ color:'var(--ink-2)' }}>${(costToday || 0).toFixed(2)}</b></div>
            </div>
          </div>

        </div>
      </div>

      {/* More stats row */}
      <div style={{ display:'flex', gap:14, flexWrap:'wrap' }}>
        {card('📈', metrics.stages_advanced,  'Etapas avanzadas',    'en pipeline',       '#0891B2')}
        {card('📅', metrics.activities_created,'Actividades creadas', 'en CRM',            '#7C3AED')}
        {card('📨', metrics.templates_sent,    'Templates enviados',  'vía automatizaciones','#D97706')}
        {card('🏠', metrics.properties_sent,   'Propiedades enviadas','búsquedas Tokko',   '#3A6351')}
      </div>

    </div>
  );
}

// ─── CampaignsPanel ───────────────────────────────────────────────────────────

const CAMP_STATUS_STYLE = {
  draft:     { bg:'#F3F4F6', color:'#6B7280',  label:'Borrador' },
  running:   { bg:'#DBEAFE', color:'#1D4ED8',  label:'▶ En ejecución' },
  paused:    { bg:'#FEF9C3', color:'#92400E',  label:'⏸ Pausada' },
  completed: { bg:'#DCFCE7', color:'#15803D',  label:'✅ Completada' },
  error:     { bg:'#FEE2E2', color:'#B91C1C',  label:'❌ Error' },
};

const smallBtn = {
  fontSize:12, padding:'6px 14px', borderRadius:8, cursor:'pointer',
  fontWeight:500, border:'1px solid var(--border)', background:'var(--white)',
  color:'var(--ink-2)', transition:'background var(--trans)',
};
const smallDangerBtn = { ...smallBtn, color:'var(--danger)', borderColor:'#FECACA', background:'#FEF2F2' };

function CampaignsPanel() {
  const { pipelines, templates } = useContext(PipochatCtx);
  const [campaigns, setCampaigns] = useState([]);
  const [showNew, setShowNew]     = useState(false);
  const [selected, setSelected]   = useState(null); // campaign being viewed/run
  const [contacts, setContacts]   = useState([]);
  const [running, setRunning]     = useState(false);

  const load = () => apiFetch('/api/campaigns').then(r => r.json()).then(d => setCampaigns(d.campaigns || []));
  useEffect(() => { load(); }, []);

  const openDetail = async (c) => {
    setSelected(c);
    const res = await apiFetch(`/api/campaigns/${c.id}/contacts`);
    const d   = await res.json();
    setContacts(d.contacts || []);
  };

  const pause = async (id) => {
    await apiFetch(`/api/campaigns/${id}/pause`, { method: 'POST' });
    load();
  };

  const reset = async (id) => {
    if (!confirm('¿Reiniciar campaña? Esto borra el progreso y vuelve a estado borrador.')) return;
    await apiFetch(`/api/campaigns/${id}/reset`, { method: 'POST' });
    setSelected(null); setContacts([]); load();
  };

  const del = async (id) => {
    if (!confirm('¿Eliminar esta campaña?')) return;
    await apiFetch(`/api/campaigns/${id}`, { method: 'DELETE' });
    setSelected(null); load();
  };

  const launch = async (campaign) => {
    setRunning(true);
    const updatedCamp = { ...campaign, status: 'running', stats: campaign.stats || { total:0, sent:0, failed:0, skipped:0 } };
    setSelected(updatedCamp);

    const es = new EventSource(`/api/campaigns/${campaign.id}/run?token=${localStorage.getItem('ll_token') || ''}`);

    es.onmessage = (e) => {
      const msg = JSON.parse(e.data);
      if (msg.type === 'progress') {
        setSelected(prev => prev ? { ...prev, stats: msg.stats, status: 'running' } : prev);
        setContacts(prev => {
          const idx = prev.findIndex(c => c.conversationId === msg.contact.conversationId);
          if (idx !== -1) { const n = [...prev]; n[idx] = msg.contact; return n; }
          return [...prev, msg.contact];
        });
      } else if (msg.type === 'done' || msg.type === 'error') {
        es.close();
        setRunning(false);
        load();
        setSelected(prev => prev ? { ...prev, stats: msg.stats || prev.stats, status: msg.type === 'done' ? 'completed' : 'error' } : prev);
      }
    };

    es.onerror = () => { es.close(); setRunning(false); load(); };
  };

  // Use fetch + ReadableStream for SSE with auth header
  const launchWithAuth = async (campaign) => {
    setRunning(true);
    const updatedCamp = { ...campaign, status: 'running', stats: { total:0, sent:0, failed:0, skipped:0 } };
    setSelected(updatedCamp);
    setContacts([]);

    const token = localStorage.getItem('ll_token') || '';
    const response = await fetch(`/api/campaigns/${campaign.id}/run`, {
      method: 'POST',
      headers: { 'Authorization': `Bearer ${token}` },
    });

    const reader   = response.body.getReader();
    const decoder  = new TextDecoder();
    let   buffer   = '';

    while (true) {
      const { done, value } = await reader.read();
      if (done) break;
      buffer += decoder.decode(value, { stream: true });
      const lines = buffer.split('\n');
      buffer = lines.pop();
      for (const line of lines) {
        if (!line.startsWith('data: ')) continue;
        try {
          const msg = JSON.parse(line.slice(6));
          if (msg.type === 'progress') {
            setSelected(prev => prev ? { ...prev, stats: msg.stats, status: 'running' } : prev);
            setContacts(prev => {
              const idx = prev.findIndex(c => c.conversationId === msg.contact.conversationId);
              const updated = [...prev];
              if (idx !== -1) updated[idx] = msg.contact;
              else updated.push(msg.contact);
              return updated;
            });
          } else if (msg.type === 'done' || msg.type === 'error') {
            setRunning(false);
            load();
            setSelected(prev => prev ? { ...prev, stats: msg.stats || prev.stats, status: msg.type === 'done' ? 'completed' : 'error' } : prev);
          }
        } catch {}
      }
    }
    setRunning(false);
  };

  if (selected) {
    const ss    = CAMP_STATUS_STYLE[selected.status] || CAMP_STATUS_STYLE.draft;
    const sent  = selected.stats?.sent || 0;
    const total = selected.stats?.total || contacts.length || 0;
    const pct   = total > 0 ? Math.round((sent / total) * 100) : 0;

    return (
      <div style={S.editor}>
        {/* Back + title */}
        <div>
          <button onClick={() => { setSelected(null); setContacts([]); load(); }}
            style={{ fontSize:13, color:'var(--ink-3)', background:'none', border:'none', cursor:'pointer', padding:0, marginBottom:10 }}>
            ← Volver a campañas
          </button>
          <div style={{ display:'flex', alignItems:'flex-start', gap:12 }}>
            <div style={{ flex:1 }}>
              <div style={S.pageTitle}>{selected.name}</div>
              {selected.description && <div style={S.pageSubtitle}>{selected.description}</div>}
            </div>
            <span style={{ fontSize:12, fontWeight:600, padding:'5px 14px', borderRadius:99, background:ss.bg, color:ss.color, flexShrink:0 }}>{ss.label}</span>
          </div>
        </div>

        {/* Stats row */}
        <div style={{ display:'flex', gap:12, flexWrap:'wrap' }}>
          {[
            { label:'Total contactos', value: total,                       color:'var(--ink)',   bg:'var(--white)' },
            { label:'Enviados',        value: selected.stats?.sent    || 0, color:'#15803D',     bg:'#F0FDF4' },
            { label:'Omitidos',        value: selected.stats?.skipped || 0, color:'#92400E',     bg:'#FFFBEB' },
            { label:'Fallidos',        value: selected.stats?.failed  || 0, color:'var(--danger)', bg:'#FFF5F5' },
          ].map(s => (
            <div key={s.label} style={{ ...S.card, flex:1, minWidth:110, textAlign:'center', padding:'16px 12px', background:s.bg }}>
              <div style={{ fontSize:28, fontWeight:800, color:s.color, letterSpacing:'-.5px' }}>{s.value}</div>
              <div style={{ fontSize:11, color:'var(--ink-3)', marginTop:4, fontWeight:500 }}>{s.label}</div>
            </div>
          ))}
        </div>

        {/* Progress bar */}
        {(selected.status === 'running' || selected.status === 'completed') && total > 0 && (
          <div style={S.card}>
            <div style={{ display:'flex', justifyContent:'space-between', fontSize:12, color:'var(--ink-3)', marginBottom:8 }}>
              <span style={{ fontWeight:600, color:'var(--ink)' }}>Progreso de envíos</span>
              <span style={{ fontWeight:700, color:'var(--green)' }}>{pct}%</span>
            </div>
            <div style={{ height:10, background:'var(--cream-dark)', borderRadius:99, overflow:'hidden' }}>
              <div style={{ height:'100%', width:`${pct}%`, background:'var(--green)', borderRadius:99, transition:'width .4s' }} />
            </div>
            <div style={{ fontSize:11, color:'var(--ink-3)', marginTop:8 }}>{sent} de {total} enviados</div>
          </div>
        )}

        {/* Action buttons */}
        <div style={{ display:'flex', gap:10, flexWrap:'wrap' }}>
          {(selected.status === 'draft' || selected.status === 'paused') && (
            <button style={S.saveBtn} onClick={() => launchWithAuth(selected)} disabled={running}>
              {running ? '⏳ Ejecutando…' : selected.status === 'paused' ? '▶ Reanudar campaña' : '🚀 Lanzar campaña'}
            </button>
          )}
          {selected.status === 'running' && (
            <button onClick={() => pause(selected.id)} style={S.outlineBtn}>⏸ Pausar</button>
          )}
          {(selected.status === 'completed' || selected.status === 'error') && (
            <button onClick={() => reset(selected.id)} style={S.outlineBtn}>↺ Reiniciar</button>
          )}
          <button onClick={() => del(selected.id)} style={S.dangerBtn}>Eliminar campaña</button>
        </div>

        {/* Contacts table */}
        {contacts.length > 0 && (
          <div style={S.card}>
            <div style={{ ...S.cardTitle, marginBottom:14 }}>Contactos ({contacts.length})</div>
            <div style={{ maxHeight:380, overflowY:'auto', margin:'0 -4px' }}>
              {contacts.map((c, i) => {
                const statusColor = c.status === 'sent' ? '#15803D' : c.status === 'failed' ? '#B91C1C' : c.status === 'skipped' ? '#92400E' : '#6B7280';
                const statusBg    = c.status === 'sent' ? '#DCFCE7' : c.status === 'failed' ? '#FEE2E2' : c.status === 'skipped' ? '#FEF3C7' : '#F3F4F6';
                const statusIcon  = c.status === 'sent' ? '✅' : c.status === 'failed' ? '❌' : c.status === 'skipped' ? '⏭️' : '⏳';
                return (
                  <div key={c.conversationId} style={{ display:'flex', alignItems:'flex-start', gap:12, padding:'11px 4px', borderBottom: i < contacts.length-1 ? '1px solid var(--border-soft)' : 'none' }}>
                    <span style={{ fontSize:16, flexShrink:0, marginTop:1 }}>{statusIcon}</span>
                    <div style={{ flex:1, minWidth:0 }}>
                      <div style={{ display:'flex', alignItems:'center', gap:8, flexWrap:'wrap' }}>
                        <span style={{ fontSize:13, fontWeight:600, color:'var(--ink)' }}>{c.contactName}</span>
                        <span style={{ fontSize:11, fontWeight:600, padding:'2px 9px', borderRadius:99, background:statusBg, color:statusColor }}>{c.status}</span>
                        {!c.within24h && <span style={{ fontSize:11, color:'#92400E', background:'#FEF3C7', padding:'2px 8px', borderRadius:99 }}>fuera 24h</span>}
                      </div>
                      {c.message && <div style={{ fontSize:12, color:'var(--ink-3)', marginTop:3, fontStyle:'italic', overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap' }}>"{c.message}"</div>}
                      {c.error   && <div style={{ fontSize:12, color:'#B91C1C', marginTop:3 }}>{c.error}</div>}
                    </div>
                  </div>
                );
              })}
            </div>
          </div>
        )}
      </div>
    );
  }

  return (
    <div style={S.editor}>
      {/* Header */}
      <div style={{ display:'flex', alignItems:'flex-start', justifyContent:'space-between', gap:16 }}>
        <div>
          <div style={S.pageTitle}>📢 Campañas de difusión</div>
          <div style={S.pageSubtitle}>Mensajes masivos personalizados por IA para cada lead. Claude lee el historial y escribe un mensaje único.</div>
        </div>
        <button style={{ ...S.saveBtn, flexShrink:0 }} onClick={() => setShowNew(true)}>+ Nueva campaña</button>
      </div>

      {campaigns.length === 0 ? (
        <div style={{ flex:1, display:'flex', alignItems:'center', justifyContent:'center', minHeight:360 }}>
          <div style={{ textAlign:'center', color:'var(--ink-3)' }}>
            <div style={{ fontSize:52, marginBottom:16 }}>📢</div>
            <div style={{ fontWeight:700, fontSize:16, color:'var(--ink)', marginBottom:8 }}>Sin campañas todavía</div>
            <div style={{ fontSize:13, maxWidth:320, margin:'0 auto', lineHeight:1.7, color:'var(--ink-3)' }}>
              Creá una campaña para enviar mensajes personalizados por IA a todos los leads de una etapa de tu pipeline.
            </div>
            <button style={{ ...S.saveBtn, marginTop:24 }} onClick={() => setShowNew(true)}>+ Crear primera campaña</button>
          </div>
        </div>
      ) : (
        <div style={{ display:'flex', flexDirection:'column', gap:10 }}>
          {campaigns.map(c => {
            const ss    = CAMP_STATUS_STYLE[c.status] || CAMP_STATUS_STYLE.draft;
            const total = c.stats?.total || 0;
            const sent  = c.stats?.sent  || 0;
            const pct   = total > 0 ? Math.round((sent / total) * 100) : 0;
            const modeIcon = c.messageMode === 'ai' ? '🤖' : c.messageMode === 'template' ? '📋' : '✍️';
            const modeLabel = c.messageMode === 'ai' ? 'IA personalizada' : c.messageMode === 'template' ? 'Template' : 'Texto fijo';
            return (
              <div key={c.id} style={{ ...S.card, cursor:'pointer', transition:'box-shadow var(--trans), border-color var(--trans)' }}
                onClick={() => openDetail(c)}
                onMouseEnter={e => e.currentTarget.style.boxShadow = 'var(--shadow-md)'}
                onMouseLeave={e => e.currentTarget.style.boxShadow = 'var(--shadow-sm)'}>
                <div style={{ display:'flex', alignItems:'flex-start', gap:14 }}>
                  {/* Mode icon */}
                  <div style={{ width:40, height:40, borderRadius:10, background:'var(--green-light)', display:'flex', alignItems:'center', justifyContent:'center', fontSize:20, flexShrink:0 }}>
                    {modeIcon}
                  </div>
                  <div style={{ flex:1, minWidth:0 }}>
                    <div style={{ display:'flex', alignItems:'center', gap:10, flexWrap:'wrap', marginBottom:2 }}>
                      <span style={{ fontSize:14, fontWeight:700, color:'var(--ink)' }}>{c.name}</span>
                      <span style={{ fontSize:11, fontWeight:600, padding:'3px 10px', borderRadius:99, background:ss.bg, color:ss.color }}>{ss.label}</span>
                      <span style={{ fontSize:11, color:'var(--ink-4)', background:'var(--cream-mid)', padding:'3px 8px', borderRadius:99 }}>{modeLabel}</span>
                    </div>
                    {c.description && <div style={{ fontSize:12, color:'var(--ink-3)', marginBottom:6 }}>{c.description}</div>}
                    {total > 0 && (
                      <div style={{ marginTop:8 }}>
                        <div style={{ display:'flex', justifyContent:'space-between', fontSize:11, color:'var(--ink-3)', marginBottom:5 }}>
                          <span>{sent} enviados de {total}</span><span style={{ fontWeight:600 }}>{pct}%</span>
                        </div>
                        <div style={{ height:5, background:'var(--cream-dark)', borderRadius:99, overflow:'hidden' }}>
                          <div style={{ height:'100%', width:`${pct}%`, background: c.status === 'completed' ? '#22C55E' : 'var(--green)', borderRadius:99 }} />
                        </div>
                      </div>
                    )}
                  </div>
                  <div style={{ fontSize:11, color:'var(--ink-4)', flexShrink:0, textAlign:'right' }}>
                    {new Date(c.createdAt).toLocaleDateString('es-AR')}
                    <div style={{ marginTop:4, color:'var(--ink-3)', fontWeight:500 }}>Ver detalle →</div>
                  </div>
                </div>
              </div>
            );
          })}
        </div>
      )}

      {showNew && (
        <CampaignModal
          pipelines={pipelines}
          templates={templates}
          onClose={() => setShowNew(false)}
          onSave={() => { setShowNew(false); load(); }}
        />
      )}
    </div>
  );
}

// ── Modal form helpers ────────────────────────────────────────────────────────
const mInput = {
  width:'100%', padding:'10px 14px', border:'1.5px solid #D1CEC8',
  borderRadius:10, fontSize:14, outline:'none', color:'#0F1A14',
  background:'#FFFFFF', boxSizing:'border-box', transition:'border-color .15s',
  display:'block',
};
function MField({ label, hint, children }) {
  return (
    <div style={{ display:'flex', flexDirection:'column', gap:6 }}>
      <div style={{ fontSize:13, fontWeight:600, color:'#374151' }}>{label}</div>
      {children}
      {hint && <div style={{ fontSize:12, color:'#6B7280', lineHeight:1.5 }}>{hint}</div>}
    </div>
  );
}

// Custom dropdown — replaces native <select> so OS never overrides text color
function MSelect({ value, onChange, options, placeholder }) {
  const [open, setOpen] = useState(false);
  const ref = useRef(null);
  const chosen = options.find(o => o.value === value);

  useEffect(() => {
    const handler = (e) => { if (ref.current && !ref.current.contains(e.target)) setOpen(false); };
    document.addEventListener('mousedown', handler);
    return () => document.removeEventListener('mousedown', handler);
  }, []);

  return (
    <div ref={ref} style={{ position:'relative' }}>
      {/* Trigger */}
      <button type="button" onClick={() => setOpen(o => !o)}
        style={{ ...mInput, display:'flex', alignItems:'center', justifyContent:'space-between', cursor:'pointer', textAlign:'left' }}>
        <span style={{ color: chosen ? '#0F1A14' : '#9CA3AF' }}>
          {chosen ? chosen.label : (placeholder || 'Seleccionar…')}
        </span>
        <span style={{ fontSize:10, color:'#6B7280', marginLeft:8 }}>{open ? '▲' : '▼'}</span>
      </button>

      {/* Dropdown list */}
      {open && (
        <div style={{
          position:'absolute', top:'calc(100% + 6px)', left:0, right:0,
          background:'#FFFFFF', border:'1.5px solid #D1CEC8', borderRadius:10,
          boxShadow:'0 8px 24px rgba(0,0,0,.12)', zIndex:200, maxHeight:220, overflowY:'auto',
        }}>
          {options.map(o => (
            <button key={o.value} type="button"
              onClick={() => { onChange(o.value); setOpen(false); }}
              style={{
                display:'block', width:'100%', padding:'10px 14px', textAlign:'left',
                background: o.value === value ? '#EBF3EF' : 'transparent',
                color: o.value === value ? '#2A4D3E' : '#0F1A14',
                fontWeight: o.value === value ? 600 : 400,
                border:'none', cursor:'pointer', fontSize:14,
                borderBottom:'1px solid #F0EDE8',
              }}
              onMouseEnter={e => { if (o.value !== value) e.currentTarget.style.background = '#F9F8F6'; }}
              onMouseLeave={e => { if (o.value !== value) e.currentTarget.style.background = 'transparent'; }}>
              {o.value === value && <span style={{ color:'#3A6351', marginRight:8 }}>✓</span>}
              {o.label}
            </button>
          ))}
        </div>
      )}
    </div>
  );
}

function CampaignModal({ pipelines, templates, onClose, onSave }) {
  const [step, setStep]     = useState(1);
  const [saving, setSaving] = useState(false);
  const [estimate, setEstimate] = useState(null);
  const [estimating, setEstimating] = useState(false);

  // Form state
  const [name, setName]             = useState('');
  const [description, setDescription] = useState('');
  const [pipelineId, setPipelineId] = useState('');
  const [stageIds, setStageIds]     = useState([]);
  const [maxContacts, setMaxContacts] = useState(200);
  const [messageMode, setMessageMode] = useState('ai');
  const [aiPrompt, setAiPrompt]     = useState('');
  const [fixedMessage, setFixedMessage] = useState('');
  const [templateId, setTemplateId] = useState('');
  const [fallbackTemplateId, setFallbackTemplateId] = useState('');
  const [delayBetweenMs, setDelayBetweenMs] = useState(2000);

  const selectedPipeline = pipelines.find(p => p._id === pipelineId);
  const stages           = selectedPipeline?.stages || [];

  const toggleStage = (id) => setStageIds(prev => prev.includes(id) ? prev.filter(x => x !== id) : [...prev, id]);

  const estimateAudience = async () => {
    setEstimating(true);
    const res = await apiFetch('/api/campaigns/estimate', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ filters: { pipelineId: pipelineId || undefined, stageIds: stageIds.length ? stageIds : undefined }, maxContacts }),
    });
    const d = await res.json();
    setEstimate(d);
    setEstimating(false);
  };

  const save = async () => {
    if (!name.trim())        { alert('Poné un nombre a la campaña.'); return; }
    if (!messageMode)        { alert('Elegí el modo de mensaje.'); return; }
    if (messageMode === 'ai'       && !aiPrompt.trim())     { alert('Escribí las instrucciones para la IA.'); return; }
    if (messageMode === 'fixed'    && !fixedMessage.trim()) { alert('Escribí el mensaje fijo.'); return; }
    if (messageMode === 'template' && !templateId)          { alert('Elegí un template.'); return; }
    setSaving(true);
    await apiFetch('/api/campaigns', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        name, description,
        filters: { pipelineId: pipelineId || undefined, stageIds: stageIds.length ? stageIds : undefined },
        maxContacts, messageMode, aiPrompt, fixedMessage, templateId, fallbackTemplateId, delayBetweenMs,
      }),
    });
    setSaving(false);
    onSave();
  };

  const stepStyle = (n) => ({
    width:28, height:28, borderRadius:'50%',
    background: step >= n ? 'var(--green)' : 'var(--cream-dark)',
    color:      step >= n ? 'white' : 'var(--ink-3)',
    display:'flex', alignItems:'center', justifyContent:'center',
    fontSize:13, fontWeight:700, flexShrink:0,
  });

  const overlay = { position:'fixed', inset:0, background:'rgba(0,0,0,0.45)', display:'flex', alignItems:'flex-start', justifyContent:'center', zIndex:1000, padding:'28px 16px', overflowY:'auto' };
  const sheet   = { background:'var(--white)', borderRadius:20, padding:'24px 28px', width:'100%', maxWidth:560, maxHeight:'90vh', overflowY:'auto', boxShadow:'0 24px 64px rgba(0,0,0,.18)', position:'relative' };
  const mHead   = { display:'flex', alignItems:'center', justifyContent:'space-between', marginBottom:16, paddingBottom:16, borderBottom:'1px solid var(--border-soft)' };
  const mTitle  = { fontSize:17, fontWeight:800, color:'var(--ink)' };
  const mClose  = { background:'none', border:'none', fontSize:20, color:'var(--ink-3)', cursor:'pointer', lineHeight:1, padding:'0 4px' };

  return (
    <div style={overlay} onClick={onClose}>
      <div style={sheet} onClick={e => e.stopPropagation()}>
        <div style={mHead}>
          <div style={mTitle}>Nueva campaña de difusión</div>
          <button style={mClose} onClick={onClose}>✕</button>
        </div>

        {/* Step indicators */}
        <div style={{ display:'flex', alignItems:'center', gap:8, padding:'16px 0', marginBottom:8 }}>
          {['Nombre', 'Audiencia', 'Mensaje'].map((label, i) => (
            <React.Fragment key={i}>
              <div style={{ display:'flex', alignItems:'center', gap:8, cursor:'pointer' }} onClick={() => setStep(i+1)}>
                <div style={stepStyle(i+1)}>{i+1}</div>
                <span style={{ fontSize:12, fontWeight:step===i+1?700:400, color:step>=i+1?'var(--ink)':'var(--ink-3)' }}>{label}</span>
              </div>
              {i < 2 && <div style={{ flex:1, height:1, background:'var(--border-color)' }} />}
            </React.Fragment>
          ))}
        </div>

        {/* Step 1 — Nombre */}
        {step === 1 && (
          <div style={{ display:'flex', flexDirection:'column', gap:16, paddingBottom:20 }}>
            <MField label="Nombre de la campaña *">
              <input style={mInput} value={name} onChange={e => setName(e.target.value)} placeholder="Ej: Reactivación leads fríos Agosto" />
            </MField>
            <MField label="Descripción (opcional)">
              <textarea style={{ ...mInput, height:80, resize:'vertical' }} value={description} onChange={e => setDescription(e.target.value)} placeholder="Notas internas sobre el objetivo de esta campaña" />
            </MField>
            <MField label="Delay entre envíos (ms)" hint="Tiempo entre cada mensaje enviado. Mínimo recomendado: 1500ms.">
              <input style={mInput} type="number" min={500} max={10000} value={delayBetweenMs} onChange={e => setDelayBetweenMs(+e.target.value)} />
            </MField>
          </div>
        )}

        {/* Step 2 — Audiencia */}
        {step === 2 && (
          <div style={{ display:'flex', flexDirection:'column', gap:16, paddingBottom:20 }}>
            <MField label="Pipeline" hint="Sin selección aplica a todas las conversaciones abiertas">
              <MSelect
                value={pipelineId}
                onChange={(v) => { setPipelineId(v); setStageIds([]); }}
                placeholder="Todos los pipelines"
                options={[
                  { value: '', label: 'Todos los pipelines' },
                  ...pipelines.map(p => ({ value: p._id, label: p.name || p.title || p._id })),
                ]}
              />
            </MField>

            {stages.length > 0 && (
              <div>
                <div style={{ fontSize:13, fontWeight:600, color:'var(--ink)', marginBottom:10 }}>Etapas <span style={{ fontSize:12, color:'var(--ink-3)', fontWeight:400 }}>(opcional — sin selección = todas)</span></div>
                <div style={{ display:'flex', flexWrap:'wrap', gap:8 }}>
                  {stages.map(s => (
                    <button key={s._id} onClick={() => toggleStage(s._id)}
                      style={{ padding:'7px 16px', borderRadius:99, fontSize:13, fontWeight:600, cursor:'pointer',
                        border: `1.5px solid ${stageIds.includes(s._id) ? 'var(--green)' : '#C9C5BE'}`,
                        background: stageIds.includes(s._id) ? 'var(--green)' : 'var(--white)',
                        color:      stageIds.includes(s._id) ? '#fff'         : '#1F2937',
                        transition:'all var(--trans)',
                      }}>
                      {s.name}
                    </button>
                  ))}
                </div>
              </div>
            )}

            <MField label="Máximo de contactos">
              <input style={mInput} type="number" min={1} max={1000} value={maxContacts} onChange={e => setMaxContacts(+e.target.value)} />
            </MField>

            <div>
              <button onClick={estimateAudience} disabled={estimating}
                style={{ padding:'9px 20px', background:'var(--green-light)', color:'var(--green-hover)', border:'1.5px solid var(--green-mid)', borderRadius:10, fontSize:13, fontWeight:600, cursor:'pointer' }}>
                {estimating ? 'Calculando…' : '🔍 Estimar audiencia'}
              </button>
              {estimate && (
                <div style={{ marginTop:12, display:'flex', gap:12 }}>
                  <div style={{ padding:'10px 16px', background:'var(--green-light)', borderRadius:10, fontSize:13 }}>
                    <span style={{ fontWeight:700, color:'var(--green)', fontSize:16 }}>{estimate.total}</span>
                    <span style={{ color:'var(--ink-3)', marginLeft:6 }}>contactos</span>
                  </div>
                  <div style={{ padding:'10px 16px', background:'#DCFCE7', borderRadius:10, fontSize:13 }}>
                    <span style={{ fontWeight:700, color:'#15803D', fontSize:16 }}>{estimate.within24h}</span>
                    <span style={{ color:'var(--ink-3)', marginLeft:6 }}>dentro de 24h</span>
                  </div>
                  <div style={{ padding:'10px 16px', background:'#FEF3C7', borderRadius:10, fontSize:13 }}>
                    <span style={{ fontWeight:700, color:'#92400E', fontSize:16 }}>{estimate.outside24h}</span>
                    <span style={{ color:'var(--ink-3)', marginLeft:6 }}>fuera de 24h</span>
                  </div>
                </div>
              )}
            </div>
          </div>
        )}

        {/* Step 3 — Mensaje */}
        {step === 3 && (
          <div style={{ display:'flex', flexDirection:'column', gap:16, paddingBottom:20 }}>
            <div>
              <div style={{ fontSize:13, fontWeight:600, color:'var(--ink)', marginBottom:10 }}>Modo de mensaje *</div>
              <div style={{ display:'flex', flexDirection:'column', gap:8 }}>
                {[
                  { value:'ai',       icon:'🤖', label:'IA personalizada', desc:'Claude lee el historial de cada lead y escribe un mensaje único para cada uno.' },
                  { value:'template', icon:'📋', label:'Template aprobado', desc:'Envía un HSM template de WhatsApp. Funciona siempre (dentro y fuera de la ventana de 24hs).' },
                  { value:'fixed',    icon:'✍️', label:'Texto fijo',        desc:'El mismo mensaje para todos. Solo enviado si el contacto escribió en las últimas 24hs.' },
                ].map(m => (
                  <label key={m.value} style={{ display:'flex', gap:12, padding:'12px 14px', border:`2px solid ${messageMode===m.value?'var(--green)':'var(--border-color)'}`, borderRadius:10, cursor:'pointer', background: messageMode===m.value?'var(--green-light)':'var(--surface)' }}>
                    <input type="radio" name="mode" value={m.value} checked={messageMode===m.value} onChange={e=>setMessageMode(e.target.value)} style={{ accentColor:'var(--green)', marginTop:2 }} />
                    <div>
                      <div style={{ fontSize:13, fontWeight:700, color:'var(--ink)' }}>{m.icon} {m.label}</div>
                      <div style={{ fontSize:12, color:'var(--ink-3)', marginTop:2 }}>{m.desc}</div>
                    </div>
                  </label>
                ))}
              </div>
            </div>

            {messageMode === 'ai' && (
              <MField label="Instrucciones para Claude *" hint="Claude va a usar esto junto al historial de cada lead para personalizar el mensaje.">
                <textarea style={{ ...mInput, height:110, resize:'vertical' }} value={aiPrompt} onChange={e => setAiPrompt(e.target.value)}
                  placeholder="Ej: Recordale al lead que tiene una propuesta pendiente. Mencioná el nombre del proyecto si aparece en la conversación. Tono amigable, informal." />
              </MField>
            )}

            {messageMode === 'fixed' && (
              <MField label="Mensaje *">
                <textarea style={{ ...mInput, height:100, resize:'vertical' }} value={fixedMessage} onChange={e => setFixedMessage(e.target.value)}
                  placeholder="Escribí el mensaje que querés enviar a todos los contactos" />
              </MField>
            )}

            {messageMode === 'template' && (
              <MField label="Template *">
                <select style={mInput} value={templateId} onChange={e => setTemplateId(e.target.value)}>
                  <option value="">Elegir template…</option>
                  {templates.map(t => <option key={t._id} value={t._id}>{t.name}</option>)}
                </select>
              </MField>
            )}

            {(messageMode === 'ai' || messageMode === 'fixed') && (
              <MField label="Template de fallback" hint="WhatsApp solo permite texto libre dentro de 24hs del último mensaje del contacto. Fuera de ese plazo se usa el template.">
                <select style={mInput} value={fallbackTemplateId} onChange={e => setFallbackTemplateId(e.target.value)}>
                  <option value="">Sin fallback (omitir contactos fuera de 24hs)</option>
                  {templates.map(t => <option key={t._id} value={t._id}>{t.name}</option>)}
                </select>
              </MField>
            )}
          </div>
        )}

        {/* Footer nav */}
        <div style={{ display:'flex', justifyContent:'space-between', paddingTop:16, borderTop:'1px solid var(--border-soft)', marginTop:8 }}>
          <button style={S.outlineBtn} onClick={step === 1 ? onClose : () => setStep(s => s - 1)}>
            {step === 1 ? 'Cancelar' : '← Atrás'}
          </button>
          {step < 3 ? (
            <button style={S.saveBtn} onClick={() => setStep(s => s + 1)}>
              Siguiente →
            </button>
          ) : (
            <button style={S.saveBtn} onClick={save} disabled={saving}>
              {saving ? 'Guardando…' : '✅ Crear campaña'}
            </button>
          )}
        </div>
      </div>
    </div>
  );
}

// ─── Instagram SVG Icon ───────────────────────────────────────────────────────
function IGIcon({ size = 24, style = {} }) {
  const id = 'ig-grad-' + size;
  return (
    <svg width={size} height={size} viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" style={{ display: 'block', flexShrink: 0, ...style }}>
      <defs>
        <radialGradient id={id} cx="30%" cy="107%" r="150%">
          <stop offset="0%"   stopColor="#fdf497" />
          <stop offset="5%"   stopColor="#fdf497" />
          <stop offset="45%"  stopColor="#fd5949" />
          <stop offset="60%"  stopColor="#d6249f" />
          <stop offset="90%"  stopColor="#285AEB" />
        </radialGradient>
      </defs>
      <rect x="1" y="1" width="22" height="22" rx="6" ry="6" fill={`url(#${id})`} />
      <circle cx="12" cy="12" r="4.5" fill="none" stroke="white" strokeWidth="1.8" />
      <circle cx="17.8" cy="6.2" r="1.3" fill="white" />
    </svg>
  );
}

// ─── InstagramPanel ───────────────────────────────────────────────────────────
function InstagramPanel() {
  const [cfg, setCfg]           = useState(null);
  const [comments, setComments] = useState([]);
  const [convs, setConvs]       = useState([]);
  const [openConv, setOpenConv] = useState(null);
  const [saving, setSaving]     = useState(false);
  const [tab, setTab]           = useState('config');
  const [saved, setSaved]       = useState(false);
  const [pages, setPages]       = useState(null);
  const [loadingPages, setLoadingPages] = useState(false);
  const [pagesError, setPagesError]     = useState('');

  const DEFAULT_COMMENT_PROMPT = `Eres un asistente de ventas en Instagram. Respondés comentarios de forma amigable, breve (1-2 oraciones) y siempre invitás a continuar la conversación por WhatsApp para más información. No hagas preguntas largas. Sé cercano y natural.`;
  const DEFAULT_DM_PROMPT = `Eres un asistente de ventas en Instagram. Respondés mensajes directos de forma amigable y útil. Tu objetivo es responder dudas y derivar a WhatsApp para concretar. Sé natural y conversacional.`;

  useEffect(() => {
    apiFetch('/api/instagram/config').then(r => r.json()).then(d => setCfg({
      enabled: false, replyToComments: true, replyToDMs: true,
      commentPrompt: DEFAULT_COMMENT_PROMPT, dmPrompt: DEFAULT_DM_PROMPT,
      pageAccessToken: '', pageId: '', igUserId: '', igUsername: '', waNumber: '',
      ...d,
    }));
  }, []);

  useEffect(() => {
    if (tab === 'comments') {
      apiFetch('/api/instagram/comments?limit=100').then(r => r.json()).then(d => setComments(Array.isArray(d) ? d : []));
    }
    if (tab === 'dms') {
      apiFetch('/api/instagram/convs').then(r => r.json()).then(d => setConvs(Array.isArray(d) ? d : []));
    }
  }, [tab]);

  async function loadPages() {
    setLoadingPages(true); setPagesError('');
    try {
      const res = await apiFetch('/api/instagram/pages');
      const data = await res.json();
      if (data.error) { setPagesError(data.error); setPages([]); }
      else setPages(data);
    } catch { setPagesError('Error al cargar páginas'); setPages([]); }
    setLoadingPages(false);
  }

  function selectPage(p) {
    setCfg(c => ({ ...c, pageId: p.pageId, pageAccessToken: p.pageToken, igUserId: p.igId, igUsername: p.igUsername }));
    setPages(null);
  }

  async function save() {
    setSaving(true);
    await apiFetch('/api/instagram/config', { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(cfg) });
    setSaving(false); setSaved(true);
    setTimeout(() => setSaved(false), 2500);
  }

  function disconnect() {
    setCfg(c => ({ ...c, enabled: false, pageId: '', pageAccessToken: '', igUserId: '', igUsername: '' }));
  }

  function toggle(label, key, hint) {
    return (
      <div style={{ display: 'flex', alignItems: 'center', gap: 12, marginBottom: 14 }}>
        <div onClick={() => setCfg(c => ({ ...c, [key]: !c[key] }))}
          style={{ width: 44, height: 24, borderRadius: 12, background: cfg[key] ? 'var(--green)' : 'var(--border)', cursor: 'pointer', position: 'relative', flexShrink: 0, transition: 'background .2s' }}>
          <div style={{ position: 'absolute', top: 3, left: cfg[key] ? 23 : 3, width: 18, height: 18, borderRadius: '50%', background: '#fff', transition: 'left .2s' }} />
        </div>
        <div>
          <div style={{ fontSize: 14, fontWeight: 600, color: 'var(--ink-1)' }}>{label}</div>
          {hint && <div style={{ fontSize: 12, color: 'var(--ink-3)' }}>{hint}</div>}
        </div>
      </div>
    );
  }

  function mfield(label, key, type, placeholder) {
    return (
      <div style={{ marginBottom: 16 }}>
        <div style={{ fontSize: 13, fontWeight: 600, color: 'var(--ink-1)', marginBottom: 6 }}>{label}</div>
        {type === 'textarea'
          ? <textarea value={cfg[key] || ''} onChange={e => setCfg(c => ({ ...c, [key]: e.target.value }))} rows={4} placeholder={placeholder}
              style={{ width: '100%', padding: '10px 12px', borderRadius: 8, border: '1px solid var(--border)', background: 'var(--surface)', color: 'var(--ink-1)', fontSize: 14, resize: 'vertical', boxSizing: 'border-box' }} />
          : <input type={type || 'text'} value={cfg[key] || ''} onChange={e => setCfg(c => ({ ...c, [key]: e.target.value }))} placeholder={placeholder}
              style={{ width: '100%', padding: '10px 12px', borderRadius: 8, border: '1px solid var(--border)', background: 'var(--surface)', color: 'var(--ink-1)', fontSize: 14, boxSizing: 'border-box' }} />
        }
      </div>
    );
  }

  if (!cfg) return <div style={{ padding: 40, color: 'var(--ink-3)' }}>Cargando...</div>;

  const isConnected = !!cfg.pageId;
  const tabStyle = (t) => ({
    padding: '8px 18px', borderRadius: 8, border: 'none', cursor: 'pointer', fontWeight: 600, fontSize: 14,
    background: tab === t ? 'var(--green)' : 'transparent', color: tab === t ? '#fff' : 'var(--ink-2)',
  });

  return (
    <div style={{ ...S.editor }}>
      <div style={{ ...S.pageTitle, display: 'flex', alignItems: 'center', gap: 10 }}><IGIcon size={28} /> Instagram</div>
      <div style={{ ...S.pageSubtitle, marginBottom: 28 }}>Respuestas automáticas a comentarios y DMs con IA</div>

      <div style={{ display: 'flex', gap: 8, marginBottom: 28, background: 'var(--surface)', borderRadius: 10, padding: 4, width: 'fit-content' }}>
        <button style={tabStyle('config')}   onClick={() => setTab('config')}>⚙️ Configuración</button>
        <button style={tabStyle('comments')} onClick={() => setTab('comments')}>💬 Comentarios</button>
        <button style={tabStyle('dms')}      onClick={() => { setTab('dms'); setOpenConv(null); }}>✉️ Conversaciones DMs</button>
      </div>

      {tab === 'config' && (
        <div>
          <div style={{ ...S.card, marginBottom: 20, padding: 24 }}>
            {!isConnected ? (
              <div>
                <div style={{ fontSize: 15, fontWeight: 700, color: 'var(--ink-1)', marginBottom: 6 }}>Conectar cuenta de Instagram</div>
                <div style={{ fontSize: 13, color: 'var(--ink-3)', marginBottom: 20 }}>
                  Usamos tu cuenta de Meta ya conectada para detectar tus páginas de Instagram.
                </div>
                {pages === null && (
                  <button style={{ ...S.saveBtn, display: 'flex', alignItems: 'center', gap: 8 }} onClick={loadPages} disabled={loadingPages}>
                    {loadingPages ? 'Buscando páginas...' : <><IGIcon size={18} /> Conectar con Instagram</>}
                  </button>
                )}
                {pagesError && <div style={{ color: '#ef4444', fontSize: 13, marginTop: 10 }}>{pagesError}</div>}
                {pages !== null && pages.length === 0 && !pagesError && (
                  <div style={{ fontSize: 13, color: 'var(--ink-3)', marginTop: 10 }}>
                    No se encontraron páginas con Instagram Business Account vinculado.
                  </div>
                )}
                {pages && pages.length > 0 && (
                  <div style={{ marginTop: 8 }}>
                    <div style={{ fontSize: 13, fontWeight: 600, color: 'var(--ink-2)', marginBottom: 10 }}>Seleccioná tu cuenta:</div>
                    {pages.map(p => (
                      <div key={p.pageId} onClick={() => selectPage(p)}
                        style={{ display: 'flex', alignItems: 'center', gap: 12, padding: '12px 16px', borderRadius: 10, border: '1px solid var(--border)', marginBottom: 8, cursor: 'pointer', background: 'var(--bg)' }}>
                        <IGIcon size={28} />
                        <div>
                          <div style={{ fontWeight: 700, color: 'var(--ink-1)', fontSize: 14 }}>@{p.igUsername || p.pageName}</div>
                          <div style={{ fontSize: 12, color: 'var(--ink-3)' }}>{p.pageName}</div>
                        </div>
                      </div>
                    ))}
                  </div>
                )}
              </div>
            ) : (
              <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
                <div style={{ display: 'flex', alignItems: 'center', gap: 14 }}>
                  <IGIcon size={36} />
                  <div>
                    <div style={{ fontWeight: 700, color: 'var(--ink-1)', fontSize: 15 }}>@{cfg.igUsername || 'Instagram conectado'}</div>
                    <div style={{ fontSize: 12, color: 'var(--green)', fontWeight: 600 }}>● Conectado</div>
                  </div>
                </div>
                <button style={S.dangerBtn} onClick={disconnect}>Desconectar</button>
              </div>
            )}
          </div>

          {isConnected && (
            <div>
              <div style={{ ...S.card, marginBottom: 20, padding: 20 }}>
                {toggle('Activar respuestas automáticas', 'enabled')}
                {toggle('Responder comentarios de posts y ads', 'replyToComments')}
                {toggle('Responder DMs', 'replyToDMs', 'Requiere permiso instagram_messaging aprobado por Meta')}
              </div>
              <div style={{ ...S.card, marginBottom: 20, padding: 20 }}>
                <div style={{ fontSize: 14, fontWeight: 700, color: 'var(--ink-1)', marginBottom: 16 }}>🤖 Configuración del agente</div>
                {mfield('WhatsApp para derivar (con código de país)', 'waNumber', 'text', '+5491112345678')}
                {mfield('Prompt para comentarios', 'commentPrompt', 'textarea')}
                {mfield('Prompt para DMs', 'dmPrompt', 'textarea')}
              </div>
              <button style={S.saveBtn} onClick={save} disabled={saving}>
                {saving ? 'Guardando...' : saved ? '✓ Guardado' : 'Guardar configuración'}
              </button>
            </div>
          )}
        </div>
      )}

      {tab === 'comments' && (
        <div>
          {comments.length === 0
            ? <div style={{ ...S.card, padding: 48, textAlign: 'center', color: 'var(--ink-3)' }}>
                <div style={{ fontSize: 40, marginBottom: 12 }}>💬</div>
                <div style={{ fontSize: 16, fontWeight: 600 }}>Sin comentarios respondidos aún</div>
              </div>
            : comments.map(c => (
              <div key={c.commentId} style={{ ...S.card, marginBottom: 12, padding: 16 }}>
                <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 8 }}>
                  <div style={{ fontWeight: 700, color: 'var(--ink-1)', fontSize: 14 }}>
                    @{c.username} {c.isAd && <span style={{ background: '#3B82F6', color: '#fff', borderRadius: 4, padding: '1px 6px', fontSize: 11, marginLeft: 6 }}>Ad</span>}
                  </div>
                  <div style={{ fontSize: 12, color: 'var(--ink-3)' }}>{new Date(c.timestamp).toLocaleString('es-AR')}</div>
                </div>
                <div style={{ fontSize: 14, color: 'var(--ink-2)', marginBottom: 8, background: 'var(--bg)', borderRadius: 6, padding: '8px 12px' }}>💬 {c.text}</div>
                <div style={{ fontSize: 14, color: 'var(--ink-1)', background: 'rgba(58,99,81,.08)', borderRadius: 6, padding: '8px 12px' }}>🤖 {c.replyText}</div>
              </div>
            ))
          }
        </div>
      )}

      {tab === 'dms' && (
        <div style={{ display: 'flex', gap: 20, alignItems: 'flex-start' }}>
          {/* Conversation list */}
          <div style={{ width: 300, flexShrink: 0 }}>
            {convs.length === 0
              ? <div style={{ ...S.card, padding: 48, textAlign: 'center', color: 'var(--ink-3)' }}>
                  <div style={{ fontSize: 40, marginBottom: 12 }}>✉️</div>
                  <div style={{ fontSize: 15, fontWeight: 600, marginBottom: 6 }}>Sin conversaciones aún</div>
                  <div style={{ fontSize: 13 }}>Los DMs respondidos por IA aparecerán acá</div>
                </div>
              : convs.map(conv => {
                  const lastMsg = conv.messages[conv.messages.length - 1];
                  const isOpen = openConv?.igsid === conv.igsid;
                  return (
                    <div key={conv.igsid} onClick={() => setOpenConv(isOpen ? null : conv)}
                      style={{ ...S.card, marginBottom: 10, padding: '14px 16px', cursor: 'pointer',
                        border: isOpen ? '1.5px solid var(--green)' : '1px solid var(--border)',
                        background: isOpen ? 'var(--green-light)' : 'var(--surface)' }}>
                      <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
                        <div style={{ width: 36, height: 36, borderRadius: '50%', background: 'var(--green-mid)',
                          display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 16, flexShrink: 0 }}>
                          {conv.username ? conv.username[0].toUpperCase() : '?'}
                        </div>
                        <div style={{ minWidth: 0, flex: 1 }}>
                          <div style={{ fontWeight: 700, fontSize: 14, color: 'var(--ink-1)', marginBottom: 2 }}>
                            @{conv.username || conv.igsid}
                          </div>
                          {lastMsg && (
                            <div style={{ fontSize: 12, color: 'var(--ink-3)', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>
                              {lastMsg.role === 'assistant' ? '🤖 ' : '👤 '}{lastMsg.content}
                            </div>
                          )}
                        </div>
                        <div style={{ fontSize: 11, color: 'var(--ink-4)', whiteSpace: 'nowrap', marginLeft: 4 }}>
                          {new Date(conv.lastActivity).toLocaleDateString('es-AR', { day: '2-digit', month: '2-digit' })}
                        </div>
                      </div>
                      <div style={{ marginTop: 8, display: 'flex', gap: 6 }}>
                        <span style={{ fontSize: 11, background: 'var(--green-light)', color: 'var(--green)', borderRadius: 4, padding: '2px 7px', fontWeight: 600 }}>
                          {conv.messages.length} mensajes
                        </span>
                      </div>
                    </div>
                  );
                })
            }
          </div>

          {/* Thread view */}
          {openConv && (
            <div style={{ flex: 1, ...S.card, padding: 0, overflow: 'hidden', minHeight: 400 }}>
              {/* Header */}
              <div style={{ padding: '14px 20px', borderBottom: '1px solid var(--border)', display: 'flex', alignItems: 'center', gap: 12 }}>
                <div style={{ width: 38, height: 38, borderRadius: '50%', background: 'var(--green-mid)',
                  display: 'flex', alignItems: 'center', justifyContent: 'center', fontWeight: 700, fontSize: 16, color: 'var(--green)' }}>
                  {openConv.username ? openConv.username[0].toUpperCase() : '?'}
                </div>
                <div>
                  <div style={{ fontWeight: 700, fontSize: 15, color: 'var(--ink-1)' }}>@{openConv.username || openConv.igsid}</div>
                  <div style={{ fontSize: 12, color: 'var(--ink-3)' }}>Última actividad: {new Date(openConv.lastActivity).toLocaleString('es-AR')}</div>
                </div>
              </div>
              {/* Messages */}
              <div style={{ padding: '20px', display: 'flex', flexDirection: 'column', gap: 12, maxHeight: 500, overflowY: 'auto' }}>
                {openConv.messages.map((msg, i) => (
                  <div key={i} style={{ display: 'flex', justifyContent: msg.role === 'assistant' ? 'flex-end' : 'flex-start' }}>
                    <div style={{
                      maxWidth: '75%', padding: '10px 14px', borderRadius: msg.role === 'assistant' ? '14px 14px 4px 14px' : '14px 14px 14px 4px',
                      background: msg.role === 'assistant' ? 'var(--green)' : 'var(--bg)',
                      color: msg.role === 'assistant' ? '#fff' : 'var(--ink-1)',
                      border: msg.role === 'user' ? '1px solid var(--border)' : 'none',
                      fontSize: 14, lineHeight: 1.5,
                    }}>
                      <div style={{ fontSize: 11, marginBottom: 4, opacity: .7 }}>
                        {msg.role === 'assistant' ? '🤖 Looplead AI' : `👤 @${openConv.username}`}
                      </div>
                      {msg.content}
                      <div style={{ fontSize: 10, marginTop: 4, opacity: .6, textAlign: 'right' }}>
                        {new Date(msg.timestamp).toLocaleTimeString('es-AR', { hour: '2-digit', minute: '2-digit' })}
                      </div>
                    </div>
                  </div>
                ))}
              </div>
            </div>
          )}
        </div>
      )}
    </div>
  );
}

// ─── Facebook SVG Icon ────────────────────────────────────────────────────────
function FBIcon({ size = 24, style = {} }) {
  return (
    <svg width={size} height={size} viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" style={{ display: 'block', flexShrink: 0, ...style }}>
      <rect width="24" height="24" rx="6" fill="#1877F2"/>
      <path d="M13.5 8H15V5.5H13C11.07 5.5 10 6.57 10 8.5V10H8V12.5H10V19H12.5V12.5H14.5L15 10H12.5V8.5C12.5 8.22 12.72 8 13 8H13.5Z" fill="white"/>
    </svg>
  );
}

// ─── FacebookPanel ────────────────────────────────────────────────────────────
function FacebookPanel() {
  const [cfg, setCfg]           = useState(null);
  const [comments, setComments] = useState([]);
  const [convs, setConvs]       = useState([]);
  const [openConv, setOpenConv] = useState(null);
  const [saving, setSaving]     = useState(false);
  const [tab, setTab]           = useState('config');
  const [saved, setSaved]       = useState(false);
  const [pages, setPages]       = useState(null);
  const [loadingPages, setLoadingPages] = useState(false);
  const [pagesError, setPagesError]     = useState('');

  const DEFAULT_COMMENT_PROMPT = `Eres un asistente de ventas en Facebook. Respondés comentarios de forma amigable, breve (1-2 oraciones) y siempre invitás a continuar la conversación por WhatsApp para más información. No hagas preguntas largas. Sé cercano y natural.`;
  const DEFAULT_MESSAGE_PROMPT = `Eres un asistente de ventas en Facebook Messenger. Respondés mensajes de forma amigable y útil. Tu objetivo es responder dudas y derivar a WhatsApp para concretar. Sé natural y conversacional.`;

  useEffect(() => {
    apiFetch('/api/facebook/config').then(r => r.json()).then(d => setCfg({
      enabled: false, replyToComments: true, replyToMessages: true,
      commentPrompt: DEFAULT_COMMENT_PROMPT, messagePrompt: DEFAULT_MESSAGE_PROMPT,
      pageAccessToken: '', pageId: '', pageName: '', waNumber: '',
      ...d,
    }));
  }, []);

  useEffect(() => {
    if (tab === 'comments') {
      apiFetch('/api/facebook/comments?limit=100').then(r => r.json()).then(d => setComments(Array.isArray(d) ? d : []));
    }
    if (tab === 'messenger') {
      apiFetch('/api/facebook/convs').then(r => r.json()).then(d => setConvs(Array.isArray(d) ? d : []));
    }
  }, [tab]);

  async function loadPages() {
    setLoadingPages(true); setPagesError('');
    try {
      const res = await apiFetch('/api/facebook/pages');
      const data = await res.json();
      if (data.error) { setPagesError(data.error); setPages([]); }
      else setPages(data);
    } catch { setPagesError('Error al cargar páginas'); setPages([]); }
    setLoadingPages(false);
  }

  function selectPage(p) {
    setCfg(c => ({ ...c, pageId: p.id, pageAccessToken: p.access_token, pageName: p.name }));
    setPages(null);
  }

  async function save() {
    setSaving(true);
    await apiFetch('/api/facebook/config', { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(cfg) });
    setSaving(false); setSaved(true);
    setTimeout(() => setSaved(false), 2500);
  }

  function disconnect() {
    setCfg(c => ({ ...c, enabled: false, pageId: '', pageAccessToken: '', pageName: '' }));
  }

  function toggle(label, key, hint) {
    return (
      <div style={{ display: 'flex', alignItems: 'center', gap: 12, marginBottom: 14 }}>
        <div onClick={() => setCfg(c => ({ ...c, [key]: !c[key] }))}
          style={{ width: 44, height: 24, borderRadius: 12, background: cfg[key] ? 'var(--green)' : 'var(--border)', cursor: 'pointer', position: 'relative', flexShrink: 0, transition: 'background .2s' }}>
          <div style={{ position: 'absolute', top: 3, left: cfg[key] ? 23 : 3, width: 18, height: 18, borderRadius: '50%', background: '#fff', transition: 'left .2s' }} />
        </div>
        <div>
          <div style={{ fontSize: 14, fontWeight: 600, color: 'var(--ink-1)' }}>{label}</div>
          {hint && <div style={{ fontSize: 12, color: 'var(--ink-3)' }}>{hint}</div>}
        </div>
      </div>
    );
  }

  function mfield(label, key, type, placeholder) {
    return (
      <div style={{ marginBottom: 16 }}>
        <div style={{ fontSize: 13, fontWeight: 600, color: 'var(--ink-1)', marginBottom: 6 }}>{label}</div>
        {type === 'textarea'
          ? <textarea value={cfg[key] || ''} onChange={e => setCfg(c => ({ ...c, [key]: e.target.value }))} rows={4} placeholder={placeholder}
              style={{ width: '100%', padding: '10px 12px', borderRadius: 8, border: '1px solid var(--border)', background: 'var(--surface)', color: 'var(--ink-1)', fontSize: 14, resize: 'vertical', boxSizing: 'border-box' }} />
          : <input type={type || 'text'} value={cfg[key] || ''} onChange={e => setCfg(c => ({ ...c, [key]: e.target.value }))} placeholder={placeholder}
              style={{ width: '100%', padding: '10px 12px', borderRadius: 8, border: '1px solid var(--border)', background: 'var(--surface)', color: 'var(--ink-1)', fontSize: 14, boxSizing: 'border-box' }} />
        }
      </div>
    );
  }

  if (!cfg) return <div style={{ padding: 40, color: 'var(--ink-3)' }}>Cargando...</div>;

  const isConnected = !!cfg.pageId;
  const tabStyle = (t) => ({
    padding: '8px 18px', borderRadius: 8, border: 'none', cursor: 'pointer', fontWeight: 600, fontSize: 14,
    background: tab === t ? 'var(--green)' : 'transparent', color: tab === t ? '#fff' : 'var(--ink-2)',
  });

  return (
    <div style={{ ...S.editor }}>
      <div style={{ ...S.pageTitle, display: 'flex', alignItems: 'center', gap: 10 }}><FBIcon size={28} /> Facebook</div>
      <div style={{ ...S.pageSubtitle, marginBottom: 28 }}>Respuestas automáticas a comentarios y mensajes de Messenger con IA</div>

      <div style={{ display: 'flex', gap: 8, marginBottom: 28, background: 'var(--surface)', borderRadius: 10, padding: 4, width: 'fit-content' }}>
        <button style={tabStyle('config')}    onClick={() => setTab('config')}>⚙️ Configuración</button>
        <button style={tabStyle('comments')}  onClick={() => setTab('comments')}>💬 Comentarios</button>
        <button style={tabStyle('messenger')} onClick={() => { setTab('messenger'); setOpenConv(null); }}>✉️ Conversaciones Messenger</button>
      </div>

      {tab === 'config' && (
        <div>
          <div style={{ ...S.card, marginBottom: 20, padding: 24 }}>
            {!isConnected ? (
              <div>
                <div style={{ fontSize: 15, fontWeight: 700, color: 'var(--ink-1)', marginBottom: 6 }}>Conectar página de Facebook</div>
                <div style={{ fontSize: 13, color: 'var(--ink-3)', marginBottom: 20 }}>
                  Usamos tu cuenta de Meta ya conectada para detectar tus páginas de Facebook.
                </div>
                {pages === null && (
                  <button style={{ ...S.saveBtn, display: 'flex', alignItems: 'center', gap: 8 }} onClick={loadPages} disabled={loadingPages}>
                    {loadingPages ? 'Buscando páginas...' : <><FBIcon size={18} /> Conectar con Facebook</>}
                  </button>
                )}
                {pagesError && <div style={{ color: '#ef4444', fontSize: 13, marginTop: 10 }}>{pagesError}</div>}
                {pages !== null && pages.length === 0 && !pagesError && (
                  <div style={{ fontSize: 13, color: 'var(--ink-3)', marginTop: 10 }}>
                    No se encontraron páginas de Facebook.
                  </div>
                )}
                {pages && pages.length > 0 && (
                  <div style={{ marginTop: 8 }}>
                    <div style={{ fontSize: 13, fontWeight: 600, color: 'var(--ink-2)', marginBottom: 10 }}>Seleccioná tu página:</div>
                    {pages.map(p => (
                      <div key={p.id} onClick={() => selectPage(p)}
                        style={{ display: 'flex', alignItems: 'center', gap: 12, padding: '12px 16px', borderRadius: 10, border: '1px solid var(--border)', marginBottom: 8, cursor: 'pointer', background: 'var(--bg)' }}>
                        <FBIcon size={28} />
                        <div>
                          <div style={{ fontWeight: 700, color: 'var(--ink-1)', fontSize: 14 }}>{p.name}</div>
                          <div style={{ fontSize: 12, color: 'var(--ink-3)' }}>ID: {p.id}</div>
                        </div>
                      </div>
                    ))}
                  </div>
                )}
              </div>
            ) : (
              <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
                <div style={{ display: 'flex', alignItems: 'center', gap: 14 }}>
                  <FBIcon size={36} />
                  <div>
                    <div style={{ fontWeight: 700, color: 'var(--ink-1)', fontSize: 15 }}>{cfg.pageName || 'Página de Facebook conectada'}</div>
                    <div style={{ fontSize: 12, color: 'var(--green)', fontWeight: 600 }}>● Conectado</div>
                  </div>
                </div>
                <button style={S.dangerBtn} onClick={disconnect}>Desconectar</button>
              </div>
            )}
          </div>

          {isConnected && (
            <div>
              <div style={{ ...S.card, marginBottom: 20, padding: 20 }}>
                {toggle('Activar respuestas automáticas', 'enabled')}
                {toggle('Responder comentarios de posts y ads', 'replyToComments')}
                {toggle('Responder mensajes de Messenger', 'replyToMessages', 'Requiere permiso pages_messaging aprobado por Meta')}
              </div>
              <div style={{ ...S.card, marginBottom: 20, padding: 20 }}>
                <div style={{ fontSize: 14, fontWeight: 700, color: 'var(--ink-1)', marginBottom: 16 }}>🤖 Configuración del agente</div>
                {mfield('WhatsApp para derivar (con código de país)', 'waNumber', 'text', '+5491112345678')}
                {mfield('Prompt para comentarios', 'commentPrompt', 'textarea')}
                {mfield('Prompt para Messenger', 'messagePrompt', 'textarea')}
              </div>
              <button style={S.saveBtn} onClick={save} disabled={saving}>
                {saving ? 'Guardando...' : saved ? '✓ Guardado' : 'Guardar configuración'}
              </button>
            </div>
          )}
        </div>
      )}

      {tab === 'comments' && (
        <div>
          {comments.length === 0
            ? <div style={{ ...S.card, padding: 48, textAlign: 'center', color: 'var(--ink-3)' }}>
                <div style={{ fontSize: 40, marginBottom: 12 }}>💬</div>
                <div style={{ fontSize: 16, fontWeight: 600 }}>Sin comentarios respondidos aún</div>
              </div>
            : comments.map(c => (
              <div key={c.commentId} style={{ ...S.card, marginBottom: 12, padding: 16 }}>
                <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 8 }}>
                  <div style={{ fontWeight: 700, color: 'var(--ink-1)', fontSize: 14 }}>
                    {c.senderName} {c.isAd && <span style={{ background: '#3B82F6', color: '#fff', borderRadius: 4, padding: '1px 6px', fontSize: 11, marginLeft: 6 }}>Ad</span>}
                  </div>
                  <div style={{ fontSize: 12, color: 'var(--ink-3)' }}>{new Date(c.timestamp).toLocaleString('es-AR')}</div>
                </div>
                <div style={{ fontSize: 14, color: 'var(--ink-2)', marginBottom: 8, background: 'var(--bg)', borderRadius: 6, padding: '8px 12px' }}>💬 {c.text}</div>
                <div style={{ fontSize: 14, color: 'var(--ink-1)', background: 'rgba(58,99,81,.08)', borderRadius: 6, padding: '8px 12px' }}>🤖 {c.replyText}</div>
              </div>
            ))
          }
        </div>
      )}

      {tab === 'messenger' && (
        <div style={{ display: 'flex', gap: 20, alignItems: 'flex-start' }}>
          {/* Conversation list */}
          <div style={{ width: 300, flexShrink: 0 }}>
            {convs.length === 0
              ? <div style={{ ...S.card, padding: 48, textAlign: 'center', color: 'var(--ink-3)' }}>
                  <div style={{ fontSize: 40, marginBottom: 12 }}>✉️</div>
                  <div style={{ fontSize: 15, fontWeight: 600, marginBottom: 6 }}>Sin conversaciones aún</div>
                  <div style={{ fontSize: 13 }}>Los mensajes de Messenger respondidos por IA aparecerán acá</div>
                </div>
              : convs.map(conv => {
                  const lastMsg = conv.messages[conv.messages.length - 1];
                  const isOpen = openConv?.psid === conv.psid;
                  return (
                    <div key={conv.psid} onClick={() => setOpenConv(isOpen ? null : conv)}
                      style={{ ...S.card, marginBottom: 10, padding: '14px 16px', cursor: 'pointer',
                        border: isOpen ? '1.5px solid var(--green)' : '1px solid var(--border)',
                        background: isOpen ? 'var(--green-light)' : 'var(--surface)' }}>
                      <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
                        <div style={{ width: 36, height: 36, borderRadius: '50%', background: 'var(--green-mid)',
                          display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 16, flexShrink: 0 }}>
                          {conv.name ? conv.name[0].toUpperCase() : '?'}
                        </div>
                        <div style={{ minWidth: 0, flex: 1 }}>
                          <div style={{ fontWeight: 700, fontSize: 14, color: 'var(--ink-1)', marginBottom: 2 }}>
                            {conv.name || conv.psid}
                          </div>
                          {lastMsg && (
                            <div style={{ fontSize: 12, color: 'var(--ink-3)', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>
                              {lastMsg.role === 'assistant' ? '🤖 ' : '👤 '}{lastMsg.content}
                            </div>
                          )}
                        </div>
                        <div style={{ fontSize: 11, color: 'var(--ink-4)', whiteSpace: 'nowrap', marginLeft: 4 }}>
                          {new Date(conv.lastActivity).toLocaleDateString('es-AR', { day: '2-digit', month: '2-digit' })}
                        </div>
                      </div>
                      <div style={{ marginTop: 8, display: 'flex', gap: 6 }}>
                        <span style={{ fontSize: 11, background: 'var(--green-light)', color: 'var(--green)', borderRadius: 4, padding: '2px 7px', fontWeight: 600 }}>
                          {conv.messages.length} mensajes
                        </span>
                      </div>
                    </div>
                  );
                })
            }
          </div>

          {/* Thread view */}
          {openConv && (
            <div style={{ flex: 1, ...S.card, padding: 0, overflow: 'hidden', minHeight: 400 }}>
              {/* Header */}
              <div style={{ padding: '14px 20px', borderBottom: '1px solid var(--border)', display: 'flex', alignItems: 'center', gap: 12 }}>
                <div style={{ width: 38, height: 38, borderRadius: '50%', background: 'var(--green-mid)',
                  display: 'flex', alignItems: 'center', justifyContent: 'center', fontWeight: 700, fontSize: 16, color: 'var(--green)' }}>
                  {openConv.name ? openConv.name[0].toUpperCase() : '?'}
                </div>
                <div>
                  <div style={{ fontWeight: 700, fontSize: 15, color: 'var(--ink-1)' }}>{openConv.name || openConv.psid}</div>
                  <div style={{ fontSize: 12, color: 'var(--ink-3)' }}>Última actividad: {new Date(openConv.lastActivity).toLocaleString('es-AR')}</div>
                </div>
              </div>
              {/* Messages */}
              <div style={{ padding: '20px', display: 'flex', flexDirection: 'column', gap: 12, maxHeight: 500, overflowY: 'auto' }}>
                {openConv.messages.map((msg, i) => (
                  <div key={i} style={{ display: 'flex', justifyContent: msg.role === 'assistant' ? 'flex-end' : 'flex-start' }}>
                    <div style={{
                      maxWidth: '75%', padding: '10px 14px', borderRadius: msg.role === 'assistant' ? '14px 14px 4px 14px' : '14px 14px 14px 4px',
                      background: msg.role === 'assistant' ? 'var(--green)' : 'var(--bg)',
                      color: msg.role === 'assistant' ? '#fff' : 'var(--ink-1)',
                      border: msg.role === 'user' ? '1px solid var(--border)' : 'none',
                      fontSize: 14, lineHeight: 1.5,
                    }}>
                      <div style={{ fontSize: 11, marginBottom: 4, opacity: .7 }}>
                        {msg.role === 'assistant' ? '🤖 Looplead AI' : `👤 ${openConv.name}`}
                      </div>
                      {msg.content}
                      <div style={{ fontSize: 10, marginTop: 4, opacity: .6, textAlign: 'right' }}>
                        {new Date(msg.timestamp).toLocaleTimeString('es-AR', { hour: '2-digit', minute: '2-digit' })}
                      </div>
                    </div>
                  </div>
                ))}
              </div>
            </div>
          )}
        </div>
      )}

    </div>
  );
}

// ─── GSIcon ───────────────────────────────────────────────────────────────────
function GSIcon({ size = 24, style = {} }) {
  return (
    <svg width={size} height={size} viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" style={{ display:'block', flexShrink:0, ...style }}>
      <rect width="24" height="24" rx="5" fill="#0F9D58"/>
      <rect x="5" y="7" width="14" height="10" rx="1" fill="white" opacity="0.2"/>
      <rect x="5" y="7" width="14" height="2.6" rx="1" fill="white" opacity="0.85"/>
      <rect x="5" y="11" width="14" height="0.7" fill="white" opacity="0.45"/>
      <rect x="5" y="13.5" width="14" height="0.7" fill="white" opacity="0.45"/>
      <rect x="9.5" y="7" width="0.7" height="10" fill="white" opacity="0.45"/>
      <rect x="13.8" y="7" width="0.7" height="10" fill="white" opacity="0.45"/>
    </svg>
  );
}

// ─── GoogleSheetsPanel ────────────────────────────────────────────────────────
function GoogleSheetsPanel() {
  const [cfg, setCfg]         = useState(null);
  const [saving, setSaving]   = useState(false);
  const [saved, setSaved]     = useState(false);
  const [headers, setHeaders] = useState(null);
  const [detecting, setDetecting] = useState(false);
  const [detectErr, setDetectErr] = useState('');
  const [preview, setPreview] = useState(null);
  const [gcalOk, setGcalOk]   = useState(null);
  const [files, setFiles]       = useState(null);
  const [filesErr, setFilesErr] = useState('');
  const [loadingFiles, setLoadingFiles] = useState(false);
  const [showPicker, setShowPicker]     = useState(false);
  const pickerRef = React.useRef(null);

  useEffect(() => {
    apiFetch('/api/google-sheets/config').then(r => r.json()).then(d =>
      setCfg({ enabled: false, spreadsheetId: '', spreadsheetName: '', defaultSheetName: '', description: '', ...d })
    );
    apiFetch('/api/integrations').then(r => r.json()).then(d => {
      setGcalOk(!!(d?.googleSheets?.connected && d?.googleSheets?.refreshToken)
        ? { ok: true, email: d.googleSheets.email }
        : { ok: false });
    }).catch(() => setGcalOk({ ok: false }));
  }, []);

  function connectSheets() {
    const tid = localStorage.getItem('ll_tenant') || '';
    // Use tenantId from session info — fetch it
    apiFetch('/api/auth/me').then(r => r.json()).then(d => {
      window.location.href = `/api/integrations/google-sheets/authorize?tid=${d.tenantId}`;
    });
  }

  async function disconnectSheets() {
    await apiFetch('/api/google-sheets/connection', { method: 'DELETE' });
    setGcalOk({ ok: false });
    setFiles(null); setFilesErr('');
  }

  // Close picker on outside click
  useEffect(() => {
    if (!showPicker) return;
    function handler(e) {
      if (pickerRef.current && !pickerRef.current.contains(e.target)) setShowPicker(false);
    }
    document.addEventListener('mousedown', handler);
    return () => document.removeEventListener('mousedown', handler);
  }, [showPicker]);

  async function openPicker() {
    setShowPicker(true);
    if (files !== null && !filesErr) return; // already loaded successfully
    setLoadingFiles(true); setFilesErr(''); setFiles(null);
    try {
      const res = await apiFetch('/api/google-sheets/list-files');
      const data = await res.json();
      if (data.error) { setFilesErr(data.error); setFiles([]); }
      else setFiles(data.files || []);
    } catch (e) { setFilesErr('Error de red al cargar planillas'); setFiles([]); }
    setLoadingFiles(false);
  }

  function pickFile(f) {
    setCfg(c => ({ ...c, spreadsheetId: `https://docs.google.com/spreadsheets/d/${f.id}`, spreadsheetName: f.name }));
    setShowPicker(false);
    setHeaders(null); setPreview(null); setDetectErr('');
  }

  async function save() {
    setSaving(true);
    await apiFetch('/api/google-sheets/config', { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(cfg) });
    setSaving(false); setSaved(true);
    setTimeout(() => setSaved(false), 2500);
  }

  async function detectColumns() {
    setDetecting(true); setDetectErr(''); setHeaders(null); setPreview(null);
    try {
      const res = await apiFetch('/api/google-sheets/headers', {
        method: 'POST', headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ spreadsheetId: cfg.spreadsheetId, sheetName: cfg.defaultSheetName || undefined }),
      });
      const data = await res.json();
      if (data.error) { setDetectErr(data.error); }
      else {
        setHeaders(data.headers || []);
        if (data.headers?.length) {
          // Also load a small preview
          const prev = await apiFetch('/api/google-sheets/read', {
            method: 'POST', headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ spreadsheetId: cfg.spreadsheetId, sheetName: cfg.defaultSheetName || undefined, limit: 3 }),
          });
          const pd = await prev.json();
          setPreview(pd.rows || []);
        }
      }
    } catch (e) { setDetectErr('Error al conectar con la API'); }
    setDetecting(false);
  }

  if (!cfg) return <div style={{ padding:40, color:'var(--ink-3)' }}>Cargando...</div>;

  const labelStyle = { fontSize:13, fontWeight:600, color:'var(--ink-2)', marginBottom:6 };
  const inputStyle = { width:'100%', padding:'10px 12px', borderRadius:8, border:'1px solid var(--border)', background:'var(--surface)', color:'var(--ink)', fontSize:14, boxSizing:'border-box' };
  const textareaStyle = { ...inputStyle, resize:'vertical', minHeight:80 };

  const hasId = !!(cfg.spreadsheetId || '').trim();

  return (
    <div style={S.editor}>
      <div style={{ ...S.pageTitle, display:'flex', alignItems:'center', gap:10 }}>
        <GSIcon size={28} /> Google Sheets
      </div>
      <div style={{ ...S.pageSubtitle, marginBottom:28 }}>Conectá una planilla para que el agente pueda leer, buscar y agregar filas automáticamente</div>

      {/* OAuth connection card */}
      <div style={{ background:'var(--surface)', borderRadius:12, padding:'16px 20px', marginBottom:20, boxShadow:'var(--shadow-sm)', display:'flex', alignItems:'center', gap:16 }}>
        <GSIcon size={36} style={{ flexShrink:0 }} />
        <div style={{ flex:1 }}>
          {gcalOk?.ok ? (
            <>
              <div style={{ fontSize:14, fontWeight:700, color:'var(--ink)' }}>Google Sheets conectado</div>
              <div style={{ fontSize:12, color:'var(--ink-3)', marginTop:2 }}>{gcalOk.email || 'Cuenta conectada'}</div>
            </>
          ) : (
            <>
              <div style={{ fontSize:14, fontWeight:700, color:'var(--ink)' }}>Conectar Google Sheets</div>
              <div style={{ fontSize:12, color:'var(--ink-3)', marginTop:2 }}>Autorizá el acceso a tus planillas una sola vez</div>
            </>
          )}
        </div>
        {gcalOk?.ok ? (
          <button onClick={disconnectSheets}
            style={{ padding:'7px 16px', borderRadius:8, border:'1px solid var(--border)', background:'transparent', color:'var(--ink-3)', fontWeight:600, fontSize:13, cursor:'pointer' }}>
            Desconectar
          </button>
        ) : (
          <button onClick={connectSheets}
            style={{ padding:'8px 20px', borderRadius:8, border:'none', background:'var(--green)', color:'#fff', fontWeight:700, fontSize:13, cursor:'pointer', display:'flex', alignItems:'center', gap:8 }}>
            <GSIcon size={16} style={{ filter:'brightness(10)' }} /> Conectar con Google
          </button>
        )}
      </div>

      {/* Enable toggle */}
      <div style={{ background:'var(--surface)', borderRadius:12, padding:'16px 20px', marginBottom:20, boxShadow:'var(--shadow-sm)', display:'flex', alignItems:'center', gap:14 }}>
        <div onClick={() => setCfg(c => ({ ...c, enabled: !c.enabled }))}
          style={{ width:44, height:24, borderRadius:12, background: cfg.enabled ? 'var(--green)' : 'var(--border)', cursor:'pointer', position:'relative', flexShrink:0, transition:'background .2s' }}>
          <div style={{ position:'absolute', top:3, left: cfg.enabled ? 23 : 3, width:18, height:18, borderRadius:'50%', background:'#fff', transition:'left .2s' }} />
        </div>
        <div>
          <div style={{ fontSize:14, fontWeight:600, color:'var(--ink)' }}>Habilitar Google Sheets</div>
          <div style={{ fontSize:12, color:'var(--ink-3)' }}>El agente tendrá acceso a las herramientas de lectura y escritura</div>
        </div>
      </div>

      {/* Spreadsheet config */}
      <div style={{ background:'var(--surface)', borderRadius:12, padding:'20px 24px', marginBottom:20, boxShadow:'var(--shadow-sm)' }}>
        <div style={{ fontSize:15, fontWeight:700, color:'var(--ink)', marginBottom:16 }}>Planilla</div>

        <div style={{ marginBottom:16 }}>
          <div style={labelStyle}>Planilla</div>
          {/* Picker button + dropdown */}
          <div style={{ position:'relative' }} ref={pickerRef}>
            <button onClick={openPicker}
              style={{ width:'100%', padding:'10px 14px', borderRadius:8, border:'1px solid var(--border)', background:'var(--surface)', color:'var(--ink)', fontSize:14, textAlign:'left', cursor:'pointer', display:'flex', alignItems:'center', gap:8, marginBottom:8 }}>
              <GSIcon size={16} />
              <span style={{ flex:1, color: cfg.spreadsheetName ? 'var(--ink)' : 'var(--ink-4)' }}>
                {cfg.spreadsheetName || 'Elegir de mis planillas…'}
              </span>
              <span style={{ fontSize:11, color:'var(--ink-4)' }}>▾</span>
            </button>
            {showPicker && (
              <div style={{ position:'absolute', top:'100%', left:0, right:0, zIndex:100, background:'var(--surface)', border:'1px solid var(--border)', borderRadius:10, boxShadow:'var(--shadow-md)', maxHeight:260, overflowY:'auto', marginTop:2 }}>
                {loadingFiles && (
                  <div style={{ padding:'14px 16px', color:'var(--ink-3)', fontSize:13 }}>Cargando tus planillas…</div>
                )}
                {!loadingFiles && filesErr && (
                  <div style={{ padding:'12px 16px', fontSize:12, color:'var(--danger)' }}>
                    ❌ {filesErr}
                  </div>
                )}
                {!loadingFiles && !filesErr && files && files.length === 0 && (
                  <div style={{ padding:'14px 16px', color:'var(--ink-3)', fontSize:13 }}>No hay planillas en tu Google Drive.</div>
                )}
                {!loadingFiles && files && files.map(f => (
                  <div key={f.id} onClick={() => pickFile(f)}
                    style={{ padding:'10px 16px', cursor:'pointer', display:'flex', alignItems:'center', gap:10, borderBottom:'1px solid var(--border-soft)' }}
                    onMouseEnter={e => e.currentTarget.style.background='var(--cream)'}
                    onMouseLeave={e => e.currentTarget.style.background='transparent'}>
                    <GSIcon size={16} />
                    <div style={{ flex:1, minWidth:0 }}>
                      <div style={{ fontSize:13, fontWeight:600, color:'var(--ink)', whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis' }}>{f.name}</div>
                      <div style={{ fontSize:11, color:'var(--ink-4)' }}>Modificada: {new Date(f.modifiedTime).toLocaleDateString('es-AR', { day:'numeric', month:'short', year:'numeric' })}</div>
                    </div>
                  </div>
                ))}
              </div>
            )}
          </div>
          {/* Manual URL input as fallback */}
          <input value={cfg.spreadsheetId || ''} onChange={e => setCfg(c => ({ ...c, spreadsheetId: e.target.value, spreadsheetName: '' }))}
            placeholder="O pegá la URL manualmente"
            style={{ ...inputStyle, fontSize:12, color:'var(--ink-3)' }} />
          <div style={{ fontSize:11, color:'var(--ink-3)', marginTop:4 }}>El sistema extrae el ID automáticamente de la URL</div>
        </div>

        <div style={{ marginBottom:16 }}>
          <div style={labelStyle}>Nombre del tab (hoja)</div>
          <input value={cfg.defaultSheetName || ''} onChange={e => setCfg(c => ({ ...c, defaultSheetName: e.target.value }))}
            placeholder="Hoja 1 (opcional — usa la primera si está vacío)"
            style={inputStyle} />
        </div>

        <div style={{ marginBottom:16 }}>
          <div style={labelStyle}>Nombre descriptivo</div>
          <input value={cfg.spreadsheetName || ''} onChange={e => setCfg(c => ({ ...c, spreadsheetName: e.target.value }))}
            placeholder="Ej: Clientes, Inventario, Registros..."
            style={inputStyle} />
        </div>

        <div style={{ marginBottom:0 }}>
          <div style={labelStyle}>Descripción para el agente</div>
          <textarea value={cfg.description || ''} onChange={e => setCfg(c => ({ ...c, description: e.target.value }))}
            placeholder="Describí qué contiene esta planilla y cuándo el agente debe usarla. Ej: 'Lista de propiedades disponibles con precio y disponibilidad. Consultá antes de responder preguntas sobre stock.'"
            style={textareaStyle} />
        </div>
      </div>

      {/* Detect columns + preview */}
      {hasId && (
        <div style={{ background:'var(--surface)', borderRadius:12, padding:'20px 24px', marginBottom:20, boxShadow:'var(--shadow-sm)' }}>
          <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between', marginBottom:12 }}>
            <div style={{ fontSize:15, fontWeight:700, color:'var(--ink)' }}>Columnas detectadas</div>
            <button onClick={detectColumns} disabled={detecting}
              style={{ padding:'7px 16px', borderRadius:8, border:'none', background:'var(--green)', color:'#fff', fontWeight:600, fontSize:13, cursor:'pointer', opacity: detecting ? .7 : 1 }}>
              {detecting ? 'Detectando...' : '🔍 Detectar columnas'}
            </button>
          </div>
          {detectErr && <div style={{ color:'var(--danger)', fontSize:13, marginBottom:8 }}>❌ {detectErr}</div>}
          {headers !== null && headers.length === 0 && !detectErr && (
            <div style={{ color:'var(--ink-3)', fontSize:13 }}>No se encontraron encabezados — ¿el tab tiene datos en la fila 1?</div>
          )}
          {headers && headers.length > 0 && (
            <>
              <div style={{ display:'flex', flexWrap:'wrap', gap:6, marginBottom:16 }}>
                {headers.map(h => (
                  <span key={h} style={{ padding:'3px 10px', borderRadius:6, background:'var(--green-light)', color:'var(--green)', fontSize:12, fontWeight:600 }}>{h}</span>
                ))}
              </div>
              {preview && preview.length > 0 && (
                <div style={{ overflowX:'auto' }}>
                  <div style={{ fontSize:12, fontWeight:600, color:'var(--ink-3)', marginBottom:8 }}>Vista previa ({preview.length} filas)</div>
                  <table style={{ width:'100%', borderCollapse:'collapse', fontSize:12 }}>
                    <thead>
                      <tr>
                        {headers.map(h => (
                          <th key={h} style={{ textAlign:'left', padding:'4px 8px', background:'var(--cream)', color:'var(--ink-2)', fontWeight:600, borderBottom:'1px solid var(--border)' }}>{h}</th>
                        ))}
                      </tr>
                    </thead>
                    <tbody>
                      {preview.map((row, i) => (
                        <tr key={i}>
                          {headers.map(h => (
                            <td key={h} style={{ padding:'4px 8px', color:'var(--ink)', borderBottom:'1px solid var(--border-soft)', maxWidth:200, overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap' }}>
                              {row[h] || ''}
                            </td>
                          ))}
                        </tr>
                      ))}
                    </tbody>
                  </table>
                </div>
              )}
            </>
          )}
        </div>
      )}

      {/* How the agent uses it */}
      <div style={{ background:'var(--cream-mid)', borderRadius:12, padding:'16px 20px', marginBottom:24, border:'1px solid var(--border-soft)' }}>
        <div style={{ fontSize:13, fontWeight:700, color:'var(--ink-2)', marginBottom:8 }}>🤖 Herramientas disponibles para el agente</div>
        <div style={{ display:'flex', flexDirection:'column', gap:6 }}>
          {[
            { name:'read_google_sheet', desc:'Lee filas de la planilla. Útil para consultar stock, precios, disponibilidad.' },
            { name:'find_in_sheet', desc:'Busca filas donde una columna coincide con un valor. Ej: buscar por email o teléfono.' },
            { name:'append_to_sheet', desc:'Agrega una fila nueva. Útil para registrar leads, reservas, formularios.' },
          ].map(t => (
            <div key={t.name} style={{ display:'flex', gap:10, alignItems:'flex-start' }}>
              <span style={{ fontFamily:'monospace', background:'var(--surface)', padding:'2px 8px', borderRadius:4, fontSize:11, color:'var(--green)', fontWeight:700, flexShrink:0, border:'1px solid var(--border-soft)' }}>{t.name}</span>
              <span style={{ fontSize:12, color:'var(--ink-3)', lineHeight:1.5 }}>{t.desc}</span>
            </div>
          ))}
        </div>
        <div style={{ fontSize:11, color:'var(--ink-4)', marginTop:10 }}>Las herramientas están disponibles automáticamente para todos los agentes cuando Google Sheets está habilitado.</div>
      </div>

      {/* Save button */}
      <button onClick={save} disabled={saving}
        style={{ padding:'12px 28px', borderRadius:10, border:'none', background:'var(--green)', color:'#fff', fontWeight:700, fontSize:15, cursor:'pointer', opacity: saving ? .7 : 1 }}>
        {saving ? 'Guardando...' : saved ? '✅ Guardado' : 'Guardar configuración'}
      </button>
    </div>
  );
}

// ─── WebhookPanel ─────────────────────────────────────────────────────────────
const WEBHOOK_EVENTS = [
  { value:'lead.created',      label:'👤 Lead creado en CRM' },
  { value:'lead.hot',          label:'🔥 Lead se vuelve caliente (score ≥ 7)' },
  { value:'handoff.triggered', label:'🤝 Handoff disparado' },
  { value:'stage.changed',     label:'📈 Etapa del pipeline cambiada' },
  { value:'ai.reply',          label:'🤖 Respuesta IA enviada' },
];

// ─── Landing Pages ────────────────────────────────────────────────────────────

const LandIcon = ({ size = 18 }) => (
  <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
    <rect x="2" y="3" width="20" height="14" rx="2" />
    <line x1="8" y1="21" x2="16" y2="21" />
    <line x1="12" y1="17" x2="12" y2="21" />
  </svg>
);

// Reusable image upload component for landing assets
function ImgUpload({ filename, tid, onUpload, onClear, label = 'Imagen', height = 72 }) {
  const [uploading, setUploading] = useState(false);
  const ref = useRef();
  async function handleFile(e) {
    const file = e.target.files[0];
    if (!file) return;
    setUploading(true);
    try {
      const fd = new FormData();
      fd.append('image', file);
      const r = await apiFetch('/api/landings/upload-image', { method: 'POST', body: fd });
      const d = await r.json();
      if (d.filename) onUpload(d.filename);
    } catch {}
    finally { setUploading(false); if (ref.current) ref.current.value = ''; }
  }
  const src = filename && tid ? `/landing-assets/${tid}/${filename}` : null;
  return (
    <div style={{ display:'flex', flexDirection:'column', gap:6 }}>
      <span style={S.label}>{label}</span>
      {src && (
        <div style={{ position:'relative', display:'inline-block' }}>
          <img src={src} style={{ height, objectFit:'cover', borderRadius:8, border:'1px solid var(--border)', display:'block', maxWidth:160 }} />
          <button onClick={() => onClear && onClear()} title="Quitar imagen"
            style={{ position:'absolute', top:-8, right:-8, width:22, height:22, border:'none', background:'var(--danger)', color:'#fff', borderRadius:'50%', cursor:'pointer', fontSize:16, lineHeight:1, display:'flex', alignItems:'center', justifyContent:'center' }}>×</button>
        </div>
      )}
      <button onClick={() => ref.current?.click()} disabled={uploading}
        style={{ ...S.outlineBtn, fontSize:12, padding:'6px 14px', width:'fit-content' }}>
        {uploading ? '⏳ Subiendo...' : src ? '🔄 Cambiar' : '📷 Subir imagen'}
      </button>
      <input ref={ref} type="file" accept="image/*" style={{ display:'none' }} onChange={handleFile} />
    </div>
  );
}

// Short random ID for sections / products / fields
const _rid = () => Math.random().toString(36).slice(2, 10);
// Slugify a string
const _slug = (s) => (s || '').toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '').slice(0, 60) || 'mi-landing';

function LandingEditor({ initial, tenantId, onBack }) {
  const [form, setForm]           = useState(() => JSON.parse(JSON.stringify(initial)));
  const [tab, setTab]             = useState('config');
  const [saving, setSaving]       = useState(false);
  const [saved, setSaved]         = useState(false);
  const [saveErr, setSaveErr]     = useState('');
  const [slugStatus, setSlugStatus] = useState('ok');
  const [openSecs, setOpenSecs]   = useState(() => new Set());
  const [openProds, setOpenProds] = useState(() => new Set());
  const [showAddMenu, setShowAddMenu] = useState(false);

  const setF    = patch => setForm(f => ({ ...f, ...patch }));
  const setHero = patch => setForm(f => ({ ...f, hero: { ...f.hero, ...patch } }));

  async function checkSlug(slug) {
    if (!slug || !/^[a-z0-9-]{2,}$/.test(slug)) { setSlugStatus('invalid'); return; }
    setSlugStatus('checking');
    try {
      const r = await apiFetch(`/api/landings/slug-check?slug=${encodeURIComponent(slug)}&id=${form.id || ''}`);
      const d = await r.json();
      setSlugStatus(d.available ? 'ok' : 'taken');
    } catch { setSlugStatus('ok'); }
  }

  // ── Section helpers ──────────────────────────────────────────────────────────
  const toggleSec  = id => setOpenSecs(s  => { const n = new Set(s);  n.has(id) ? n.delete(id) : n.add(id); return n; });
  const toggleProd = id => setOpenProds(s => { const n = new Set(s);  n.has(id) ? n.delete(id) : n.add(id); return n; });

  const updateSection = (id, patch) =>
    setForm(f => ({ ...f, sections: f.sections.map(s => s.id === id ? { ...s, ...patch } : s) }));

  const removeSection = id => {
    setForm(f => ({ ...f, sections: f.sections.filter(s => s.id !== id) }));
    setOpenSecs(s => { const n = new Set(s); n.delete(id); return n; });
  };

  const moveSection = (id, dir) => setForm(f => {
    const arr = [...f.sections], i = arr.findIndex(s => s.id === id), j = i + dir;
    if (j < 0 || j >= arr.length) return f;
    [arr[i], arr[j]] = [arr[j], arr[i]];
    return { ...f, sections: arr };
  });

  function addSection(type) {
    setShowAddMenu(false);
    const id = _rid();
    let sec;
    if (type === 'text')     sec = { id, type, content:'', align:'left' };
    if (type === 'image')    sec = { id, type, filename:'', url:'', alt:'' };
    if (type === 'products') sec = { id, type, title:'', columns:3, items:[] };
    if (type === 'cta')      sec = { id, type, text:'Consultar por WhatsApp', message:'Hola! Vi tu página y quiero más información.' };
    if (type === 'form')     sec = { id, type, title:'Dejanos tus datos', subtitle:'', fields:[
      { id:_rid(), label:'Nombre',    placeholder:'Tu nombre completo',   type:'text', required:true },
      { id:_rid(), label:'WhatsApp',  placeholder:'+54 9 11 XXXX XXXX',  type:'tel',  required:true },
    ], submitLabel:'Enviar por WhatsApp', waMessage:'Hola! Me contacto desde tu landing page.' };
    if (!sec) return;
    setForm(f => ({ ...f, sections:[...f.sections, sec] }));
    setOpenSecs(s => new Set([...s, id]));
  }

  // ── Product helpers ──────────────────────────────────────────────────────────
  const addProduct = secId => {
    const pid = _rid();
    updateSection(secId, { items:[...(form.sections.find(s=>s.id===secId)?.items||[]), {
      id:pid, name:'Producto', description:'', price:'', badge:'', filename:'',
      ctaText:'Consultar', waMessage:'Hola! Me interesa {{name}}, ¿me dan más info?',
    }]});
    setOpenProds(s => new Set([...s, pid]));
  };
  const updateProduct = (secId, pid, patch) =>
    setForm(f => ({ ...f, sections:f.sections.map(s => s.id===secId ? { ...s, items:s.items.map(p => p.id===pid ? { ...p,...patch } : p) } : s) }));
  const removeProduct = (secId, pid) => {
    setForm(f => ({ ...f, sections:f.sections.map(s => s.id===secId ? { ...s, items:s.items.filter(p=>p.id!==pid) } : s) }));
    setOpenProds(s => { const n=new Set(s); n.delete(pid); return n; });
  };

  // ── Bulk CSV import ──────────────────────────────────────────────────────────
  const [bulkModal, setBulkModal] = useState(null); // { secId, rows, mode:'replace'|'append' }

  function parseCSV(text) {
    const lines = text.replace(/\r\n/g,'\n').replace(/\r/g,'\n').split('\n').filter(l => l.trim());
    if (lines.length < 2) return [];
    // Parse header
    const parseRow = line => {
      const cols = []; let cur = '', inQ = false;
      for (let i = 0; i < line.length; i++) {
        const c = line[i];
        if (c === '"' && !inQ) { inQ = true; continue; }
        if (c === '"' && inQ && line[i+1] === '"') { cur += '"'; i++; continue; }
        if (c === '"' && inQ) { inQ = false; continue; }
        if (c === ',' && !inQ) { cols.push(cur.trim()); cur = ''; continue; }
        cur += c;
      }
      cols.push(cur.trim());
      return cols;
    };
    const headers = parseRow(lines[0]).map(h => h.toLowerCase().replace(/\s+/g,'_'));
    const idx = k => headers.indexOf(k);
    return lines.slice(1).map(line => {
      const c = parseRow(line);
      const get = k => (c[idx(k)] || '').trim();
      const name = get('nombre') || get('name');
      if (!name) return null;
      const imageUrl = get('imagen_url') || get('image_url') || get('imagen') || '';
      return {
        id: _rid(), name,
        description: get('descripcion') || get('description'),
        price: get('precio') || get('price'),
        badge: get('badge') || get('etiqueta'),
        ctaText: get('texto_boton') || get('cta') || 'Consultar',
        waMessage: (get('mensaje_wa') || get('mensaje') || 'Hola! Me interesa {{name}}, ¿me dan más info?').replace(/\{nombre\}/g,'{{name}}'),
        filename: '',
        imageUrl,
      };
    }).filter(Boolean);
  }

  function downloadTemplate() {
    const csv = [
      'nombre,descripcion,precio,badge,texto_boton,mensaje_wa,imagen_url',
      '"Remera Básica Negra","100% algodón. Talles S al XXL.","$8.990","Más vendido","Consultar","Hola! Me interesa {{name}}, ¿me dan más info?","https://ejemplo.com/imagen1.jpg"',
      '"Hoodie Premium","Buzo con capucha, interior afelpado.","$15.990","Nuevo","Consultar","Hola! Me interesa {{name}}, ¿me dan más info?","https://ejemplo.com/imagen2.jpg"',
      '"Pantalón Cargo","Varios bolsillos, tela resistente.","$12.500","","Consultar","Hola! Me interesa {{name}}, ¿me dan más info?",""',
    ].join('\n');
    const a = document.createElement('a');
    a.href = 'data:text/csv;charset=utf-8,﻿' + encodeURIComponent(csv);
    a.download = 'template-productos.csv';
    document.body.appendChild(a); a.click(); document.body.removeChild(a);
  }

  function onBulkFile(secId, e) {
    const file = e.target.files?.[0]; if (!file) return;
    const reader = new FileReader();
    reader.onload = ev => {
      const rows = parseCSV(ev.target.result);
      setBulkModal({ secId, rows, mode:'append' });
    };
    reader.readAsText(file, 'UTF-8');
    e.target.value = '';
  }

  function confirmBulk() {
    if (!bulkModal) return;
    const { secId, rows, mode } = bulkModal;
    setForm(f => ({ ...f, sections: f.sections.map(s => {
      if (s.id !== secId) return s;
      const existing = mode === 'append' ? (s.items || []) : [];
      return { ...s, items: [...existing, ...rows] };
    })}));
    setBulkModal(null);
  }

  // ── Form field helpers ───────────────────────────────────────────────────────
  const addField    = secId => updateSection(secId, { fields:[...(form.sections.find(s=>s.id===secId)?.fields||[]), { id:_rid(), label:'Campo', placeholder:'', type:'text', required:false }] });
  const updateField = (secId, fid, patch) =>
    setForm(f => ({ ...f, sections:f.sections.map(s => s.id===secId ? { ...s, fields:s.fields.map(fi => fi.id===fid ? { ...fi,...patch } : fi) } : s) }));
  const removeField = (secId, fid) =>
    setForm(f => ({ ...f, sections:f.sections.map(s => s.id===secId ? { ...s, fields:s.fields.filter(fi=>fi.id!==fid) } : s) }));

  // ── Save ─────────────────────────────────────────────────────────────────────
  async function save(andPublish = false) {
    setSaving(true); setSaveErr('');
    const data = andPublish ? { ...form, published:true } : form;
    try {
      const url    = form.id ? `/api/landings/${form.id}` : '/api/landings';
      const method = form.id ? 'PUT' : 'POST';
      const r = await apiFetch(url, { method, headers:{ 'Content-Type':'application/json' }, body:JSON.stringify(data) });
      if (!r.ok) { const d = await r.json().catch(()=>({})); setSaveErr(d.error||'Error al guardar'); }
      else { const sv = await r.json(); setForm(sv); setSaved(true); setTimeout(()=>setSaved(false), 3000); }
    } catch(e) { setSaveErr(e.message); }
    finally { setSaving(false); }
  }

  const landingUrl = form.slug ? `${window.location.origin}/l/${form.slug}` : '';

  const SEC_META = {
    text:     { icon:'📝', label:'Texto libre' },
    image:    { icon:'🖼️', label:'Imagen' },
    products: { icon:'🛍️', label:'Productos' },
    cta:      { icon:'💬', label:'Botón WhatsApp' },
    form:     { icon:'📋', label:'Formulario de leads' },
  };
  const slugInfo = {
    ok:       { color:'var(--green)',   text:'✓ Disponible' },
    taken:    { color:'var(--danger)',  text:'✗ No disponible — elegí otro' },
    invalid:  { color:'#D97706',        text:'Solo minúsculas, números y guiones' },
    checking: { color:'var(--muted)',   text:'Verificando...' },
  };

  return (
    <div style={{ flex:1, display:'flex', flexDirection:'column', width:'100%', overflow:'hidden' }}>
      {/* ── Top bar ─────────────────────────────────────────────────────────── */}
      <div style={{ display:'flex', alignItems:'center', gap:10, padding:'13px 20px', borderBottom:'1px solid var(--border-soft)', background:'white', flexShrink:0, flexWrap:'wrap' }}>
        <button onClick={onBack} style={{ ...S.outlineBtn, fontSize:12, padding:'6px 14px' }}>← Volver</button>
        <span style={{ flex:1, fontWeight:700, fontSize:14, color:'var(--ink)', overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap', minWidth:0 }}>
          {form.title || 'Sin título'}
        </span>
        {landingUrl && (
          <a href={landingUrl} target="_blank" rel="noopener"
            style={{ ...S.outlineBtn, fontSize:12, padding:'6px 14px', textDecoration:'none', display:'inline-flex', alignItems:'center', gap:4 }}>
            Ver ↗
          </a>
        )}
        {saved    && <span style={{ fontSize:12, color:'var(--green)', fontWeight:600 }}>✓ Guardado</span>}
        {saveErr  && <span style={{ fontSize:12, color:'var(--danger)' }}>{saveErr}</span>}
        <button onClick={() => save(false)} disabled={saving} style={S.outlineBtn}>
          {saving ? 'Guardando...' : 'Guardar'}
        </button>
        <button onClick={() => save(true)} disabled={saving} style={S.btnPrimary}>
          {form.published ? '● Publicada' : '🚀 Publicar'}
        </button>
      </div>

      {/* ── Tabs ────────────────────────────────────────────────────────────── */}
      <div style={{ display:'flex', borderBottom:'1px solid var(--border-soft)', background:'white', flexShrink:0 }}>
        {[['config','⚙️ Configuración'],['hero','🎯 Hero'],['sections','📐 Secciones']].map(([k,lbl]) => (
          <button key={k} onClick={() => setTab(k)} style={{
            padding:'10px 18px', border:'none', background:'none', cursor:'pointer',
            fontSize:13, fontWeight: tab===k ? 700 : 400,
            color: tab===k ? 'var(--green)' : 'var(--ink-3)',
            borderBottom: tab===k ? '2px solid var(--green)' : '2px solid transparent',
          }}>{lbl}</button>
        ))}
      </div>

      {/* ── Tab body ────────────────────────────────────────────────────────── */}
      <div style={{ flex:1, overflowY:'auto', padding:'24px 28px', background:'var(--cream)' }}>

        {/* CONFIGURACIÓN */}
        {tab === 'config' && (
          <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr', gap:18, alignItems:'start' }}>
            {/* Columna izquierda */}
            <div style={{ display:'flex', flexDirection:'column', gap:18 }}>
              <div style={S.card}>
                <p style={{ ...S.cardTitle, marginBottom:16 }}>General</p>
                <div style={{ display:'flex', flexDirection:'column', gap:14 }}>
                  <Field label="Nombre interno">
                    <input style={S.input} value={form.title}
                      onChange={e => { const t=e.target.value; setF({ title:t }); if (!form.id) setF({ slug:_slug(t) }); }}
                      placeholder="Mi landing de verano" />
                  </Field>
                  <Field label="URL — /l/...">
                    <input style={{ ...S.input, fontFamily:'monospace' }}
                      value={form.slug}
                      onChange={e => { setF({ slug: e.target.value.toLowerCase().replace(/[^a-z0-9-]/g,'') }); setSlugStatus('ok'); }}
                      onBlur={e => checkSlug(e.target.value)}
                      placeholder="mi-landing" />
                    {form.slug && <span style={{ fontSize:11, color: slugInfo[slugStatus]?.color||'var(--muted)' }}>{slugInfo[slugStatus]?.text||''}</span>}
                    {form.slug && <span style={{ fontSize:11, color:'var(--ink-4)', fontFamily:'monospace' }}>agent.thelooplead.com/l/{form.slug}</span>}
                  </Field>
                  <Field label="Número de WhatsApp">
                    <input style={S.input} value={form.whatsappNumber}
                      onChange={e => setF({ whatsappNumber: e.target.value })}
                      placeholder="5491123456789 (sin + ni espacios)" />
                  </Field>
                </div>
              </div>
            </div>
            {/* Columna derecha */}
            <div style={{ display:'flex', flexDirection:'column', gap:18 }}>
              <div style={S.card}>
                <p style={{ ...S.cardTitle, marginBottom:16 }}>Diseño</p>
                <div style={{ display:'flex', flexDirection:'column', gap:14 }}>
                  <Field label="Color principal">
                    <div style={{ display:'flex', gap:10, alignItems:'center' }}>
                      <input type="color" value={form.primaryColor||'#3A6351'}
                        onChange={e => setF({ primaryColor: e.target.value })}
                        style={{ width:40, height:34, padding:2, border:'1.5px solid var(--border)', borderRadius:8, cursor:'pointer', background:'white' }} />
                      <input style={{ ...S.input, fontFamily:'monospace' }}
                        value={form.primaryColor||'#3A6351'}
                        onChange={e => setF({ primaryColor: e.target.value })} />
                    </div>
                  </Field>
                  <div style={{ display:'flex', alignItems:'center', gap:10 }}>
                    <Toggle on={form.floatingButton !== false} onChange={v => setF({ floatingButton:v })} />
                    <span style={{ fontSize:13 }}>Botón flotante de WhatsApp</span>
                  </div>
                  <ImgUpload filename={form.logoFilename} tid={tenantId} label="Logo (opcional)"
                    onUpload={fn => setF({ logoFilename:fn })}
                    onClear={() => setF({ logoFilename:'' })} height={44} />
                </div>
              </div>
              <div style={S.card}>
                <p style={{ ...S.cardTitle, marginBottom:4 }}>SEO</p>
                <p style={S.cardDesc}>Metadatos para compartir en redes sociales</p>
                <div style={{ display:'flex', flexDirection:'column', gap:12 }}>
                  <Field label="Título og:title">
                    <input style={S.input} value={form.metaTitle||''}
                      onChange={e => setF({ metaTitle: e.target.value })}
                      placeholder={form.hero?.headline||form.title||''} />
                  </Field>
                  <Field label="Descripción og:description">
                    <input style={S.input} value={form.metaDescription||''}
                      onChange={e => setF({ metaDescription: e.target.value })}
                      placeholder={form.hero?.subtitle||''} />
                  </Field>
                </div>
              </div>
            </div>
          </div>
        )}

        {/* HERO */}
        {tab === 'hero' && (
          <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr', gap:18, alignItems:'start' }}>
            <div style={S.card}>
              <p style={{ ...S.cardTitle, marginBottom:16 }}>Contenido del hero</p>
              <div style={{ display:'flex', flexDirection:'column', gap:14 }}>
                <Field label="Titular principal *">
                  <input style={{ ...S.input, fontSize:14, fontWeight:600 }}
                    value={form.hero?.headline||''}
                    onChange={e => setHero({ headline: e.target.value })}
                    placeholder="El titular más importante de tu landing" />
                </Field>
                <Field label="Subtítulo (opcional)">
                  <textarea style={{ ...S.textarea, minHeight:72 }}
                    value={form.hero?.subtitle||''}
                    onChange={e => setHero({ subtitle: e.target.value })}
                    placeholder="Describí tu propuesta de valor en 1-2 oraciones" />
                </Field>
                <ImgUpload filename={form.hero?.filename} tid={tenantId}
                  label="Imagen del hero (opcional — crea layout split de 2 columnas)"
                  onUpload={fn => setHero({ filename:fn })}
                  onClear={() => setHero({ filename:'' })} height={90} />
              </div>
            </div>
            <div style={S.card}>
              <p style={{ ...S.cardTitle, marginBottom:16 }}>Botón CTA principal</p>
              <div style={{ display:'flex', flexDirection:'column', gap:14 }}>
                <div style={{ display:'flex', alignItems:'center', gap:10 }}>
                  <Toggle on={form.hero?.ctaEnabled !== false} onChange={v => setHero({ ctaEnabled:v })} />
                  <span style={{ fontSize:13 }}>Mostrar botón en el hero</span>
                </div>
                {form.hero?.ctaEnabled !== false && <>
                  <Field label="Texto del botón">
                    <input style={S.input} value={form.hero?.ctaText||''}
                      onChange={e => setHero({ ctaText: e.target.value })}
                      placeholder="Consultar por WhatsApp" />
                  </Field>
                  <Field label="Mensaje pre-llenado en WhatsApp">
                    <input style={S.input} value={form.hero?.waMessage||''}
                      onChange={e => setHero({ waMessage: e.target.value })}
                      placeholder="Hola! Vi tu página y quiero más información." />
                  </Field>
                </>}
              </div>
            </div>
          </div>
        )}

        {/* SECCIONES */}
        {tab === 'sections' && (
          <div style={{ display:'flex', flexDirection:'column', gap:10 }}>
            {form.sections.length === 0 && (
              <div style={{ ...S.card, textAlign:'center', padding:'40px 24px', borderStyle:'dashed' }}>
                <div style={{ fontSize:36, marginBottom:10 }}>📐</div>
                <p style={{ color:'var(--muted)', fontSize:13.5 }}>Agregá bloques para construir tu landing page</p>
              </div>
            )}

            {form.sections.map((sec, idx) => {
              const meta = SEC_META[sec.type] || { icon:'📄', label: sec.type };
              const open = openSecs.has(sec.id);
              return (
                <div key={sec.id} style={{ background:'white', border:'1px solid var(--border)', borderRadius:'var(--r)', overflow:'hidden' }}>
                  {/* Header */}
                  <div onClick={() => toggleSec(sec.id)}
                    style={{ display:'flex', alignItems:'center', gap:10, padding:'11px 14px', cursor:'pointer', userSelect:'none', background: open ? 'var(--green-light)' : 'white', transition:'background .12s' }}>
                    <span style={{ fontSize:15 }}>{meta.icon}</span>
                    <span style={{ flex:1, fontSize:13.5, fontWeight:600, color: open ? 'var(--green-hover)' : 'var(--ink)' }}>
                      {meta.label}
                      {sec.type === 'products' && sec.items?.length ? ` (${sec.items.length})` : ''}
                      {sec.type === 'form' && sec.fields?.length ? ` (${sec.fields.length} campos)` : ''}
                    </span>
                    <div style={{ display:'flex', gap:4 }} onClick={e => e.stopPropagation()}>
                      <button onClick={() => moveSection(sec.id,-1)} disabled={idx===0}
                        style={{ background:'none', border:'1px solid var(--border)', borderRadius:6, padding:'2px 7px', cursor:'pointer', fontSize:12, color:'var(--ink-3)' }}>↑</button>
                      <button onClick={() => moveSection(sec.id,1)} disabled={idx===form.sections.length-1}
                        style={{ background:'none', border:'1px solid var(--border)', borderRadius:6, padding:'2px 7px', cursor:'pointer', fontSize:12, color:'var(--ink-3)' }}>↓</button>
                      <button onClick={() => removeSection(sec.id)}
                        style={{ background:'none', border:'1px solid var(--border)', borderRadius:6, padding:'2px 7px', cursor:'pointer', fontSize:12, color:'var(--danger)' }}>🗑</button>
                    </div>
                    <span style={{ color:'var(--muted)', fontSize:13 }}>{open ? '▾' : '▸'}</span>
                  </div>

                  {/* Body */}
                  {open && (
                    <div style={{ padding:'16px 16px', background:'var(--cream)', borderTop:'1px solid var(--border-soft)', display:'flex', flexDirection:'column', gap:12 }}>

                      {sec.type === 'text' && <>
                        <Field label="Contenido"><textarea style={{ ...S.textarea, minHeight:90 }} value={sec.content}
                          onChange={e => updateSection(sec.id, { content:e.target.value })} placeholder="Escribí el texto de esta sección..." /></Field>
                        <Field label="Alineación">
                          <select style={S.select} value={sec.align||'left'} onChange={e => updateSection(sec.id, { align:e.target.value })}>
                            <option value="left">Izquierda</option>
                            <option value="center">Centrado</option>
                          </select>
                        </Field>
                      </>}

                      {sec.type === 'image' && <>
                        <ImgUpload filename={sec.filename} tid={tenantId} label="Imagen"
                          onUpload={fn => updateSection(sec.id, { filename:fn })}
                          onClear={() => updateSection(sec.id, { filename:'' })} height={100} />
                        <Field label="Alt text (opcional)">
                          <input style={S.input} value={sec.alt||''} onChange={e => updateSection(sec.id, { alt:e.target.value })} placeholder="Descripción de la imagen" />
                        </Field>
                      </>}

                      {sec.type === 'cta' && <>
                        <Field label="Titular (opcional)">
                          <input style={S.input} value={sec.headline||''} onChange={e => updateSection(sec.id, { headline:e.target.value })} placeholder="¿Tenés dudas? Escribinos" />
                        </Field>
                        <Field label="Subtexto (opcional)">
                          <input style={S.input} value={sec.subtext||''} onChange={e => updateSection(sec.id, { subtext:e.target.value })} placeholder="Respondemos en minutos por WhatsApp" />
                        </Field>
                        <Field label="Texto del botón">
                          <input style={S.input} value={sec.text} onChange={e => updateSection(sec.id, { text:e.target.value })} placeholder="Consultar por WhatsApp" />
                        </Field>
                        <Field label="Mensaje de WhatsApp al hacer clic">
                          <input style={S.input} value={sec.message} onChange={e => updateSection(sec.id, { message:e.target.value })} placeholder="Hola! Quiero consultar sobre..." />
                        </Field>
                      </>}

                      {sec.type === 'products' && <>
                        <div style={S.row}>
                          <div style={S.col}>
                            <span style={S.label}>Título de la sección (opcional)</span>
                            <input style={S.input} value={sec.title||''} onChange={e => updateSection(sec.id, { title:e.target.value })} placeholder="Nuestros productos" />
                          </div>
                          <div style={{ ...S.col, flex:'0 0 auto' }}>
                            <span style={S.label}>Columnas</span>
                            <div style={{ display:'flex', gap:6 }}>
                              {[2,3].map(n => <button key={n} onClick={() => updateSection(sec.id, { columns:n })}
                                style={{ ...S.chip((sec.columns||3)===n), padding:'5px 14px', fontSize:12 }}>{n}</button>)}
                            </div>
                          </div>
                        </div>
                        <div style={{ display:'flex', flexDirection:'column', gap:8 }}>
                          {(sec.items||[]).map(prod => {
                            const pOpen = openProds.has(prod.id);
                            return (
                              <div key={prod.id} style={{ border:'1px solid var(--border)', borderRadius:'var(--r-sm)', background:'white', overflow:'hidden' }}>
                                <div onClick={() => toggleProd(prod.id)}
                                  style={{ display:'flex', alignItems:'center', gap:8, padding:'9px 12px', cursor:'pointer', userSelect:'none' }}>
                                  {prod.filename && <img src={`/landing-assets/${tenantId}/${prod.filename}`} style={{ width:28, height:28, objectFit:'cover', borderRadius:4, flexShrink:0 }} />}
                                  <span style={{ flex:1, fontSize:13, fontWeight:600 }}>{prod.name||'Producto sin nombre'}</span>
                                  {prod.price && <span style={{ fontSize:12, color:'var(--green)', fontWeight:700 }}>{prod.price}</span>}
                                  <button onClick={e => { e.stopPropagation(); removeProduct(sec.id, prod.id); }}
                                    style={{ background:'none', border:'none', color:'var(--danger)', cursor:'pointer', fontSize:15, padding:'0 2px' }}>×</button>
                                  <span style={{ color:'var(--muted)', fontSize:13 }}>{pOpen ? '▾' : '▸'}</span>
                                </div>
                                {pOpen && (
                                  <div style={{ padding:'14px', borderTop:'1px solid var(--border-soft)', background:'#fafaf8', display:'flex', flexDirection:'column', gap:11 }}>
                                    <div style={S.row}>
                                      <div style={S.col}><span style={S.label}>Nombre *</span>
                                        <input style={S.input} value={prod.name} onChange={e => updateProduct(sec.id, prod.id, { name:e.target.value })} placeholder="Nombre" /></div>
                                      <div style={S.col}><span style={S.label}>Precio</span>
                                        <input style={S.input} value={prod.price||''} onChange={e => updateProduct(sec.id, prod.id, { price:e.target.value })} placeholder="$1.500" /></div>
                                    </div>
                                    <div><span style={S.label}>Descripción</span>
                                      <textarea style={{ ...S.textarea, minHeight:56 }} value={prod.description||''} onChange={e => updateProduct(sec.id, prod.id, { description:e.target.value })} placeholder="Breve descripción..." /></div>
                                    <div style={S.row}>
                                      <div style={S.col}><span style={S.label}>Badge (ej: Nuevo)</span>
                                        <input style={S.input} value={prod.badge||''} onChange={e => updateProduct(sec.id, prod.id, { badge:e.target.value })} /></div>
                                      <div style={S.col}><span style={S.label}>Texto del botón</span>
                                        <input style={S.input} value={prod.ctaText||''} onChange={e => updateProduct(sec.id, prod.id, { ctaText:e.target.value })} placeholder="Consultar" /></div>
                                    </div>
                                    <div><span style={S.label}>Mensaje WhatsApp — usa {'{{name}}'} para el nombre del producto</span>
                                      <input style={S.input} value={prod.waMessage||''} onChange={e => updateProduct(sec.id, prod.id, { waMessage:e.target.value })} placeholder="Hola! Me interesa {{name}}, ¿me dan más info?" /></div>
                                    <ImgUpload filename={prod.filename} tid={tenantId} label="Imagen del producto"
                                      onUpload={fn => updateProduct(sec.id, prod.id, { filename:fn })}
                                      onClear={() => updateProduct(sec.id, prod.id, { filename:'' })} height={68} />
                                  </div>
                                )}
                              </div>
                            );
                          })}
                        </div>
                        <div style={{ display:'flex', gap:8, alignItems:'center', flexWrap:'wrap' }}>
                          <button onClick={() => addProduct(sec.id)}
                            style={{ ...S.outlineBtn, fontSize:12, padding:'7px 16px' }}>+ Agregar producto</button>
                          <label style={{ ...S.outlineBtn, fontSize:12, padding:'7px 16px', cursor:'pointer', display:'inline-flex', alignItems:'center', gap:6 }}>
                            📥 Carga masiva (CSV)
                            <input type="file" accept=".csv,text/csv" style={{ display:'none' }}
                              onChange={e => onBulkFile(sec.id, e)} />
                          </label>
                          <button onClick={downloadTemplate}
                            style={{ fontSize:11, color:'var(--muted)', background:'none', border:'none', cursor:'pointer', textDecoration:'underline', padding:0 }}>
                            ↓ Descargar template
                          </button>
                        </div>
                      </>}

                      {sec.type === 'form' && <>
                        <div style={S.row}>
                          <div style={S.col}><span style={S.label}>Título</span>
                            <input style={S.input} value={sec.title||''} onChange={e => updateSection(sec.id, { title:e.target.value })} placeholder="Dejanos tus datos" /></div>
                        </div>
                        <div><span style={S.label}>Subtítulo (opcional)</span>
                          <input style={S.input} value={sec.subtitle||''} onChange={e => updateSection(sec.id, { subtitle:e.target.value })} placeholder="Completá el formulario y te contactamos" /></div>
                        <div>
                          <span style={S.label}>Campos</span>
                          <div style={{ display:'flex', flexDirection:'column', gap:6, marginTop:6 }}>
                            {(sec.fields||[]).map(fi => (
                              <div key={fi.id} style={{ display:'flex', gap:6, alignItems:'center', background:'white', border:'1px solid var(--border)', borderRadius:8, padding:'7px 10px' }}>
                                <input style={{ ...S.input, flex:2, padding:'5px 9px', fontSize:12 }}
                                  value={fi.label} onChange={e => updateField(sec.id, fi.id, { label:e.target.value })} placeholder="Nombre del campo" />
                                <select style={{ ...S.select, flex:1, padding:'5px 9px', fontSize:12 }}
                                  value={fi.type} onChange={e => updateField(sec.id, fi.id, { type:e.target.value })}>
                                  <option value="text">Texto</option>
                                  <option value="email">Email</option>
                                  <option value="tel">Teléfono</option>
                                  <option value="textarea">Área de texto</option>
                                  <option value="select">Selección</option>
                                </select>
                                <input style={{ ...S.input, flex:2, padding:'5px 9px', fontSize:12 }}
                                  value={fi.placeholder||''} onChange={e => updateField(sec.id, fi.id, { placeholder:e.target.value })} placeholder="Placeholder..." />
                                <label style={{ display:'flex', alignItems:'center', gap:3, fontSize:11, whiteSpace:'nowrap', cursor:'pointer' }}>
                                  <input type="checkbox" checked={fi.required} onChange={e => updateField(sec.id, fi.id, { required:e.target.checked })} /> Req.
                                </label>
                                <button onClick={() => removeField(sec.id, fi.id)}
                                  style={{ background:'none', border:'none', color:'var(--danger)', cursor:'pointer', fontSize:17, padding:'0 2px', lineHeight:1 }}>×</button>
                              </div>
                            ))}
                          </div>
                          <button onClick={() => addField(sec.id)}
                            style={{ ...S.outlineBtn, fontSize:12, padding:'5px 14px', marginTop:7, width:'fit-content' }}>+ Agregar campo</button>
                        </div>
                        <div style={S.row}>
                          <div style={S.col}><span style={S.label}>Texto del botón submit</span>
                            <input style={S.input} value={sec.submitLabel||''} onChange={e => updateSection(sec.id, { submitLabel:e.target.value })} placeholder="Enviar por WhatsApp" /></div>
                        </div>
                        <div><span style={S.label}>Mensaje inicial de WhatsApp (antes de los datos del form)</span>
                          <input style={S.input} value={sec.waMessage||''} onChange={e => updateSection(sec.id, { waMessage:e.target.value })} placeholder="Hola! Me contacto desde tu landing page." /></div>
                      </>}

                    </div>
                  )}
                </div>
              );
            })}

            {/* Add section button */}
            <div style={{ position:'relative', marginTop:4 }}>
              <button onClick={() => setShowAddMenu(m => !m)}
                style={{ ...S.outlineBtn, width:'100%', justifyContent:'center', display:'flex', gap:6 }}>
                + Agregar bloque
              </button>
              {showAddMenu && (
                <div style={{ position:'absolute', top:'100%', left:0, right:0, marginTop:4, background:'white', border:'1px solid var(--border)', borderRadius:'var(--r)', boxShadow:'var(--shadow-md)', zIndex:60, overflow:'hidden' }}>
                  {Object.entries(SEC_META).map(([type, meta]) => (
                    <button key={type} onClick={() => addSection(type)}
                      style={{ display:'flex', alignItems:'center', gap:12, width:'100%', padding:'11px 16px', border:'none', background:'none', cursor:'pointer', fontSize:13, fontWeight:500, color:'var(--ink)', textAlign:'left' }}
                      onMouseEnter={e => e.currentTarget.style.background='var(--green-light)'}
                      onMouseLeave={e => e.currentTarget.style.background='none'}>
                      <span style={{ fontSize:18, width:24, textAlign:'center' }}>{meta.icon}</span>
                      {meta.label}
                    </button>
                  ))}
                </div>
              )}
            </div>
          </div>
        )}

      </div>

      {/* ── Modal carga masiva ───────────────────────────────────────────────── */}
      {bulkModal && (
        <div style={{ position:'fixed', inset:0, background:'rgba(0,0,0,.5)', display:'flex', alignItems:'center', justifyContent:'center', zIndex:400 }}>
          <div style={{ background:'white', borderRadius:'var(--r-lg)', padding:28, width:'min(90vw,680px)', maxHeight:'80vh', display:'flex', flexDirection:'column', gap:20, boxShadow:'var(--shadow-lg)' }}>
            <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between' }}>
              <h3 style={{ fontSize:17, fontWeight:700 }}>Carga masiva de productos</h3>
              <button onClick={() => setBulkModal(null)} style={{ background:'none', border:'none', fontSize:20, cursor:'pointer', color:'var(--muted)', lineHeight:1 }}>✕</button>
            </div>

            {bulkModal.rows.length === 0 ? (
              <div style={{ textAlign:'center', padding:'24px 0', color:'var(--danger)' }}>
                <p style={{ fontSize:14 }}>No se encontraron productos en el archivo.</p>
                <p style={{ fontSize:12, color:'var(--muted)', marginTop:6 }}>Verificá que el CSV tenga la columna <code>nombre</code> y esté en el formato correcto.</p>
              </div>
            ) : (
              <>
                <p style={{ fontSize:13, color:'var(--muted)' }}>{bulkModal.rows.length} productos encontrados</p>
                <div style={{ overflowY:'auto', maxHeight:280, border:'1px solid var(--border)', borderRadius:'var(--r-sm)' }}>
                  <table style={{ width:'100%', borderCollapse:'collapse', fontSize:12 }}>
                    <thead>
                      <tr style={{ background:'var(--cream)', position:'sticky', top:0 }}>
                        {['Img','Nombre','Descripción','Precio','Badge','Mensaje WA'].map(h => (
                          <th key={h} style={{ padding:'8px 10px', textAlign:'left', fontWeight:600, color:'var(--ink-3)', borderBottom:'1px solid var(--border)', whiteSpace:'nowrap' }}>{h}</th>
                        ))}
                      </tr>
                    </thead>
                    <tbody>
                      {bulkModal.rows.map((r,i) => (
                        <tr key={i} style={{ borderBottom:'1px solid var(--border-soft)' }}>
                          <td style={{ padding:'7px 10px' }}>
                            {r.imageUrl
                              ? <img src={r.imageUrl} alt="" style={{ width:36, height:36, objectFit:'cover', borderRadius:6, display:'block' }} onError={e => e.target.style.display='none'} />
                              : <span style={{ fontSize:18 }}>🛍️</span>}
                          </td>
                          <td style={{ padding:'7px 10px', fontWeight:600, color:'var(--ink)' }}>{r.name}</td>
                          <td style={{ padding:'7px 10px', color:'var(--muted)', maxWidth:140, overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap' }}>{r.description||'—'}</td>
                          <td style={{ padding:'7px 10px', color:'var(--green)', fontWeight:600 }}>{r.price||'—'}</td>
                          <td style={{ padding:'7px 10px' }}>{r.badge ? <span style={{ background:'var(--green-light)', color:'var(--green)', borderRadius:99, padding:'2px 8px', fontSize:11, fontWeight:600 }}>{r.badge}</span> : '—'}</td>
                          <td style={{ padding:'7px 10px', color:'var(--muted)', maxWidth:180, overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap' }}>{r.waMessage}</td>
                        </tr>
                      ))}
                    </tbody>
                  </table>
                </div>

                <div style={{ display:'flex', alignItems:'center', gap:16 }}>
                  <span style={{ fontSize:13, fontWeight:600 }}>¿Cómo importar?</span>
                  {['append','replace'].map(m => (
                    <label key={m} style={{ display:'flex', alignItems:'center', gap:6, fontSize:13, cursor:'pointer' }}>
                      <input type="radio" name="bulkMode" value={m}
                        checked={bulkModal.mode === m}
                        onChange={() => setBulkModal(b => ({ ...b, mode:m }))} />
                      {m === 'append' ? 'Agregar a los existentes' : 'Reemplazar todos'}
                    </label>
                  ))}
                </div>

                <div style={{ display:'flex', gap:8, justifyContent:'flex-end' }}>
                  <button onClick={() => setBulkModal(null)} style={S.outlineBtn}>Cancelar</button>
                  <button onClick={confirmBulk} style={S.btnPrimary}>
                    ✓ Importar {bulkModal.rows.length} productos
                  </button>
                </div>
              </>
            )}
          </div>
        </div>
      )}
    </div>
  );
}

function LandingsPanel() {
  const [landings, setLandings]   = useState(null);
  const [editing, setEditing]     = useState(null);
  const [tid, setTid]             = useState('');
  const [confirmDel, setConfirmDel] = useState(null);

  useEffect(() => {
    apiFetch('/api/auth/me').then(r => r.json()).then(d => setTid(d.tenantId||''));
    load();
  }, []);

  function load() {
    apiFetch('/api/landings').then(r => r.json()).then(d => setLandings(Array.isArray(d) ? d : []));
  }

  function newLanding() {
    setEditing({
      _new:true, title:'Nueva Landing',
      slug:'mi-landing-'+Math.random().toString(36).slice(2,6),
      primaryColor:'#3A6351', published:false, whatsappNumber:'', floatingButton:true,
      hero:{ headline:'', subtitle:'', ctaEnabled:true, ctaText:'Consultar por WhatsApp', waMessage:'Hola! Vi tu página y quiero más información.' },
      sections:[],
    });
  }

  async function doDelete(id) {
    await apiFetch(`/api/landings/${id}`, { method:'DELETE' });
    setConfirmDel(null); load();
  }

  const landingUrl = slug => `${window.location.origin}/l/${slug}`;

  if (editing !== null) {
    return <LandingEditor initial={editing} tenantId={tid} onBack={() => { setEditing(null); load(); }} />;
  }

  return (
    <div style={{ flex:1, overflowY:'auto', background:'var(--cream)' }}><div style={{ maxWidth:900, margin:'0 auto', padding:'32px 28px' }}>
      <div style={{ display:'flex', alignItems:'flex-start', justifyContent:'space-between', gap:16, marginBottom:28 }}>
        <div>
          <h2 style={S.pageTitle}>Landing Pages</h2>
          <p style={S.pageSubtitle}>Páginas de captación de leads con formulario y CTA de WhatsApp</p>
        </div>
        <button onClick={newLanding} style={S.btnPrimary}>+ Nueva landing</button>
      </div>

      {landings === null && <div style={{ textAlign:'center', padding:'48px 0', color:'var(--muted)' }}>Cargando...</div>}

      {landings !== null && landings.length === 0 && (
        <div style={{ textAlign:'center', padding:'64px 24px', background:'var(--surface)', border:'1.5px dashed var(--border)', borderRadius:'var(--r-lg)' }}>
          <div style={{ fontSize:42, marginBottom:14 }}>🌐</div>
          <h3 style={{ fontSize:17, fontWeight:700, marginBottom:8 }}>Sin landing pages todavía</h3>
          <p style={{ color:'var(--muted)', fontSize:13.5, marginBottom:24, lineHeight:1.6 }}>
            Creá tu primera landing en pocos pasos y compartila por WhatsApp para captar leads.
          </p>
          <button onClick={newLanding} style={S.btnPrimary}>+ Crear primera landing</button>
        </div>
      )}

      {(landings||[]).map(l => (
        <div key={l.id} style={{ ...S.card, display:'flex', alignItems:'center', gap:14, marginBottom:14 }}>
          <div style={{ flex:1, minWidth:0 }}>
            <div style={{ display:'flex', alignItems:'center', gap:8, marginBottom:4 }}>
              <span style={{ fontSize:14.5, fontWeight:700, color:'var(--ink)' }}>{l.title}</span>
              <span style={{ fontSize:11, fontWeight:700, padding:'2px 9px', borderRadius:99,
                background: l.published ? 'var(--green-light)' : 'var(--cream-dark)',
                color: l.published ? 'var(--green)' : 'var(--ink-3)' }}>
                {l.published ? '● Publicada' : '○ Borrador'}
              </span>
            </div>
            <a href={landingUrl(l.slug)} target="_blank" rel="noopener"
              style={{ fontSize:12, color:'var(--muted)', textDecoration:'none', fontFamily:'monospace' }}>
              /l/{l.slug}
            </a>
          </div>
          <div style={{ display:'flex', gap:6, flexShrink:0 }}>
            <button onClick={() => { navigator.clipboard.writeText(landingUrl(l.slug)); }}
              style={{ ...S.outlineBtn, fontSize:12, padding:'6px 13px' }}>📋 Copiar URL</button>
            <a href={landingUrl(l.slug)} target="_blank" rel="noopener"
              style={{ ...S.outlineBtn, fontSize:12, padding:'6px 13px', textDecoration:'none', display:'inline-flex', alignItems:'center' }}>Ver ↗</a>
            <button onClick={() => setEditing(l)}
              style={{ ...S.outlineBtn, fontSize:12, padding:'6px 13px' }}>Editar</button>
            <button onClick={() => setConfirmDel(l.id)}
              style={{ ...S.dangerBtn, fontSize:12, padding:'6px 13px' }}>Eliminar</button>
          </div>
        </div>
      ))}

      {confirmDel && (
        <div style={{ position:'fixed', inset:0, background:'rgba(0,0,0,.45)', display:'flex', alignItems:'center', justifyContent:'center', zIndex:300 }}>
          <div style={{ background:'white', borderRadius:'var(--r-lg)', padding:32, maxWidth:400, width:'90%', boxShadow:'var(--shadow-lg)' }}>
            <h3 style={{ fontSize:17, fontWeight:700, marginBottom:10 }}>¿Eliminar landing?</h3>
            <p style={{ color:'var(--muted)', fontSize:14, marginBottom:24, lineHeight:1.6 }}>Esta acción no se puede deshacer. La URL quedará inactiva.</p>
            <div style={{ display:'flex', gap:8, justifyContent:'flex-end' }}>
              <button onClick={() => setConfirmDel(null)} style={S.outlineBtn}>Cancelar</button>
              <button onClick={() => doDelete(confirmDel)} style={{ ...S.btnPrimary, background:'var(--danger)', boxShadow:'none' }}>Eliminar</button>
            </div>
          </div>
        </div>
      )}
    </div></div>
  );
}

// ─────────────────────────────────────────────────────────────────────────────
// Promotions
// ─────────────────────────────────────────────────────────────────────────────

const PROMO_STATUS = {
  active:   { label:'Activa',      color:'#15803D', bg:'#F0FDF4', dot:'#22C55E' },
  expired:  { label:'Expirada',    color:'#92400E', bg:'#FEF3C7', dot:'#F59E0B' },
  upcoming: { label:'Próxima',     color:'#1D4ED8', bg:'#EFF6FF', dot:'#3B82F6' },
  disabled: { label:'Deshabilitada', color:'#6B7280', bg:'#F3F4F6', dot:'#9CA3AF' },
};

function promoStatus(p) {
  if (!p.enabled) return 'disabled';
  const now = new Date();
  if (p.startsAt  && new Date(p.startsAt)  > now) return 'upcoming';
  if (p.expiresAt && new Date(p.expiresAt) < now) return 'expired';
  return 'active';
}

function fmtDate(iso) {
  if (!iso) return '';
  return new Date(iso).toLocaleDateString('es-AR', { day:'2-digit', month:'2-digit', year:'numeric' });
}

function toInputDate(iso) {
  if (!iso) return '';
  return iso.slice(0,16); // yyyy-MM-ddTHH:mm
}

const ACTION_LABELS = {
  add_tags:      { icon:'🏷️', label:'Agregar etiquetas' },
  create_lead:   { icon:'📊', label:'Agregar a embudo' },
  update_status: { icon:'🔄', label:'Cambiar estado' },
  add_note:      { icon:'📝', label:'Agregar nota al lead' },
};

function _actid() { return Math.random().toString(36).slice(2,10); }

function PromotionEditor({ promo, tenantId, onSave, onCancel }) {
  const { teams, users, pipelines, tags } = usePipochat();
  const isNew = !promo.id;
  const [form, setForm] = useState(() => ({
    name:               promo.name               || '',
    keywords:           (promo.keywords || []).join(', '),
    message:            promo.message            || '',
    imageUrls:          (promo.imageUrls|| []).join('\n'),
    startsAt:           toInputDate(promo.startsAt  || ''),
    expiresAt:          toInputDate(promo.expiresAt || ''),
    enabled:            promo.enabled            ?? true,
    priority:           promo.priority           ?? 10,
    assets:             promo.assets             || [],
    assignMode:           promo.assignMode           || 'none',
    assignTeamId:         promo.assignTeamId         || '',
    assignOperatorId:     promo.assignOperatorId     || '',
    actions:              promo.actions              || [],
    agentInstructions:    promo.agentInstructions    || '',
    questions:            promo.questions             || [],
    buttonReplies:        promo.buttonReplies         || [],
    interactiveMessage:   promo.interactiveMessage    || null,
  }));
  const [saving, setSaving]   = useState(false);
  const [uploading, setUploading] = useState(false);
  const [err, setErr]         = useState('');

  const setF = p => setForm(f => ({ ...f, ...p }));

  // ── Action helpers ───────────────────────────────────────────────────────────
  const addAction = type => {
    const defaults = {
      add_tags:      { id:_actid(), type, tags:[] },
      create_lead:   { id:_actid(), type, pipelineId:'', pipelineName:'', stageId:'', stageName:'' },
      update_status: { id:_actid(), type, status:'open' },
      add_note:      { id:_actid(), type, note:'' },
    };
    setF({ actions: [...form.actions, defaults[type]] });
  };
  const removeAction = id => setF({ actions: form.actions.filter(a => a.id !== id) });
  const updateAction = (id, patch) => setF({ actions: form.actions.map(a => a.id === id ? { ...a, ...patch } : a) });

  async function uploadFile(e) {
    const file = e.target.files?.[0]; if (!file) return;
    e.target.value = '';
    if (!promo.id) { setErr('Guardá la promoción primero para poder subir archivos.'); return; }
    setUploading(true);
    const fd = new FormData(); fd.append('file', file);
    const r  = await apiFetch(`/api/promotions/${promo.id}/upload`, { method:'POST', body: fd });
    const d  = await r.json();
    if (d.asset) setF({ assets: [...form.assets, d.asset] });
    setUploading(false);
  }

  async function deleteAsset(filename) {
    if (!promo.id) return;
    await apiFetch(`/api/promotions/${promo.id}/assets/${filename}`, { method:'DELETE' });
    setF({ assets: form.assets.filter(a => a.filename !== filename) });
  }

  function isImg(a) { return /^image\//.test(a.mimeType); }

  async function save() {
    if (!form.name.trim()) { setErr('El nombre es requerido.'); return; }
    setSaving(true); setErr('');
    const selectedTeam = teams.find(t => t._id === form.assignTeamId);
    const selectedUser = users.find(u => u._id === form.assignOperatorId);
    const body = {
      name:                form.name.trim(),
      keywords:            form.keywords.split(',').map(k => k.trim()).filter(Boolean),
      message:             form.message.trim(),
      imageUrls:           form.imageUrls.split('\n').map(u => u.trim()).filter(Boolean),
      startsAt:            form.startsAt  ? new Date(form.startsAt).toISOString()  : null,
      expiresAt:           form.expiresAt ? new Date(form.expiresAt).toISOString() : null,
      enabled:             form.enabled,
      priority:            Number(form.priority) || 10,
      assets:              form.assets,
      assignMode:          form.assignMode,
      assignTeamId:        form.assignMode === 'team'     ? form.assignTeamId     : null,
      assignTeamName:      form.assignMode === 'team'     ? (selectedTeam?.name || '') : null,
      assignOperatorId:    form.assignMode === 'operator' ? form.assignOperatorId : null,
      assignOperatorName:  form.assignMode === 'operator' ? (selectedUser?.name  || '') : null,
      actions:             form.actions,
      agentInstructions:   form.agentInstructions.trim() || null,
      questions:           form.questions.map(({ _newOpt, ...q }) => q),
      buttonReplies:       form.buttonReplies.map(({ _newOpt, ...br }) => ({
        ...br,
        questions: (br.questions || []).map(({ _newOpt: _, ...q }) => q),
      })),
      interactiveMessage:  form.interactiveMessage || null,
    };
    const method = isNew ? 'POST' : 'PUT';
    const url    = isNew ? '/api/promotions' : `/api/promotions/${promo.id}`;
    const r = await apiFetch(url, { method, headers:{'Content-Type':'application/json'}, body: JSON.stringify(body) });
    const saved = await r.json();
    setSaving(false);
    if (saved.error) { setErr(saved.error); return; }
    onSave(saved);
  }

  return (
    <div style={{ position:'fixed', inset:0, background:'rgba(0,0,0,.5)', display:'flex', alignItems:'center', justifyContent:'center', zIndex:400, padding:16 }}>
      <div style={{ background:'white', borderRadius:'var(--r-lg)', width:'min(98vw,760px)', maxHeight:'92vh', display:'flex', flexDirection:'column', boxShadow:'var(--shadow-xl)' }}>
        {/* Header */}
        <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between', padding:'20px 24px', borderBottom:'1px solid var(--border-soft)', flexShrink:0 }}>
          <h3 style={{ fontSize:16, fontWeight:700, margin:0 }}>{isNew ? 'Nueva promoción' : 'Editar promoción'}</h3>
          <button onClick={onCancel} style={{ background:'none', border:'none', fontSize:20, cursor:'pointer', color:'var(--muted)', lineHeight:1 }}>✕</button>
        </div>

        {/* Body */}
        <div style={{ overflowY:'auto', flex:1, padding:24, display:'flex', flexDirection:'column', gap:20 }}>

          {/* Row 1: name + enabled + priority */}
          <div style={{ display:'grid', gridTemplateColumns:'1fr auto auto', gap:12, alignItems:'end' }}>
            <Field label="Nombre interno *">
              <input style={S.input} value={form.name} onChange={e => setF({ name:e.target.value })} placeholder="Promo Verano 2026" />
            </Field>
            <Field label="Prioridad">
              <input type="number" style={{ ...S.input, width:80 }} value={form.priority} onChange={e => setF({ priority:e.target.value })} min={1} max={100} />
            </Field>
            <Field label="Estado">
              <div style={{ display:'flex', alignItems:'center', gap:8, height:38 }}>
                <Toggle on={form.enabled} onChange={v => setF({ enabled:v })} />
                <span style={{ fontSize:13 }}>{form.enabled ? 'Activa' : 'Desactivada'}</span>
              </div>
            </Field>
          </div>

          {/* Keywords */}
          <Field label="Palabras clave (separadas por coma)">
            <input style={S.input} value={form.keywords}
              onChange={e => setF({ keywords:e.target.value })}
              placeholder="descuento, promo verano, oferta, 2x1..." />
            <span style={{ fontSize:11, color:'var(--muted)' }}>Cuando el cliente escriba cualquiera de estas palabras, el agente usa esta promoción.</span>
          </Field>

          {/* Validity dates */}
          <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr', gap:12 }}>
            <Field label="Válida desde (opcional)">
              <input type="datetime-local" style={S.input} value={form.startsAt} onChange={e => setF({ startsAt:e.target.value })} />
            </Field>
            <Field label="Expira (opcional)">
              <input type="datetime-local" style={S.input} value={form.expiresAt} onChange={e => setF({ expiresAt:e.target.value })} />
            </Field>
          </div>

          {/* Message — text OR interactive buttons/list */}
          <div>
            <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between', marginBottom:8 }}>
              <span style={S.label}>Mensaje inicial de WhatsApp *</span>
              <div style={{ display:'flex', gap:6 }}>
                <button
                  onClick={() => setF({ interactiveMessage: null })}
                  style={{ ...S.chip(!form.interactiveMessage), fontSize:12, padding:'4px 12px' }}>
                  💬 Texto
                </button>
                <button
                  onClick={() => setF({ interactiveMessage: form.interactiveMessage || { type:'button', body:{ text:'' }, action:{ buttons:[] } } })}
                  style={{ ...S.chip(!!form.interactiveMessage), fontSize:12, padding:'4px 12px' }}>
                  🔘 Botones interactivos
                </button>
              </div>
            </div>
            {!form.interactiveMessage ? (
              <textarea style={{ ...S.textarea, minHeight:100 }}
                value={form.message} onChange={e => setF({ message:e.target.value })}
                placeholder="¡Aprovechá nuestra promo! 30% off en toda la línea de verano hasta el 31/01. Usá el código VERANO30 al hacer tu pedido 🌞" />
            ) : (
              <InteractiveMessageBuilder
                value={form.interactiveMessage}
                onChange={iv => setF({ interactiveMessage: iv })} />
            )}
          </div>

          {/* Assets */}
          <div>
            <span style={S.label}>Imágenes y archivos adjuntos</span>
            <div style={{ display:'flex', flexWrap:'wrap', gap:10, marginTop:8 }}>
              {form.assets.map(a => (
                <div key={a.filename} style={{ position:'relative', border:'1px solid var(--border)', borderRadius:'var(--r-sm)', overflow:'hidden', background:'var(--cream)' }}>
                  {isImg(a)
                    ? <img src={`/promo-assets/${tenantId}/${a.filename}`} style={{ width:80, height:80, objectFit:'cover', display:'block' }} alt={a.original} />
                    : <div style={{ width:80, height:80, display:'flex', flexDirection:'column', alignItems:'center', justifyContent:'center', gap:4 }}>
                        <span style={{ fontSize:24 }}>{a.mimeType.includes('pdf') ? '📄' : '📎'}</span>
                        <span style={{ fontSize:9, color:'var(--muted)', textAlign:'center', padding:'0 4px', wordBreak:'break-all' }}>{a.original.slice(0,16)}</span>
                      </div>
                  }
                  <button onClick={() => deleteAsset(a.filename)}
                    style={{ position:'absolute', top:2, right:2, width:18, height:18, borderRadius:'50%', background:'rgba(0,0,0,.55)', border:'none', color:'white', fontSize:10, cursor:'pointer', display:'flex', alignItems:'center', justifyContent:'center' }}>✕</button>
                </div>
              ))}
              <label style={{ width:80, height:80, border:'2px dashed var(--border)', borderRadius:'var(--r-sm)', display:'flex', flexDirection:'column', alignItems:'center', justifyContent:'center', cursor:'pointer', color:'var(--muted)', gap:4, fontSize:11 }}>
                {uploading ? '⏳' : '+'}<span style={{ fontSize:10 }}>{uploading ? 'Subiendo...' : 'Subir archivo'}</span>
                <input type="file" style={{ display:'none' }} onChange={uploadFile} accept="image/*,application/pdf,.doc,.docx,.mp4,.mov" />
              </label>
            </div>
            {!promo.id && <span style={{ fontSize:11, color:'var(--muted)', marginTop:4, display:'block' }}>Guardá primero para poder subir archivos.</span>}
          </div>

          {/* Assignment */}
          <div style={{ border:'1px solid var(--border)', borderRadius:'var(--r)', padding:16, display:'flex', flexDirection:'column', gap:14 }}>
            <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between' }}>
              <div>
                <span style={{ fontSize:13, fontWeight:600 }}>Asignación automática</span>
                <p style={{ fontSize:12, color:'var(--muted)', margin:'2px 0 0' }}>Al dispararse la promo, asigna la conversación automáticamente</p>
              </div>
            </div>
            <div style={{ display:'flex', gap:8 }}>
              {[['none','Sin asignar'],['team','Equipo (round-robin)'],['operator','Operador específico']].map(([v,l]) => (
                <button key={v} onClick={() => setF({ assignMode:v })}
                  style={{ ...S.chip(form.assignMode===v), fontSize:12, padding:'6px 14px' }}>{l}</button>
              ))}
            </div>
            {form.assignMode === 'team' && (
              <div>
                <span style={S.label}>Equipo</span>
                <select style={{ ...S.select, marginTop:6 }} value={form.assignTeamId} onChange={e => setF({ assignTeamId:e.target.value })}>
                  <option value="">— Seleccioná un equipo —</option>
                  {teams.map(t => <option key={t._id} value={t._id}>{t.name}</option>)}
                </select>
                <p style={{ fontSize:11, color:'var(--muted)', marginTop:6 }}>
                  🔄 El equipo distribuye las conversaciones en round-robin entre sus operadores automáticamente.
                </p>
              </div>
            )}
            {form.assignMode === 'operator' && (
              <div>
                <span style={S.label}>Operador</span>
                <select style={{ ...S.select, marginTop:6 }} value={form.assignOperatorId} onChange={e => setF({ assignOperatorId:e.target.value })}>
                  <option value="">— Seleccioná un operador —</option>
                  {users.map(u => <option key={u._id} value={u._id}>{u.name}{u.email ? ` (${u.email})` : ''}</option>)}
                </select>
              </div>
            )}
          </div>

          {/* Actions */}
          <div style={{ border:'1px solid var(--border)', borderRadius:'var(--r)', padding:16, display:'flex', flexDirection:'column', gap:14 }}>
            <div>
              <span style={{ fontSize:13, fontWeight:600 }}>Acciones adicionales</span>
              <p style={{ fontSize:12, color:'var(--muted)', margin:'2px 0 0' }}>El agente ejecuta estas acciones automáticamente al disparar la promo</p>
            </div>

            {/* Action list */}
            {form.actions.map(a => {
              const meta = ACTION_LABELS[a.type] || { icon:'⚡', label:a.type };
              return (
                <div key={a.id} style={{ background:'var(--cream)', border:'1px solid var(--border-soft)', borderRadius:'var(--r-sm)', padding:'12px 14px', display:'flex', flexDirection:'column', gap:10 }}>
                  <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between' }}>
                    <span style={{ fontSize:13, fontWeight:600 }}>{meta.icon} {meta.label}</span>
                    <button onClick={() => removeAction(a.id)} style={{ background:'none', border:'none', color:'var(--muted)', cursor:'pointer', fontSize:16, lineHeight:1 }}>✕</button>
                  </div>

                  {a.type === 'add_tags' && (
                    <div>
                      <span style={S.label}>Etiquetas a agregar</span>
                      <input style={{ ...S.input, marginTop:6 }}
                        value={(a.tags||[]).join(', ')}
                        onChange={e => updateAction(a.id, { tags: e.target.value.split(',').map(t=>t.trim()).filter(Boolean) })}
                        placeholder="promo-verano, interesado, descuento" />
                      {tags.length > 0 && (
                        <div style={{ display:'flex', flexWrap:'wrap', gap:4, marginTop:6 }}>
                          {tags.slice(0,12).map(t => (
                            <button key={t.id||t.name} onClick={() => {
                              const cur = a.tags||[];
                              const nm  = t.name||t;
                              updateAction(a.id, { tags: cur.includes(nm) ? cur.filter(x=>x!==nm) : [...cur,nm] });
                            }} style={{ ...S.chip((a.tags||[]).includes(t.name||t)), fontSize:11, padding:'3px 10px' }}>
                              {t.name||t}
                            </button>
                          ))}
                        </div>
                      )}
                    </div>
                  )}

                  {a.type === 'create_lead' && (
                    <div style={{ display:'flex', flexDirection:'column', gap:8 }}>
                      <div>
                        <span style={S.label}>Embudo (pipeline)</span>
                        <select style={{ ...S.select, marginTop:6, color:'var(--ink)' }} value={a.pipelineId||''}
                          onChange={e => {
                            const pip = pipelines.find(p => p._id===e.target.value || p.id===e.target.value);
                            updateAction(a.id, { pipelineId:e.target.value, pipelineName:pip?.title||pip?.name||'', stageId:'', stageName:'' });
                          }}>
                          <option value="">— Seleccioná un embudo —</option>
                          {pipelines.map(p => <option key={p._id||p.id} value={p._id||p.id} style={{ color:'#0F1A14', background:'#fff' }}>{p.title||p.name}</option>)}
                        </select>
                      </div>
                      {a.pipelineId && (() => {
                        const pip = pipelines.find(p => (p._id||p.id)===a.pipelineId);
                        const stages = pip?.stages || pip?.steps || [];
                        return stages.length > 0 ? (
                          <div>
                            <span style={S.label}>Etapa inicial</span>
                            <select style={{ ...S.select, marginTop:6, color:'var(--ink)' }} value={a.stageId||''}
                              onChange={e => {
                                const st = stages.find(s => (s._id||s.id)===e.target.value);
                                updateAction(a.id, { stageId:e.target.value, stageName:st?.name||'' });
                              }}>
                              <option value="">— Primera etapa —</option>
                              {stages.map(s => <option key={s._id||s.id} value={s._id||s.id} style={{ color:'#0F1A14', background:'#fff' }}>{s.name}</option>)}
                            </select>
                          </div>
                        ) : null;
                      })()}
                    </div>
                  )}

                  {a.type === 'update_status' && (
                    <div>
                      <span style={S.label}>Estado de la conversación</span>
                      <div style={{ display:'flex', gap:6, marginTop:6 }}>
                        {[['open','Abierta'],['pending','Pendiente'],['closed','Cerrada']].map(([v,l]) => (
                          <button key={v} onClick={() => updateAction(a.id, { status:v })}
                            style={{ ...S.chip(a.status===v), fontSize:12, padding:'5px 14px' }}>{l}</button>
                        ))}
                      </div>
                    </div>
                  )}

                  {a.type === 'add_note' && (
                    <div>
                      <span style={S.label}>Nota para el lead</span>
                      <input style={{ ...S.input, marginTop:6 }} value={a.note||''}
                        onChange={e => updateAction(a.id, { note:e.target.value })}
                        placeholder="Cliente consultó por promo de verano, interesado en descuento 30%" />
                    </div>
                  )}
                </div>
              );
            })}

            {/* Add action dropdown */}
            <div style={{ display:'flex', gap:6, flexWrap:'wrap' }}>
              {Object.entries(ACTION_LABELS).map(([type, { icon, label }]) => (
                <button key={type} onClick={() => addAction(type)}
                  style={{ ...S.outlineBtn, fontSize:12, padding:'6px 12px', display:'flex', alignItems:'center', gap:4 }}>
                  + {icon} {label}
                </button>
              ))}
            </div>
          </div>

          {/* External image URLs */}
          <Field label="URLs de imágenes externas (una por línea, opcional)">
            <textarea style={{ ...S.textarea, minHeight:60, fontFamily:'monospace', fontSize:12 }}
              value={form.imageUrls} onChange={e => setF({ imageUrls:e.target.value })}
              placeholder={"https://tu-web.com/imagen-promo.jpg\nhttps://otro-sitio.com/flyer.png"} />
          </Field>

          {/* Agent instructions */}
          <Field label="🤖 Instrucciones al agente (post-promo)" help="El agente seguirá estas instrucciones después de enviar el mensaje de la promo. Usá texto libre: podés indicar preguntas a hacer, opciones a presentar, precios, formas de pago, etc.">
            <textarea style={{ ...S.textarea, minHeight:90 }}
              value={form.agentInstructions||''} onChange={e => setF({ agentInstructions:e.target.value })}
              placeholder={"Ej: Después de enviar la promo, preguntá si quiere conocer los precios o las formas de pago.\n- Precios: desde $15.000/mes o pago único $180.000\n- Formas de pago: contado, 3/6/12 cuotas sin interés"} />
          </Field>

          {/* Interactive questions */}
          <div style={{ borderTop:'1px solid var(--border-soft)', paddingTop:16 }}>
            <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between', marginBottom:10 }}>
              <div>
                <div style={{ fontSize:13, fontWeight:600 }}>💬 Preguntas con opciones</div>
                <div style={{ fontSize:11, color:'var(--muted)', marginTop:2 }}>El agente las envía después de la promo como lista numerada. El cliente responde y el agente continúa.</div>
              </div>
              <button onClick={() => setF({ questions: [...form.questions, { id: Date.now().toString(36), question:'', options:[] }] })}
                style={{ ...S.outlineBtn, fontSize:12, padding:'5px 12px', flexShrink:0 }}>+ Agregar pregunta</button>
            </div>

            {form.questions.length === 0 && (
              <div style={{ fontSize:12, color:'var(--muted)', fontStyle:'italic', padding:'10px 0' }}>
                Sin preguntas configuradas. Agregá una para que el agente la envíe después del mensaje de promo.
              </div>
            )}

            {form.questions.map((q, qi) => {
              const updQ = (patch) => setF({ questions: form.questions.map((x,i) => i===qi ? {...x,...patch} : x) });
              const removeQ = () => setF({ questions: form.questions.filter((_,i) => i!==qi) });
              const addOpt = () => { const v = q._newOpt?.trim(); if (!v) return; updQ({ options:[...q.options, v], _newOpt:'' }); };
              return (
                <div key={q.id} style={{ background:'var(--cream)', borderRadius:10, padding:14, marginBottom:10, border:'1px solid var(--border-soft)' }}>
                  <div style={{ display:'flex', alignItems:'flex-start', gap:10, marginBottom:10 }}>
                    <div style={{ flex:1 }}>
                      <div style={{ fontSize:11, fontWeight:600, color:'var(--muted)', marginBottom:4 }}>TEXTO DE LA PREGUNTA</div>
                      <input style={{ ...S.input, width:'100%' }}
                        value={q.question} onChange={e => updQ({ question:e.target.value })}
                        placeholder="Ej: ¿Qué te gustaría saber?" />
                    </div>
                    <button onClick={removeQ} style={{ background:'none', border:'none', color:'var(--muted)', fontSize:18, cursor:'pointer', marginTop:20, lineHeight:1 }}>✕</button>
                  </div>

                  <div style={{ fontSize:11, fontWeight:600, color:'var(--muted)', marginBottom:6 }}>OPCIONES ({q.options.length}/10)</div>
                  <div style={{ display:'flex', flexWrap:'wrap', gap:6, marginBottom:8 }}>
                    {q.options.map((opt, oi) => {
                      const EMOJI = ['1️⃣','2️⃣','3️⃣','4️⃣','5️⃣','6️⃣','7️⃣','8️⃣','9️⃣','🔟'];
                      return (
                        <span key={oi} style={{ display:'inline-flex', alignItems:'center', gap:4, background:'var(--white)', border:'1px solid var(--border)', borderRadius:20, padding:'4px 10px', fontSize:12 }}>
                          {EMOJI[oi]} {opt}
                          <button onClick={() => updQ({ options: q.options.filter((_,i)=>i!==oi) })}
                            style={{ background:'none', border:'none', color:'var(--muted)', cursor:'pointer', fontSize:13, lineHeight:1, padding:0 }}>×</button>
                        </span>
                      );
                    })}
                  </div>
                  {q.options.length < 10 && (
                    <div style={{ display:'flex', gap:6 }}>
                      <input style={{ ...S.input, flex:1, fontSize:12 }}
                        value={q._newOpt||''} onChange={e => updQ({ _newOpt:e.target.value })}
                        onKeyDown={e => e.key==='Enter' && addOpt()}
                        placeholder="Nueva opción... (Enter para agregar)" />
                      <button onClick={addOpt} style={{ ...S.btnPrimary, fontSize:12, padding:'6px 14px' }}>+</button>
                    </div>
                  )}
                  {q.question && q.options.length > 0 && (
                    <div style={{ marginTop:10, background:'var(--white)', borderRadius:8, padding:'10px 12px', fontSize:12, color:'var(--ink-2)', borderLeft:'3px solid var(--green)', lineHeight:1.6 }}>
                      <div style={{ fontWeight:600, marginBottom:4, fontSize:11, color:'var(--muted)' }}>PREVIEW EN WHATSAPP</div>
                      {q.question} 👇<br/>
                      {q.options.map((o,i) => {
                        const EMOJI = ['1️⃣','2️⃣','3️⃣','4️⃣','5️⃣','6️⃣','7️⃣','8️⃣','9️⃣','🔟'];
                        return <span key={i}>{EMOJI[i]} {o}<br/></span>;
                      })}
                    </div>
                  )}
                </div>
              );
            })}
          </div>

          {/* Button reply triggers — shown only when promo has reply buttons */}
          {(() => {
            const im = form.interactiveMessage;
            const btns = im?.type === 'button' ? (im?.action?.buttons || []) : [];
            if (!btns.length) return null;

            const updBR = (i, patch) => setF({ buttonReplies: form.buttonReplies.map((x, j) => j===i ? {...x,...patch} : x) });
            const removeBR = (i) => setF({ buttonReplies: form.buttonReplies.filter((_,j) => j!==i) });
            const addBRQuestion = (i) => updBR(i, { questions: [...(form.buttonReplies[i].questions||[]), { id: Date.now().toString(36), question:'', options:[] }] });
            const updBRQuestion = (bi, qi, patch) => updBR(bi, { questions: (form.buttonReplies[bi].questions||[]).map((q,j) => j===qi ? {...q,...patch} : q) });
            const removeBRQuestion = (bi, qi) => updBR(bi, { questions: (form.buttonReplies[bi].questions||[]).filter((_,j) => j!==qi) });
            const addBRQOpt = (bi, qi) => {
              const q = (form.buttonReplies[bi].questions||[])[qi];
              const v = q?._newOpt?.trim();
              if (!v) return;
              updBRQuestion(bi, qi, { options: [...(q.options||[]), v], _newOpt: '' });
            };

            return (
              <div style={{ borderTop:'1px solid var(--border-soft)', paddingTop:16 }}>
                <div style={{ marginBottom:10 }}>
                  <div style={{ fontSize:13, fontWeight:600 }}>🔀 Respuestas a botones</div>
                  <div style={{ fontSize:11, color:'var(--muted)', marginTop:2 }}>Configurá qué envía el bot cuando el usuario hace click en cada botón de la botonera de arriba.</div>
                </div>

                {btns.map((btn, bi) => {
                  const title = btn.reply?.title || btn.title || `Botón ${bi+1}`;
                  // Find existing trigger or create a placeholder
                  const triggerIdx = form.buttonReplies.findIndex(br => br.matchTitle?.toLowerCase() === title.toLowerCase());
                  const hasTrigger = triggerIdx !== -1;
                  const trigger = hasTrigger ? form.buttonReplies[triggerIdx] : null;
                  const ti = triggerIdx;

                  return (
                    <div key={bi} style={{ background:'var(--cream)', borderRadius:10, padding:14, marginBottom:12, border:'1px solid var(--border-soft)' }}>
                      <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between', marginBottom:10 }}>
                        <div style={{ display:'flex', alignItems:'center', gap:8 }}>
                          <span style={{ background:'var(--green)', color:'#fff', borderRadius:20, padding:'3px 12px', fontSize:12, fontWeight:600 }}>"{title}"</span>
                          <span style={{ fontSize:11, color:'var(--muted)' }}>cuando el usuario elige este botón...</span>
                        </div>
                        {!hasTrigger ? (
                          <button onClick={() => setF({ buttonReplies: [...form.buttonReplies, { id: Date.now().toString(36), matchTitle: title, message:'', imageUrls:[], questions:[] }] })}
                            style={{ ...S.outlineBtn, fontSize:12, padding:'5px 12px' }}>+ Configurar respuesta</button>
                        ) : (
                          <button onClick={() => removeBR(ti)} style={{ background:'none', border:'none', color:'var(--muted)', cursor:'pointer', fontSize:18 }}>✕</button>
                        )}
                      </div>

                      {hasTrigger && trigger && (
                        <div style={{ display:'flex', flexDirection:'column', gap:10 }}>
                          {/* Message */}
                          <div>
                            <div style={{ fontSize:11, fontWeight:600, color:'var(--muted)', marginBottom:4 }}>MENSAJE DE RESPUESTA</div>
                            <textarea style={{ ...S.textarea, minHeight:70 }}
                              value={trigger.message||''} onChange={e => updBR(ti, { message: e.target.value })}
                              placeholder={"Ej:\n💪 ¡Excelente elección! Estos son los precios:\n1. $10.000/mes por 3 meses\n2. $12.000/mes por 2 meses\n3. $14.000 por 1 mes"} />
                          </div>

                          {/* Image URLs */}
                          <div>
                            <div style={{ fontSize:11, fontWeight:600, color:'var(--muted)', marginBottom:4 }}>IMAGEN (URL, opcional)</div>
                            <input style={{ ...S.input, width:'100%' }}
                              value={(trigger.imageUrls||[])[0]||''} onChange={e => updBR(ti, { imageUrls: e.target.value ? [e.target.value] : [] })}
                              placeholder="https://..." />
                          </div>

                          {/* Setear atributo del contacto */}
                          <div>
                            <div style={{ fontSize:11, fontWeight:600, color:'var(--muted)', marginBottom:4 }}>SETEAR ATRIBUTO (opcional)</div>
                            <div style={{ display:'flex', gap:8 }}>
                              <input style={{ ...S.input, flex:1 }} value={trigger.setAttribute?.key||''} placeholder="atributo (ej. intencion)"
                                onChange={e => updBR(ti, { setAttribute: { key: e.target.value, value: trigger.setAttribute?.value||'' } })} />
                              <input style={{ ...S.input, flex:1 }} value={trigger.setAttribute?.value||''} placeholder="valor (ej. quiero_visitar)"
                                onChange={e => updBR(ti, { setAttribute: { key: trigger.setAttribute?.key||'', value: e.target.value } })} />
                            </div>
                            <div style={{ fontSize:10, color:'var(--muted)', marginTop:3 }}>Guarda este atributo en el contacto cuando toca el botón (viaja a Tokko).</div>
                          </div>

                          {/* Disparar un WhatsApp Flow */}
                          <div>
                            <div style={{ fontSize:11, fontWeight:600, color:'var(--muted)', marginBottom:4 }}>DISPARAR WHATSAPP FLOW (opcional)</div>
                            <input style={{ ...S.input, width:'100%', marginBottom:6 }} value={trigger.flow?.flowId||''} placeholder="Flow ID (whatsAppFlowId)"
                              onChange={e => updBR(ti, { flow: { ...(trigger.flow||{}), flowId: e.target.value } })} />
                            <textarea style={{ ...S.textarea, minHeight:50 }} value={trigger.flow?.bodyText||''} placeholder="Texto que acompaña el flow (el cuerpo del mensaje con el botón)"
                              onChange={e => updBR(ti, { flow: { ...(trigger.flow||{}), bodyText: e.target.value } })} />
                            <input style={{ ...S.input, width:'100%', marginTop:6 }} value={trigger.flow?.ctaText||''} placeholder="Texto del botón que abre el flow (ej. Empezar)"
                              onChange={e => updBR(ti, { flow: { ...(trigger.flow||{}), ctaText: e.target.value } })} />
                          </div>

                          {/* Questions */}
                          <div>
                            <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between', marginBottom:6 }}>
                              <div style={{ fontSize:11, fontWeight:600, color:'var(--muted)' }}>PREGUNTAS DE SEGUIMIENTO</div>
                              <button onClick={() => addBRQuestion(ti)} style={{ ...S.outlineBtn, fontSize:11, padding:'3px 10px' }}>+ Pregunta</button>
                            </div>
                            {(trigger.questions||[]).map((q, qi) => (
                              <div key={q.id||qi} style={{ background:'var(--white)', borderRadius:8, padding:10, marginBottom:8, border:'1px solid var(--border-soft)' }}>
                                <div style={{ display:'flex', gap:8, marginBottom:8 }}>
                                  <input style={{ ...S.input, flex:1, fontSize:12 }}
                                    value={q.question||''} onChange={e => updBRQuestion(ti, qi, { question:e.target.value })}
                                    placeholder="Ej: ¿Qué clase preferís?" />
                                  <button onClick={() => removeBRQuestion(ti, qi)} style={{ background:'none', border:'none', color:'var(--muted)', cursor:'pointer', fontSize:16 }}>✕</button>
                                </div>
                                <div style={{ display:'flex', flexWrap:'wrap', gap:5, marginBottom:6 }}>
                                  {(q.options||[]).map((opt, oi) => (
                                    <span key={oi} style={{ display:'inline-flex', alignItems:'center', gap:4, background:'var(--cream)', border:'1px solid var(--border)', borderRadius:20, padding:'3px 8px', fontSize:11 }}>
                                      {opt}
                                      <button onClick={() => updBRQuestion(ti, qi, { options:(q.options||[]).filter((_,i)=>i!==oi) })}
                                        style={{ background:'none', border:'none', color:'var(--muted)', cursor:'pointer', fontSize:12, lineHeight:1, padding:0 }}>×</button>
                                    </span>
                                  ))}
                                </div>
                                <div style={{ display:'flex', gap:6 }}>
                                  <input style={{ ...S.input, flex:1, fontSize:11 }}
                                    value={q._newOpt||''} onChange={e => updBRQuestion(ti, qi, { _newOpt:e.target.value })}
                                    onKeyDown={e => e.key==='Enter' && addBRQOpt(ti, qi)}
                                    placeholder="Nueva opción... (Enter)" />
                                  <button onClick={() => addBRQOpt(ti, qi)} style={{ ...S.btnPrimary, fontSize:11, padding:'5px 10px' }}>+</button>
                                </div>
                              </div>
                            ))}
                          </div>
                        </div>
                      )}
                    </div>
                  );
                })}
              </div>
            );
          })()}

          {/* Respuestas por TÍTULO de botón — para botones de un template/difusión (sin botonera interactiva) */}
          {(() => {
            const im = form.interactiveMessage;
            const btnTitles = (im?.type === 'button' ? (im?.action?.buttons || []) : []).map(b => (b.reply?.title||b.title||'').toLowerCase());
            const orphans = (form.buttonReplies||[]).map((br, i) => ({ br, i })).filter(({ br }) => !btnTitles.includes((br.matchTitle||'').toLowerCase()));
            const updBR = (i, patch) => setF({ buttonReplies: form.buttonReplies.map((x,j)=> j===i ? {...x,...patch} : x) });
            const removeBR = (i) => setF({ buttonReplies: form.buttonReplies.filter((_,j)=>j!==i) });
            const addBR = () => setF({ buttonReplies: [...(form.buttonReplies||[]), { id: Date.now().toString(36), matchTitle:'', message:'', imageUrls:[], questions:[] }] });
            return (
              <div style={{ borderTop:'1px solid var(--border-soft)', paddingTop:16, marginTop:16 }}>
                <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between', marginBottom:8 }}>
                  <div>
                    <div style={{ fontSize:13, fontWeight:600 }}>🔘 Respuestas por botón (template / difusión)</div>
                    <div style={{ fontSize:11, color:'var(--muted)', marginTop:2 }}>Para los botones de un template (ej. Quiero visitar, Hablar con asesor). Poné el título EXACTO del botón.</div>
                  </div>
                  <button onClick={addBR} style={{ ...S.outlineBtn, fontSize:12, padding:'5px 12px' }}>+ Respuesta</button>
                </div>
                {orphans.length === 0 && <div style={{ fontSize:11, color:'var(--muted)' }}>Sin respuestas por título. Agregá una con el botón de arriba.</div>}
                {orphans.map(({ br, i }) => (
                  <div key={br.id||i} style={{ background:'var(--cream)', borderRadius:10, padding:14, marginBottom:12, border:'1px solid var(--border-soft)' }}>
                    <div style={{ display:'flex', gap:8, alignItems:'center', marginBottom:10 }}>
                      <input style={{ ...S.input, flex:1, fontWeight:600 }} value={br.matchTitle||''} placeholder="Título EXACTO del botón (ej. Hablar con asesor)"
                        onChange={e => updBR(i, { matchTitle: e.target.value })} />
                      <button onClick={() => removeBR(i)} style={{ background:'none', border:'none', color:'var(--muted)', cursor:'pointer', fontSize:18 }}>✕</button>
                    </div>
                    <div style={{ display:'flex', flexDirection:'column', gap:10 }}>
                      <div>
                        <div style={{ fontSize:11, fontWeight:600, color:'var(--muted)', marginBottom:4 }}>MENSAJE DE RESPUESTA</div>
                        <textarea style={{ ...S.textarea, minHeight:60 }} value={br.message||''} onChange={e => updBR(i, { message:e.target.value })} placeholder="Mensaje que manda el bot al tocar este botón (dejalo vacío si solo dispara un flow)" />
                      </div>
                      <div>
                        <div style={{ fontSize:11, fontWeight:600, color:'var(--muted)', marginBottom:4 }}>SETEAR ATRIBUTO (opcional)</div>
                        <div style={{ display:'flex', gap:8 }}>
                          <input style={{ ...S.input, flex:1 }} value={br.setAttribute?.key||''} placeholder="atributo (ej. intencion)"
                            onChange={e => updBR(i, { setAttribute: { key:e.target.value, value: br.setAttribute?.value||'' } })} />
                          <input style={{ ...S.input, flex:1 }} value={br.setAttribute?.value||''} placeholder="valor (ej. quiero_visitar)"
                            onChange={e => updBR(i, { setAttribute: { key: br.setAttribute?.key||'', value:e.target.value } })} />
                        </div>
                        <div style={{ fontSize:10, color:'var(--muted)', marginTop:3 }}>Se guarda en el contacto y viaja a Tokko.</div>
                      </div>
                      <div>
                        <div style={{ fontSize:11, fontWeight:600, color:'var(--muted)', marginBottom:4 }}>DISPARAR WHATSAPP FLOW (opcional)</div>
                        <input style={{ ...S.input, width:'100%', marginBottom:6 }} value={br.flow?.flowId||''} placeholder="Flow ID (whatsAppFlowId)"
                          onChange={e => updBR(i, { flow: { ...(br.flow||{}), flowId:e.target.value } })} />
                        <textarea style={{ ...S.textarea, minHeight:50 }} value={br.flow?.bodyText||''} placeholder="Texto que acompaña el flow (cuerpo del mensaje con el botón)"
                          onChange={e => updBR(i, { flow: { ...(br.flow||{}), bodyText:e.target.value } })} />
                        <input style={{ ...S.input, width:'100%', marginTop:6 }} value={br.flow?.ctaText||''} placeholder="Texto del botón que abre el flow (ej. Empezar)"
                          onChange={e => updBR(i, { flow: { ...(br.flow||{}), ctaText:e.target.value } })} />
                      </div>
                    </div>
                  </div>
                ))}
              </div>
            );
          })()}

          {err && <p style={{ color:'var(--danger)', fontSize:13 }}>{err}</p>}
        </div>

        {/* Footer */}
        <div style={{ display:'flex', gap:10, justifyContent:'flex-end', padding:'16px 24px', borderTop:'1px solid var(--border-soft)', flexShrink:0 }}>
          <button onClick={onCancel} style={S.outlineBtn}>Cancelar</button>
          <button onClick={save} disabled={saving} style={S.btnPrimary}>
            {saving ? 'Guardando...' : isNew ? 'Crear promoción' : 'Guardar cambios'}
          </button>
        </div>
      </div>
    </div>
  );
}

function PromotionsPanel() {
  const [promos, setPromos]     = useState(null);
  const [editing, setEditing]   = useState(null);
  const [conflicts, setConflicts] = useState({});
  const [search, setSearch]     = useState('');
  const [filterStatus, setFilterStatus] = useState('all');
  const [tid, setTid]           = useState('');
  const [confirmDel, setConfirmDel] = useState(null);

  function load() {
    apiFetch('/api/promotions').then(r=>r.json()).then(d => setPromos(Array.isArray(d)?d:[]));
    apiFetch('/api/promotions/conflicts').then(r=>r.json()).then(setConflicts);
  }

  useEffect(() => {
    apiFetch('/api/auth/me').then(r=>r.json()).then(d=>setTid(d.tenantId||''));
    load();
  }, []);

  const newPromo = () => setEditing({ enabled:true, priority:10, keywords:[], assets:[], imageUrls:[] });

  async function doDelete(id) {
    await apiFetch(`/api/promotions/${id}`, { method:'DELETE' });
    setConfirmDel(null); load();
  }

  function handleSave(saved) {
    setEditing(null); load();
  }

  const filtered = (promos||[]).filter(p => {
    if (filterStatus !== 'all' && promoStatus(p) !== filterStatus) return false;
    if (search && !p.name.toLowerCase().includes(search.toLowerCase()) &&
        !p.keywords.some(k => k.toLowerCase().includes(search.toLowerCase()))) return false;
    return true;
  });

  const counts = { all: (promos||[]).length };
  for (const s of ['active','upcoming','expired','disabled']) counts[s] = (promos||[]).filter(p=>promoStatus(p)===s).length;
  const conflictKws = Object.keys(conflicts);

  return (
    <div style={{ flex:1, overflowY:'auto', background:'var(--cream)' }}>
      {editing && <PromotionEditor promo={editing} tenantId={tid} onSave={handleSave} onCancel={()=>setEditing(null)} />}

      <div style={{ maxWidth:980, margin:'0 auto', padding:'32px 28px' }}>

        {/* Header */}
        <div style={{ display:'flex', alignItems:'flex-start', justifyContent:'space-between', gap:16, marginBottom:24 }}>
          <div>
            <h2 style={S.pageTitle}>🎁 Promociones</h2>
            <p style={S.pageSubtitle}>Palabras clave que disparan mensajes, imágenes y archivos automáticamente</p>
          </div>
          <button onClick={newPromo} style={S.btnPrimary}>+ Nueva promoción</button>
        </div>

        {/* Conflict warning */}
        {conflictKws.length > 0 && (
          <div style={{ background:'#FEF3C7', border:'1px solid #FCD34D', borderRadius:'var(--r)', padding:'12px 16px', marginBottom:20, fontSize:13 }}>
            <strong>⚠️ Palabras clave compartidas:</strong>{' '}
            {conflictKws.map(kw => (
              <span key={kw} style={{ background:'white', border:'1px solid #FCD34D', borderRadius:99, padding:'1px 8px', marginRight:4, fontSize:12 }}>
                "{kw}" — {conflicts[kw].join(' vs ')}
              </span>
            ))}
            <span style={{ color:'var(--muted)', marginLeft:4 }}>La de mayor prioridad gana.</span>
          </div>
        )}

        {/* Filters */}
        <div style={{ display:'flex', gap:10, marginBottom:18, flexWrap:'wrap', alignItems:'center' }}>
          <input style={{ ...S.input, maxWidth:240, flex:1 }} value={search} onChange={e=>setSearch(e.target.value)} placeholder="Buscar por nombre o keyword..." />
          <div style={{ display:'flex', gap:4 }}>
            {[['all','Todas'],['active','Activas'],['upcoming','Próximas'],['expired','Expiradas'],['disabled','Desactivadas']].map(([v,l]) => (
              <button key={v} onClick={()=>setFilterStatus(v)} style={{ ...S.chip(filterStatus===v), padding:'5px 13px', fontSize:12 }}>
                {l} {counts[v]>0 ? <span style={{ fontSize:10, opacity:.7 }}>({counts[v]})</span> : ''}
              </button>
            ))}
          </div>
        </div>

        {promos === null && <div style={{ textAlign:'center', padding:'48px 0', color:'var(--muted)' }}>Cargando...</div>}

        {promos !== null && filtered.length === 0 && (
          <div style={{ textAlign:'center', padding:'64px 24px', background:'var(--surface)', border:'1.5px dashed var(--border)', borderRadius:'var(--r-lg)' }}>
            <div style={{ fontSize:42, marginBottom:14 }}>🎁</div>
            <h3 style={{ fontSize:17, fontWeight:700, marginBottom:8 }}>
              {search || filterStatus!=='all' ? 'Sin resultados' : 'Sin promociones todavía'}
            </h3>
            <p style={{ color:'var(--muted)', fontSize:13.5, marginBottom:24, lineHeight:1.6 }}>
              {search || filterStatus!=='all'
                ? 'Probá con otros filtros.'
                : 'Creá tu primera promo: palabras clave + mensaje + imagen. El agente la usa automáticamente.'}
            </p>
            {!search && filterStatus==='all' && <button onClick={newPromo} style={S.btnPrimary}>+ Crear primera promoción</button>}
          </div>
        )}

        <div style={{ display:'flex', flexDirection:'column', gap:12 }}>
          {filtered.map(p => {
            const st     = promoStatus(p);
            const stInfo = PROMO_STATUS[st];
            const myConflicts = p.keywords.filter(k => conflicts[k.toLowerCase()]);
            return (
              <div key={p.id} style={{ ...S.card, display:'flex', gap:16, alignItems:'flex-start' }}>
                {/* Status dot */}
                <div style={{ width:10, height:10, borderRadius:'50%', background:stInfo.dot, marginTop:6, flexShrink:0 }} />

                <div style={{ flex:1, minWidth:0 }}>
                  <div style={{ display:'flex', alignItems:'center', gap:8, flexWrap:'wrap', marginBottom:4 }}>
                    <span style={{ fontWeight:700, fontSize:15 }}>{p.name}</span>
                    <span style={{ fontSize:11, fontWeight:600, padding:'2px 9px', borderRadius:99, background:stInfo.bg, color:stInfo.color }}>{stInfo.label}</span>
                    {p.expiresAt && <span style={{ fontSize:11, color:'var(--muted)' }}>→ {fmtDate(p.expiresAt)}</span>}
                    {p.startsAt && st==='upcoming' && <span style={{ fontSize:11, color:'var(--muted)' }}>desde {fmtDate(p.startsAt)}</span>}
                    {myConflicts.length > 0 && <span style={{ fontSize:11, color:'#92400E', background:'#FEF3C7', padding:'1px 7px', borderRadius:99 }}>⚠ kw compartida</span>}
                    {p.assignMode === 'team'     && <span style={{ fontSize:11, color:'#1D4ED8', background:'#EFF6FF', padding:'1px 8px', borderRadius:99 }}>👥 {p.assignTeamName || 'Equipo'}</span>}
                    {p.assignMode === 'operator' && <span style={{ fontSize:11, color:'#6D28D9', background:'#F5F3FF', padding:'1px 8px', borderRadius:99 }}>👤 {p.assignOperatorName || 'Operador'}</span>}
                    {(p.actions||[]).map(a => {
                      const lbl = { add_tags:'🏷️ Tags', create_lead:'📊 Embudo', update_status:'🔄 Estado', add_note:'📝 Nota' }[a.type] || a.type;
                      return <span key={a.id} style={{ fontSize:11, color:'#374151', background:'#F3F4F6', padding:'1px 8px', borderRadius:99 }}>{lbl}</span>;
                    })}
                  </div>
                  {/* Keywords */}
                  {p.keywords.length > 0 && (
                    <div style={{ display:'flex', flexWrap:'wrap', gap:4, marginBottom:6 }}>
                      {p.keywords.map(k => (
                        <span key={k} style={{ fontSize:11, padding:'2px 8px', borderRadius:99, background:'var(--green-light)', color:'var(--green)', fontWeight:500 }}>{k}</span>
                      ))}
                    </div>
                  )}
                  {/* Message preview */}
                  {p.message && <p style={{ fontSize:12.5, color:'var(--ink-2)', margin:0, lineHeight:1.5, display:'-webkit-box', WebkitLineClamp:2, WebkitBoxOrient:'vertical', overflow:'hidden' }}>{p.message}</p>}
                  {/* Assets */}
                  {(p.assets?.length > 0 || p.imageUrls?.length > 0) && (
                    <div style={{ display:'flex', gap:6, marginTop:8, flexWrap:'wrap' }}>
                      {(p.assets||[]).filter(a=>/^image\//.test(a.mimeType)).map(a => (
                        <img key={a.filename} src={`/promo-assets/${tid}/${a.filename}`} style={{ width:40, height:40, objectFit:'cover', borderRadius:6 }} alt={a.original} />
                      ))}
                      {(p.assets||[]).filter(a=>!/^image\//.test(a.mimeType)).map(a => (
                        <span key={a.filename} style={{ fontSize:11, background:'var(--cream-mid)', padding:'4px 8px', borderRadius:6 }}>📄 {a.original}</span>
                      ))}
                      {(p.imageUrls||[]).slice(0,3).map((u,i) => (
                        <img key={i} src={u} style={{ width:40, height:40, objectFit:'cover', borderRadius:6 }} alt="" onError={e=>e.target.style.display='none'} />
                      ))}
                    </div>
                  )}
                </div>

                {/* Actions */}
                <div style={{ display:'flex', gap:6, flexShrink:0 }}>
                  <button onClick={() => setEditing(p)} style={{ ...S.outlineBtn, fontSize:12, padding:'6px 13px' }}>Editar</button>
                  <button onClick={() => setConfirmDel(p.id)} style={{ ...S.dangerBtn, fontSize:12, padding:'6px 13px' }}>Eliminar</button>
                </div>
              </div>
            );
          })}
        </div>
      </div>

      {/* Delete confirm */}
      {confirmDel && (
        <div style={{ position:'fixed', inset:0, background:'rgba(0,0,0,.45)', display:'flex', alignItems:'center', justifyContent:'center', zIndex:300 }}>
          <div style={{ background:'white', borderRadius:'var(--r-lg)', padding:32, maxWidth:400, width:'90%', boxShadow:'var(--shadow-lg)' }}>
            <h3 style={{ fontSize:17, fontWeight:700, marginBottom:10 }}>¿Eliminar promoción?</h3>
            <p style={{ color:'var(--muted)', fontSize:14, marginBottom:24, lineHeight:1.6 }}>Esta acción no se puede deshacer.</p>
            <div style={{ display:'flex', gap:8, justifyContent:'flex-end' }}>
              <button onClick={()=>setConfirmDel(null)} style={S.outlineBtn}>Cancelar</button>
              <button onClick={()=>doDelete(confirmDel)} style={{ ...S.btnPrimary, background:'var(--danger)', boxShadow:'none' }}>Eliminar</button>
            </div>
          </div>
        </div>
      )}
    </div>
  );
}

// ─── WhatsApp Flow Builder ─────────────────────────────────────────────────────

function genCId() {
  return 'c' + Date.now().toString(36) + Math.random().toString(36).slice(2, 5);
}

const COMP_TYPES = [
  { value: 'TextHeading',       label: '📌 Título (grande)',       hasText: true  },
  { value: 'TextSubheading',    label: '🔤 Subtítulo',             hasText: true  },
  { value: 'TextBody',          label: '📝 Texto libre',           hasText: true  },
  { value: 'TextInput',         label: '✏️ Campo de texto',        hasForm: true  },
  { value: 'TextArea',          label: '📋 Área de texto',         hasForm: true  },
  { value: 'Dropdown',          label: '▼ Desplegable (buscable)', hasForm: true, hasOptions: true },
  { value: 'RadioButtonsGroup', label: '⊙ Opción única',           hasForm: true, hasOptions: true },
  { value: 'CheckboxGroup',     label: '☑ Múltiple opción',        hasForm: true, hasOptions: true },
  { value: 'DatePicker',        label: '📅 Selector de fecha',     hasForm: true  },
];

function WaFlowScreenPreview({ screen }) {
  if (!screen) return null;
  const comps = screen.components || [];
  return (
    <div style={{ background:'#fff', borderRadius:8, overflow:'hidden', boxShadow:'0 2px 12px rgba(0,0,0,.15)', fontFamily:'system-ui,sans-serif' }}>
      <div style={{ background:'#075e54', color:'white', padding:'10px 14px', fontSize:13, fontWeight:600 }}>
        {screen.title || 'Pantalla'}
      </div>
      <div style={{ padding:'12px 14px', display:'flex', flexDirection:'column', gap:8 }}>
        {comps.map(c => {
          switch (c.type) {
            case 'TextHeading':
              return <div key={c.id} style={{ fontSize:15, fontWeight:700, color:'#111', lineHeight:1.3 }}>{c.text || 'Título'}</div>;
            case 'TextSubheading':
              return <div key={c.id} style={{ fontSize:13, fontWeight:600, color:'#333', lineHeight:1.4 }}>{c.text || 'Subtítulo'}</div>;
            case 'TextBody':
              return <div key={c.id} style={{ fontSize:12, color:'#555', lineHeight:1.5, whiteSpace:'pre-wrap' }}>{c.text || 'Texto...'}</div>;
            case 'TextInput':
              return (
                <div key={c.id}>
                  <div style={{ fontSize:10, color:'#888', marginBottom:3 }}>{c.label || 'Campo'}{c.required ? ' *' : ''}</div>
                  <div style={{ border:'1px solid #ddd', borderRadius:6, padding:'6px 10px', fontSize:12, color:'#bbb', background:'#fafafa' }}>{c.helperText || 'Escribí acá...'}</div>
                </div>
              );
            case 'TextArea':
              return (
                <div key={c.id}>
                  <div style={{ fontSize:10, color:'#888', marginBottom:3 }}>{c.label || 'Campo'}{c.required ? ' *' : ''}</div>
                  <div style={{ border:'1px solid #ddd', borderRadius:6, padding:'6px 10px', fontSize:12, color:'#bbb', background:'#fafafa', minHeight:44 }}>{c.helperText || 'Escribí acá...'}</div>
                </div>
              );
            case 'Dropdown':
              return (
                <div key={c.id}>
                  <div style={{ fontSize:10, color:'#888', marginBottom:3 }}>{c.label || 'Selección'}{c.required ? ' *' : ''}</div>
                  <div style={{ border:'1px solid #ddd', borderRadius:6, padding:'6px 10px', fontSize:12, color:'#aaa', background:'#fafafa', display:'flex', justifyContent:'space-between' }}>
                    <span>Seleccioná una opción</span><span style={{ fontSize:10 }}>▼</span>
                  </div>
                  {(c.options||[]).slice(0,3).map(o => (
                    <div key={o.id} style={{ fontSize:11, color:'#555', padding:'2px 8px' }}>• {o.title}</div>
                  ))}
                  {(c.options||[]).length > 3 && <div style={{ fontSize:10, color:'#aaa', padding:'0 8px' }}>+{c.options.length-3} más...</div>}
                </div>
              );
            case 'RadioButtonsGroup':
              return (
                <div key={c.id}>
                  <div style={{ fontSize:10, color:'#888', marginBottom:3 }}>{c.label || 'Opción'}{c.required ? ' *' : ''}</div>
                  {(c.options||[]).slice(0,4).map((o, i) => (
                    <div key={o.id} style={{ display:'flex', alignItems:'center', gap:7, padding:'3px 0', fontSize:12, color:'#333' }}>
                      <div style={{ width:13, height:13, borderRadius:'50%', border:'2px solid #ccc', flexShrink:0, background: i===0?'#25D366':'transparent' }} />
                      {o.title}
                    </div>
                  ))}
                </div>
              );
            case 'CheckboxGroup':
              return (
                <div key={c.id}>
                  <div style={{ fontSize:10, color:'#888', marginBottom:3 }}>{c.label || 'Opciones'}{c.required ? ' *' : ''}</div>
                  {(c.options||[]).slice(0,4).map(o => (
                    <div key={o.id} style={{ display:'flex', alignItems:'center', gap:7, padding:'3px 0', fontSize:12, color:'#333' }}>
                      <div style={{ width:13, height:13, borderRadius:3, border:'2px solid #ccc', flexShrink:0 }} />
                      {o.title}
                    </div>
                  ))}
                </div>
              );
            case 'DatePicker':
              return (
                <div key={c.id}>
                  <div style={{ fontSize:10, color:'#888', marginBottom:3 }}>{c.label || 'Fecha'}{c.required ? ' *' : ''}</div>
                  <div style={{ border:'1px solid #ddd', borderRadius:6, padding:'6px 10px', fontSize:12, color:'#aaa', background:'#fafafa', display:'flex', justifyContent:'space-between' }}>
                    <span>DD/MM/AAAA</span><span>📅</span>
                  </div>
                </div>
              );
            default: return null;
          }
        })}
        {comps.length === 0 && <div style={{ fontSize:11, color:'#ccc', textAlign:'center', padding:'12px 0' }}>Sin componentes</div>}
      </div>
      <div style={{ padding:'10px 14px', borderTop:'1px solid #f0f0f0' }}>
        <div style={{ background:'#25D366', color:'white', borderRadius:22, padding:'9px', textAlign:'center', fontSize:13, fontWeight:600 }}>
          {screen.footer?.label || 'Siguiente'}
        </div>
      </div>
    </div>
  );
}

function FlowCompEditor({ comp, onChange, onDelete, onMoveUp, onMoveDown, isFirst, isLast }) {
  const typeInfo = COMP_TYPES.find(t => t.value === comp.type) || {};
  const [expanded, setExpanded] = useState(true);

  function addOption() {
    onChange({ ...comp, options: [...(comp.options||[]), { id: genCId(), title: '' }] });
  }
  function removeOption(idx) {
    onChange({ ...comp, options: (comp.options||[]).filter((_, i) => i !== idx) });
  }
  function updateOption(idx, title) {
    onChange({ ...comp, options: (comp.options||[]).map((o, i) => i === idx ? { ...o, title } : o) });
  }
  function bulkPaste(text) {
    const lines = text.split('\n').map(l => l.trim()).filter(Boolean);
    const newOpts = lines.map(l => ({ id: genCId(), title: l }));
    onChange({ ...comp, options: [...(comp.options||[]), ...newOpts] });
  }

  return (
    <div style={{ border:'1px solid var(--border)', borderRadius:10, background:'var(--cream)', marginBottom:6, overflow:'hidden' }}>
      <div style={{ display:'flex', alignItems:'center', gap:6, padding:'8px 10px', cursor:'pointer', background:'var(--cream-mid)' }}
           onClick={() => setExpanded(e => !e)}>
        <span style={{ fontSize:11, color:'var(--muted)', width:12 }}>{expanded ? '▼' : '▶'}</span>
        <span style={{ fontSize:12.5, fontWeight:600, flex:1, color:'var(--ink)' }}>{typeInfo.label || comp.type}</span>
        {comp.name && <span style={{ fontSize:10, color:'var(--muted)', fontFamily:'monospace' }}>{comp.name}</span>}
        <button onClick={e => { e.stopPropagation(); onMoveUp(); }} disabled={isFirst}
          style={{ background:'none', border:'none', cursor:'pointer', color:'var(--muted)', fontSize:12, padding:'0 3px', opacity: isFirst?.3:1 }}>↑</button>
        <button onClick={e => { e.stopPropagation(); onMoveDown(); }} disabled={isLast}
          style={{ background:'none', border:'none', cursor:'pointer', color:'var(--muted)', fontSize:12, padding:'0 3px', opacity: isLast?.3:1 }}>↓</button>
        <button onClick={e => { e.stopPropagation(); onDelete(); }}
          style={{ background:'none', border:'none', cursor:'pointer', color:'var(--danger)', fontSize:13, padding:'0 3px' }}>✕</button>
      </div>
      {expanded && (
        <div style={{ padding:'10px 12px', display:'flex', flexDirection:'column', gap:9 }}>
          {typeInfo.hasText && (
            <div>
              <label style={S.label}>Texto</label>
              {comp.type === 'TextBody'
                ? <textarea rows={3} style={{ ...S.textarea, minHeight:56, fontSize:12 }} value={comp.text||''} onChange={e => onChange({ ...comp, text: e.target.value })} placeholder="Texto del cuerpo..." />
                : <input style={{ ...S.input, fontSize:12 }} value={comp.text||''} onChange={e => onChange({ ...comp, text: e.target.value })} placeholder="Texto..." />
              }
            </div>
          )}
          {typeInfo.hasForm && (
            <>
              <div style={{ display:'flex', gap:8 }}>
                <div style={{ flex:1 }}>
                  <label style={S.label}>Nombre del campo (clave)</label>
                  <input style={{ ...S.input, fontSize:12, fontFamily:'monospace' }} value={comp.name||''} onChange={e => onChange({ ...comp, name: e.target.value.replace(/\s/g,'_').toLowerCase() })} placeholder="ej: sede_elegida" />
                </div>
                <div style={{ flex:1 }}>
                  <label style={S.label}>Etiqueta visible</label>
                  <input style={{ ...S.input, fontSize:12 }} value={comp.label||''} onChange={e => onChange({ ...comp, label: e.target.value })} placeholder="ej: Sede" />
                </div>
              </div>
              {comp.type === 'TextInput' && (
                <div>
                  <label style={S.label}>Tipo de input</label>
                  <select style={{ ...S.select, fontSize:12 }} value={comp.inputType||'text'} onChange={e => onChange({ ...comp, inputType: e.target.value })}>
                    {['text','number','email','phone','password'].map(t => <option key={t} value={t}>{t}</option>)}
                  </select>
                </div>
              )}
              <div>
                <label style={S.label}>Texto de ayuda (opcional)</label>
                <input style={{ ...S.input, fontSize:12 }} value={comp.helperText||''} onChange={e => onChange({ ...comp, helperText: e.target.value })} placeholder="Ej: Ingresá tu sucursal" />
              </div>
              <div style={{ display:'flex', alignItems:'center', gap:8 }}>
                <Toggle on={comp.required||false} onChange={v => onChange({ ...comp, required: v })} />
                <span style={{ fontSize:12, color:'var(--ink-2)' }}>Campo obligatorio</span>
              </div>
            </>
          )}
          {typeInfo.hasOptions && (
            <div>
              <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between', marginBottom:6 }}>
                <label style={{ ...S.label, marginBottom:0 }}>Opciones ({(comp.options||[]).length})</label>
                <div style={{ display:'flex', gap:6 }}>
                  <button onClick={() => {
                    const text = prompt('Pegá las opciones (una por línea):');
                    if (text) bulkPaste(text);
                  }} style={{ fontSize:11, color:'var(--ink-3)', background:'none', border:'1px solid var(--border)', borderRadius:6, padding:'3px 9px', cursor:'pointer' }}>📋 Pegar en masa</button>
                  <button onClick={addOption} style={{ fontSize:11, color:'var(--green)', background:'none', border:'none', cursor:'pointer', fontWeight:600 }}>+ Agregar</button>
                </div>
              </div>
              <div style={{ maxHeight:200, overflowY:'auto', display:'flex', flexDirection:'column', gap:4 }}>
                {(comp.options||[]).map((o, i) => (
                  <div key={o.id} style={{ display:'flex', gap:5 }}>
                    <input style={{ ...S.input, fontSize:11, flex:1, padding:'6px 10px' }} value={o.title} onChange={e => updateOption(i, e.target.value)} placeholder={`Opción ${i+1}`} />
                    <button onClick={() => removeOption(i)} style={{ background:'none', border:'none', cursor:'pointer', color:'var(--danger)', fontSize:13, padding:'0 4px', flexShrink:0 }}>✕</button>
                  </div>
                ))}
              </div>
              {!(comp.options||[]).length && (
                <div style={{ fontSize:12, color:'var(--muted)', fontStyle:'italic', textAlign:'center', padding:'8px 0' }}>Sin opciones. Usá "Pegar en masa" para agregar muchas a la vez.</div>
              )}
            </div>
          )}
        </div>
      )}
    </div>
  );
}

function FlowScreenPanel({ screen, onChange, allScreenIds }) {
  function addComp(type) {
    const nc = { id: genCId(), type, text:'', name:'', label:'', required:false, options:[] };
    onChange({ ...screen, components: [...screen.components, nc] });
  }
  function updateComp(idx, updated) {
    onChange({ ...screen, components: screen.components.map((c,i) => i===idx ? updated : c) });
  }
  function removeComp(idx) {
    onChange({ ...screen, components: screen.components.filter((_,i) => i!==idx) });
  }
  function moveComp(idx, dir) {
    const comps = [...screen.components];
    const to = idx + dir;
    if (to < 0 || to >= comps.length) return;
    [comps[idx], comps[to]] = [comps[to], comps[idx]];
    onChange({ ...screen, components: comps });
  }

  return (
    <div style={{ display:'flex', flexDirection:'column', gap:14 }}>
      {/* Screen meta */}
      <div style={{ ...S.card, padding:'16px 20px' }}>
        <div style={{ display:'flex', gap:12, marginBottom:12 }}>
          <div style={{ flex:1 }}>
            <label style={S.label}>ID de pantalla (sin espacios)</label>
            <input style={{ ...S.input, fontSize:12, fontFamily:'monospace' }} value={screen.id}
              onChange={e => onChange({ ...screen, id: e.target.value.toUpperCase().replace(/[^A-Z0-9_]/g,'_') })}
              placeholder="PANTALLA_1" />
          </div>
          <div style={{ flex:1 }}>
            <label style={S.label}>Título visible en la pantalla</label>
            <input style={{ ...S.input, fontSize:12 }} value={screen.title}
              onChange={e => onChange({ ...screen, title: e.target.value })}
              placeholder="Tu sede Megatlon" />
          </div>
        </div>
        <div style={{ display:'flex', alignItems:'center', gap:8 }}>
          <Toggle on={!!screen.isTerminal} onChange={v => onChange({
            ...screen, isTerminal: v,
            footer: { ...screen.footer, action: v?'complete':'navigate', label: v?'Volver al chat':screen.footer.label }
          })} />
          <span style={{ fontSize:13, color:'var(--ink-2)' }}>🏁 Pantalla terminal (última — cierra el flow y vuelve al chat)</span>
        </div>
      </div>

      {/* Components */}
      <div style={{ ...S.card, padding:'16px 20px' }}>
        <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between', marginBottom:12 }}>
          <div style={{ fontSize:14, fontWeight:700 }}>Componentes</div>
          <select style={{ ...S.select, width:'auto', fontSize:12, padding:'6px 12px' }}
            value="" onChange={e => { if (e.target.value) addComp(e.target.value); }}>
            <option value="">+ Agregar componente...</option>
            {COMP_TYPES.map(t => <option key={t.value} value={t.value}>{t.label}</option>)}
          </select>
        </div>
        {screen.components.length === 0 && (
          <div style={{ textAlign:'center', padding:'24px 0', color:'var(--muted)', fontSize:13, fontStyle:'italic' }}>
            Sin componentes. Seleccioná uno del menú de arriba para comenzar.
          </div>
        )}
        {screen.components.map((c, i) => (
          <FlowCompEditor key={c.id} comp={c}
            onChange={u => updateComp(i, u)}
            onDelete={() => removeComp(i)}
            onMoveUp={() => moveComp(i, -1)}
            onMoveDown={() => moveComp(i, 1)}
            isFirst={i===0} isLast={i===screen.components.length-1}
          />
        ))}
      </div>

      {/* Footer */}
      <div style={{ ...S.card, padding:'16px 20px' }}>
        <div style={{ fontSize:14, fontWeight:700, marginBottom:12 }}>Botón del footer</div>
        <div style={{ display:'flex', gap:12 }}>
          <div style={{ flex:1 }}>
            <label style={S.label}>Texto del botón</label>
            <input style={{ ...S.input, fontSize:12 }} value={screen.footer.label}
              onChange={e => onChange({ ...screen, footer: { ...screen.footer, label: e.target.value } })}
              placeholder={screen.isTerminal ? 'Volver al chat' : 'Siguiente'} />
          </div>
          {!screen.isTerminal && (
            <div style={{ flex:1 }}>
              <label style={S.label}>Ir a pantalla</label>
              <select style={{ ...S.select, fontSize:12 }} value={screen.footer.nextScreen||''}
                onChange={e => onChange({ ...screen, footer: { ...screen.footer, nextScreen: e.target.value } })}>
                <option value="">— elegir pantalla destino —</option>
                {allScreenIds.filter(id => id !== screen.id).map(id => <option key={id} value={id}>{id}</option>)}
              </select>
            </div>
          )}
        </div>
      </div>
    </div>
  );
}

function FlowCredentialsModal({ onSave, onCancel }) {
  const [wabaId, setWabaId]         = useState('');
  const [token, setToken]           = useState('');
  const [wabaAccounts, setWabaAccounts] = useState(null); // null=loading, []= none, [...]= list
  const [hasMetaInteg, setHasMetaInteg] = useState(false);
  const [loadingWabas, setLoadingWabas] = useState(false);
  const [saving, setSaving]         = useState(false);
  const [error, setError]           = useState('');

  useEffect(() => {
    apiFetch('/api/wa-flows/config/credentials').then(r => r.json()).then(d => {
      if (d.wabaId) setWabaId(d.wabaId);
      setHasMetaInteg(!!d.hasMetaIntegration);
      // Auto-fetch WABA accounts if Meta integration exists
      if (d.hasMetaIntegration) fetchWabaAccounts();
    }).catch(() => {});
  }, []);

  async function fetchWabaAccounts() {
    setLoadingWabas(true); setError('');
    try {
      const res = await apiFetch('/api/wa-flows/config/waba-accounts');
      const data = await res.json();
      if (!res.ok) throw new Error(data.error || 'Error buscando cuentas');
      setWabaAccounts(data);
      // Auto-select if only one
      if (data.length === 1) setWabaId(data[0].id);
    } catch(e) { setError(e.message); setWabaAccounts([]); }
    finally { setLoadingWabas(false); }
  }

  async function handleSave() {
    if (!wabaId.trim()) { setError('Seleccioná o ingresá un WABA ID.'); return; }
    // token is optional if Meta integration already has one
    setSaving(true); setError('');
    try {
      const body = { metaWabaId: wabaId.trim() };
      if (token.trim()) body.metaFlowToken = token.trim();
      const res = await apiFetch('/api/wa-flows/config/credentials', {
        method:'PATCH', headers:{'Content-Type':'application/json'},
        body: JSON.stringify(body)
      });
      if (!res.ok) throw new Error('Error guardando');
      onSave();
    } catch(e) { setError(e.message); setSaving(false); }
  }

  return (
    <div style={{ position:'fixed', inset:0, background:'rgba(0,0,0,.6)', zIndex:1200, display:'flex', alignItems:'center', justifyContent:'center' }}>
      <div style={{ background:'white', borderRadius:16, padding:28, width:500, maxWidth:'94vw', boxShadow:'0 24px 64px rgba(0,0,0,.25)' }}>
        <h3 style={{ fontSize:16, fontWeight:700, marginBottom:6 }}>🔑 Configurar cuenta WhatsApp Business</h3>

        {/* Meta integration detected */}
        {hasMetaInteg && (
          <div style={{ background:'var(--green-light)', borderRadius:10, padding:'10px 14px', marginBottom:16, fontSize:13, color:'var(--green-hover)' }}>
            ✅ <strong>Token de Meta detectado</strong> — se usará tu conexión de Meta Ads existente. Solo elegí la cuenta de WhatsApp Business.
          </div>
        )}
        {!hasMetaInteg && (
          <p style={{ fontSize:13, color:'var(--muted)', marginBottom:16, lineHeight:1.55 }}>
            Necesitás conectar Meta en <strong>Integraciones</strong>, o ingresar un token con permiso <code style={{ background:'#f3f4f6', padding:'1px 4px', borderRadius:4, fontSize:11 }}>whatsapp_business_management</code>.
          </p>
        )}

        <div style={{ display:'flex', flexDirection:'column', gap:12 }}>
          {/* WABA selector */}
          <div>
            <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between', marginBottom:5 }}>
              <label style={{ ...S.label, marginBottom:0 }}>WhatsApp Business Account</label>
              {hasMetaInteg && (
                <button onClick={fetchWabaAccounts} disabled={loadingWabas}
                  style={{ fontSize:11, color:'var(--green)', background:'none', border:'none', cursor:'pointer', fontWeight:600 }}>
                  {loadingWabas ? '⏳ Buscando...' : '↻ Actualizar lista'}
                </button>
              )}
            </div>
            {wabaAccounts && wabaAccounts.length > 0 ? (
              <select style={S.select} value={wabaId} onChange={e => setWabaId(e.target.value)}>
                <option value="">— Seleccioná tu cuenta —</option>
                {wabaAccounts.map(a => (
                  <option key={a.id} value={a.id}>{a.name} ({a.id})</option>
                ))}
              </select>
            ) : (
              <input style={S.input} value={wabaId} onChange={e => setWabaId(e.target.value)}
                placeholder={loadingWabas ? 'Buscando cuentas...' : '636424209287516'} disabled={loadingWabas} />
            )}
            {wabaAccounts && wabaAccounts.length === 0 && !loadingWabas && (
              <div style={{ fontSize:11, color:'var(--muted)', marginTop:4 }}>No se encontraron cuentas con este token. Ingresá el ID manualmente.</div>
            )}
          </div>

          {/* Token — only show if no Meta integration */}
          {!hasMetaInteg && (
            <div>
              <label style={S.label}>Token de Meta (con whatsapp_business_management)</label>
              <input style={S.input} type="password" value={token} onChange={e => setToken(e.target.value)} placeholder="EAABx0..." />
            </div>
          )}
          {/* Optional: override token even if Meta integration exists */}
          {hasMetaInteg && (
            <details style={{ fontSize:12, color:'var(--muted)' }}>
              <summary style={{ cursor:'pointer' }}>Usar un token diferente (opcional)</summary>
              <div style={{ marginTop:8 }}>
                <input style={{ ...S.input, fontSize:12 }} type="password" value={token} onChange={e => setToken(e.target.value)} placeholder="EAABx0... (deja vacío para usar el de Meta Ads)" />
              </div>
            </details>
          )}

          {error && <div style={{ fontSize:12, color:'var(--danger)', lineHeight:1.4 }}>{error}</div>}
          <div style={{ display:'flex', gap:10, justifyContent:'flex-end', marginTop:4 }}>
            <button onClick={onCancel} style={S.outlineBtn}>Cancelar</button>
            <button onClick={handleSave} disabled={saving || !wabaId.trim()} style={S.btnPrimary}>
              {saving ? 'Guardando...' : 'Guardar'}
            </button>
          </div>
        </div>
      </div>
    </div>
  );
}

function ImportJsonModal({ onImport, onCancel }) {
  const [text, setText] = useState('');
  const [error, setError] = useState('');

  function handleImport() {
    setError('');
    try {
      onImport(text.trim());
    } catch(e) { setError(e.message); }
  }

  return (
    <div style={{ position:'fixed', inset:0, background:'rgba(0,0,0,.65)', zIndex:1200, display:'flex', alignItems:'center', justifyContent:'center' }}>
      <div style={{ background:'white', borderRadius:16, padding:28, width:660, maxWidth:'94vw', boxShadow:'0 24px 64px rgba(0,0,0,.25)' }}>
        <h3 style={{ fontSize:16, fontWeight:700, marginBottom:6 }}>📥 Importar WhatsApp Flow JSON</h3>
        <p style={{ fontSize:13, color:'var(--muted)', marginBottom:14, lineHeight:1.55 }}>
          Pegá un JSON estándar de WhatsApp Flow (versión 6.x). Las pantallas, componentes y opciones se van a cargar automáticamente en el editor.
        </p>
        <textarea
          style={{ ...S.textarea, minHeight:260, fontFamily:'monospace', fontSize:11, lineHeight:1.5 }}
          value={text}
          onChange={e => setText(e.target.value)}
          placeholder={'{\n  "version": "6.1",\n  "screens": [...]\n}'}
        />
        {error && <div style={{ fontSize:12, color:'var(--danger)', marginTop:8, lineHeight:1.4 }}>{error}</div>}
        <div style={{ display:'flex', gap:10, justifyContent:'flex-end', marginTop:14 }}>
          <button onClick={onCancel} style={S.outlineBtn}>Cancelar</button>
          <button onClick={handleImport} disabled={!text.trim()} style={S.btnPrimary}>Cargar en el editor</button>
        </div>
      </div>
    </div>
  );
}

function FlowEditorModal({ flow: initialFlow, onSave, onCancel, onPublish }) {
  const [flow, setFlow] = useState(() => ({
    ...initialFlow,
    screens: (initialFlow.screens && initialFlow.screens.length)
      ? initialFlow.screens.map(s => ({ ...s, components: s.components||[] }))
      : [{ id:'PANTALLA_1', title:'Pantalla 1', isTerminal:true, components:[], footer:{ label:'Volver al chat', action:'complete', nextScreen:'' } }]
  }));
  const [activeIdx, setActiveIdx] = useState(0);
  const [saving, setSaving]       = useState(false);
  const [publishing, setPublishing] = useState(false);
  const [error, setError]         = useState('');
  const [showCreds, setShowCreds] = useState(false);
  const [previewJson, setPreviewJson] = useState(null);
  const [showImport, setShowImport] = useState(false);

  function importFromJson(rawText) {
    try {
      const json = JSON.parse(rawText);
      const metaScreens = json.screens || [];
      if (!metaScreens.length) throw new Error('El JSON no tiene pantallas (screens).');
      const screens = metaScreens.map(s => {
        const children = s.layout?.children || [];
        const footerChild = children.find(c => c.type === 'Footer');
        const compChildren = children.filter(c => c.type !== 'Footer');
        const action = footerChild?.['on-click-action'] || {};
        const isTerminal = !!(s.terminal || action.name === 'complete');
        const components = compChildren.map(c => {
          const comp = { id: genCId(), type: c.type || 'TextBody' };
          if (c.text   !== undefined) comp.text      = c.text;
          if (c.name   !== undefined) comp.name      = c.name;
          if (c.label  !== undefined) comp.label     = c.label;
          if (c.required !== undefined) comp.required = c.required;
          if (c['helper-text'])  comp.helperText = c['helper-text'];
          if (c['input-type'])   comp.inputType  = c['input-type'];
          if (c['data-source'])  comp.options = c['data-source'].map(o => ({ id: o.id || genCId(), title: o.title }));
          return comp;
        });
        return {
          id: s.id,
          title: s.title || s.id,
          isTerminal,
          components,
          footer: {
            label: footerChild?.label || (isTerminal ? 'Volver al chat' : 'Siguiente'),
            action: isTerminal ? 'complete' : 'navigate',
            nextScreen: action.next?.name || '',
          },
        };
      });
      setFlow(f => ({ ...f, screens }));
      setActiveIdx(0);
      setShowImport(false);
      setError('');
    } catch(e) {
      throw new Error('JSON inválido: ' + e.message);
    }
  }

  const activeScreen = flow.screens[Math.min(activeIdx, flow.screens.length-1)];
  const allScreenIds = flow.screens.map(s => s.id);

  function addScreen() {
    const n = flow.screens.length + 1;
    const ns = { id:`PANTALLA_${n}`, title:`Pantalla ${n}`, isTerminal:false, components:[], footer:{ label:'Siguiente', action:'navigate', nextScreen:'' } };
    const screens = [...flow.screens, ns];
    setFlow({ ...flow, screens });
    setActiveIdx(screens.length - 1);
  }

  function removeScreen(idx) {
    if (flow.screens.length <= 1) return;
    const screens = flow.screens.filter((_,i) => i !== idx);
    setFlow({ ...flow, screens });
    setActiveIdx(Math.min(activeIdx, screens.length - 1));
  }

  function updateScreen(idx, updated) {
    setFlow({ ...flow, screens: flow.screens.map((s,i) => i===idx ? updated : s) });
  }

  async function handleSave() {
    setSaving(true); setError('');
    try {
      const isNew = !flow.id || flow._isNew;
      const url = isNew ? '/api/wa-flows' : `/api/wa-flows/${flow.id}`;
      const method = isNew ? 'POST' : 'PUT';
      const res = await apiFetch(url, { method, headers:{'Content-Type':'application/json'},
        body: JSON.stringify({ name: flow.name, screens: flow.screens }) });
      if (!res.ok) { const e = await res.json(); throw new Error(e.error || 'Error guardando'); }
      const saved = await res.json();
      onSave(saved);
    } catch(e) { setError(e.message); }
    finally { setSaving(false); }
  }

  async function handlePublish(skipSaveFirst) {
    if (!flow.id || flow._isNew) { setError('Guardá el flow primero antes de publicar.'); return; }
    setPublishing(true); setError('');
    try {
      const res = await apiFetch(`/api/wa-flows/${flow.id}/publish`, {
        method:'POST', headers:{'Content-Type':'application/json'}, body:'{}'
      });
      const e = await res.json();
      if (!res.ok) {
        if ((e.error||'').toLowerCase().includes('credencial') || (e.error||'').toLowerCase().includes('token') || (e.error||'').toLowerCase().includes('waba')) {
          setShowCreds(true); setPublishing(false); return;
        }
        // Show full Meta error + detail if available
        const detail = e.detail ? JSON.stringify(e.detail, null, 2) : null;
        setError(e.error || 'Error publicando');
        if (detail) setPreviewJson('// ERROR DETAIL:\n' + detail);
        setPublishing(false); return;
      }
      onPublish && onPublish(e);
    } catch(e) { setError(e.message); }
    finally { setPublishing(false); }
  }

  async function loadPreviewJson() {
    if (!flow.id || flow._isNew) { setError('Guardá el flow primero para ver el JSON.'); return; }
    try {
      const res = await apiFetch(`/api/wa-flows/${flow.id}/preview-json`);
      const data = await res.json();
      setPreviewJson(JSON.stringify(data, null, 2));
    } catch(e) { setError('Error cargando JSON'); }
  }

  return (
    <div style={{ position:'fixed', inset:0, background:'rgba(15,26,20,.6)', zIndex:900, display:'flex', flexDirection:'column' }}>
      {showCreds && <FlowCredentialsModal onSave={() => { setShowCreds(false); handlePublish(); }} onCancel={() => setShowCreds(false)} />}
      {showImport && <ImportJsonModal onImport={importFromJson} onCancel={() => setShowImport(false)} />}
      {previewJson && (
        <div style={{ position:'fixed', inset:0, background:'rgba(0,0,0,.75)', zIndex:1100, display:'flex', alignItems:'center', justifyContent:'center' }}>
          <div style={{ background:'#1e1e2e', color:'#cdd6f4', borderRadius:12, padding:24, width:700, maxWidth:'92vw', maxHeight:'82vh', overflow:'auto', position:'relative' }}>
            <button onClick={() => setPreviewJson(null)} style={{ position:'absolute', top:12, right:16, background:'none', border:'none', color:'#aaa', fontSize:20, cursor:'pointer' }}>✕</button>
            <div style={{ fontSize:13, fontWeight:700, color:'#89b4fa', marginBottom:12 }}>📋 WhatsApp Flow JSON (v6.1)</div>
            <pre style={{ fontSize:11, lineHeight:1.6, whiteSpace:'pre-wrap', wordBreak:'break-word', margin:0 }}>{previewJson}</pre>
          </div>
        </div>
      )}

      {/* Header */}
      <div style={{ background:'white', borderBottom:'1px solid var(--border)', padding:'12px 20px', display:'flex', alignItems:'center', gap:12, flexShrink:0, boxShadow:'0 1px 4px rgba(0,0,0,.06)' }}>
        <button onClick={onCancel} style={{ background:'none', border:'none', cursor:'pointer', color:'var(--muted)', fontSize:20, padding:'0 4px', lineHeight:1 }}>←</button>
        <input style={{ ...S.input, maxWidth:320, fontSize:14, fontWeight:600 }} value={flow.name}
          onChange={e => setFlow({ ...flow, name: e.target.value })} placeholder="Nombre del flow" />
        <div style={{ flex:1 }} />
        {error && <div style={{ fontSize:12, color:'var(--danger)', maxWidth:300, lineHeight:1.3 }}>{error}</div>}
        <button onClick={() => setShowImport(true)} style={{ ...S.outlineBtn, fontSize:12, padding:'6px 14px' }}>📥 Importar JSON</button>
        <button onClick={loadPreviewJson} style={{ ...S.outlineBtn, fontSize:12, padding:'6px 14px' }}>{'{ }'} Ver JSON</button>
        <button onClick={handleSave} disabled={saving} style={{ ...S.btnPrimary, fontSize:12, padding:'7px 18px' }}>
          {saving ? 'Guardando...' : '💾 Guardar borrador'}
        </button>
        {flow.id && !flow._isNew && (
          <button onClick={() => handlePublish()} disabled={publishing} style={{ ...S.btnPrimary, fontSize:12, padding:'7px 18px', background:'#075e54' }}>
            {publishing ? 'Publicando...' : '🚀 Publicar en Meta'}
          </button>
        )}
      </div>

      {/* Body: 3 panels */}
      <div style={{ flex:1, display:'flex', overflow:'hidden' }}>

        {/* Left: screen list */}
        <div style={{ width:210, background:'white', borderRight:'1px solid var(--border)', display:'flex', flexDirection:'column', flexShrink:0 }}>
          <div style={{ padding:'12px 14px 8px', fontSize:10, fontWeight:700, color:'var(--ink-4)', textTransform:'uppercase', letterSpacing:.9 }}>Pantallas</div>
          <div style={{ flex:1, overflowY:'auto', padding:'0 8px' }}>
            {flow.screens.map((s, i) => (
              <div key={s.id+i} style={{ display:'flex', alignItems:'center', gap:3, marginBottom:3 }}>
                <button onClick={() => setActiveIdx(i)} style={{
                  flex:1, padding:'8px 10px', border:'none', borderRadius:8, cursor:'pointer', textAlign:'left',
                  background: i===activeIdx ? 'var(--green-light)' : 'transparent',
                  color: i===activeIdx ? 'var(--green)' : 'var(--ink-2)',
                  fontWeight: i===activeIdx ? 600 : 400 }}>
                  <div style={{ fontSize:10, color: i===activeIdx?'var(--green)':'var(--muted)', marginBottom:1 }}>
                    {s.isTerminal ? '🏁 terminal' : `→ ${s.footer?.nextScreen||'?'}`}
                  </div>
                  <div style={{ fontSize:12, lineHeight:1.3 }}>{s.id}</div>
                </button>
                <button onClick={() => removeScreen(i)} disabled={flow.screens.length<=1}
                  style={{ background:'none', border:'none', cursor:'pointer', color:'var(--danger)', fontSize:13, padding:'0 4px', opacity:flow.screens.length<=1?.3:1, flexShrink:0 }}>✕</button>
              </div>
            ))}
          </div>
          <div style={{ padding:'8px 12px 14px' }}>
            <button onClick={addScreen} style={{ width:'100%', padding:'8px 0', background:'var(--green-light)', color:'var(--green)', border:'none', borderRadius:8, cursor:'pointer', fontSize:12, fontWeight:600 }}>
              + Nueva pantalla
            </button>
          </div>
        </div>

        {/* Center: screen editor */}
        <div style={{ flex:1, overflowY:'auto', padding:20, background:'var(--cream)' }}>
          {activeScreen
            ? <FlowScreenPanel screen={activeScreen} onChange={u => updateScreen(activeIdx, u)} allScreenIds={allScreenIds} />
            : <div style={{ textAlign:'center', padding:'48px', color:'var(--muted)' }}>Seleccioná una pantalla</div>
          }
        </div>

        {/* Right: phone preview */}
        <div style={{ width:264, background:'#dfe8e4', borderLeft:'1px solid #c8d5cf', padding:16, display:'flex', flexDirection:'column', gap:10, overflowY:'auto', flexShrink:0 }}>
          <div style={{ fontSize:10, fontWeight:700, color:'#666', textTransform:'uppercase', letterSpacing:.9 }}>Vista previa WhatsApp</div>
          <div style={{ display:'flex', gap:4, flexWrap:'wrap' }}>
            {flow.screens.map((s, i) => (
              <button key={s.id+i} onClick={() => setActiveIdx(i)} style={{
                fontSize:10, padding:'2px 8px', borderRadius:99, border:'none', cursor:'pointer',
                background: i===activeIdx?'#075e54':'rgba(255,255,255,.7)',
                color: i===activeIdx?'white':'#555', fontWeight: i===activeIdx?600:400 }}>
                {i+1}. {s.id.length > 8 ? s.id.slice(0,8)+'…' : s.id}
              </button>
            ))}
          </div>
          <WaFlowScreenPreview screen={activeScreen} />
          <div style={{ fontSize:10, color:'#888', textAlign:'center', lineHeight:1.4 }}>
            Preview aproximado — la UI real varía según el dispositivo.
          </div>
        </div>
      </div>
    </div>
  );
}

function FlowsPanel() {
  const [flows, setFlows]         = useState(null);
  const [editing, setEditing]     = useState(null);
  const [confirmDel, setConfirmDel] = useState(null);
  const [publishing, setPublishing] = useState(null);
  const [pubResult, setPubResult] = useState(null);
  const [showCreds, setShowCreds] = useState(false);

  function load() {
    apiFetch('/api/wa-flows').then(r => r.json()).then(d => setFlows(Array.isArray(d)?d:[])).catch(() => setFlows([]));
  }

  useEffect(() => { load(); }, []);

  async function doDelete(id) {
    await apiFetch(`/api/wa-flows/${id}`, { method:'DELETE' });
    setConfirmDel(null); load();
  }

  async function doDuplicate(flow) {
    const copy = JSON.parse(JSON.stringify(flow));
    delete copy.id; delete copy.metaFlowId; delete copy.createdAt; delete copy.updatedAt;
    copy.name   = `${flow.name} (copia)`;
    copy.status = 'draft';
    await apiFetch('/api/wa-flows', {
      method:'POST', headers:{'Content-Type':'application/json'}, body: JSON.stringify(copy),
    });
    load();
  }

  async function quickPublish(flow) {
    setPublishing(flow.id); setPubResult(null);
    try {
      const res = await apiFetch(`/api/wa-flows/${flow.id}/publish`, {
        method:'POST', headers:{'Content-Type':'application/json'}, body:'{}'
      });
      const data = await res.json();
      if (!res.ok) throw new Error(data.error || 'Error publicando');
      setPubResult({ ok:true, msg:`✅ Flow publicado en Meta (ID: ${data.metaFlowId})`, flowId:flow.id });
      load();
    } catch(e) {
      setPubResult({ ok:false, msg:`❌ ${e.message}`, flowId:flow.id });
    } finally { setPublishing(null); }
  }

  return (
    <div style={{ flex:1, overflowY:'auto', background:'var(--cream)' }}>
      {showCreds && <FlowCredentialsModal onSave={() => setShowCreds(false)} onCancel={() => setShowCreds(false)} />}
      {editing && (
        <FlowEditorModal
          flow={editing}
          onSave={() => { setEditing(null); load(); }}
          onCancel={() => setEditing(null)}
          onPublish={() => { setEditing(null); load(); }}
        />
      )}
      {confirmDel && (
        <div style={{ position:'fixed', inset:0, background:'rgba(0,0,0,.45)', zIndex:800, display:'flex', alignItems:'center', justifyContent:'center' }}>
          <div style={{ background:'white', borderRadius:14, padding:28, width:380, boxShadow:'0 12px 40px rgba(0,0,0,.2)' }}>
            <h3 style={{ fontSize:15, fontWeight:700, marginBottom:10 }}>¿Eliminar este flow?</h3>
            <p style={{ fontSize:13, color:'var(--muted)', marginBottom:20, lineHeight:1.5 }}>Se elimina del dashboard. Si ya fue publicado en Meta, seguirá existiendo allí con su Flow ID.</p>
            <div style={{ display:'flex', gap:10, justifyContent:'flex-end' }}>
              <button onClick={() => setConfirmDel(null)} style={S.outlineBtn}>Cancelar</button>
              <button onClick={() => doDelete(confirmDel)} style={{ ...S.btnPrimary, background:'var(--danger)', boxShadow:'none' }}>Eliminar</button>
            </div>
          </div>
        </div>
      )}

      <div style={{ maxWidth:860, margin:'0 auto', padding:'32px 28px' }}>
        {/* Header */}
        <div style={{ display:'flex', alignItems:'flex-start', justifyContent:'space-between', gap:16, marginBottom:24 }}>
          <div>
            <h2 style={S.pageTitle}>📱 WhatsApp Flows</h2>
            <p style={S.pageSubtitle}>
              Formularios nativos de WhatsApp con pantallas, campos de texto, menús desplegables y más.
              Publicados en Meta y enviados directamente desde el agente o campañas.
            </p>
          </div>
          <div style={{ display:'flex', gap:8 }}>
            <button onClick={() => setShowCreds(true)} style={{ ...S.outlineBtn, fontSize:12, padding:'7px 14px' }}>🔑 Credenciales Meta</button>
            <button onClick={() => setEditing({ _isNew:true, name:'Nuevo Flow', screens:[], status:'draft' })} style={S.btnPrimary}>+ Nuevo Flow</button>
          </div>
        </div>

        {/* Publish result banner */}
        {pubResult && (
          <div style={{ marginBottom:16, padding:'12px 16px', borderRadius:10,
            background: pubResult.ok?'var(--green-light)':'var(--danger-light)',
            color: pubResult.ok?'var(--green)':'var(--danger)',
            fontSize:13, display:'flex', alignItems:'center', justifyContent:'space-between', gap:12 }}>
            <span>{pubResult.msg}</span>
            <button onClick={() => setPubResult(null)} style={{ background:'none', border:'none', cursor:'pointer', fontSize:16, color:'inherit', flexShrink:0 }}>✕</button>
          </div>
        )}

        {/* Loading */}
        {flows === null && <div style={{ textAlign:'center', padding:'48px', color:'var(--muted)' }}>Cargando...</div>}

        {/* Empty */}
        {flows !== null && flows.length === 0 && (
          <div style={{ textAlign:'center', padding:'64px 24px', background:'var(--surface)', border:'1.5px dashed var(--border)', borderRadius:'var(--r-lg)' }}>
            <div style={{ fontSize:48, marginBottom:14 }}>📱</div>
            <h3 style={{ fontSize:17, fontWeight:700, marginBottom:8 }}>Sin flows todavía</h3>
            <p style={{ color:'var(--muted)', fontSize:13.5, marginBottom:24, lineHeight:1.65, maxWidth:440, margin:'0 auto 24px' }}>
              Creá formularios nativos de WhatsApp: menús con buscador, campos de texto, fechas y más.
              El agente puede enviarlos y las respuestas quedan guardadas como atributos del contacto.
            </p>
            <button onClick={() => setEditing({ _isNew:true, name:'Nuevo Flow', screens:[], status:'draft' })} style={S.btnPrimary}>
              + Crear primer Flow
            </button>
          </div>
        )}

        {/* Flow list */}
        <div style={{ display:'flex', flexDirection:'column', gap:12 }}>
          {(flows||[]).map(flow => {
            const isPublished = flow.status === 'published';
            const isPublishingThis = publishing === flow.id;
            const totalFields = (flow.screens||[]).reduce((a,s) => a + (s.components||[]).filter(c=>c.name).length, 0);
            return (
              <div key={flow.id} style={{ ...S.card, display:'flex', alignItems:'flex-start', gap:16 }}>
                <div style={{ fontSize:32, flexShrink:0, marginTop:2 }}>📋</div>
                <div style={{ flex:1, minWidth:0 }}>
                  <div style={{ display:'flex', alignItems:'center', gap:8, flexWrap:'wrap', marginBottom:5 }}>
                    <span style={{ fontWeight:700, fontSize:15 }}>{flow.name}</span>
                    <span style={{ fontSize:11, fontWeight:600, padding:'2px 9px', borderRadius:99,
                      background: isPublished?'var(--green-light)':'#FEF3C7',
                      color: isPublished?'var(--green)':'#92400E' }}>
                      {isPublished ? '✅ Publicado' : '📝 Borrador'}
                    </span>
                    {flow.metaFlowId && (
                      <span style={{ fontSize:11, color:'var(--muted)', fontFamily:'monospace' }}>Meta: {flow.metaFlowId}</span>
                    )}
                  </div>
                  <div style={{ fontSize:12, color:'var(--muted)', marginBottom:8 }}>
                    {(flow.screens||[]).length} pantalla{(flow.screens||[]).length!==1?'s':''} · {totalFields} campo{totalFields!==1?'s':''}
                    {' · '}Actualizado {new Date(flow.updatedAt).toLocaleDateString('es-AR',{day:'2-digit',month:'2-digit',year:'2-digit'})}
                  </div>
                  <div style={{ display:'flex', flexWrap:'wrap', gap:4 }}>
                    {(flow.screens||[]).map(s => (
                      <span key={s.id} style={{ fontSize:11, padding:'2px 8px', borderRadius:99, background:'var(--cream-mid)', color:'var(--ink-2)' }}>
                        {s.isTerminal?'🏁':'→'} {s.id}
                      </span>
                    ))}
                  </div>
                </div>
                <div style={{ display:'flex', gap:8, flexShrink:0, alignItems:'center', flexWrap:'wrap', justifyContent:'flex-end' }}>
                  <button onClick={() => setEditing(flow)} style={{ ...S.outlineBtn, fontSize:12, padding:'6px 14px' }}>✏️ Editar</button>
                  <button onClick={() => doDuplicate(flow)} style={{ ...S.outlineBtn, fontSize:12, padding:'6px 14px' }}>📋 Duplicar</button>
                  {!isPublished && (
                    <button onClick={() => quickPublish(flow)} disabled={isPublishingThis}
                      style={{ ...S.btnPrimary, fontSize:12, padding:'6px 14px', background:'#075e54' }}>
                      {isPublishingThis ? '⏳' : '🚀 Publicar'}
                    </button>
                  )}
                  <button onClick={() => setConfirmDel(flow.id)} style={{ ...S.dangerBtn, fontSize:12, padding:'6px 12px' }}>🗑</button>
                </div>
              </div>
            );
          })}
        </div>

        {/* How-to tip */}
        {flows && flows.length > 0 && (
          <div style={{ marginTop:24, padding:'16px 20px', background:'var(--green-light)', borderRadius:'var(--r)', fontSize:13, color:'var(--green-hover)', lineHeight:1.65 }}>
            <strong>💡 Cómo usar:</strong> En el editor del agente, campañas o promociones, elegí tipo <em>📋 WhatsApp Flow</em> y pegá el <strong>Meta Flow ID</strong> que aparece acá después de publicar. Las respuestas del usuario se guardan automáticamente como atributos del contacto en Pipochat.
          </div>
        )}
      </div>
    </div>
  );
}

function WebhookPanel() {
  const [webhooks, setWebhooks] = useState([]);
  const [showNew, setShowNew]   = useState(false);
  const [logs, setLogs]         = useState([]);
  const [activeTab, setActiveTab] = useState('webhooks');

  const load = () => {
    apiFetch('/api/webhooks').then(r => r.json()).then(d => setWebhooks(d.webhooks || [])).catch(() => {});
    apiFetch('/api/webhooks/logs').then(r => r.json()).then(d => setLogs(d.logs || [])).catch(() => {});
  };

  useEffect(() => { load(); }, []);

  const toggle = async (id, enabled) => {
    await apiFetch(`/api/webhooks/${id}`, { method:'PUT', headers:{'Content-Type':'application/json'}, body: JSON.stringify({ enabled }) });
    load();
  };

  const del = async (id) => {
    if (!confirm('¿Eliminar este webhook?')) return;
    await apiFetch(`/api/webhooks/${id}`, { method:'DELETE' });
    load();
  };

  const testWebhook = async (id) => {
    await apiFetch(`/api/webhooks/${id}/test`, { method:'POST' });
    setTimeout(load, 500);
  };

  return (
    <div style={S.editor}>
      {/* Header */}
      <div style={{ display:'flex', alignItems:'flex-start', justifyContent:'space-between', gap:16 }}>
        <div>
          <div style={S.pageTitle}>🔗 Webhooks salientes</div>
          <div style={S.pageSubtitle}>Enviá eventos a Zapier, Make, n8n o cualquier URL cuando algo pase en LoopLead.</div>
        </div>
        <button style={{ ...S.saveBtn, flexShrink:0 }} onClick={() => setShowNew(true)}>+ Nuevo webhook</button>
      </div>

      {/* Tabs */}
      <div style={{ display:'flex', gap:0, borderBottom:'2px solid var(--border-soft)' }}>
        {['webhooks','logs'].map(t => (
          <button key={t} onClick={() => setActiveTab(t)} style={{
            padding:'9px 20px', fontSize:13, fontWeight:activeTab===t ? 700 : 500,
            color: activeTab===t ? 'var(--green)' : 'var(--ink-3)',
            background:'none', border:'none',
            borderBottom: activeTab===t ? '2px solid var(--green)' : '2px solid transparent',
            cursor:'pointer', marginBottom:-2, transition:'color var(--trans)',
          }}>{t === 'webhooks' ? 'Webhooks' : 'Historial de envíos'}</button>
        ))}
      </div>

      {activeTab === 'webhooks' && (
        <div style={{ display:'flex', flexDirection:'column', gap:10 }}>
          {webhooks.length === 0 ? (
            <div style={{ flex:1, display:'flex', alignItems:'center', justifyContent:'center', minHeight:360 }}>
              <div style={{ textAlign:'center', color:'var(--ink-3)' }}>
                <div style={{ fontSize:52, marginBottom:16 }}>🔗</div>
                <div style={{ fontWeight:700, fontSize:16, color:'var(--ink)', marginBottom:8 }}>Sin webhooks configurados</div>
                <div style={{ fontSize:13, maxWidth:300, margin:'0 auto', lineHeight:1.7 }}>Conectá LoopLead con Zapier, Make o tu propio sistema para recibir eventos en tiempo real.</div>
                <button style={{ ...S.saveBtn, marginTop:24 }} onClick={() => setShowNew(true)}>+ Crear primer webhook</button>
              </div>
            </div>
          ) : webhooks.map(w => (
            <div key={w.id} style={{ ...S.card, display:'flex', alignItems:'flex-start', gap:16 }}>
              {/* Status dot */}
              <div style={{ width:10, height:10, borderRadius:'50%', marginTop:5, flexShrink:0, background: w.enabled ? '#22C55E' : '#D1D5DB' }} />

              {/* Info */}
              <div style={{ flex:1, minWidth:0 }}>
                <div style={{ display:'flex', alignItems:'center', gap:10, flexWrap:'wrap', marginBottom:6 }}>
                  <span style={{ fontSize:14, fontWeight:700, color:'var(--ink)' }}>{w.name}</span>
                  {w.enabled
                    ? <span style={{ fontSize:11, fontWeight:600, color:'#15803D', background:'#DCFCE7', padding:'2px 9px', borderRadius:99 }}>Activo</span>
                    : <span style={{ fontSize:11, fontWeight:600, color:'#6B7280', background:'#F3F4F6', padding:'2px 9px', borderRadius:99 }}>Inactivo</span>
                  }
                </div>
                <div style={{ fontSize:12, color:'var(--ink-3)', fontFamily:'monospace', background:'var(--cream)', padding:'5px 10px', borderRadius:7, display:'inline-block', maxWidth:'100%', overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap', marginBottom:10 }}>
                  {w.url}
                </div>
                <div style={{ display:'flex', gap:6, flexWrap:'wrap' }}>
                  {(w.events || []).map(e => {
                    const ev = WEBHOOK_EVENTS.find(x => x.value === e);
                    return (
                      <span key={e} style={{ fontSize:11, background:'var(--green-light)', color:'var(--green-hover)', padding:'3px 10px', borderRadius:99, fontWeight:500 }}>
                        {ev?.label || e}
                      </span>
                    );
                  })}
                </div>
              </div>

              {/* Actions */}
              <div style={{ display:'flex', gap:8, flexShrink:0, alignItems:'center' }}>
                <button onClick={() => testWebhook(w.id)} style={smallBtn}>🧪 Probar</button>
                <button onClick={() => toggle(w.id, !w.enabled)} style={smallBtn}>
                  {w.enabled ? '⏸ Pausar' : '▶ Activar'}
                </button>
                <button onClick={() => del(w.id)} style={smallDangerBtn}>Eliminar</button>
              </div>
            </div>
          ))}
        </div>
      )}

      {activeTab === 'logs' && (
        <div style={S.card}>
          {logs.length === 0 ? (
            <div style={{ textAlign:'center', padding:'32px 0', color:'var(--ink-3)', fontSize:13 }}>
              <div style={{ fontSize:32, marginBottom:10 }}>📭</div>
              Sin envíos aún — los registros aparecen aquí cuando se dispara un evento.
            </div>
          ) : (
            <div>
              {logs.map((l, i) => (
                <div key={i} style={{ display:'flex', alignItems:'flex-start', gap:12, padding:'11px 0', borderBottom: i < logs.length-1 ? '1px solid var(--border-soft)' : 'none' }}>
                  <span style={{ fontSize:15, flexShrink:0, marginTop:1 }}>{l.success ? '✅' : '❌'}</span>
                  <div style={{ flex:1, minWidth:0 }}>
                    <div style={{ fontSize:13, fontWeight:600, color:'var(--ink)' }}>{l.event}</div>
                    <div style={{ fontSize:12, color:'var(--ink-3)', fontFamily:'monospace', overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap' }}>{l.url}</div>
                    {l.error && <div style={{ fontSize:12, color:'#B91C1C', marginTop:2 }}>{l.error}</div>}
                    {l.statusCode && <div style={{ fontSize:11, color:'var(--ink-4)', marginTop:2 }}>HTTP {l.statusCode}</div>}
                  </div>
                  <div style={{ fontSize:11, color:'var(--ink-4)', flexShrink:0, textAlign:'right' }}>
                    {l.firedAt ? new Date(l.firedAt).toLocaleString('es-AR') : ''}
                  </div>
                </div>
              ))}
            </div>
          )}
        </div>
      )}

      {showNew && <WebhookModal onClose={() => setShowNew(false)} onSave={() => { setShowNew(false); load(); }} />}
    </div>
  );
}

function WebhookModal({ onClose, onSave }) {
  const [name, setName]     = useState('');
  const [url, setUrl]       = useState('');
  const [events, setEvents] = useState([]);
  const [secret, setSecret] = useState('');
  const [saving, setSaving] = useState(false);

  const toggleEvent = (e) => setEvents(prev => prev.includes(e) ? prev.filter(x => x !== e) : [...prev, e]);

  const save = async () => {
    if (!name.trim() || !url.trim() || events.length === 0) {
      alert('Completá nombre, URL y al menos un evento.');
      return;
    }
    setSaving(true);
    await apiFetch('/api/webhooks', { method:'POST', headers:{'Content-Type':'application/json'}, body: JSON.stringify({ name, url, events, secret }) });
    setSaving(false);
    onSave();
  };

  const overlay = { position:'fixed', inset:0, background:'rgba(0,0,0,0.45)', display:'flex', alignItems:'flex-start', justifyContent:'center', zIndex:1000, padding:'28px 16px', overflowY:'auto' };
  const sheet   = { background:'var(--white)', borderRadius:20, padding:'24px 28px', width:'100%', maxWidth:500, boxShadow:'0 24px 64px rgba(0,0,0,.18)' };

  return (
    <div style={overlay} onClick={onClose}>
      <div style={sheet} onClick={e => e.stopPropagation()}>
        <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between', marginBottom:20, paddingBottom:16, borderBottom:'1px solid var(--border-soft)' }}>
          <div style={{ fontSize:17, fontWeight:800, color:'var(--ink)' }}>Nuevo webhook</div>
          <button style={{ background:'none', border:'none', fontSize:20, color:'var(--ink-3)', cursor:'pointer', lineHeight:1, padding:'0 4px' }} onClick={onClose}>✕</button>
        </div>

        <div style={{ display:'flex', flexDirection:'column', gap:16 }}>
          <label style={S.label}>
            Nombre
            <input style={S.input} value={name} onChange={e => setName(e.target.value)} placeholder="Ej: Zapier leads calientes" />
          </label>

          <label style={S.label}>
            URL destino
            <input style={S.input} value={url} onChange={e => setUrl(e.target.value)} placeholder="https://hooks.zapier.com/..." />
          </label>

          <div>
            <div style={{ fontSize:12, fontWeight:700, color:'var(--ink-3)', textTransform:'uppercase', letterSpacing:.7, marginBottom:10 }}>Eventos que disparan el webhook</div>
            <div style={{ display:'flex', flexDirection:'column', gap:9 }}>
              {WEBHOOK_EVENTS.map(ev => (
                <label key={ev.value} style={{ display:'flex', alignItems:'center', gap:10, cursor:'pointer', fontSize:13, color:'var(--ink-2)', padding:'8px 12px', borderRadius:10, border:`1.5px solid ${events.includes(ev.value) ? 'var(--green)' : 'var(--border)'}`, background: events.includes(ev.value) ? 'var(--green-light)' : 'var(--white)', transition:'all var(--trans)' }}>
                  <input type="checkbox" checked={events.includes(ev.value)} onChange={() => toggleEvent(ev.value)} style={{ accentColor:'var(--green)', width:16, height:16, flexShrink:0 }} />
                  {ev.label}
                </label>
              ))}
            </div>
          </div>

          <label style={S.label}>
            Secret (opcional)
            <input style={S.input} value={secret} onChange={e => setSecret(e.target.value)} placeholder="Para verificar firma HMAC" />
            <span style={{ fontSize:11, color:'var(--ink-3)', marginTop:4, display:'block' }}>
              Si configurás un secret, cada request incluye el header <code>X-LoopLead-Signature</code> con HMAC-SHA256.
            </span>
          </label>
        </div>

        <div style={{ display:'flex', justifyContent:'flex-end', gap:10, marginTop:24, paddingTop:16, borderTop:'1px solid var(--border-soft)' }}>
          <button style={S.outlineBtn} onClick={onClose}>Cancelar</button>
          <button style={S.saveBtn} onClick={save} disabled={saving}>{saving ? 'Guardando…' : 'Crear webhook'}</button>
        </div>
      </div>
    </div>
  );
}

// ─── AccountPanel ─────────────────────────────────────────────────────────────
function AccountPanel({ onGoCredits }) {
  const [data,   setData]   = useState(null);
  const [err,    setErr]    = useState(false);
  const [show,   setShow]   = useState(false);   // reveal API token
  const [copied, setCopied] = useState('');

  useEffect(() => {
    apiFetch('/api/account').then(r => r.json()).then(setData).catch(() => setErr(true));
  }, []);

  const copy = (label, val) => {
    if (!val) return;
    try { navigator.clipboard?.writeText(val); setCopied(label); setTimeout(() => setCopied(''), 1500); } catch(e) {}
  };

  const mask    = (t) => !t ? '—' : (t.length <= 8 ? '••••' : t.slice(0,4) + '••••••' + t.slice(-4));
  const fmtArs  = (n) => 'ARS ' + (Number(n)||0).toLocaleString('es-AR', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
  const fmtDate = (d) => { try { return d ? new Date(d).toLocaleDateString('es-AR', { day:'2-digit', month:'2-digit', year:'numeric' }) : '—'; } catch(e){ return d || '—'; } };

  const Row = ({ label, value, copyVal, mono, last }) => (
    <div style={{ display:'flex', justifyContent:'space-between', alignItems:'center', gap:12, padding:'11px 0', borderBottom: last ? 'none' : '1px solid var(--border-soft)' }}>
      <div style={{ fontSize:12.5, color:'var(--ink-4)', flexShrink:0 }}>{label}</div>
      <div style={{ display:'flex', alignItems:'center', gap:8, minWidth:0 }}>
        <span style={{ fontSize:13, color:'var(--ink)', fontFamily: mono ? 'monospace':'inherit', overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap' }}>{value}</span>
        {copyVal && (
          <button onClick={() => copy(label, copyVal)}
            style={{ fontSize:11, color:'var(--ink-3)', background:'var(--cream)', border:'1px solid var(--border)', borderRadius:6, padding:'3px 9px', cursor:'pointer', flexShrink:0, transition:'all .15s' }}>
            {copied === label ? '✓ copiado' : 'copiar'}
          </button>
        )}
      </div>
    </div>
  );

  if (err) return (
    <div style={{ ...S.editor }}>
      <div>
        <div style={S.pageTitle}>👤 Mi cuenta</div>
        <div style={S.pageSubtitle}>Datos de tu cuenta, conexión y plan.</div>
      </div>
      <div style={{ ...S.card, color:'var(--danger)' }}>No se pudo cargar la info de la cuenta. Probá recargar la página.</div>
    </div>
  );
  if (!data) return (
    <div style={{ ...S.editor }}>
      <div>
        <div style={S.pageTitle}>👤 Mi cuenta</div>
        <div style={S.pageSubtitle}>Datos de tu cuenta, conexión y plan.</div>
      </div>
      <div style={{ ...S.card, color:'var(--ink-4)' }}>Cargando…</div>
    </div>
  );

  const b = data.billing || {};

  return (
    <div style={{ ...S.editor }}>
      <div>
        <div style={S.pageTitle}>👤 Mi cuenta</div>
        <div style={S.pageSubtitle}>Datos de tu cuenta, conexión y plan. Tocá “copiar” para llevarte cualquier dato.</div>
      </div>

      <div style={S.card}>
        <div style={S.cardTitle}>🪪 Identidad</div>
        <Row label="Nombre"    value={data.name || '—'} />
        <Row label="Tenant ID" value={'#' + data.tenantId} copyVal={data.tenantId} mono />
        <Row label="Email"     value={data.email || '—'} copyVal={data.email} />
        <Row label="Alta"      value={fmtDate(data.createdAt)} last />
      </div>

      <div style={S.card}>
        <div style={S.cardTitle}>🔌 Conexión</div>
        <Row label="Webhook URL"  value={data.webhookUrl} copyVal={data.webhookUrl} mono />
        <Row label="Pipochat API" value={data.pipochatApiUrl || '—'} copyVal={data.pipochatApiUrl} mono />
        <div style={{ display:'flex', justifyContent:'space-between', alignItems:'center', gap:12, padding:'11px 0', borderBottom:'1px solid var(--border-soft)' }}>
          <div style={{ fontSize:12.5, color:'var(--ink-4)' }}>API Token</div>
          <div style={{ display:'flex', alignItems:'center', gap:8, minWidth:0 }}>
            <span style={{ fontSize:13, fontFamily:'monospace', overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap' }}>
              {show ? (data.pipochatApiToken || '—') : mask(data.pipochatApiToken)}
            </span>
            <button onClick={() => setShow(s => !s)} style={{ fontSize:11, color:'var(--ink-3)', background:'var(--cream)', border:'1px solid var(--border)', borderRadius:6, padding:'3px 9px', cursor:'pointer', flexShrink:0 }}>{show ? 'ocultar':'ver'}</button>
            <button onClick={() => copy('API Token', data.pipochatApiToken)} style={{ fontSize:11, color:'var(--ink-3)', background:'var(--cream)', border:'1px solid var(--border)', borderRadius:6, padding:'3px 9px', cursor:'pointer', flexShrink:0 }}>{copied === 'API Token' ? '✓ copiado':'copiar'}</button>
          </div>
        </div>
        <Row label="Meta WABA ID" value={data.metaWabaId || '— (no conectado)'} copyVal={data.metaWabaId} mono last />
      </div>

      <div style={S.card}>
        <div style={S.cardTitle}>💳 Plan & créditos</div>
        <Row label="Saldo disponible"  value={fmtArs(b.balanceArs)} />
        <Row label="Consumido (total)" value={fmtArs(b.totalConsumedArs)} />
        <Row label="Comprado (total)"  value={fmtArs(b.totalPurchasedArs)} />
        <Row label="Estado"            value={b.paused ? '⏸️ Pausado (sin saldo)' : '✅ Activo'} last />
        <div style={{ marginTop:16 }}>
          <button style={S.saveBtn} onClick={() => onGoCredits && onGoCredits()}>💳 Cargar créditos</button>
        </div>
      </div>
    </div>
  );
}

// ─── DeliveriesPanel ──────────────────────────────────────────────────────────
// ─── Difusion -> Tokko (campaign-tokko) ─────────────────────────────────────
// CsvInput: texto libre; emite array (split por coma) al perder foco → permite espacios
function CsvInput({ value, onChange, ...rest }) {
  const [raw, setRaw] = useState((value||[]).join(', '));
  return <input {...rest} value={raw} onChange={e=>setRaw(e.target.value)} onBlur={()=>onChange(raw.split(',').map(x=>x.trim()).filter(Boolean))} />;
}

function CampaignTokkoPanel() {
  const [cfg, setCfg] = useState(null);
  const [saving, setSaving] = useState(false);
  const [msg, setMsg] = useState('');
  const [test, setTest] = useState({});

  const load = () => apiFetch('/api/campaign-tokko').then(r=>r.json()).then(setCfg).catch(()=>setCfg({enabled:false,token:'',rules:[]}));
  useEffect(()=>{ load(); }, []);
  if (!cfg) return <div style={S.page}><div style={S.pageSubtitle}>Cargando…</div></div>;

  const csv = (arr)=>(arr||[]).join(', ');
  const parseCsv = (s)=>String(s||'').split(',').map(x=>x.trim()).filter(Boolean);
  const upd = (patch)=>setCfg(c=>({ ...c, ...patch }));
  const updRule = (i,patch)=>setCfg(c=>({ ...c, rules: c.rules.map((r,idx)=>idx===i?{ ...r, ...patch }:r) }));
  const updTrigger = (i,patch)=>setCfg(c=>({ ...c, rules: c.rules.map((r,idx)=>idx===i?{ ...r, trigger:{ ...(r.trigger||{}), ...patch } }:r) }));
  const addRule = ()=>setCfg(c=>({ ...c, rules:[...(c.rules||[]), { id:'rule_'+Date.now().toString(36), name:'Nueva campaña', enabled:true, campaignKey:'', trigger:{ type:'keyword', keywords:[] }, inboxIds:[], delayMinutes:10, tokkoLabels:[], source:'difusion_pipochat' }] }));
  const delRule = (i)=>{ if(!confirm('¿Eliminar esta campaña?')) return; setCfg(c=>({ ...c, rules: c.rules.filter((_,idx)=>idx!==i) })); };

  const save = async ()=>{
    setSaving(true); setMsg('');
    const r = await apiFetch('/api/campaign-tokko', { method:'PUT', headers:{'Content-Type':'application/json'}, body: JSON.stringify(cfg) }).then(r=>r.json()).catch(e=>({error:e.message}));
    setSaving(false);
    if (r.error) setMsg('❌ '+r.error); else { setCfg(r); setMsg('✅ Guardado'); setTimeout(()=>setMsg(''),2500); }
  };
  const runTest = async (rule)=>{
    const t = test[rule.id] || {};
    setTest(s=>({ ...s, [rule.id]:{ ...t, running:true, result:null } }));
    const res = await apiFetch('/api/campaign-tokko/test', { method:'POST', headers:{'Content-Type':'application/json'}, body: JSON.stringify({ ruleId: rule.id, name: t.name||'test', phone: t.phone||'' }) }).then(r=>r.json()).catch(e=>({success:false,error:e.message}));
    setTest(s=>({ ...s, [rule.id]:{ ...t, running:false, result:res } }));
  };

  return (
    <div style={S.page}>
      <div style={S.pageHeader}>
        <div>
          <div style={{ fontSize:22, fontWeight:800, marginBottom:4 }}>📣 Difusión → Tokko</div>
          <div style={S.pageSubtitle}>Cuando un contacto de una campaña dice la palabra clave (ej: el botón "quiero más info de SA"), se envía a Tokko con las etiquetas que definas. Con anti-duplicado y temporizador.</div>
        </div>
        <button onClick={save} disabled={saving} style={S.btnPrimary}>{saving?'Guardando…':'Guardar cambios'}</button>
      </div>
      {msg && <div style={{ marginBottom:12, fontSize:13, fontWeight:600 }}>{msg}</div>}

      <div style={{ background:'var(--surface)', border:'1px solid var(--border)', borderRadius:12, padding:16, marginBottom:16 }}>
        <label style={{ display:'flex', alignItems:'center', gap:10, cursor:'pointer', marginBottom:14 }}>
          <input type="checkbox" checked={!!cfg.enabled} onChange={e=>upd({enabled:e.target.checked})} />
          <span style={{ fontWeight:700, fontSize:14 }}>Módulo activo</span>
          <span style={{ fontSize:12, color:'var(--muted)' }}>{cfg.enabled?'Enviando a Tokko':'Apagado (no envía)'}</span>
        </label>
        <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr', gap:12 }}>
          <div>
            <label style={S.label}>Tokko API Key</label>
            <input type="password" style={S.input} value={cfg.tokkoApiKey||''} onChange={e=>upd({tokkoApiKey:e.target.value})} placeholder="clave de la API de Tokko" />
          </div>
          <div>
            <label style={S.label}>Tokko API URL (opcional)</label>
            <input style={S.input} value={cfg.tokkoApiUrl||''} onChange={e=>upd({tokkoApiUrl:e.target.value})} placeholder="https://tokkobroker.com/api/v1/" />
          </div>
        </div>
      </div>

      <div style={{ display:'flex', justifyContent:'space-between', alignItems:'center', marginBottom:10 }}>
        <div style={{ fontWeight:700, fontSize:15 }}>Campañas</div>
        <button onClick={addRule} style={{ ...S.outlineBtn }}>+ Nueva campaña</button>
      </div>

      {(cfg.rules||[]).length===0 ? (
        <div style={{ textAlign:'center', padding:'40px 20px', color:'var(--muted)' }}>Sin campañas. Agregá una con "+ Nueva campaña".</div>
      ) : (cfg.rules||[]).map((rule,i)=>{
        const t = test[rule.id] || {};
        const tt = rule.trigger?.type || 'keyword';
        return (
          <div key={rule.id} style={{ background:'var(--surface)', border:'1px solid var(--border)', borderRadius:12, padding:16, marginBottom:12 }}>
            <div style={{ display:'flex', alignItems:'center', gap:10, marginBottom:12 }}>
              <label style={{ display:'flex', alignItems:'center', gap:6, cursor:'pointer' }}>
                <input type="checkbox" checked={!!rule.enabled} onChange={e=>updRule(i,{enabled:e.target.checked})} />
                <span style={{ fontSize:12, color:'var(--muted)' }}>{rule.enabled?'Activa':'Inactiva'}</span>
              </label>
              <input style={{ ...S.input, fontWeight:700, flex:1 }} value={rule.name||''} onChange={e=>updRule(i,{name:e.target.value})} placeholder="Nombre de la campaña" />
              <button onClick={()=>delRule(i)} style={{ padding:'6px 10px', borderRadius:8, border:'1px solid #fee2e2', background:'transparent', color:'#ef4444', cursor:'pointer', fontSize:12 }}>Eliminar</button>
            </div>

            <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr', gap:12, marginBottom:12 }}>
              <div>
                <label style={S.label}>Clave de campaña (id interno)</label>
                <input style={S.input} value={rule.campaignKey||''} onChange={e=>updRule(i,{campaignKey:e.target.value})} placeholder="difusion_serena_arredondo" />
              </div>
              <div>
                <label style={S.label}>Disparador</label>
                <select style={S.input} value={tt} onChange={e=>updTrigger(i,{type:e.target.value})}>
                  <option value="keyword">Palabra clave</option>
                  <option value="webhook">Webhook (Pipochat/Monitor)</option>
                </select>
              </div>
            </div>

            {tt==='keyword' && (
              <div style={{ marginBottom:12 }}>
                <label style={S.label}>Palabras clave (separadas por coma)</label>
                <div style={{ display:'flex', gap:8 }}>
                  <CsvInput style={{ ...S.input, flex:1 }} value={rule.trigger?.keywords} onChange={arr=>updTrigger(i,{keywords:arr})} placeholder="info de sa, quiero mas info" />
                  <select style={{ ...S.input, width:180 }} value={rule.trigger?.matchMode||'contains'} onChange={e=>updTrigger(i,{matchMode:e.target.value})}>
                    <option value="contains">Contiene la frase</option>
                    <option value="exact">Coincidencia exacta</option>
                  </select>
                </div>
                <div style={{ fontSize:11, color:'var(--muted)', marginTop:4 }}>Ignora mayúsculas/acentos. <b>Contiene</b> = el mensaje incluye la frase. <b>Exacta</b> = el mensaje es idéntico a una palabra clave.</div>
              </div>
            )}

            <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr', gap:12, marginBottom:12 }}>
              <div>
                <label style={S.label}>Etiquetas para Tokko (coma)</label>
                <CsvInput style={S.input} value={rule.tokkoLabels} onChange={arr=>updRule(i,{tokkoLabels:arr})} placeholder="Serena Arredondo, Fabric, Serena GF" />
              </div>
              <div>
                <label style={S.label}>Espera antes de enviar (min)</label>
                <input type="number" style={S.input} value={rule.delayMinutes==null?10:rule.delayMinutes} onChange={e=>updRule(i,{delayMinutes:parseInt(e.target.value||'0',10)})} />
              </div>
            </div>

            <details style={{ marginBottom:12 }}>
              <summary style={{ cursor:'pointer', fontSize:12, color:'var(--muted)' }}>Opciones avanzadas</summary>
              <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr', gap:12, marginTop:10 }}>
                <div>
                  <label style={S.label}>Emprendimiento Tokko (id, opcional)</label>
                  <input style={S.input} value={rule.developmentId||''} onChange={e=>updRule(i,{developmentId:e.target.value})} placeholder="(vacío)" />
                </div>
                <div>
                  <label style={S.label}>Asesor asignado (email, opcional)</label>
                  <input style={S.input} value={rule.advisorEmail||''} onChange={e=>updRule(i,{advisorEmail:e.target.value})} placeholder="(vacío)" />
                </div>
                <div style={{ gridColumn:'1 / -1' }}>
                  <label style={S.label}>Líneas / inbox IDs (coma, vacío = todas)</label>
                  <CsvInput style={S.input} value={rule.inboxIds} onChange={arr=>updRule(i,{inboxIds:arr})} placeholder="(vacío = cualquier línea)" />
                </div>
              </div>
            </details>

            <div style={{ borderTop:'1px solid var(--border-soft)', paddingTop:12, display:'flex', alignItems:'center', gap:8, flexWrap:'wrap' }}>
              <input style={{ ...S.input, width:150 }} value={t.name||''} onChange={e=>setTest(s=>({ ...s, [rule.id]:{ ...t, name:e.target.value } }))} placeholder="Nombre test" />
              <input style={{ ...S.input, width:170 }} value={t.phone||''} onChange={e=>setTest(s=>({ ...s, [rule.id]:{ ...t, phone:e.target.value } }))} placeholder="Teléfono test" />
              <button onClick={()=>runTest(rule)} disabled={t.running || !t.phone} style={{ ...S.outlineBtn }}>{t.running?'Enviando…':'🧪 Probar envío'}</button>
              {t.result && (t.result.success
                ? <span style={{ fontSize:13, color:'#16a34a', fontWeight:600 }}>✅ Enviado a Tokko{t.result.contactId?(' — id '+t.result.contactId):''}</span>
                : <span style={{ fontSize:13, color:'var(--danger)', fontWeight:600 }}>❌ {t.result.error}</span>)}
              <span style={{ fontSize:11, color:'var(--muted)' }}>El test ignora el anti-duplicado.</span>
            </div>
          </div>
        );
      })}

      <div style={{ marginTop:10, fontSize:12, color:'var(--muted)' }}>Los envíos quedan registrados en <strong>📤 Envíos de leads</strong>.</div>
    </div>
  );
}

function DeliveriesPanel() {
  const [rows, setRows]       = useState(null);
  const [pending, setPending] = useState([]); // [LOOP-PATCH campaign-tokko] pending
  const [dest, setDest]       = useState('all');
  const [loading, setLoading] = useState(false);

  // Test-lead state
  const [testOpen, setTestOpen] = useState(false);
  const [forms, setForms]       = useState([]);
  const [tForm, setTForm]       = useState('');
  const [tName, setTName]       = useState('Juan Prueba');
  const [tPhone, setTPhone]     = useState('5491100000000');
  const [tEmail, setTEmail]     = useState('prueba@test.com');
  const [tExtra, setTExtra]     = useState([]);              // [{ k, v }]
  const [tDest, setTDest]       = useState({ tokko: true, sheets: true });
  const [sending, setSending]   = useState(false);
  const [tResult, setTResult]   = useState(null);
  const inp = { flex:1, minWidth:120, fontSize:12, padding:'7px 9px', borderRadius:7, border:'1px solid var(--border)', background:'var(--white)' };

  const load = (d) => {
    setLoading(true);
    const q = d && d !== 'all' ? `?destination=${d}` : '';
    apiFetch('/api/deliveries' + q).then(r => r.json()).then(x => setRows(x.deliveries || [])).catch(() => setRows([])).finally(() => setLoading(false));
    apiFetch('/api/campaign-tokko/pending').then(r => r.json()).then(x => setPending(Array.isArray(x) ? x : [])).catch(() => setPending([]));
  };
  useEffect(() => { load(dest); }, [dest]);

  useEffect(() => {
    apiFetch('/api/integrations').then(r => r.json()).then(cfg => {
      const fsc = cfg?.metaLeadAds?.formSheetsConfig || {};
      const names = cfg?.metaLeadAds?.formNames || {};
      const list = Object.keys(fsc).map(id => ({ id, name: names[id] || id }));
      setForms(list);
      setTForm(prev => prev || (list[0] ? list[0].id : ''));
    }).catch(() => {});
  }, []);

  const sendTest = async () => {
    setSending(true); setTResult(null);
    try {
      const extra = {};
      tExtra.forEach(e => { const k = (e.k || '').trim(); if (k) extra[k] = e.v || ''; });
      const destinations = Object.entries(tDest).filter(([, v]) => v).map(([k]) => k);
      const res = await apiFetch('/api/leads/test', {
        method: 'POST', headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ formId: tForm, fields: { nombre: tName, telefono: tPhone, email: tEmail, extra }, destinations }),
      });
      const d = await res.json();
      setTResult(d.result || {});
      load(dest);
    } catch (e) { setTResult({ error: e.message }); }
    setSending(false);
  };

  const fmt = (ts) => { try { const d = new Date(ts); return d.toLocaleDateString('es-AR',{day:'2-digit',month:'2-digit'}) + ' ' + d.toLocaleTimeString('es-AR',{hour:'2-digit',minute:'2-digit'}); } catch(e){ return ''; } };
  const destBadge = (d) => d === 'tokko'
    ? <span style={{ fontSize:10, fontWeight:700, color:'#7c3aed', background:'#f3e8ff', borderRadius:4, padding:'2px 6px', flexShrink:0 }}>Tokko</span>
    : <span style={{ fontSize:10, fontWeight:700, color:'#166534', background:'#dcfce7', borderRadius:4, padding:'2px 6px', flexShrink:0 }}>Sheets</span>;
  const statusBadge = (s) => {
    const m = { ok:['#166534','#dcfce7','✅ enviado'], error:['#b91c1c','#fef2f2','✕ error'], skip:['#92400e','#fef3c7','— omitido'] }[s] || ['#444','#eee',s];
    return <span style={{ fontSize:10, fontWeight:700, color:m[0], background:m[1], borderRadius:4, padding:'2px 6px', flexShrink:0 }}>{m[2]}</span>;
  };
  const filterBtn = (key, label) => (
    <button onClick={() => setDest(key)}
      style={{ fontSize:12, fontWeight:600, padding:'6px 14px', borderRadius:8, cursor:'pointer',
        border:'1px solid ' + (dest===key?'var(--green)':'var(--border)'),
        background: dest===key?'var(--green)':'var(--surface)', color: dest===key?'#fff':'var(--ink-3)' }}>
      {label}
    </button>
  );

  return (
    <div style={{ ...S.editor }}>
      <div>
        <div style={S.pageTitle}>📤 Envíos de leads</div>
        <div style={S.pageSubtitle}>Todo lo que el agente envió a plataformas externas (Tokko, Google Sheets). Filtrá por destino.</div>
      </div>

      {/* Test de lead */}
      <div style={S.card}>
        <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between', cursor:'pointer' }} onClick={() => setTestOpen(o => !o)}>
          <div style={{ fontWeight:700, fontSize:14 }}>🧪 Enviar lead de prueba</div>
          <span style={{ color:'var(--ink-4)', fontSize:12 }}>{testOpen ? '▲ ocultar' : '▼ abrir'}</span>
        </div>
        {testOpen && (
          <div style={{ marginTop:12, display:'flex', flexDirection:'column', gap:10 }}>
            <div style={{ fontSize:12, color:'var(--ink-4)', lineHeight:1.5 }}>Manda un lead ficticio por el pipeline real (usa el mapeo y los valores fijos del form elegido). Aparece en el log marcado como 🧪 test.</div>
            <label style={{ fontSize:12, fontWeight:600 }}>Formulario
              <select value={tForm} onChange={e => setTForm(e.target.value)} style={{ width:'100%', marginTop:4, padding:'7px 9px', borderRadius:7, border:'1px solid var(--border)', background:'var(--white)' }}>
                {forms.length === 0 && <option value="">(sin forms con Sheets configurado)</option>}
                {forms.map(f => <option key={f.id} value={f.id}>{f.name}</option>)}
              </select>
            </label>
            <div style={{ display:'flex', gap:8, flexWrap:'wrap' }}>
              <input value={tName}  onChange={e => setTName(e.target.value)}  placeholder="Nombre"   style={inp} />
              <input value={tPhone} onChange={e => setTPhone(e.target.value)} placeholder="Teléfono" style={inp} />
              <input value={tEmail} onChange={e => setTEmail(e.target.value)} placeholder="Email"    style={inp} />
            </div>
            {tExtra.map((e, i) => (
              <div key={i} style={{ display:'flex', gap:6 }}>
                <input value={e.k} onChange={ev => setTExtra(p => p.map((x, j) => j !== i ? x : { ...x, k: ev.target.value }))} placeholder="Campo (ej: ¿cuál_es_tu_presupuesto_aproximado?)" style={{ ...inp, flex:2 }} />
                <input value={e.v} onChange={ev => setTExtra(p => p.map((x, j) => j !== i ? x : { ...x, v: ev.target.value }))} placeholder="Valor" style={{ ...inp, flex:1 }} />
                <button onClick={() => setTExtra(p => p.filter((_, j) => j !== i))} style={{ background:'none', border:'none', cursor:'pointer', color:'var(--ink-4)', fontSize:13 }}>✕</button>
              </div>
            ))}
            <button onClick={() => setTExtra(p => [...p, { k:'', v:'' }])} style={{ alignSelf:'flex-start', fontSize:12, color:'var(--green)', background:'none', border:'1px dashed var(--green-mid)', borderRadius:6, padding:'4px 10px', cursor:'pointer' }}>+ Campo adicional</button>
            <div style={{ display:'flex', gap:16, alignItems:'center', flexWrap:'wrap' }}>
              <span style={{ fontSize:12, fontWeight:600 }}>Enviar a:</span>
              <label style={{ fontSize:12, display:'flex', gap:5, alignItems:'center', cursor:'pointer' }}><input type="checkbox" checked={tDest.tokko} onChange={e => setTDest(d => ({ ...d, tokko: e.target.checked }))} /> Tokko</label>
              <label style={{ fontSize:12, display:'flex', gap:5, alignItems:'center', cursor:'pointer' }}><input type="checkbox" checked={tDest.sheets} onChange={e => setTDest(d => ({ ...d, sheets: e.target.checked }))} /> Google Sheets</label>
            </div>
            <button onClick={sendTest} disabled={sending || !tForm} style={{ ...S.saveBtn, alignSelf:'flex-start', opacity: (sending || !tForm) ? .6 : 1 }}>{sending ? 'Enviando…' : '🚀 Enviar prueba'}</button>
            {tResult && (
              <div style={{ fontSize:12.5, background:'var(--cream)', borderRadius:8, padding:'10px 12px', display:'flex', flexDirection:'column', gap:4 }}>
                {tResult.error && <span style={{ color:'var(--danger)' }}>Error: {tResult.error}</span>}
                {tResult.tokko && <span>Tokko: <b style={{ color: tResult.tokko.status==='ok'?'#166534':tResult.tokko.status==='error'?'#b91c1c':'#92400e' }}>{tResult.tokko.status}</b> — {tResult.tokko.detail}</span>}
                {tResult.sheets && <span>Sheets: <b style={{ color: tResult.sheets.status==='ok'?'#166534':tResult.sheets.status==='error'?'#b91c1c':'#92400e' }}>{tResult.sheets.status}</b> — {tResult.sheets.detail}</span>}
              </div>
            )}
          </div>
        )}
      </div>

      <div style={{ display:'flex', gap:8, flexWrap:'wrap', alignItems:'center' }}>
        {filterBtn('all','Todos')}
        {filterBtn('tokko','Tokko')}
        {filterBtn('sheets','Google Sheets')}
        <button onClick={() => load(dest)} style={{ marginLeft:'auto', fontSize:12, color:'var(--ink-3)', background:'none', border:'1px solid var(--border)', borderRadius:8, padding:'6px 12px', cursor:'pointer' }}>↺ Actualizar</button>
      </div>
      {pending.length > 0 && (
        <div style={{ ...S.card, border:'1px solid #fde68a', background:'#fffbeb' }}>
          <div style={{ fontWeight:700, fontSize:13, marginBottom:8, color:'#92400e' }}>⏳ Pendientes de envío ({pending.length})</div>
          {pending.map(p => (
            <div key={p.id} style={{ display:'flex', alignItems:'center', gap:10, padding:'7px 4px', borderBottom:'1px solid #fef3c7', fontSize:13 }}>
              <span style={{ fontSize:10, fontWeight:700, color:'#92400e', background:'#fef3c7', borderRadius:4, padding:'2px 6px', flexShrink:0 }}>⏳ pendiente</span>
              <span style={{ flex:1, minWidth:0, overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap' }}><b>{p.name || '—'}</b>{p.phone ? (' · ' + p.phone) : ''}</span>
              <span style={{ fontSize:11, color:'var(--ink-4)' }}>{p.campaignKey}</span>
              <span style={{ fontSize:11, color:'var(--ink-4)', fontFamily:'monospace', flexShrink:0 }} title="se enviará aprox. a esta hora">→ {fmt(p.fireAt)}</span>
            </div>
          ))}
        </div>
      )}
      <div style={S.card}>
        {loading && <div style={{ padding:16, color:'var(--ink-4)', fontSize:13 }}>Cargando…</div>}
        {!loading && rows && rows.length === 0 && <div style={{ padding:16, color:'var(--ink-4)', fontSize:13 }}>Sin envíos todavía para este filtro.</div>}
        {!loading && rows && rows.length > 0 && rows.map(r => (
          <div key={r.id} style={{ display:'flex', alignItems:'center', gap:10, padding:'9px 4px', borderBottom:'1px solid var(--border-soft)', fontSize:13 }}>
            <span style={{ fontSize:11, color:'var(--ink-4)', width:84, flexShrink:0, fontFamily:'monospace' }}>{fmt(r.ts)}</span>
            {destBadge(r.destination)}
            {statusBadge(r.status)}
            {r.source === 'test' && <span style={{ fontSize:10, fontWeight:700, color:'#b45309', background:'#fffbeb', borderRadius:4, padding:'2px 6px', flexShrink:0 }}>🧪 test</span>}
            <span style={{ flex:1, minWidth:0, overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap' }}>
              <b>{r.name || '—'}</b>{r.phone ? ` · ${r.phone}` : ''}{r.formName ? ` · ${r.formName}` : ''}
            </span>
            {r.detail && <span style={{ fontSize:11, color: r.status==='error'?'var(--danger)':'var(--ink-4)', maxWidth:220, overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap', flexShrink:0 }} title={r.detail}>{r.detail}</span>}
          </div>
        ))}
      </div>
    </div>
  );
}

// ─── CreditsPanel ─────────────────────────────────────────────────────────────
function CreditsPanel() {
  const [data,    setData]    = useState(null);
  const [txs,     setTxs]     = useState([]);
  const [loading, setLoading] = useState(false);
  const [buying,  setBuying]  = useState(null); // packageId being processed

  function load() {
    apiFetch('/api/billing/account').then(r => r.json()).then(setData).catch(() => {});
    apiFetch('/api/billing/transactions').then(r => r.json()).then(d => setTxs(d.transactions || [])).catch(() => {});
  }

  useEffect(() => { load(); }, []);

  async function buyPackage(pkg) {
    setBuying(pkg.id);
    try {
      const res  = await apiFetch('/api/billing/create-preference', {
        method:  'POST',
        headers: { 'Content-Type': 'application/json' },
        body:    JSON.stringify({ packageId: pkg.id }),
      });
      const data = await res.json();
      if (data.initPoint) {
        window.open(data.initPoint, '_blank');
      } else {
        alert('Error al crear la preferencia de pago: ' + (data.error || 'desconocido'));
      }
    } catch (e) {
      alert('Error: ' + e.message);
    } finally {
      setBuying(null);
    }
  }

  const acc      = data?.account;
  const packages = data?.packages || [];
  const balance  = acc?.balanceArs ?? 0;
  const paused   = acc?.paused;
  const active   = acc?.totalPurchasedArs > 0;

  const fmtArs = (n) => 'ARS ' + Math.abs(n).toLocaleString('es-AR', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
  const fmtDate = (ts) => {
    const d = new Date(ts);
    return d.toLocaleDateString('es-AR', { day:'2-digit', month:'2-digit' }) + ' ' + d.toLocaleTimeString('es-AR', { hour:'2-digit', minute:'2-digit' });
  };

  return (
    <div style={{ ...S.editor }}>
      <div>
        <div style={S.pageTitle}>💳 Créditos</div>
        <div style={S.pageSubtitle}>Recargá créditos prepagos para que el agente de IA funcione.</div>
      </div>

      {/* Balance card */}
      <div style={{ ...S.card, borderLeft: paused ? '4px solid var(--danger)' : active ? '4px solid var(--green)' : '4px solid var(--border)' }}>
        <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between', flexWrap:'wrap', gap:12 }}>
          <div>
            <div style={{ fontSize:11, fontWeight:700, color:'var(--ink-4)', textTransform:'uppercase', letterSpacing:.7, marginBottom:4 }}>Saldo disponible</div>
            <div style={{ fontSize:32, fontWeight:900, color: paused ? 'var(--danger)' : 'var(--green)', letterSpacing:'-1px' }}>
              {acc ? fmtArs(balance) : '—'}
            </div>
            {paused && (
              <div style={{ display:'flex', alignItems:'center', gap:6, marginTop:6, color:'var(--danger)', fontSize:13, fontWeight:600 }}>
                ⚠️ Sin créditos — agente pausado
              </div>
            )}
            {!active && !paused && (
              <div style={{ color:'var(--ink-4)', fontSize:12, marginTop:4 }}>
                Sin recarga todavía — el agente funciona gratis hasta que cargues créditos.
              </div>
            )}
          </div>
          {active && (
            <div style={{ display:'flex', gap:16, flexWrap:'wrap' }}>
              <div style={{ textAlign:'center' }}>
                <div style={{ fontSize:15, fontWeight:700 }}>{acc ? fmtArs(acc.totalPurchasedArs) : '—'}</div>
                <div style={{ fontSize:11, color:'var(--ink-4)' }}>Total comprado</div>
              </div>
              <div style={{ textAlign:'center' }}>
                <div style={{ fontSize:15, fontWeight:700 }}>{acc ? fmtArs(acc.totalConsumedArs) : '—'}</div>
                <div style={{ fontSize:11, color:'var(--ink-4)' }}>Total consumido</div>
              </div>
            </div>
          )}
        </div>
      </div>

      {/* Packages */}
      <div style={S.card}>
        <div style={S.cardTitle}>Recargar créditos</div>
        <div style={{ fontSize:12, color:'var(--ink-4)', marginBottom:16 }}>
          1 crédito = 1 ARS · Precios sin markup · Pagás con MercadoPago
        </div>
        <div style={{ display:'flex', gap:14, flexWrap:'wrap' }}>
          {packages.map(pkg => (
            <div key={pkg.id} style={{
              flex: 1, minWidth: 180,
              border: '1.5px solid var(--border)',
              borderRadius: 'var(--r)',
              padding: '18px 20px',
              display:'flex', flexDirection:'column', gap:8,
              background: 'var(--cream)',
              transition: 'box-shadow .15s',
            }}>
              <div style={{ fontSize:17, fontWeight:800 }}>{pkg.name}</div>
              <div style={{ fontSize:13, color:'var(--ink-3)' }}>{pkg.description}</div>
              <div style={{ fontSize:22, fontWeight:900, color:'var(--green)', margin:'4px 0' }}>
                ARS {pkg.ars.toLocaleString('es-AR')}
              </div>
              <div style={{ fontSize:12, color:'var(--ink-4)' }}>
                ~{pkg.approxConvs.toLocaleString()} conversaciones
              </div>
              <button
                onClick={() => buyPackage(pkg)}
                disabled={buying === pkg.id}
                style={{ ...S.saveBtn, marginTop:8, width:'100%', opacity: buying === pkg.id ? .6 : 1 }}
              >
                {buying === pkg.id ? 'Redirigiendo…' : 'Pagar con MP'}
              </button>
            </div>
          ))}
        </div>
      </div>

      {/* Transaction history */}
      {txs.length > 0 && (
        <div style={S.card}>
          <div style={S.cardTitle}>Historial de movimientos</div>
          <table style={{ width:'100%', borderCollapse:'collapse', marginTop:14, fontSize:13 }}>
            <thead>
              <tr style={{ borderBottom:'2px solid var(--border-soft)' }}>
                {['Fecha','Descripción','Monto'].map(h => (
                  <th key={h} style={{ padding:'6px 12px', textAlign:'left', fontSize:11, fontWeight:700, color:'var(--ink-4)', textTransform:'uppercase', letterSpacing:.7 }}>{h}</th>
                ))}
              </tr>
            </thead>
            <tbody>
              {txs.map(tx => (
                <tr key={tx.id} style={{ borderBottom:'1px solid var(--border-soft)' }}>
                  <td style={{ padding:'8px 12px', color:'var(--ink-3)', whiteSpace:'nowrap' }}>{fmtDate(tx.ts)}</td>
                  <td style={{ padding:'8px 12px' }}>{tx.description}</td>
                  <td style={{ padding:'8px 12px', fontWeight:600, color: tx.amountArs >= 0 ? 'var(--green)' : 'var(--ink-2)', textAlign:'right', whiteSpace:'nowrap' }}>
                    {tx.amountArs >= 0 ? '+' : ''}{fmtArs(tx.amountArs)}
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      )}
    </div>
  );
}

// ─── MetricsPanel ─────────────────────────────────────────────────────────────
function MetricsPanel() {
  const [data, setData] = useState(null);

  useEffect(() => {
    apiFetch('/api/metrics').then(r => r.json()).then(setData).catch(() => {});
  }, []);

  if (!data) return <div style={S.editor}><div style={{ color:'var(--ink-3)', fontSize:13 }}>Cargando…</div></div>;

  const usage = data.usage || { totalInputTokens:0, totalOutputTokens:0, totalCostUsd:0, monthly:{} };
  const months = Object.entries(usage.monthly || {}).sort((a,b) => b[0].localeCompare(a[0]));
  const currentMonth = new Date().toISOString().slice(0,7);
  const thisMonth = usage.monthly?.[currentMonth] || { input:0, output:0, costUsd:0 };
  const days = Object.entries(usage.daily || {}).sort((a,b) => b[0].localeCompare(a[0]));
  const todayKey = new Date().toISOString().slice(0,10);
  const today = usage.daily?.[todayKey] || { input:0, output:0, costUsd:0 };

  const fmt = (n) => n >= 1000000 ? (n/1000000).toFixed(1)+'M' : n >= 1000 ? (n/1000).toFixed(0)+'k' : String(n);
  const fmtCost = (n) => '$' + (n||0).toFixed(4);

  const StatCard = ({ label, value, sub }) => (
    <div style={{ ...S.card, textAlign:'center', flex:1, minWidth:130 }}>
      <div style={{ fontSize:22, fontWeight:800, color:'var(--green)', letterSpacing:'-.5px' }}>{value}</div>
      <div style={{ fontSize:13, fontWeight:600, color:'var(--ink)', marginTop:2 }}>{label}</div>
      {sub && <div style={{ fontSize:11, color:'var(--ink-4)', marginTop:2 }}>{sub}</div>}
    </div>
  );

  return (
    <div style={{ ...S.editor }}>
      <div>
        <div style={S.pageTitle}>📊 Métricas</div>
        <div style={S.pageSubtitle}>Uso del agente de IA y actividad del sistema.</div>
      </div>

      {/* Today summary */}
      <div style={S.card}>
        <div style={S.cardTitle}>Hoy — {todayKey}</div>
        <div style={{ display:'flex', gap:12, flexWrap:'wrap', marginTop:14 }}>
          <StatCard label="Tokens entrada" value={fmt(today.input)} sub="Claude input" />
          <StatCard label="Tokens salida" value={fmt(today.output)} sub="Claude output" />
          <StatCard label="Gasto de hoy" value={fmtCost(today.costUsd)} sub="USD hoy" />
        </div>
      </div>

      {/* This month summary */}
      <div style={S.card}>
        <div style={S.cardTitle}>Este mes — {currentMonth}</div>
        <div style={{ display:'flex', gap:12, flexWrap:'wrap', marginTop:14 }}>
          <StatCard label="Tokens entrada" value={fmt(thisMonth.input)} sub="Claude input" />
          <StatCard label="Tokens salida" value={fmt(thisMonth.output)} sub="Claude output" />
          <StatCard label="Costo estimado" value={fmtCost(thisMonth.costUsd)} sub="USD este mes" />
        </div>
      </div>

      {/* All time */}
      <div style={S.card}>
        <div style={S.cardTitle}>Total acumulado</div>
        <div style={{ display:'flex', gap:12, flexWrap:'wrap', marginTop:14 }}>
          <StatCard label="Tokens entrada" value={fmt(usage.totalInputTokens)} />
          <StatCard label="Tokens salida" value={fmt(usage.totalOutputTokens)} />
          <StatCard label="Costo total" value={fmtCost(usage.totalCostUsd)} sub="USD acumulado" />
        </div>
      </div>

      {/* Monthly history */}
      {months.length > 0 && (
        <div style={S.card}>
          <div style={S.cardTitle}>Historial mensual</div>
          <table style={{ width:'100%', borderCollapse:'collapse', marginTop:14, fontSize:13 }}>
            <thead>
              <tr style={{ borderBottom:'2px solid var(--border-soft)' }}>
                {['Mes','Tokens entrada','Tokens salida','Costo USD'].map(h => (
                  <th key={h} style={{ padding:'6px 12px', textAlign:'left', fontSize:11, fontWeight:700, color:'var(--ink-4)', textTransform:'uppercase', letterSpacing:.7 }}>{h}</th>
                ))}
              </tr>
            </thead>
            <tbody>
              {months.map(([month, m]) => (
                <tr key={month} style={{ borderBottom:'1px solid var(--border-soft)' }}>
                  <td style={{ padding:'9px 12px', fontWeight:600, color:'var(--ink)' }}>{month}</td>
                  <td style={{ padding:'9px 12px', color:'var(--ink-2)' }}>{fmt(m.input)}</td>
                  <td style={{ padding:'9px 12px', color:'var(--ink-2)' }}>{fmt(m.output)}</td>
                  <td style={{ padding:'9px 12px', fontWeight:600, color:'var(--green)' }}>{fmtCost(m.costUsd)}</td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      )}

      {/* Daily history (gasto por día) */}
      {days.length > 0 && (
        <div style={S.card}>
          <div style={S.cardTitle}>Gasto por día (últimos {Math.min(days.length, 30)} días)</div>
          <table style={{ width:'100%', borderCollapse:'collapse', marginTop:14, fontSize:13 }}>
            <thead>
              <tr style={{ borderBottom:'2px solid var(--border-soft)' }}>
                {['Día','Tokens entrada','Tokens salida','Costo USD'].map(h => (
                  <th key={h} style={{ padding:'6px 12px', textAlign:'left', fontSize:11, fontWeight:700, color:'var(--ink-4)', textTransform:'uppercase', letterSpacing:.7 }}>{h}</th>
                ))}
              </tr>
            </thead>
            <tbody>
              {days.slice(0,30).map(([d, m]) => (
                <tr key={d} style={{ borderBottom:'1px solid var(--border-soft)', background: d===todayKey ? 'var(--green-light,#EBF3EF)' : 'transparent' }}>
                  <td style={{ padding:'9px 12px', fontWeight:600, color:'var(--ink)' }}>{d}{d===todayKey ? ' (hoy)' : ''}</td>
                  <td style={{ padding:'9px 12px', color:'var(--ink-2)' }}>{fmt(m.input)}</td>
                  <td style={{ padding:'9px 12px', color:'var(--ink-2)' }}>{fmt(m.output)}</td>
                  <td style={{ padding:'9px 12px', fontWeight:600, color:'var(--green)' }}>{fmtCost(m.costUsd)}</td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      )}

      {/* Action metrics */}
      <ActionMetricsCard />
    </div>
  );
}

// ─── CTWA Analytics Panel ─────────────────────────────────────────────────────
function CTWAPanel() {
  const [stats, setStats]   = React.useState([]);
  const [loading, setLoading] = React.useState(true);
  const [expanded, setExpanded] = React.useState({});   // campaign → open/close
  const [view, setView]     = React.useState('campaign'); // 'campaign' | 'adset' | 'ad'

  React.useEffect(() => {
    apiFetch('/api/ctwa/stats')
      .then(r => r.json())
      .then(d => { setStats(d.stats || []); setLoading(false); })
      .catch(() => setLoading(false));
  }, []);

  const pct = v => v == null ? '—' : (v * 100).toFixed(0) + '%';

  const bar = (val, color = 'var(--green)') => (
    <div style={{ display:'flex', alignItems:'center', gap:8 }}>
      <div style={{ flex:1, background:'var(--cream-dark)', borderRadius:99, height:6, overflow:'hidden' }}>
        <div style={{ width:`${Math.min(val*100,100)}%`, background:color, height:'100%', borderRadius:99, transition:'width .4s' }} />
      </div>
      <div style={{ fontSize:11, color:'var(--ink-3)', minWidth:30, textAlign:'right' }}>{pct(val)}</div>
    </div>
  );

  // Aggregate by campaign
  const byCampaign = React.useMemo(() => {
    const map = new Map();
    for (const s of stats) {
      const k = s.campaign;
      if (!map.has(k)) map.set(k, { campaign: k, total:0, leads:0, converted:0, adsets: new Map() });
      const c = map.get(k);
      c.total     += s.total;
      c.leads     += s.leads;
      c.converted += s.converted;
      // adset level
      const ak = s.adset;
      if (!c.adsets.has(ak)) c.adsets.set(ak, { adset: ak, total:0, leads:0, converted:0, ads:[] });
      const a = c.adsets.get(ak);
      a.total     += s.total;
      a.leads     += s.leads;
      a.converted += s.converted;
      a.ads.push(s);
    }
    return Array.from(map.values()).sort((a,b) => b.total - a.total);
  }, [stats]);

  if (loading) return <div style={{ padding:40, textAlign:'center', color:'var(--ink-4)' }}>Cargando…</div>;

  if (!stats.length) return (
    <div style={{ padding:40 }}>
      <div style={{ ...S.card, textAlign:'center', padding:40 }}>
        <div style={{ fontSize:40, marginBottom:12 }}>🎯</div>
        <div style={{ fontWeight:700, fontSize:16, marginBottom:8 }}>Sin datos de campañas CTWA todavía</div>
        <div style={{ color:'var(--ink-3)', fontSize:13, maxWidth:400, margin:'0 auto' }}>
          Cuando lleguen leads por Click-to-WhatsApp desde Meta, vas a ver acá el rendimiento de cada campaña, conjunto de anuncios y anuncio — y cuántos avanzan hasta tu etapa de conversión.
        </div>
        <div style={{ marginTop:20, fontSize:12, color:'var(--ink-4)', background:'var(--cream)', borderRadius:8, padding:'10px 16px', display:'inline-block' }}>
          💡 Asegurate de tener el webhook CTWA configurado en Pipochat y la etapa de conversión definida en el agente.
        </div>
      </div>
    </div>
  );

  const headerCell = (label, w) => (
    <th style={{ padding:'8px 12px', textAlign:'left', fontSize:11, fontWeight:600, color:'var(--ink-4)', textTransform:'uppercase', letterSpacing:'.04em', width:w, whiteSpace:'nowrap' }}>{label}</th>
  );

  const renderRow = (item, level = 0) => {
    const isOpen = expanded[item.campaign + (item.adset||'') + (item.ad||'')];
    const indent = level * 20;
    const key    = item.campaign + '|' + (item.adset||'') + '|' + (item.ad||'');
    const hasChildren = level < 2 && (level === 0 ? item.adsets?.size > 0 : item.ads?.length > 0);
    const label  = level === 0 ? item.campaign : level === 1 ? item.adset : item.ad;
    const convR  = item.total > 0 ? item.converted / item.total : 0;
    const leadR  = item.total > 0 ? item.leads     / item.total : 0;

    return (
      <React.Fragment key={key}>
        <tr style={{ borderBottom:'1px solid var(--border-soft)', background: level===0 ? 'var(--cream)' : 'transparent' }}>
          <td style={{ padding:'10px 12px', paddingLeft: 12 + indent }}>
            <div style={{ display:'flex', alignItems:'center', gap:6 }}>
              {hasChildren && (
                <button type="button" onClick={() => setExpanded(p => ({ ...p, [key]: !isOpen }))}
                  style={{ background:'none', border:'none', cursor:'pointer', fontSize:11, color:'var(--ink-4)', padding:0, lineHeight:1 }}>
                  {isOpen ? '▾' : '▸'}
                </button>
              )}
              {!hasChildren && <span style={{ display:'inline-block', width:14 }} />}
              <span style={{ fontSize: level===0?13:12, fontWeight: level===0?600:400, color:'var(--ink)' }}>
                {level===0?'📢':level===1?'📁':'📣'} {label}
              </span>
            </div>
          </td>
          <td style={{ padding:'10px 12px', textAlign:'center', fontWeight:600, fontSize:14 }}>{item.total}</td>
          <td style={{ padding:'10px 12px', textAlign:'center', color:'var(--ink-2)' }}>{item.leads}</td>
          <td style={{ padding:'10px 12px', minWidth:120 }}>{bar(leadR, '#6366f1')}</td>
          <td style={{ padding:'10px 12px', textAlign:'center', color: item.converted>0?'var(--green)':'var(--ink-3)', fontWeight: item.converted>0?700:400 }}>{item.converted}</td>
          <td style={{ padding:'10px 12px', minWidth:120 }}>{bar(convR)}</td>
        </tr>
        {isOpen && level === 0 && Array.from(item.adsets.values()).map(a => renderRow({ ...a, campaign: item.campaign }, 1))}
        {isOpen && level === 1 && item.ads.map(a => renderRow(a, 2))}
      </React.Fragment>
    );
  };

  // Summary totals
  const total     = byCampaign.reduce((s,c) => s + c.total, 0);
  const leads     = byCampaign.reduce((s,c) => s + c.leads, 0);
  const converted = byCampaign.reduce((s,c) => s + c.converted, 0);

  return (
    <div style={{ padding:24, display:'flex', flexDirection:'column', gap:20 }}>
      <div>
        <div style={{ fontWeight:800, fontSize:20, marginBottom:4 }}>🎯 Campañas CTWA</div>
        <div style={{ color:'var(--ink-3)', fontSize:13 }}>Rendimiento de campañas Click-to-WhatsApp desde Meta</div>
      </div>

      {/* Summary cards */}
      <div style={{ display:'flex', gap:12, flexWrap:'wrap' }}>
        {[
          { label:'Contactos totales', value:total,     icon:'💬', color:'var(--ink)' },
          { label:'Leads creados',     value:leads,     icon:'🎯', color:'#6366f1' },
          { label:'Conversiones',      value:converted, icon:'✅', color:'var(--green)' },
          { label:'Tasa de conversión',value: total>0 ? pct(converted/total) : '—', icon:'📈', color:'var(--green)' },
        ].map(({ label, value, icon, color }) => (
          <div key={label} style={{ ...S.card, flex:1, minWidth:140, padding:'16px 20px' }}>
            <div style={{ fontSize:22 }}>{icon}</div>
            <div style={{ fontWeight:800, fontSize:24, color, marginTop:6 }}>{value}</div>
            <div style={{ fontSize:11, color:'var(--ink-4)', marginTop:2 }}>{label}</div>
          </div>
        ))}
      </div>

      {/* Table */}
      <div style={S.card}>
        <div style={{ overflowX:'auto' }}>
          <table style={{ width:'100%', borderCollapse:'collapse', fontSize:13 }}>
            <thead>
              <tr style={{ borderBottom:'2px solid var(--border)' }}>
                {headerCell('Campaña / Conjunto / Anuncio', '40%')}
                {headerCell('Contactos', 80)}
                {headerCell('Leads', 70)}
                {headerCell('Lead rate', 130)}
                {headerCell('Conversiones', 90)}
                {headerCell('Conv. rate', 130)}
              </tr>
            </thead>
            <tbody>
              {byCampaign.map(c => renderRow(c, 0))}
            </tbody>
          </table>
        </div>
        <div style={{ fontSize:11, color:'var(--ink-4)', marginTop:12, paddingTop:12, borderTop:'1px solid var(--border-soft)' }}>
          💡 Hacé click en ▸ para desplegar conjuntos de anuncios y anuncios individuales · La etapa de conversión se configura en cada agente
        </div>
      </div>
    </div>
  );
}

// ─── Reconnect button ─────────────────────────────────────────────────────────
function ReconnectBtn() {
  const [status, setStatus] = useState('idle'); // idle | loading | ok | error | blocked

  const handleClick = async (e) => {
    e.stopPropagation();
    setStatus('loading');
    try {
      // First check current status — might already be authenticated
      const sr = await apiFetch('/api/pipochat/status');
      const sd = await sr.json();
      if (sd.internalApi?.status === 'authenticated') {
        setStatus('ok');
        setTimeout(() => window.location.reload(), 800);
        return;
      }
      // Not yet — try to force login
      const r = await apiFetch('/api/reconnect', { method: 'POST' });
      const d = await r.json();
      if (r.status === 429) { setStatus('blocked'); setTimeout(() => setStatus('idle'), 8000); return; }
      if (!r.ok) { setStatus('error'); setTimeout(() => setStatus('idle'), 5000); return; }
      setStatus('ok');
      setTimeout(() => window.location.reload(), 800);
    } catch { setStatus('error'); setTimeout(() => setStatus('idle'), 5000); }
  };

  const label = { idle:'Reconectar', loading:'…', ok:'✓', error:'Error', blocked:'Bloqueado' }[status];
  const color = { idle:'#B45309', loading:'#B45309', ok:'var(--green)', error:'var(--danger)', blocked:'#6B7280' }[status];

  return (
    <button onClick={handleClick} disabled={status === 'loading' || status === 'ok'}
      title={status === 'blocked' ? 'Pipochat sigue bloqueado, esperá unos minutos' : 'Reconectar con Pipochat'}
      style={{ fontSize:10, padding:'2px 7px', borderRadius:6, border:`1px solid ${color}`,
               background:'transparent', color, cursor:'pointer', fontWeight:600, lineHeight:1.4 }}>
      {label}
    </button>
  );
}

// ─── MetaReportPanel — Reporte Meta Ads × Pipochat ────────────────────────────
function MetaReportPanel() {
  const [data, setData]       = React.useState(null);
  const [loading, setLoading] = React.useState(true);
  const [err, setErr]         = React.useState('');
  const [preset, setPreset]   = React.useState('maximum');
  const [visits, setVisits]   = React.useState('0');
  const [savedV, setSavedV]   = React.useState(false);
  const [previewAd, setPreviewAd] = React.useState(null);

  const load = (p) => {
    setLoading(true); setErr('');
    apiFetch('/api/reports/meta-pipochat?datePreset=' + encodeURIComponent(p))
      .then(r => r.json())
      .then(d => { if (d && d.error) setErr(d.error); else { setData(d); setVisits(String((d.funnel && d.funnel.visits) || 0)); } })
      .catch(e => setErr(String(e && e.message || e)))
      .finally(() => setLoading(false));
  };
  React.useEffect(() => { load(preset); }, []);

  const saveVisits = () => {
    const n = Math.max(0, Math.floor(Number(visits) || 0));
    apiFetch('/api/reports/meta-pipochat/visits', { method:'POST', headers:{'Content-Type':'application/json'}, body: JSON.stringify({ visits: n }) })
      .then(r => r.json()).then(() => { setVisits(String(n)); setSavedV(true); setTimeout(() => setSavedV(false), 1800); }).catch(() => {});
  };

  const cur  = (data && data.currency) || 'ARS';
  const fmt  = (n) => (n == null ? '—' : Number(n).toLocaleString('es-AR', { style:'currency', currency: cur, maximumFractionDigits: 0 }));
  const num  = (n) => (n == null ? '—' : Number(n).toLocaleString('es-AR'));
  const pct  = (n) => (n == null ? '—' : Number(n).toFixed(1) + '%');
  const fmtDate = (d) => (d ? new Date(d.length <= 10 ? d + 'T00:00:00' : d).toLocaleDateString('es-AR') : '—');
  const PRESETS = [['maximum','Todo'],['last_7d','7 días'],['last_30d','30 días'],['last_90d','90 días'],['this_month','Este mes'],['last_month','Mes pasado']];
  const FLOW_LABEL = { ene:'ENE Nicaragua', dorrego:'Dorrego Place', perfilamiento:'Perfilamiento' };
  const vNum = Math.max(0, Math.floor(Number(visits) || 0));
  const costPerVisit = (data && vNum > 0) ? data.totals.spend / vNum : null;
  const leadToVisit = (data && data.funnel.qualifiedContacts > 0 && vNum > 0) ? (vNum / data.funnel.qualifiedContacts) * 100 : null;

  const card = { background:'#fff', border:'1px solid var(--border-soft)', borderRadius:14, padding:16 };
  const kpi  = (label, value, sub) => (
    <div style={{ ...card, flex:'1 1 150px', minWidth:140, display:'flex', flexDirection:'column' }}>
      <div style={{ fontSize:12, color:'var(--ink-4)', fontWeight:600, minHeight:32, lineHeight:1.3 }}>{label}</div>
      <div style={{ fontSize:24, fontWeight:800, color:'var(--ink)', marginTop:4 }}>{value}</div>
      {sub && <div style={{ fontSize:11, color:'var(--ink-4)', marginTop:2 }}>{sub}</div>}
    </div>
  );

  return (
    <div style={{ flex:1, overflowY:'auto', width:'100%', maxWidth:1100, margin:'0 auto', padding:'24px 28px', boxSizing:'border-box' }}>
      <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between', flexWrap:'wrap', gap:12 }}>
        <div>
          <div style={S.pageTitle}>📈 Reporte Meta Ads × Pipochat</div>
          {data && <div style={{ fontSize:12, color:'var(--ink-4)', marginTop:2 }}>
            Cuenta: <b>{data.accountName}</b> · Moneda: {data.currency} · Actualizado: {new Date(data.generatedAt).toLocaleString('es-AR')}
          </div>}
          {data && data.funnel.trackingSince && <div style={{ fontSize:12, color:'var(--ink-4)', marginTop:2 }}>
            Mensajería contada desde: <b>{fmtDate(data.funnel.trackingSince)}</b>
          </div>}
        </div>
        <div style={{ display:'flex', gap:8, alignItems:'center' }}>
          <select value={preset} onChange={e => { setPreset(e.target.value); load(e.target.value); }}
            style={{ padding:'8px 10px', borderRadius:10, border:'1px solid var(--border-soft)', fontSize:13 }}>
            {PRESETS.map(([v,l]) => <option key={v} value={v}>{l}</option>)}
          </select>
          <button onClick={() => load(preset)} disabled={loading}
            style={{ padding:'8px 16px', background:'var(--green)', color:'#fff', border:'none', borderRadius:10, fontWeight:700, fontSize:13, cursor: loading?'wait':'pointer' }}>
            {loading ? '⏳ Actualizando…' : '🔄 Actualizar'}
          </button>
        </div>
      </div>

      {err && <div style={{ ...card, marginTop:16, background:'#fee2e2', borderColor:'#fca5a5', color:'#991b1b' }}>⚠️ {err}</div>}
      {loading && !data && <div style={{ marginTop:20, color:'var(--ink-4)' }}>Cargando datos de Meta y Pipochat…</div>}

      {data && (
        <div style={{ marginTop:18, display:'flex', flexDirection:'column', gap:18 }}>
          {/* Totales */}
          <div style={{ display:'flex', gap:12, flexWrap:'wrap' }}>
            {kpi('Gasto total', fmt(data.totals.spend))}
            {kpi('Conversaciones', num(data.totals.conversations), 'iniciadas (Meta)')}
            {kpi('Costo / conversación', fmt(data.totals.costPerConv))}
            {kpi('Leads calificados', num(data.totals.qualifiedLeads), `${data.funnel.qualifiedMinMessages}+ mensajes`)}
            {kpi('Costo / lead calificado', fmt(data.totals.costPerQualified))}
            {kpi('Costo / visita', costPerVisit == null ? '—' : fmt(costPerVisit), vNum > 0 ? num(vNum) + ' visitas' : 'cargá las visitas ↓')}
          </div>

          {/* Embudo Pipochat */}
          <div style={card}>
            <div style={{ fontWeight:700, marginBottom:4 }}>🔻 Embudo de conversión (Pipochat)</div>
            <div style={{ fontSize:12, color:'var(--ink-4)', marginBottom:12 }}>
              Lead calificado = contacto con <b>{data.funnel.qualifiedMinMessages} o más mensajes</b> intercambiados
              {data.funnel.trackingSince ? ` (contando desde el ${new Date(data.funnel.trackingSince).toLocaleDateString('es-AR')})` : ''}.
            </div>
            <div style={{ display:'flex', gap:12, flexWrap:'wrap', alignItems:'stretch' }}>
              {kpi('Contactos totales', num(data.funnel.totalContacts))}
              <div style={{ display:'flex', alignItems:'center', fontSize:22, color:'var(--ink-4)' }}>→</div>
              {kpi(`Calificados (${data.funnel.qualifiedMinMessages}+ mensajes)`, num(data.funnel.qualifiedContacts), pct(data.funnel.qualifiedPct) + ' de contactos')}
              <div style={{ display:'flex', alignItems:'center', fontSize:22, color:'var(--ink-4)' }}>→</div>
              <div style={{ ...card, flex:'1 1 180px', minWidth:170, borderColor:'var(--green)' }}>
                <div style={{ fontSize:12, color:'var(--ink-4)', fontWeight:600 }}>Visitas concretadas ✏️</div>
                <div style={{ display:'flex', gap:6, alignItems:'center', marginTop:4 }}>
                  <input type="number" min="0" value={visits}
                    onChange={e => setVisits(e.target.value)} onBlur={saveVisits}
                    onKeyDown={e => { if (e.key === 'Enter') e.target.blur(); }}
                    style={{ width:78, fontSize:22, fontWeight:800, color:'var(--ink)', border:'1px solid var(--border-soft)', borderRadius:8, padding:'2px 8px' }} />
                  {savedV && <span style={{ fontSize:11, color:'var(--green)', fontWeight:700 }}>✓ guardado</span>}
                </div>
                <div style={{ fontSize:11, color:'var(--ink-4)', marginTop:3 }}>{leadToVisit == null ? 'editá el número, se guarda solo' : pct(leadToVisit) + ' de los leads'}</div>
              </div>
            </div>
            <div style={{ display:'flex', gap:12, flexWrap:'wrap', marginTop:12 }}>
              {kpi('% conversión', pct(data.funnel.qualifiedPct), 'contactos → lead calificado')}
              {kpi('Costo por visita', costPerVisit == null ? '—' : fmt(costPerVisit), 'gasto total ÷ visitas')}
            </div>
          </div>

          {/* Campañas */}
          {data.campaigns.map(c => (
            <div key={c.campaignId} style={card}>
              <div style={{ display:'flex', justifyContent:'space-between', flexWrap:'wrap', gap:8, alignItems:'baseline' }}>
                <div style={{ fontWeight:800, fontSize:16 }}>{c.name}</div>
                <div style={{ fontSize:12, color:'var(--ink-4)' }}>Flow: {FLOW_LABEL[c.flowKey] || '—'} · Iniciada: {fmtDate(c.startDate)}</div>
              </div>
              <div style={{ display:'flex', gap:12, flexWrap:'wrap', marginTop:12 }}>
                {kpi('Gasto', fmt(c.spend))}
                {kpi('Conversaciones', num(c.conversations))}
                {kpi('Costo / conversación', fmt(c.costPerConv))}
              </div>

              {/* Anuncios */}
              <div style={{ fontWeight:700, fontSize:13, marginTop:16, marginBottom:8, color:'var(--ink-4)' }}>Anuncios</div>
              <div style={{ display:'flex', gap:12, flexWrap:'wrap' }}>
                {c.ads.map(a => (
                  <div key={a.adId} onClick={() => (a.previewIframe || a.thumbnail) && setPreviewAd(a)}
                    title="Clic para ver el anuncio"
                    style={{ width:230, border:'1px solid ' + (a.isWinner ? 'var(--green)' : 'var(--border-soft)'), borderRadius:12, overflow:'hidden', background:'#fff', boxShadow: a.isWinner ? '0 0 0 2px var(--green) inset' : 'none', cursor: (a.previewIframe || a.thumbnail) ? 'pointer' : 'default' }}>
                    <div style={{ position:'relative', height:150, background:'#f3f4f6', display:'flex', alignItems:'center', justifyContent:'center' }}>
                      {a.thumbnail
                        ? <img src={a.thumbnail} alt={a.name} style={{ width:'100%', height:'100%', objectFit:'cover' }} />
                        : <span style={{ color:'var(--ink-4)', fontSize:12 }}>sin preview</span>}
                      {a.isWinner && <div style={{ position:'absolute', top:8, left:8, background:'var(--green)', color:'#fff', fontSize:11, fontWeight:800, padding:'3px 8px', borderRadius:999 }}>🏆 Ganador</div>}
                      {(a.previewIframe || a.thumbnail) && <div style={{ position:'absolute', bottom:8, right:8, background:'rgba(0,0,0,.6)', color:'#fff', fontSize:11, fontWeight:600, padding:'3px 8px', borderRadius:999 }}>🔍 Ver</div>}
                    </div>
                    <div style={{ padding:'10px 12px' }}>
                      <div style={{ fontWeight:700, fontSize:13, whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis' }}>{a.name}</div>
                      <div style={{ fontSize:12, color:'var(--ink-4)', marginTop:4 }}>Gasto: {fmt(a.spend)}</div>
                      <div style={{ fontSize:12, color:'var(--ink-4)' }}>Conversaciones: {num(a.conversations)}</div>
                      <div style={{ fontSize:13, fontWeight:700, marginTop:2 }}>Costo/conv: {fmt(a.costPerConv)}</div>
                    </div>
                  </div>
                ))}
              </div>
            </div>
          ))}

          {/* Notas */}
          {data.warnings && data.warnings.length > 0 && (
            <div style={{ ...card, background:'#fffbeb', borderColor:'#fde68a', fontSize:12, color:'#92400e' }}>
              <b>Notas metodológicas</b>
              <ul style={{ margin:'8px 0 0', paddingLeft:18 }}>
                {data.warnings.map((w,i) => <li key={i} style={{ marginBottom:4 }}>{w}</li>)}
              </ul>
            </div>
          )}
        </div>
      )}

      {previewAd && (
        <div onClick={() => setPreviewAd(null)} style={{ position:'fixed', inset:0, background:'rgba(0,0,0,.65)', zIndex:10000, display:'flex', alignItems:'center', justifyContent:'center', padding:20 }}>
          <div onClick={e => e.stopPropagation()} style={{ background:'#fff', borderRadius:16, padding:16, width:'100%', maxWidth:420, maxHeight:'92vh', overflow:'auto', boxShadow:'0 20px 60px rgba(0,0,0,.4)' }}>
            <div style={{ display:'flex', justifyContent:'space-between', alignItems:'center', marginBottom:10, gap:10 }}>
              <div style={{ fontWeight:800, fontSize:15 }}>{previewAd.name}{previewAd.isWinner ? ' 🏆' : ''}</div>
              <button onClick={() => setPreviewAd(null)} style={{ background:'transparent', border:'none', fontSize:20, cursor:'pointer', color:'var(--ink-4)', lineHeight:1 }}>✕</button>
            </div>
            {previewAd.previewIframe
              ? <iframe src={previewAd.previewIframe} title={previewAd.name} style={{ width:'100%', height:580, border:'1px solid var(--border-soft)', borderRadius:10 }} />
              : (previewAd.thumbnail ? <img src={previewAd.thumbnail} alt={previewAd.name} style={{ width:'100%', borderRadius:10 }} /> : <div style={{ color:'var(--ink-4)' }}>Sin preview</div>)}
            <div style={{ fontSize:12, color:'var(--ink-4)', marginTop:10 }}>
              Gasto {fmt(previewAd.spend)} · {num(previewAd.conversations)} conversaciones · {fmt(previewAd.costPerConv)}/conv
            </div>
            {previewAd.previewIframe && <a href={previewAd.previewIframe} target="_blank" rel="noreferrer" style={{ fontSize:11, color:'var(--green)', fontWeight:600, display:'inline-block', marginTop:6 }}>Abrir en Meta ↗</a>}
          </div>
        </div>
      )}
    </div>
  );
}

function TenantDashboard({ onLogout }) {
  const [agents, setAgents] = useState([]);
  const [selectedId, setSelectedId] = useState(null);
  const [showNew, setShowNew] = useState(false);
  const [toast, setToast] = useState(null);
  const [contactDetailId, setContactDetailId] = useState(null);

  const _VALID = ['home','agents','kb','media','catalog','properties','tags','conv-rules','op-timeout','no-reply','nurturing','reminders','proactive','contextual-tags','assignment-log','handoff','scoring','campaigns','webhooks','integrations','metrics','meta-report','ctwa','debug','onboarding','instagram','facebook','google-sheets','landings','promotions','account','credits','backup','deliveries','campaign-tokko','contacts','contact-detail'];
  const _ALIASES = { integraciones: 'integrations', metricas: 'metrics', dashboard: 'home' };

  const [view, _setView] = useState(() => {
    try {
      const hash = window.location.hash.replace('#', '');
      if (hash && _VALID.includes(hash)) return hash;
      if (hash && _ALIASES[hash]) return _ALIASES[hash];
      const saved = localStorage.getItem('ll_last_view');
      if (saved && _VALID.includes(saved)) return saved;
    } catch(e) {}
    return 'home';
  });

  // Wrap setView so every navigation is persisted immediately
  const setView = (v) => {
    _setView(v);
    try {
      localStorage.setItem('ll_last_view', v);
      window.history.replaceState({}, '', v && v !== 'agents' ? '#' + v : window.location.pathname + window.location.search);
    } catch(e) {}
  };
  const [pipochatData, setPipochatData] = useState({ pipelines:[], tags:[], users:[], teams:[], chatbots:[], templates:[], meetings:[], inboxes:[], connected:false });

  // Handle OAuth redirect params on mount
  useEffect(() => {
    const params = new URLSearchParams(window.location.search);
    const gcal = params.get('gcal');
    if (gcal === 'connected') {
      setToast({ type: 'success', msg: '✅ Google Calendar conectado correctamente' });
      setTimeout(() => setToast(null), 5000);
    } else if (gcal === 'error') {
      const msg = params.get('msg') || 'Error desconocido';
      setToast({ type: 'error', msg: `❌ Error conectando Google Calendar: ${msg}` });
      setTimeout(() => setToast(null), 7000);
    }
    // Clean up URL params without reloading
    if (gcal) {
      const url = window.location.pathname + window.location.hash;
      window.history.replaceState({}, '', url);
    }
  }, []);

  // Load pipochat data once
  useEffect(() => {
    apiFetch('/api/pipochat/status').then(r => r.json()).then(status => {
      // External API works → show connected; internal JWT may or may not be ready
      if (!status.connected) return;

      // Always set connected=true based on external API
      setPipochatData(prev => ({ ...prev, connected: true }));

      // Only load internal-API data if JWT is authenticated
      if (status.internalApi?.status !== 'authenticated') return;

      Promise.all([
        apiFetch('/api/pipochat/pipelines').then(r => r.json()),
        apiFetch('/api/pipochat/tags').then(r => r.json()),
        apiFetch('/api/pipochat/users').then(r => r.json()),
        apiFetch('/api/pipochat/teams').then(r => r.json()),
        apiFetch('/api/pipochat/chatbots').then(r => r.json()),
        apiFetch('/api/pipochat/templates').then(r => r.json()),
        apiFetch('/api/pipochat/meetings').then(r => r.json()),
        apiFetch('/api/pipochat/inboxes').then(r => r.json()).catch(() => ({ inboxes: [] })),
      ]).then(([pd, td, ud, tmd, cbd, tmpl, mtg, ibx]) => {
        const users = (ud.users || [])
          .filter(u => !u.roles?.includes('bot'))
          .map(u => ({ _id: u._id, name: u.fullName || u.name || u.email || u._id, email: u.email }));
        const teams = (tmd.teams || []).map(t => ({ _id: t._id, name: t.title || t.name || t._id, operatorIds: t.operatorIds || [] }));
        const inboxes = (ibx.inboxes || []).map(i => ({ _id: i._id, name: i.name || i.phoneNumber || i._id, phoneNumber: i.phoneNumber }));
        setPipochatData({
          pipelines: pd.pipelines || [],
          tags:      td.tags      || [],
          users,
          teams,
          chatbots:  cbd.chatbots || [],
          templates: tmpl.templates || [],
          meetings:  mtg.meetings  || [],
          inboxes,
          connected: true,
        });
      }).catch(() => {});
    }).catch(() => {});
  }, []);

  const loadAgents = useCallback(async () => {
    const list = await api.list();
    setAgents(list);
    if (!selectedId && list.length > 0) setSelectedId(list[0].id);
  }, [selectedId]);

  useEffect(() => { loadAgents(); }, []);

  const selectedAgent = agents.find(a => a.id === selectedId);

  const navItem = (v, icon, label) => (
    <button style={S.sideItem(view === v)} onClick={() => setView(v)}>
      <span>{icon}</span><span>{label}</span>
    </button>
  );

  const navItemSub = (v, icon, label, hint) => (
    <button style={S.sideItemWithSub(view === v)} onClick={() => setView(v)}>
      <div style={S.sideItemLabel}><span>{icon}</span><span>{label}</span></div>
      <div style={S.sideItemHint(view === v)}>{hint}</div>
    </button>
  );

  return (
    <PipochatCtx.Provider value={pipochatData}>
      {toast && (
        <div style={{ position:'fixed', top:18, left:'50%', transform:'translateX(-50%)', zIndex:9999,
          background: toast.type === 'success' ? '#dcfce7' : '#fee2e2',
          color: toast.type === 'success' ? '#15803d' : '#991b1b',
          border: `1px solid ${toast.type === 'success' ? '#86efac' : '#fca5a5'}`,
          borderRadius:10, padding:'10px 20px', fontSize:14, fontWeight:600,
          boxShadow:'0 4px 20px rgba(0,0,0,.12)', maxWidth:500, textAlign:'center' }}>
          {toast.msg}
        </div>
      )}
      <div style={S.app}>
        {/* Sidebar */}
        <div style={S.sidebar}>
          <div style={S.sideHeader}>
            <PipochatLogo size={38} />
            <div>
              <div style={S.sideTitle}>
                <span style={{ color:'var(--ink)' }}>pipo</span><span style={{ color:'var(--green)' }}>chat</span>
              </div>
              <div style={S.sideSubtitle}>
                {pipochatData.connected
                  ? <span style={{ color:'var(--green)', fontWeight:600 }}>● Conectado</span>
                  : <span style={{ display:'flex', alignItems:'center', gap:6 }}>
                      <span style={{ color:'#B45309', fontWeight:600 }}>● Sin conexión</span>
                      <ReconnectBtn />
                    </span>}
              </div>
            </div>
          </div>

          {/* Home */}
          <div style={{ padding:'0 10px 10px' }}>
            {navItem('home', '🏠', 'Dashboard')}
            {navItem('copilot', '🤖', 'Copiloto')}
          </div>

          {/* Agents list */}
          <div style={S.sideSection}>
            <div style={S.sideSectionLabel}>Mis agentes</div>
            {agents.length === 0 && (
              <p style={{ fontSize:12, color:'var(--ink-4)', padding:'4px 10px' }}>Sin agentes aún</p>
            )}
            {agents.map(a => (
              <button key={a.id} style={S.sideItem(view === 'agents' && a.id === selectedId)}
                onClick={() => { setView('agents'); setSelectedId(a.id); }}>
                <div style={S.sideItemDot(a.isActive)} />
                <span style={{ overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap' }}>{a.name}</span>
              </button>
            ))}
            <button style={S.newBtn} onClick={() => setShowNew(true)}>+ Nuevo agente</button>
          </div>

          {/* Conocimiento */}
          <div style={{ ...S.sideSection, borderTop:'1px solid var(--border-soft)', paddingTop:16 }}>
            <div style={S.sideSectionLabel}>Conocimiento</div>
            {navItem('kb',      '📚', 'Base de conocimiento')}
            {navItem('learning','🧠', 'Aprendizaje')}
            {navItem('media',   '📎', 'Archivos')}
            {navItem('catalog',    '🏪', 'Catálogo')}
            {navItem('properties', '🏠', 'Propiedades')}
          </div>

          {/* Automatizaciones */}
          <div style={{ ...S.sideSection, borderTop:'1px solid var(--border-soft)', paddingTop:16 }}>
            <div style={S.sideSectionLabel}>Automatizaciones</div>
            {navItemSub('conv-rules', '⚡', 'Reglas',          'Por evento o condición')}
            {navItemSub('no-reply',   '💤', 'Sin respuesta',   'Contacto no respondió al bot')}
            {navItemSub('op-timeout', '⏱️', 'Timeout operador','Operador inactivo')}
            {navItemSub('assignment-log', '🎯', 'Logs asignación','Reparto del round-robin')}
            {navItemSub('nurturing',  '🌱', 'Nurturing',       'Secuencias programadas')}
            {navItemSub('reminders',  '🔔', 'Recordatorios',   'WhatsApp antes de reuniones')}
            {navItemSub('proactive',  '🤖', 'Agente Proactivo','Follow-up automático con IA')}
            {navItemSub('contextual-tags', '🏷️', 'Etiquetado IA',  'Tags automáticos por contexto')}
            {navItemSub('handoff',    '🤝', 'Handoff',         'Resumen IA para el asesor')}
            {navItemSub('scoring',    '⭐', 'Lead Scoring',    'Puntaje 1-10 por conversación')}
            {navItemSub('campaigns',  '📢', 'Campañas',        'Difusión masiva personalizada')}
          </div>

          {/* Integraciones & Métricas */}
          <div style={{ ...S.sideSection, borderTop:'1px solid var(--border-soft)', paddingTop:16 }}>
            <div style={S.sideSectionLabel}>Datos</div>
            {navItemSub('integrations', '🔌', 'Integraciones', 'Tokko, Meta, Lead Ads')}
            {navItemSub('instagram',     React.createElement(IGIcon, {size: 18}), 'Instagram',      'DMs y comentarios con IA')}
            {navItemSub('facebook',      React.createElement(FBIcon, {size: 18}), 'Facebook',       'Messenger y comentarios con IA')}
            {navItemSub('google-sheets', React.createElement(GSIcon, {size: 18}), 'Google Sheets',  'Leer y escribir en planillas')}
            {navItemSub('landings',      React.createElement(LandIcon, {size: 18}), 'Landing Pages',  'Páginas para captar leads')}
            {navItemSub('promotions',    '🎁', 'Promociones',     'Keywords que disparan promos con imagen y fecha')}
            {navItemSub('wa-flows',     '📱', 'WA Flows',        'Constructor de formularios nativos de WhatsApp')}
            {navItemSub('webhooks',      '🔗', 'Webhooks',       'Conectar con Zapier / Make')}
            {navItem('campaign-tokko', '📣', 'Difusión → Tokko')}
            {navItem('deliveries', '📤', 'Envíos de leads')}
            {navItem('contacts', '📇', 'Contactos')}
            {navItem('metrics', '📊', 'Métricas')}
            {navItem('meta-report', '📈', 'Reporte Meta')}
            {navItem('ctwa',    '🎯', 'Campañas CTWA')}
            {navItem('debug',   '🔍', 'Debug Webhooks')}
          </div>

          {/* Configuración */}
          <div style={{ ...S.sideSection, borderTop:'1px solid var(--border-soft)', paddingTop:16 }}>
            <div style={S.sideSectionLabel}>Configuración</div>
            {navItem('account',   '👤', 'Mi cuenta')}
            {navItem('tags',      '🏷️', 'Etiquetas')}
            {navItem('onboarding','🚀', 'Configuración AI')}
            {navItem('credits',   '💳', 'Créditos')}
            {navItem('backup',    '💾', 'Backup & Restaurar')}
          </div>

          {/* Logout */}
          <div style={{ marginTop:'auto', padding:'10px 10px 14px', borderTop:'1px solid var(--border-soft)' }}>
            <button onClick={() => { clearSession(); onLogout(); }}
              style={{ width:'100%', padding:'8px 14px', background:'transparent', color:'var(--ink-4)', border:'1px solid var(--border-soft)', borderRadius:10, fontSize:12, cursor:'pointer', textAlign:'left', transition:'color .15s' }}>
              {localStorage.getItem('ll_admin_token') ? '← Volver al panel admin' : '↩ Cerrar sesión'}
            </button>
          </div>
        </div>

        {/* Main */}
        <div style={S.main}>
          {view === 'home'        && <HomePanel />}
          {view === 'copilot'     && <CopilotPanel />}
          {view === 'onboarding' && <OnboardingPanel />}
          {view === 'kb'         && <KBPanel />}
          {view === 'learning'   && <LearningPanel />}
          {view === 'media'      && <MediaPanel />}
          {view === 'catalog'    && <CatalogPanel />}
          {view === 'properties' && <PropertyPanel />}
          {view === 'tags'       && <TagsPanel />}
          {view === 'conv-rules' && <ConvRulesPanel />}
          {view === 'op-timeout' && <OperatorTimeoutPanel />}
          {view === 'no-reply'   && <ContactNoReplyPanel />}
          {view === 'nurturing'     && <NurturingPanel />}
          {view === 'reminders'     && <RemindersPanel />}
          {view === 'proactive'     && <ProactivePanel />}
          {view === 'contextual-tags' && <ContextualTagsPanel />}
          {view === 'assignment-log' && <AssignmentLogPanel />}
          {view === 'handoff'       && <HandoffPanel />}
          {view === 'scoring'       && <ScoringPanel />}
          {view === 'campaigns'     && <CampaignsPanel />}
          {view === 'instagram'     && <InstagramPanel />}
          {view === 'facebook'      && <FacebookPanel />}
          {view === 'google-sheets' && <GoogleSheetsPanel />}
          {view === 'landings'      && <LandingsPanel />}
          {view === 'promotions'    && <PromotionsPanel />}
          {view === 'wa-flows'      && <FlowsPanel />}
          {view === 'webhooks'      && <WebhookPanel />}
          {view === 'integrations'  && <IntegracionesPanel />}
          {view === 'campaign-tokko' && <CampaignTokkoPanel />}
          {view === 'deliveries'    && <DeliveriesPanel />}
          {view === 'contacts'      && <ContactsTablePanel onOpenDetail={(id) => { setContactDetailId(id); setView('contact-detail'); }} />}
          {view === 'contact-detail' && <ContactDetailPanel contactId={contactDetailId} onBack={() => setView('contacts')} />}
          {view === 'metrics'       && <MetricsPanel />}
          {view === 'meta-report'   && <MetaReportPanel />}
          {view === 'ctwa'          && <CTWAPanel />}
          {view === 'debug'         && <DebugPanel />}
          {view === 'credits'       && <CreditsPanel />}
          {view === 'account'       && <AccountPanel onGoCredits={() => setView('credits')} />}
          {view === 'backup'        && <BackupPanel />}
          {view === 'agents' && (
            <>
              <AgentEditor agentId={selectedId} onDelete={() => { setAgents(a => a.filter(x => x.id !== selectedId)); setSelectedId(null); loadAgents(); }} />
              <TestChatPanel agentId={selectedId} agentName={selectedAgent?.name} />
            </>
          )}
        </div>
      </div>

      {showNew && <NewAgentModal onClose={() => setShowNew(false)} onCreate={agent => { setAgents(a => [...a, agent]); setSelectedId(agent.id); setView('agents'); }} />}
    </PipochatCtx.Provider>
  );
}

// ─── App (session router) ─────────────────────────────────────────────────────
function ImpersonationBar() {
  const back = () => {
    const adminToken = localStorage.getItem('ll_admin_token');
    localStorage.removeItem('ll_admin_token');
    if (adminToken) saveSession(adminToken, 'admin'); else clearSession();
    window.location.reload();
  };
  return (
    <div style={{ position:'fixed', bottom:14, left:'50%', transform:'translateX(-50%)', zIndex:9999,
      background:'#111827', color:'#fff', borderRadius:999, padding:'8px 16px', display:'flex', alignItems:'center', gap:12,
      boxShadow:'0 4px 18px rgba(0,0,0,.35)', fontSize:12.5, fontWeight:600 }}>
      <span>⚡ Estás dentro de un tenant como Admin</span>
      <button onClick={back} style={{ background:'#ef4444', color:'#fff', border:'none', borderRadius:999, padding:'5px 12px', fontSize:12, fontWeight:700, cursor:'pointer' }}>
        ← Volver al Admin
      </button>
    </div>
  );
}

// Modo "solo wizard" para el link compartido /onboarding/<token> — sin login, sin menú.
function OnboardingLinkApp({ token }) {
  return (
    <div style={{ minHeight:'100vh', background:'var(--cream)' }}>
      <div style={{ background:'var(--surface)', borderBottom:'1px solid var(--border)', padding:'14px 24px', display:'flex', alignItems:'center', gap:10 }}>
        <span style={{ fontWeight:800, fontSize:18, color:'var(--green)' }}>Looplead</span>
        <span style={{ fontSize:13, color:'var(--ink-3)' }}>· Configuración inicial</span>
      </div>
      <div style={{ maxWidth:780, margin:'0 auto', padding:'24px 16px' }}>
        <OnboardingWizardPanel obToken={token} />
      </div>
    </div>
  );
}

function App() {
  const [session, setSession] = useState(() => getToken() ? { token: getToken(), role: getRole() } : null);

  if (!session) return <LoginScreen onLogin={(role) => setSession({ token: getToken(), role })} />;
  if (session.role === 'admin') return <AdminPanel onLogout={() => setSession(null)} />;
  const impersonating = !!localStorage.getItem('ll_admin_token');
  return (
    <React.Fragment>
      <TenantDashboard onLogout={() => {
        const adminToken = localStorage.getItem('ll_admin_token');
        if (adminToken) { localStorage.removeItem('ll_admin_token'); saveSession(adminToken, 'admin'); window.location.reload(); }
        else setSession(null);
      }} />
      {impersonating && <ImpersonationBar />}
    </React.Fragment>
  );
}

const __obLink = window.location.pathname.match(/^\/onboarding\/([^/]+)\/?$/);
ReactDOM.createRoot(document.getElementById('root')).render(
  __obLink ? <OnboardingLinkApp token={decodeURIComponent(__obLink[1])} /> : <App />
);
