// AGENTFORGE-IA — Biblioteca
const Library = ({ data, openAgent, setRoute, onDeleteCustomAgent, onRunAgent, onEditAgent, onDeployAgent }) => {
  const me = (() => { try { return JSON.parse(sessionStorage.getItem('af_user')); } catch { return null; } })();
  const cats = data.categories;
  const [rows, setRows] = React.useState([]);
  const [loadingRows, setLoadingRows] = React.useState(true);
  const [rowsError, setRowsError] = React.useState('');
  const [busyCancelId, setBusyCancelId] = React.useState('');
  const [personalizeOpen, setPersonalizeOpen] = React.useState(false);
  const [personalizeRow, setPersonalizeRow] = React.useState(null);
  const [personalizeForm, setPersonalizeForm] = React.useState({
    empresa: '',
    descripcion: '',
    productos: '',
    audiencia: '',
    tono: 'profesional',
    faqs: '',
    instrucciones: '',
  });
  const [personalizeSaving, setPersonalizeSaving] = React.useState(false);
  const [renameOpen, setRenameOpen] = React.useState(false);
  const [renameRow, setRenameRow] = React.useState(null);
  const [renameForm, setRenameForm] = React.useState({ name: '', tagline: '' });
  const [renameSaving, setRenameSaving] = React.useState(false);
  const [openRowMenu, setOpenRowMenu] = React.useState('');
  const [deploymentFilter, setDeploymentFilter] = React.useState('all');
  const [menuPos, setMenuPos] = React.useState({ x: 0, y: 0 });
  const menuRef = React.useRef(null);

  /**
   * Devuelve una identidad estable para comparar filas sin usar el nombre.
   * @param {Record<string, any>} row
   * @returns {string}
   */
  const rowStableKey = React.useCallback((row) => {
    const dbId = String(row?.agentDbId || row?.agent?.agentDbId || '').trim();
    if (dbId) return `db:${dbId}`;
    const slug = String(row?.id || row?.agent?.id || row?.agent?.slug || '').trim();
    return slug ? `slug:${slug}` : '';
  }, []);

  /**
   * Actualiza caches locales para que el nombre sea coherente al volver de ruta.
   * @param {string} agentId
   * @param {string} agentSlug
   * @param {string} name
   * @param {string} tagline
   * @returns {void}
   */
  const persistLocalRename = React.useCallback((agentId, agentSlug, name, tagline) => {
    const matchesAgent = (agent) => (
      String(agent?.agentDbId || '') === String(agentId || '') ||
      String(agent?.id || '') === String(agentSlug || '') ||
      String(agent?.slug || '') === String(agentSlug || '')
    );
    try {
      const raw = localStorage.getItem('af_custom_agents_v1') || '[]';
      const list = JSON.parse(raw);
      if (Array.isArray(list)) {
        localStorage.setItem('af_custom_agents_v1', JSON.stringify(list.map((agent) => (
          matchesAgent(agent)
            ? { ...agent, name, tagline: tagline || agent.tagline || '', updatedAt: Date.now() }
            : agent
        ))));
      }
    } catch (_) {}
    try {
      const latest = JSON.parse(localStorage.getItem('af_last_created_agent') || 'null');
      if (latest && matchesAgent(latest)) {
        localStorage.setItem('af_last_created_agent', JSON.stringify({
          ...latest,
          name,
          tagline: tagline || latest.tagline || '',
          updatedAt: Date.now(),
        }));
      }
    } catch (_) {}
  }, []);

  /**
   * Carga agentes instalados del usuario autenticado.
   * @returns {Promise<void>}
   */
  const loadPurchasedAgents = React.useCallback(async () => {
    const token = sessionStorage.getItem('af_token') || '';
    if (!token) {
      setRows([]);
      setLoadingRows(false);
      return;
    }

    setLoadingRows(true);
    setRowsError('');
    try {
      const res = await fetch('/api/v1/purchases/my-agents', {
        headers: { Authorization: 'Bearer ' + token },
      });
      if (!res.ok) {
        let reason = `HTTP ${res.status}`;
        try {
          const payload = await res.json();
          reason = payload?.detail || reason;
        } catch (_) {}
        setRowsError(`No se pudieron cargar tus agentes instalados (${reason}).`);
        setRows([]);
        return;
      }
      const purchased = await res.json();
      const normalized = (Array.isArray(purchased) ? purchased : []).map((p, idx) => {
        const agent = data.agents.find((a) => a.id === p.agent_slug);
        const cat = agent ? cats.find((c) => c.id === agent.cat) : null;
        const visibleAgent = {
          ...(agent || {}),
          id: p.agent_slug || String(p.agent_id),
          name: p.agent_name || agent?.name || 'Agente',
          tagline: p.agent_tagline || agent?.tagline || '',
          baseName: p.base_agent_name || agent?.name || '',
          color: agent?.color || '#ff5b1f',
          verified: !!agent?.verified,
        };
        return {
          id: p.agent_slug || p.agent_id,
          agentDbId: p.agent_id || '',
          deployment: p.status === 'active' ? 'producción' : p.status || 'activo',
          region: 'eu-west',
          runs7d: 0,
          success: 1.0,
          p95: 0,
          owner: (me?.full_name || me?.email || 'U').slice(0, 2).toUpperCase(),
          lastRun: '—',
          cost7d: 0,
          agent: visibleAgent,
          cat,
          _idx: idx,
        };
      });
      setRows(normalized);
      setRowsError('');
    } catch (_) {
      setRowsError('Error de red al cargar la biblioteca.');
      setRows([]);
    } finally {
      setLoadingRows(false);
    }
  }, [cats, data.agents, me?.email, me?.full_name]);

  const loadPersonalization = React.useCallback((agentId) => {
    try {
      const raw = localStorage.getItem('af_agent_ctx_' + agentId);
      if (!raw) return null;
      return JSON.parse(raw);
    } catch (_) { return null; }
  }, []);

  const savePersonalization = React.useCallback(async (agentId, form) => {
    try {
      localStorage.setItem('af_agent_ctx_' + agentId, JSON.stringify(form));
      window.afNotify && window.afNotify('Contexto del agente guardado');
    } catch (_) {
      window.afNotify && window.afNotify('No se pudo guardar el contexto');
    }
  }, []);

  const openRenameAgent = React.useCallback((row) => {
    setRenameRow(row);
    setRenameForm({
      name: row?.agent?.name || '',
      tagline: row?.agent?.tagline || '',
    });
    setRenameOpen(true);
  }, []);

  const saveRenameAgent = React.useCallback(async () => {
    const token = sessionStorage.getItem('af_token') || '';
    const name = renameForm.name.trim();
    const agentId = renameRow?.agentDbId || renameRow?.agent?.agentDbId || '';
    const agentSlug = renameRow?.id || renameRow?.agent?.id || '';
    const tagline = renameForm.tagline.trim();
    if (!name) {
      window.afNotify && window.afNotify('El nombre del agente es obligatorio');
      return;
    }
    setRenameSaving(true);
    try {
      let updated = null;
      if (agentId && token) {
        let res = await fetch('/api/v1/purchases/' + agentId, {
          method: 'PATCH',
          headers: { 'Content-Type': 'application/json', Authorization: 'Bearer ' + token },
          body: JSON.stringify({
            display_name: name,
            display_tagline: tagline || null,
          }),
        });
        if (!res.ok && (res.status === 403 || res.status === 404)) {
          res = await fetch('/api/v1/agents/' + agentId, {
            method: 'PATCH',
            headers: { 'Content-Type': 'application/json', Authorization: 'Bearer ' + token },
            body: JSON.stringify({
              name,
              tagline: tagline || null,
            }),
          });
        }
        if (!res.ok) {
          window.afNotify && window.afNotify('No se pudo renombrar el agente');
          return;
        }
        updated = await res.json().catch(() => null);
      }
      const finalName = updated?.agent_name || updated?.name || name;
      const finalTagline = updated?.agent_tagline || updated?.tagline || tagline;
      persistLocalRename(agentId, agentSlug, finalName, finalTagline);
      try {
        window.dispatchEvent(new CustomEvent('af:agent:renamed', {
          detail: {
            agentId: String(agentId || ''),
            agentSlug: String(agentSlug || ''),
            agentName: finalName,
            agentTagline: finalTagline,
          },
        }));
      } catch (_) {}
      try { window.dispatchEvent(new CustomEvent('af:catalog:refresh')); } catch (_) {}
      window.afNotify && window.afNotify('Nombre del agente actualizado');
      setRenameOpen(false);
      setRenameRow(null);
      await loadPurchasedAgents();
    } catch (_) {
      window.afNotify && window.afNotify('Error de red al renombrar');
    } finally {
      setRenameSaving(false);
    }
  }, [loadPurchasedAgents, persistLocalRename, renameForm.name, renameForm.tagline, renameRow]);

  /**
   * Elimina un agente local del espacio del usuario.
   * @param {string} localAgentId
   * @returns {void}
   */
  const removeLocalAgent = React.useCallback((localAgentId) => {
    if (!localAgentId) return;
    const ok = window.confirm('¿Eliminar este agente local de tu espacio?');
    if (!ok) return;
    if (typeof onDeleteCustomAgent === 'function') {
      onDeleteCustomAgent(localAgentId);
    }
    const last = localStorage.getItem('af_last_created_agent');
    if (last) {
      try {
        const parsed = JSON.parse(last);
        if (parsed?.id === localAgentId) {
          localStorage.removeItem('af_last_created_agent');
        }
      } catch (_) {}
    }
    window.afNotify && window.afNotify('Agente local eliminado');
  }, [onDeleteCustomAgent]);

  /**
   * Elimina un agente instalado del espacio del usuario.
   * @param {string} agentDbId UUID del agente en base de datos.
   * @returns {Promise<void>}
   */
  const cancelPurchasedAgent = React.useCallback(async (agentDbId) => {
    if (!agentDbId) return;
    const ok = window.confirm('¿Eliminar este agente de tu espacio? Se desactivarán también sus despliegues. Podrás volver a comprarlo cuando quieras.');
    if (!ok) return;
    setBusyCancelId(agentDbId);
    try {
      const token = sessionStorage.getItem('af_token') || '';
      const res = await fetch('/api/v1/purchases/' + agentDbId, {
        method: 'DELETE',
        headers: { Authorization: 'Bearer ' + token },
      });
      if (!res.ok) {
        let reason = `HTTP ${res.status}`;
        try {
          const payload = await res.json();
          reason = payload?.detail || reason;
        } catch (_) {}
        window.afNotify && window.afNotify(`No se pudo eliminar el agente (${reason})`);
        return;
      }
      window.afNotify && window.afNotify('Agente eliminado correctamente');
      await loadPurchasedAgents();
    } catch (_) {
      window.afNotify && window.afNotify('Error de red al eliminar el agente');
    } finally {
      setBusyCancelId('');
    }
  }, [loadPurchasedAgents]);

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

  React.useEffect(() => {
    const refresh = () => loadPurchasedAgents();
    window.addEventListener('af:library:refresh', refresh);
    return () => window.removeEventListener('af:library:refresh', refresh);
  }, [loadPurchasedAgents]);

  React.useEffect(() => {
    const applyRename = (event) => {
      const detail = event?.detail || {};
      const agentId = String(detail.agentId || '');
      const agentSlug = String(detail.agentSlug || '');
      const agentName = String(detail.agentName || '').trim();
      const agentTagline = String(detail.agentTagline || '').trim();
      if (!agentName || (!agentId && !agentSlug)) return;

      setRows((prev) => prev.map((row) => {
        const sameAgent =
          String(row.agentDbId || '') === agentId ||
          String(row.id || '') === agentSlug ||
          String(row.agent?.id || '') === agentSlug;
        if (!sameAgent) return row;
        return {
          ...row,
          agent: {
            ...(row.agent || {}),
            name: agentName,
            tagline: agentTagline || row.agent?.tagline || '',
          },
        };
      }));
    };

    window.addEventListener('af:agent:renamed', applyRename);
    return () => window.removeEventListener('af:agent:renamed', applyRename);
  }, []);

  React.useEffect(() => {
    if (!openRowMenu) return;
    const onDocClick = (e) => {
      if (menuRef.current && !menuRef.current.contains(e.target)) {
        setOpenRowMenu('');
      }
    };
    document.addEventListener('mousedown', onDocClick);
    return () => document.removeEventListener('mousedown', onDocClick);
  }, [openRowMenu]);

  React.useLayoutEffect(() => {
    if (!openRowMenu || !menuRef.current) return;
    const rect = menuRef.current.getBoundingClientRect();
    const margin = 10;
    let nextX = menuPos.x;
    let nextY = menuPos.y;
    if (rect.right > window.innerWidth - margin) {
      nextX -= (rect.right - (window.innerWidth - margin));
    }
    if (rect.left < margin) {
      nextX += (margin - rect.left);
    }
    if (rect.bottom > window.innerHeight - margin) {
      nextY -= (rect.bottom - (window.innerHeight - margin));
    }
    if (rect.top < margin) {
      nextY += (margin - rect.top);
    }
    if (nextX !== menuPos.x || nextY !== menuPos.y) {
      setMenuPos({ x: nextX, y: nextY });
    }
  }, [openRowMenu, menuPos.x, menuPos.y]);


  // "Mis agentes" debe representar solo instalaciones activas del backend.
  // Los borradores/locales viven en Editor/Marketplace para evitar reapariciones fantasma.
  const allRows = Array.from(
    rows.reduce((acc, row) => {
      const key = rowStableKey(row);
      if (!key) return acc;
      const current = acc.get(key);
      if (!current || (!current.agentDbId && row.agentDbId)) {
        acc.set(key, row);
      }
      return acc;
    }, new Map()).values()
  );
  const visibleRows = allRows.filter((r) => {
    if (deploymentFilter === 'all') return true;
    if (deploymentFilter === 'live') return r.deployment === 'producción' || r.deployment === 'active';
    if (deploymentFilter === 'draft') return r.deployment === 'borrador' || r.deployment === 'draft';
    if (deploymentFilter === 'staging') return r.deployment === 'staging';
    return true;
  });

  const totalRuns = visibleRows.reduce((s, r) => s + (r.runs7d || 0), 0);
  const totalCost = visibleRows.reduce((s, r) => s + (r.cost7d || 0), 0);
  const liveCount = visibleRows.filter(r => r.deployment === 'producción' || r.deployment === 'active').length;
  const avgSuccess = visibleRows.length > 0 ? visibleRows.reduce((s, r) => s + (r.success || 0), 0) / visibleRows.length : 0;
  const fmt = n => n.toLocaleString('es-ES');

  /**
   * Abre el playground con el agente seleccionado.
   * @param {string} agentId
   * @returns {void}
   */
  const openPlaygroundFor = (agentId) => {
    if (typeof onRunAgent === 'function') {
      onRunAgent(agentId);
      return;
    }
    setRoute('playground');
  };

  /**
   * Exporta la tabla actual de agentes a CSV.
   * @returns {void}
   */
  const exportLibraryCsv = () => {
    const header = ['agente', 'estado', 'region', 'ejec_7d', 'exito', 'latencia_p95', 'propietario', 'ultima_ejec'];
    const rowsCsv = allRows.map((r) => [
      r.agent?.name || r.id,
      r.deployment,
      r.region,
      String(r.runs7d || 0),
      r.runs7d > 0 ? `${(r.success * 100).toFixed(1)}%` : 'N/D',
      r.p95 ? `${r.p95} ms` : 'N/D',
      r.owner,
      r.lastRun || 'N/D',
    ]);
    const csv = [header, ...rowsCsv]
      .map((line) => line.map((v) => `"${String(v).replaceAll('"', '""')}"`).join(','))
      .join('\n');
    const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = 'agentforge-mis-agentes.csv';
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);
    URL.revokeObjectURL(url);
    window.afNotify && window.afNotify('Exportación de Mis agentes completada');
  };

  const Spark = ({ color, seed = 1 }) => {
    const pts = Array.from({ length: 24 }, (_, i) => {
      const v = 0.4 + 0.6 * Math.abs(Math.sin(i * 0.6 + seed) * Math.cos(i * 0.3 + seed * 1.7));
      return [i * (100/23), 28 - v * 22];
    });
    const d = 'M ' + pts.map(p => p.join(',')).join(' L ');
    return (
      <svg className="kpi-spark" viewBox="0 0 100 28" preserveAspectRatio="none">
        <path d={d} fill="none" stroke={color} strokeWidth="1.4" />
        <path d={d + ` L 100,28 L 0,28 Z`} fill={color} opacity="0.12" />
      </svg>
    );
  };

  return (
    <div>
      <div className="page-head">
        <h1>Mis agentes</h1>
        <span className="crumbs mono">espacio <span>›</span> <span style={{ color: 'var(--ink)' }}>{me?.name || 'Mi espacio'} / producción</span></span>
        <div className="actions">
          <select className="select" value={deploymentFilter} onChange={(e) => setDeploymentFilter(e.target.value)} style={{ width: 170 }}>
            <option value="all">Estado: todos</option>
            <option value="live">Estado: producción</option>
            <option value="staging">Estado: staging</option>
            <option value="draft">Estado: borrador</option>
          </select>
          <button className="btn btn-primary" onClick={() => setRoute('onboarding')}><Icon name="plus" size={13} /> Nuevo agente</button>
        </div>
      </div>

      <div className="section">
        <div className="kpi-row">
          <div className="kpi"><div className="lbl">Despliegues activos</div><div className="val">{liveCount}<small style={{ fontSize: 13, color: 'var(--ink-3)', fontWeight: 400 }}> / {visibleRows.length}</small></div><div className="delta"><Icon name="check" size={11} /> estado actual</div><Spark color="var(--ok)" seed={1} /></div>
          <div className="kpi"><div className="lbl">Ejecuciones · últimos 7 d</div><div className="val">{(totalRuns/1000).toFixed(1).replace('.',',')} k</div><div className="delta"><Icon name="check" size={11} /> agregado visible</div><Spark color="var(--brand)" seed={3} /></div>
          <div className="kpi"><div className="lbl">Tasa de éxito media</div><div className="val">{allRows.length ? (avgSuccess*100).toFixed(1).replace('.',',') + ' %' : 'N/D'}</div><div className="delta"><Icon name="check" size={11} /> promedio actual</div><Spark color="var(--info)" seed={5} /></div>
          <div className="kpi"><div className="lbl">Gasto · últimos 7 d</div><div className="val">{totalCost.toFixed(2).replace('.',',')} €</div><div className="delta"><Icon name="check" size={11} /> coste acumulado</div><Spark color="var(--violet)" seed={7} /></div>
        </div>

        <div className="section-title" style={{ marginTop: 28 }}>
          <span>Agentes desplegados</span><span style={{ color: 'var(--ink-4)' }}>·</span>
          <span style={{ color: 'var(--ink-3)', textTransform: 'none', letterSpacing: 0, fontFamily: 'var(--sans)' }}>{visibleRows.length} visibles</span>
          <span className="line" />
          <button className="btn btn-ghost btn-sm" onClick={exportLibraryCsv}><Icon name="download" size={11} /> Exportar CSV</button>
        </div>

        {rowsError && rows.length === 0 && (
          <div style={{ marginBottom: 12, padding: '10px 12px', border: '1px solid rgba(255,91,31,0.3)', borderRadius: 8, color: '#ff9b7a', fontSize: 12.5, display: 'flex', justifyContent: 'space-between', alignItems: 'center', gap: 10 }}>
            <span>{rowsError}</span>
            <div style={{ display: 'flex', gap: 8 }}>
              <button className="btn btn-sm" onClick={loadPurchasedAgents}>Reintentar</button>
              <button className="btn btn-sm btn-primary" onClick={() => setRoute('marketplace')}>Marketplace</button>
            </div>
          </div>
        )}

        <div className="card" style={{ overflow: 'visible' }}>
          <table className="lib-table">
            <thead>
              <tr>
                <th style={{ paddingLeft: 16 }}>Agente</th>
                <th>Estado</th>
                <th>Región</th>
                <th>Ejec. · 7 d</th>
                <th>Éxito</th>
                <th>Latencia p95</th>
                <th>Propietario</th>
                <th>Última ejec.</th>
                <th style={{ paddingRight: 16, textAlign: 'right' }}>Acciones</th>
              </tr>
            </thead>
            <tbody>
              {loadingRows && (
                <tr>
                  <td colSpan={9} style={{ padding: '16px', color: 'var(--ink-3)' }}>Cargando agentes instalados...</td>
                </tr>
              )}
              {!loadingRows && visibleRows.length === 0 && (
                <tr>
                  <td colSpan={9} style={{ padding: '16px', color: 'var(--ink-3)' }}>No hay agentes para el filtro seleccionado.</td>
                </tr>
              )}
              {visibleRows.map(r => (
                <tr key={r.id} style={{ cursor: 'pointer' }} onClick={() => openPlaygroundFor(r.id)}>
                  <td style={{ paddingLeft: 16 }}>
                    <div className="agent-cell">
                      <div className="agent-icon" style={{ width: 28, height: 28, color: r.agent.color, background: `${r.agent.color}1a`, borderColor: `${r.agent.color}33` }}>
                        <Icon name={r.cat?.icon || 'sparkles'} size={14} />
                      </div>
                      <div>
                        <div style={{ fontWeight: 600, display: 'flex', gap: 5, alignItems: 'center' }}>{r.agent.name} {r.agent.verified && <Icon name="verified" size={12} style={{ color: 'var(--brand)' }} />}</div>
                        <div className="mono" style={{ fontSize: 10.5, color: 'var(--ink-4)' }}>{r.id} · {r.cat?.name || 'Sin categoría'}</div>
                      </div>
                    </div>
                  </td>
                  <td>
                    <span className="deployment">
                      <span className={'status-dot ' + (r.deployment === 'producción' || r.deployment === 'active' ? 'live' : r.deployment === 'staging' ? 'staged' : 'draft')} />
                      {r.deployment}
                    </span>
                  </td>
                  <td className="mono" style={{ color: 'var(--ink-2)', fontSize: 12 }}>{r.region}</td>
                  <td className="mono">{fmt(r.runs7d)}</td>
                  <td>
                    <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
                      <div style={{ width: 50, height: 4, background: 'var(--bg-3)', borderRadius: 4, overflow: 'hidden' }}>
                        <div style={{ width: `${r.success*100}%`, height: '100%', background: r.success > 0.97 ? 'var(--ok)' : r.success > 0.93 ? 'var(--warn)' : 'var(--bad)' }} />
                      </div>
                      <span className="mono" style={{ fontSize: 11.5 }}>{r.runs7d > 0 ? (r.success*100).toFixed(1).replace('.',',') + ' %' : 'N/D'}</span>
                    </div>
                  </td>
                  <td className="mono">{r.p95 ? r.p95 + ' ms' : '—'}</td>
                  <td>
                    <div style={{ width: 22, height: 22, borderRadius: '50%', background: 'var(--bg-3)', display: 'grid', placeItems: 'center', fontSize: 10, fontWeight: 600, color: 'var(--ink-2)' }}>{r.owner}</div>
                  </td>
                  <td className="mono" style={{ color: 'var(--ink-3)', fontSize: 11.5 }}>{r.lastRun}</td>
                  <td style={{ paddingRight: 16 }}>
                    <div className="library-actions-cell" style={{ display: 'flex', gap: 6, justifyContent: 'flex-end', alignItems: 'center', position: 'relative', flexWrap: 'wrap' }}>
                      <button className="btn btn-sm library-action-btn" onClick={e => { e.stopPropagation(); openPlaygroundFor(r.id); }}><Icon name="play" size={11} /> <span className="library-action-label">Probar</span></button>
                      <button
                        className="btn btn-ghost btn-sm library-action-btn"
                        onClick={e => {
                          e.stopPropagation();
                          if (typeof onEditAgent === 'function') {
                            onEditAgent(r);
                          }
                        }}
                      >
                        <Icon name="edit" size={11} /> <span className="library-action-label">Editar</span>
                      </button>
                      <button
                        className="btn btn-ghost btn-sm library-action-btn"
                        onClick={e => {
                          e.stopPropagation();
                          const stored = loadPersonalization(r.id);
                          setPersonalizeForm(stored || {
                            empresa: '', descripcion: '', productos: '',
                            audiencia: '', tono: 'profesional', faqs: '', instrucciones: '',
                          });
                          setPersonalizeRow(r);
                          setPersonalizeOpen(true);
                        }}
                      >
                        <Icon name="sparkles" size={11} /> <span className="library-action-label">Personalizar</span>
                      </button>
                      <button
                        className="btn btn-primary btn-sm library-action-btn"
                        onClick={e => {
                          e.stopPropagation();
                          const ok = window.confirm(
                            `¿Ir a Implementación para desplegar "${r.agent?.name || r.id}"?\n\nPodrás configurar el canal (Web, WhatsApp, Telegram) y obtener el enlace de despliegue.`
                          );
                          if (!ok) return;
                          if (typeof onDeployAgent === 'function') {
                            onDeployAgent(r);
                          }
                        }}
                      >
                        <Icon name="send" size={11} /> <span className="library-action-label">Desplegar</span>
                      </button>
                      <button className="btn btn-ghost btn-icon btn-sm" onClick={e => {
                        e.stopPropagation();
                        if (openRowMenu === r.id) {
                          setOpenRowMenu('');
                          return;
                        }
                        const rect = e.currentTarget.getBoundingClientRect();
                        const estimatedHeight = 196;
                        const openUp = (window.innerHeight - rect.bottom) < estimatedHeight;
                        setMenuPos({
                          x: Math.max(12, rect.right - 176),
                          y: openUp ? Math.max(12, rect.top - estimatedHeight - 6) : Math.max(12, rect.bottom + 6),
                        });
                        setOpenRowMenu(r.id);
                      }}>
                        <Icon name="dot-menu" size={14} />
                      </button>
                    </div>
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
        <div className="section-title" style={{ marginTop: 28 }}>
          <span>Actividad reciente</span><span className="line" />
        </div>
        <div className="card card-pad" style={{ color: 'var(--ink-3)', fontSize: 12.5 }}>
          {visibleRows.length > 0
            ? 'La actividad reciente se alimentará con ejecuciones reales de tus agentes.'
            : 'Sin agentes activos, no hay actividad reciente todavía.'}
        </div>
      </div>
      {renameOpen && (
        <div
          style={{
            position: 'fixed', inset: 0, zIndex: 10000,
            background: 'rgba(0,0,0,0.55)', display: 'flex',
            alignItems: 'center', justifyContent: 'center',
          }}
          onClick={(e) => { if (e.target === e.currentTarget) setRenameOpen(false); }}
        >
          <div style={{
            background: 'var(--bg-1)', border: '1px solid var(--line-2)',
            borderRadius: 12, width: '100%', maxWidth: 520,
            padding: '22px 26px', boxShadow: '0 20px 60px rgba(0,0,0,.5)',
          }}>
            <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 16 }}>
              <div>
                <h2 style={{ margin: 0, fontSize: 16, fontWeight: 700 }}>Renombrar agente</h2>
                <div style={{ fontSize: 12, color: 'var(--ink-3)', marginTop: 2 }}>
                  Este nombre se usará en Mis agentes, Editor y despliegues.
                </div>
              </div>
              <button className="btn btn-ghost btn-icon" onClick={() => setRenameOpen(false)}><Icon name="x" size={14} /></button>
            </div>
            <div style={{ display: 'grid', gap: 12 }}>
              <label style={{ fontSize: 12, color: 'var(--ink-2)', fontWeight: 600 }}>
                Nombre visible
                <input className="input" value={renameForm.name} onChange={(e) => setRenameForm((f) => ({ ...f, name: e.target.value }))} style={{ marginTop: 5 }} placeholder="Ej: Asistente Cloud Ernesto" />
              </label>
              <label style={{ fontSize: 12, color: 'var(--ink-2)', fontWeight: 600 }}>
                Descripción breve
                <textarea className="input" rows={3} value={renameForm.tagline} onChange={(e) => setRenameForm((f) => ({ ...f, tagline: e.target.value }))} style={{ marginTop: 5, resize: 'vertical' }} placeholder="Ej: Responde consultas sobre Azure, Google Cloud y AWS" />
              </label>
              {renameRow?.agent?.baseName && renameRow.agent.baseName !== renameForm.name && (
                <div style={{ fontSize: 11.5, color: 'var(--ink-3)' }}>
                  Agente base: <span className="mono">{renameRow.agent.baseName}</span>
                </div>
              )}
            </div>
            <div style={{ display: 'flex', gap: 8, justifyContent: 'flex-end', marginTop: 18 }}>
              <button className="btn btn-ghost" onClick={() => setRenameOpen(false)}>Cancelar</button>
              <button className="btn btn-primary" onClick={saveRenameAgent} disabled={renameSaving}>
                {renameSaving ? 'Guardando...' : 'Guardar nombre'}
              </button>
            </div>
          </div>
        </div>
      )}
      {personalizeOpen && personalizeRow && (
        <div
          style={{
            position: 'fixed', inset: 0, zIndex: 10000,
            background: 'rgba(0,0,0,0.55)', display: 'flex',
            alignItems: 'center', justifyContent: 'center',
          }}
          onClick={(e) => { if (e.target === e.currentTarget) setPersonalizeOpen(false); }}
        >
          <div style={{
            background: 'var(--bg-1)', border: '1px solid var(--line-2)',
            borderRadius: 12, width: '100%', maxWidth: 560,
            maxHeight: '88vh', overflowY: 'auto',
            padding: '24px 28px', boxShadow: '0 20px 60px rgba(0,0,0,.5)',
          }}>
            <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 18 }}>
              <div>
                <h2 style={{ margin: 0, fontSize: 16, fontWeight: 700 }}>
                  <Icon name="sparkles" size={15} style={{ marginRight: 6, color: 'var(--brand)' }} />
                  Personalizar agente
                </h2>
                <div style={{ fontSize: 12, color: 'var(--ink-3)', marginTop: 2 }}>
                  {personalizeRow.agent?.name} — añade contexto de tu negocio para mejorar la inteligencia del agente
                </div>
              </div>
              <button className="btn btn-ghost btn-icon btn-sm" onClick={() => setPersonalizeOpen(false)}>
                <Icon name="x" size={14} />
              </button>
            </div>

            <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
              <div>
                <label style={{ fontSize: 12, color: 'var(--ink-2)', fontWeight: 600, display: 'block', marginBottom: 4 }}>Nombre de empresa</label>
                <input
                  className="input"
                  placeholder="Ej: Acme Corp"
                  value={personalizeForm.empresa}
                  onChange={e => setPersonalizeForm(f => ({ ...f, empresa: e.target.value }))}
                />
              </div>
              <div>
                <label style={{ fontSize: 12, color: 'var(--ink-2)', fontWeight: 600, display: 'block', marginBottom: 4 }}>Descripción del negocio</label>
                <textarea
                  className="input"
                  rows={2}
                  placeholder="¿A qué se dedica tu empresa? ¿Cuál es su propuesta de valor?"
                  value={personalizeForm.descripcion}
                  onChange={e => setPersonalizeForm(f => ({ ...f, descripcion: e.target.value }))}
                  style={{ resize: 'vertical' }}
                />
              </div>
              <div>
                <label style={{ fontSize: 12, color: 'var(--ink-2)', fontWeight: 600, display: 'block', marginBottom: 4 }}>Productos / Servicios</label>
                <textarea
                  className="input"
                  rows={2}
                  placeholder="Lista los principales productos o servicios que ofreces"
                  value={personalizeForm.productos}
                  onChange={e => setPersonalizeForm(f => ({ ...f, productos: e.target.value }))}
                  style={{ resize: 'vertical' }}
                />
              </div>
              <div>
                <label style={{ fontSize: 12, color: 'var(--ink-2)', fontWeight: 600, display: 'block', marginBottom: 4 }}>Audiencia objetivo</label>
                <input
                  className="input"
                  placeholder="Ej: PyMEs del sector retail en España"
                  value={personalizeForm.audiencia}
                  onChange={e => setPersonalizeForm(f => ({ ...f, audiencia: e.target.value }))}
                />
              </div>
              <div>
                <label style={{ fontSize: 12, color: 'var(--ink-2)', fontWeight: 600, display: 'block', marginBottom: 4 }}>Tono de comunicación</label>
                <select
                  className="select"
                  value={personalizeForm.tono}
                  onChange={e => setPersonalizeForm(f => ({ ...f, tono: e.target.value }))}
                >
                  <option value="profesional">Profesional</option>
                  <option value="cercano">Cercano y amigable</option>
                  <option value="tecnico">Técnico y preciso</option>
                  <option value="formal">Formal</option>
                </select>
              </div>
              <div>
                <label style={{ fontSize: 12, color: 'var(--ink-2)', fontWeight: 600, display: 'block', marginBottom: 4 }}>Preguntas frecuentes (FAQ)</label>
                <textarea
                  className="input"
                  rows={3}
                  placeholder={"P: ¿Cuál es vuestro horario?\nR: Lunes a viernes de 9h a 18h."}
                  value={personalizeForm.faqs}
                  onChange={e => setPersonalizeForm(f => ({ ...f, faqs: e.target.value }))}
                  style={{ resize: 'vertical', fontFamily: 'var(--mono)', fontSize: 12 }}
                />
              </div>
              <div>
                <label style={{ fontSize: 12, color: 'var(--ink-2)', fontWeight: 600, display: 'block', marginBottom: 4 }}>Instrucciones adicionales</label>
                <textarea
                  className="input"
                  rows={2}
                  placeholder="Cualquier instrucción extra que deba seguir el agente"
                  value={personalizeForm.instrucciones}
                  onChange={e => setPersonalizeForm(f => ({ ...f, instrucciones: e.target.value }))}
                  style={{ resize: 'vertical' }}
                />
              </div>
            </div>

            <div style={{ display: 'flex', gap: 8, justifyContent: 'flex-end', marginTop: 20 }}>
              <button className="btn btn-ghost" onClick={() => setPersonalizeOpen(false)}>Cancelar</button>
              <button
                className="btn btn-primary"
                disabled={personalizeSaving}
                onClick={async () => {
                  setPersonalizeSaving(true);
                  await savePersonalization(personalizeRow.id, personalizeForm);
                  setPersonalizeSaving(false);
                  setPersonalizeOpen(false);
                }}
              >
                {personalizeSaving ? 'Guardando…' : 'Guardar contexto'}
              </button>
            </div>
          </div>
        </div>
      )}
      {openRowMenu && (() => {
        const row = visibleRows.find((x) => x.id === openRowMenu) || allRows.find((x) => x.id === openRowMenu);
        if (!row) return null;
        const menuNode = (
          <div
            ref={menuRef}
            style={{
              position: 'fixed',
              left: menuPos.x,
              top: menuPos.y,
              zIndex: 9999,
              background: 'var(--bg-1)',
              border: '1px solid var(--line-2)',
              borderRadius: 8,
              minWidth: 168,
              boxShadow: '0 12px 28px rgba(0,0,0,.35)',
              overflow: 'hidden',
            }}
            onClick={(e) => e.stopPropagation()}
          >
            {!!row.agentDbId && (
              <button
                className="btn btn-ghost"
                style={{ width: '100%', justifyContent: 'flex-start', borderRadius: 0 }}
                onClick={() => { setOpenRowMenu(''); openAgent(row.id); }}
              >
                <Icon name="sparkles" size={12} /> Ver detalles
              </button>
            )}
            {!!row.agentDbId && (
              <button
                className="btn btn-ghost"
                style={{ width: '100%', justifyContent: 'flex-start', borderRadius: 0 }}
                onClick={() => {
                  setOpenRowMenu('');
                  openRenameAgent(row);
                }}
              >
                <Icon name="edit" size={12} /> Renombrar agente
              </button>
            )}
            <button
              className="btn btn-ghost"
              style={{ width: '100%', justifyContent: 'flex-start', borderRadius: 0 }}
              onClick={() => {
                setOpenRowMenu('');
                const stored = loadPersonalization(row.id);
                setPersonalizeForm(stored || {
                  empresa: '', descripcion: '', productos: '',
                  audiencia: '', tono: 'profesional', faqs: '', instrucciones: '',
                });
                setPersonalizeRow(row);
                setPersonalizeOpen(true);
              }}
            >
              <Icon name="sparkles" size={12} /> Personalizar agente
            </button>
            <div style={{ height: 1, background: 'var(--line)', margin: '2px 0' }} />
            {!!row.agentDbId && (
              <button
                className="btn btn-ghost"
                style={{ width: '100%', justifyContent: 'flex-start', borderRadius: 0, color: '#fda4af' }}
                onClick={() => { setOpenRowMenu(''); cancelPurchasedAgent(row.agentDbId); }}
                disabled={busyCancelId === row.agentDbId}
              >
                <Icon name="x" size={12} /> {busyCancelId === row.agentDbId ? 'Eliminando…' : 'Eliminar agente'}
              </button>
            )}
            {!row.agentDbId && (
              <button
                className="btn btn-ghost"
                style={{ width: '100%', justifyContent: 'flex-start', borderRadius: 0, color: '#fda4af' }}
                onClick={() => { setOpenRowMenu(''); removeLocalAgent(row.id); }}
              >
                <Icon name="x" size={12} /> Borrar agente
              </button>
            )}
          </div>
        );
        if (typeof ReactDOM !== 'undefined' && ReactDOM.createPortal) {
          return ReactDOM.createPortal(menuNode, document.body);
        }
        return menuNode;
      })()}
    </div>
  );
};
window.Library = Library;
