// AGENTFORGE-IA — Panel de administración de usuarios

const ROLE_META = {
  propietario:  { label: 'Propietario',  color: '#7c3aed', bg: 'rgba(124,58,237,0.15)' },
  administrador:{ label: 'Administrador',color: '#f472b6', bg: 'rgba(244,114,182,0.15)' },
  constructor:  { label: 'Builder',      color: '#34d399', bg: 'rgba(52,211,153,0.15)' },
  revisor:      { label: 'Revisor',      color: '#60a5fa', bg: 'rgba(96,165,250,0.15)' },
  lector:       { label: 'Lector',       color: '#fbbf24', bg: 'rgba(251,191,36,0.15)' },
  operador_sensible: { label: 'Operador sensible', color: '#ef4444', bg: 'rgba(239,68,68,0.15)' },
};
const ALL_ROLES = Object.keys(ROLE_META);
const ROLE_SECTION_PERMS = {
  propietario: { crm:'manage',scheduling:'manage',builder:'manage',playground:'manage',deployment:'manage',integrations:'manage',billing:'manage',settings:'manage',runs:'manage',analytics:'manage',admin:'manage',library:'manage' },
  administrador: { crm:'edit',scheduling:'edit',builder:'edit',playground:'edit',deployment:'edit',integrations:'edit',billing:'view',settings:'edit',runs:'view',analytics:'view',admin:'edit',library:'edit' },
  constructor: { builder:'edit',playground:'edit',deployment:'edit',library:'view',integrations:'edit' },
  revisor: { crm:'view',scheduling:'view',runs:'view',analytics:'view',library:'view',playground:'view',integrations:'view' },
  lector: { runs:'view',analytics:'view',library:'view',playground:'view',integrations:'view' },
  operador_sensible: { ops_finance:'manage',ops_sales:'manage',ops_marketing:'manage',ops_operations:'manage',ops_hr:'manage',ops_support:'manage',billing:'view',integrations:'view',runs:'view',analytics:'view' },
};
const PERM_LEVEL = { view: 1, edit: 2, manage: 3 };
const PERM_LABEL = { view: 'ver', edit: 'editar', manage: 'total' };

function computeUserSections(user) {
  if (user?.is_admin) return { playground: 'manage', integrations: 'manage' };
  const merged = {};
  const roles = Array.isArray(user?.roles) ? user.roles : [];
  for (const role of roles) {
    for (const [section, level] of Object.entries(ROLE_SECTION_PERMS[role] || {})) {
      if (!merged[section] || PERM_LEVEL[level] > PERM_LEVEL[merged[section]]) {
        merged[section] = level;
      }
    }
  }
  return merged;
}

function computeSectionsFromRoles(roles) {
  const merged = {};
  const safeRoles = Array.isArray(roles) ? roles : [];
  for (const role of safeRoles) {
    for (const [section, level] of Object.entries(ROLE_SECTION_PERMS[role] || {})) {
      if (!merged[section] || PERM_LEVEL[level] > PERM_LEVEL[merged[section]]) {
        merged[section] = level;
      }
    }
  }
  return merged;
}

const AdminPanel = () => {
  const [adminTab, setAdminTab] = React.useState('users');
  const [users, setUsers] = React.useState([]);
  const [loading, setLoading] = React.useState(true);
  const [error, setError] = React.useState('');
  const [search, setSearch] = React.useState('');
  const [playgroundFilter, setPlaygroundFilter] = React.useState('all');
  const [integrationsFilter, setIntegrationsFilter] = React.useState('all');

  // Edit modal state
  const [editUser, setEditUser] = React.useState(null);
  const [editName, setEditName] = React.useState('');
  const [editEmail, setEditEmail] = React.useState('');
  const [editPhone, setEditPhone] = React.useState('');
  const [editCompany, setEditCompany] = React.useState('');
  const [editIsActive, setEditIsActive] = React.useState(true);
  const [editIsAdmin, setEditIsAdmin] = React.useState(false);
  const [editSaving, setEditSaving] = React.useState(false);
  const [editError, setEditError] = React.useState('');

  // Password reset modal state
  const [passwordUser, setPasswordUser] = React.useState(null);
  const [newPassword, setNewPassword] = React.useState('');
  const [newPasswordConfirm, setNewPasswordConfirm] = React.useState('');
  const [passwordSaving, setPasswordSaving] = React.useState(false);
  const [passwordError, setPasswordError] = React.useState('');

  // Agents drawer state
  const [agentsUser, setAgentsUser] = React.useState(null);
  const [agentsList, setAgentsList] = React.useState([]);
  const [agentsLoading, setAgentsLoading] = React.useState(false);

  // Roles drawer state
  const [rolesUser, setRolesUser] = React.useState(null);
  const [userRoles, setUserRoles] = React.useState([]);
  const [initialRolesSnapshot, setInitialRolesSnapshot] = React.useState([]);
  const [rolesLoading, setRolesLoading] = React.useState(false);
  const [addingRole, setAddingRole] = React.useState('');
  const [rolesSaving, setRolesSaving] = React.useState(false);

  // Register modal state
  const [showRegister, setShowRegister] = React.useState(false);

  // Subscriptions tab state
  const [subs, setSubs] = React.useState([]);
  const [subsLoading, setSubsLoading] = React.useState(false);
  const [subsFilter, setSubsFilter] = React.useState('all');
  const [subsError, setSubsError] = React.useState('');
  const [globalIntegrations, setGlobalIntegrations] = React.useState([]);
  const [globalIntegrationsLoading, setGlobalIntegrationsLoading] = React.useState(false);
  const [globalIntegrationsError, setGlobalIntegrationsError] = React.useState('');
  const [globalSyncRunning, setGlobalSyncRunning] = React.useState(false);
  const [globalForm, setGlobalForm] = React.useState({
    slug: 'twenty',
    account_name: '',
    api_key: '',
    webhook_url: '',
  });

  const getToken = () => sessionStorage.getItem('af_token') || '';

  const loadUsers = React.useCallback(async () => {
    setLoading(true);
    setError('');
    try {
      const res = await fetch('/api/v1/admin/users', {
        headers: { Authorization: 'Bearer ' + getToken() },
      });
      if (!res.ok) {
        const d = await res.json().catch(() => ({}));
        setError(d.detail || 'Error al cargar usuarios.');
        return;
      }
      const data = await res.json();
      setUsers(Array.isArray(data) ? data : (data.items || []));
    } catch (_) {
      setError('Error de red.');
    } finally {
      setLoading(false);
    }
  }, []);

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

  const loadSubscriptions = React.useCallback(async (f) => {
    setSubsLoading(true);
    setSubsError('');
    const filt = f || subsFilter;
    try {
      const res = await fetch('/api/v1/admin/subscriptions?filter=' + filt, {
        headers: { Authorization: 'Bearer ' + getToken() },
      });
      if (!res.ok) { setSubsError('Error al cargar suscripciones.'); return; }
      const data = await res.json();
      setSubs(Array.isArray(data) ? data : []);
    } catch (_) {
      setSubsError('Error de red.');
    } finally {
      setSubsLoading(false);
    }
  }, [subsFilter]);

  React.useEffect(() => {
    if (adminTab === 'subs') loadSubscriptions();
  }, [adminTab]);

  const loadGlobalIntegrations = React.useCallback(async () => {
    setGlobalIntegrationsLoading(true);
    setGlobalIntegrationsError('');
    try {
      const res = await fetch('/api/v1/admin/integrations/global', {
        headers: { Authorization: 'Bearer ' + getToken() },
      });
      if (!res.ok) {
        const d = await res.json().catch(() => ({}));
        setGlobalIntegrationsError(d.detail || 'Error al cargar integraciones globales.');
        return;
      }
      const data = await res.json();
      setGlobalIntegrations(Array.isArray(data) ? data : []);
    } catch (_) {
      setGlobalIntegrationsError('Error de red.');
    } finally {
      setGlobalIntegrationsLoading(false);
    }
  }, []);

  React.useEffect(() => {
    if (adminTab === 'integrations') loadGlobalIntegrations();
  }, [adminTab, loadGlobalIntegrations]);

  const saveGlobalIntegration = async () => {
    const slug = (globalForm.slug || '').trim().toLowerCase();
    if (!slug) {
      window.alert('Debes seleccionar un slug.');
      return;
    }
    const payload = {
      slug,
      account_name: globalForm.account_name.trim() || null,
      api_key: globalForm.api_key.trim() || null,
      webhook_url: globalForm.webhook_url.trim() || null,
    };
    const res = await fetch('/api/v1/admin/integrations/global/' + slug, {
      method: 'PUT',
      headers: {
        'Content-Type': 'application/json',
        Authorization: 'Bearer ' + getToken(),
      },
      body: JSON.stringify(payload),
    });
    if (!res.ok) {
      const d = await res.json().catch(() => ({}));
      window.alert(d.detail || 'No se pudo guardar la integración global.');
      return;
    }
    window.afNotify && window.afNotify('Integración global guardada');
    setGlobalForm((prev) => ({ ...prev, api_key: '' }));
    await loadGlobalIntegrations();
  };

  const removeGlobalIntegration = async (slug) => {
    if (!window.confirm(`¿Eliminar la integración global "${slug}"?`)) return;
    const res = await fetch('/api/v1/admin/integrations/global/' + slug, {
      method: 'DELETE',
      headers: { Authorization: 'Bearer ' + getToken() },
    });
    if (!res.ok) {
      const d = await res.json().catch(() => ({}));
      window.alert(d.detail || 'No se pudo eliminar la integración.');
      return;
    }
    window.afNotify && window.afNotify('Integración eliminada');
    await loadGlobalIntegrations();
  };

  const runTwentySync = async () => {
    setGlobalSyncRunning(true);
    try {
      const res = await fetch('/api/v1/leads/sync/twenty', {
        method: 'POST',
        headers: { Authorization: 'Bearer ' + getToken() },
      });
      const d = await res.json().catch(() => ({}));
      if (!res.ok) {
        window.alert(d.detail || 'Error en sincronización.');
        return;
      }
      window.afNotify && window.afNotify(`Sync twenty: ${d.synced} ok / ${d.skipped} omitidos`);
      await loadGlobalIntegrations();
    } catch (_) {
      window.alert('Error de red en sincronización.');
    } finally {
      setGlobalSyncRunning(false);
    }
  };

  const freezeSub = async (subId) => {
    const res = await fetch('/api/v1/admin/subscriptions/' + subId + '/freeze', {
      method: 'PATCH', headers: { Authorization: 'Bearer ' + getToken() },
    });
    if (res.ok) { window.afNotify && window.afNotify('Suscripción congelada'); loadSubscriptions(); }
    else { const d = await res.json().catch(() => ({})); window.alert(d.detail || 'Error al congelar.'); }
  };

  const unfreezeSub = async (subId) => {
    const res = await fetch('/api/v1/admin/subscriptions/' + subId + '/unfreeze', {
      method: 'PATCH', headers: { Authorization: 'Bearer ' + getToken() },
    });
    if (res.ok) { window.afNotify && window.afNotify('Suscripción reactivada'); loadSubscriptions(); }
    else { const d = await res.json().catch(() => ({})); window.alert(d.detail || 'Error al reactivar.'); }
  };

  const remindSub = async (subId) => {
    const res = await fetch('/api/v1/admin/subscriptions/' + subId + '/remind', {
      method: 'POST', headers: { Authorization: 'Bearer ' + getToken() },
    });
    if (res.ok) { window.afNotify && window.afNotify('Email de recordatorio enviado'); }
    else { const d = await res.json().catch(() => ({})); window.alert(d.detail || 'Error al enviar email.'); }
  };

  const toggleActive = async (user) => {
    try {
      const res = await fetch('/api/v1/admin/users/' + user.id, {
        method: 'PATCH',
        headers: { 'Content-Type': 'application/json', Authorization: 'Bearer ' + getToken() },
        body: JSON.stringify({ is_active: !user.is_active }),
      });
      if (!res.ok) return;
      const updated = await res.json();
      setUsers(prev => prev.map(u => u.id === user.id ? { ...u, ...updated } : u));
    } catch (_) {}
  };

  const deleteUser = async (user) => {
    if (!window.confirm('¿Eliminar a ' + (user.full_name || user.email) + '? Esta acción no se puede deshacer.')) return;
    try {
      const res = await fetch('/api/v1/admin/users/' + user.id, {
        method: 'DELETE',
        headers: { Authorization: 'Bearer ' + getToken() },
      });
      if (!res.ok) {
        let reason = `HTTP ${res.status}`;
        try {
          const payload = await res.json();
          reason = payload?.detail || reason;
        } catch (_) {}
        window.alert('No se pudo eliminar el usuario: ' + reason);
        return;
      }
      setUsers(prev => prev.filter(u => u.id !== user.id));
      window.afNotify && window.afNotify('Usuario eliminado');
    } catch (_) {}
  };

  const toggleMfaByAdmin = async (user) => {
    const currentlyEnabled = !!user.mfa_enabled;
    const targetEnabled = !currentlyEnabled;
    const actionLabel = targetEnabled ? 'habilitar' : 'deshabilitar';
    if (!window.confirm(`¿Seguro que deseas ${actionLabel} MFA para ${user.full_name || user.email}?`)) return;
    try {
      const res = await fetch('/api/v1/admin/users/' + user.id + '/mfa', {
        method: 'PATCH',
        headers: { 'Content-Type': 'application/json', Authorization: 'Bearer ' + getToken() },
        body: JSON.stringify({
          enabled: targetEnabled,
          reset_secret: targetEnabled ? false : true,
        }),
      });
      if (!res.ok) {
        const d = await res.json().catch(() => ({}));
        window.alert(d.detail || 'No se pudo cambiar el estado de MFA.');
        return;
      }
      const d = await res.json().catch(() => ({}));
      setUsers(prev => prev.map(u => u.id === user.id ? { ...u, mfa_enabled: targetEnabled } : u));
      if (window.afNotify) {
        window.afNotify(
          targetEnabled
            ? 'MFA activado. El usuario deberá configurarlo en su próximo login.'
            : 'MFA desactivado para el usuario.'
        );
      }
    } catch (_) {
      window.alert('Error de red al cambiar MFA.');
    }
  };

  const openEdit = (user) => {
    setEditUser(user);
    setEditName(user.full_name || '');
    setEditEmail(user.email || '');
    setEditPhone(user.phone || '');
    setEditCompany(user.company || '');
    setEditIsActive(!!user.is_active);
    setEditIsAdmin(!!user.is_admin);
    setEditError('');
  };

  const saveEdit = async () => {
    if (!editUser) return;
    setEditSaving(true);
    setEditError('');
    try {
      const res = await fetch('/api/v1/admin/users/' + editUser.id, {
        method: 'PATCH',
        headers: { 'Content-Type': 'application/json', Authorization: 'Bearer ' + getToken() },
        body: JSON.stringify({
          full_name: editName.trim(),
          email: editEmail.trim(),
          phone: editPhone.trim() || null,
          company: editCompany.trim() || null,
          is_active: editIsActive,
          is_admin: editIsAdmin,
        }),
      });
      if (!res.ok) {
        const d = await res.json().catch(() => ({}));
        setEditError(d.detail || 'Error al guardar.');
        return;
      }
      const updated = await res.json();
      setUsers(prev => prev.map(u => u.id === editUser.id ? { ...u, ...updated } : u));
      setEditUser(null);
    } catch (_) {
      setEditError('Error de red.');
    } finally {
      setEditSaving(false);
    }
  };

  const openPasswordReset = (user) => {
    setPasswordUser(user);
    setNewPassword('');
    setNewPasswordConfirm('');
    setPasswordError('');
  };

  const savePasswordReset = async () => {
    if (!passwordUser) return;
    if (newPassword.length < 8) {
      setPasswordError('La contraseña debe tener al menos 8 caracteres.');
      return;
    }
    if (newPassword !== newPasswordConfirm) {
      setPasswordError('Las contraseñas no coinciden.');
      return;
    }

    setPasswordSaving(true);
    setPasswordError('');
    try {
      const res = await fetch('/api/v1/admin/users/' + passwordUser.id + '/password', {
        method: 'PATCH',
        headers: { 'Content-Type': 'application/json', Authorization: 'Bearer ' + getToken() },
        body: JSON.stringify({ password: newPassword }),
      });
      if (!res.ok) {
        const d = await res.json().catch(() => ({}));
        setPasswordError(d.detail || 'No se pudo cambiar la contraseña.');
        return;
      }
      setPasswordUser(null);
      window.afNotify && window.afNotify('Contraseña actualizada');
    } catch (_) {
      setPasswordError('Error de red.');
    } finally {
      setPasswordSaving(false);
    }
  };

  const openAgents = async (user) => {
    setAgentsUser(user);
    setAgentsList([]);
    setAgentsLoading(true);
    try {
      const res = await fetch('/api/v1/admin/users/' + user.id + '/agents', {
        headers: { Authorization: 'Bearer ' + getToken() },
      });
      if (res.ok) {
        const data = await res.json();
        setAgentsList(Array.isArray(data) ? data : (data.items || []));
      }
    } catch (_) {}
    setAgentsLoading(false);
  };

  const openRoles = async (user) => {
    setRolesUser(user);
    setUserRoles(user.roles || []);
    setInitialRolesSnapshot(Array.isArray(user.roles) ? user.roles : []);
    setAddingRole('');
    setRolesLoading(true);
    try {
      const res = await fetch('/api/v1/admin/users/' + user.id + '/roles', {
        headers: { Authorization: 'Bearer ' + getToken() },
      });
      if (res.ok) {
        const data = await res.json();
        const loadedRoles = Array.isArray(data) ? data : [];
        setUserRoles(loadedRoles);
        setInitialRolesSnapshot(loadedRoles);
      }
    } catch (_) {}
    setRolesLoading(false);
  };

  const addRole = async () => {
    if (!addingRole || !rolesUser) return;
    setRolesSaving(true);
    try {
      const res = await fetch('/api/v1/admin/users/' + rolesUser.id + '/roles', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json', Authorization: 'Bearer ' + getToken() },
        body: JSON.stringify({ role: addingRole }),
      });
      if (res.ok) {
        const updated = await res.json();
        setUserRoles(updated);
        setUsers(prev => prev.map(u => u.id === rolesUser.id ? { ...u, roles: updated } : u));
        setAddingRole('');
      }
    } catch (_) {}
    setRolesSaving(false);
  };

  const removeRole = async (role) => {
    if (!rolesUser) return;
    setRolesSaving(true);
    try {
      const res = await fetch('/api/v1/admin/users/' + rolesUser.id + '/roles/' + role, {
        method: 'DELETE',
        headers: { Authorization: 'Bearer ' + getToken() },
      });
      if (res.ok) {
        const updated = await res.json();
        setUserRoles(updated);
        setUsers(prev => prev.map(u => u.id === rolesUser.id ? { ...u, roles: updated } : u));
      }
    } catch (_) {}
    setRolesSaving(false);
  };

  const filteredUsers = React.useMemo(() => {
    const q = search.toLowerCase().trim();
    return users.filter((u) => {
      const matchesQuery = !q ||
        (u.email || '').toLowerCase().includes(q) ||
        (u.full_name || '').toLowerCase().includes(q);
      if (!matchesQuery) return false;

      const sections = computeUserSections(u);
      const hasPlayground = !!sections.playground;
      const hasIntegrations = !!sections.integrations;

      const playgroundOk =
        playgroundFilter === 'all' ||
        (playgroundFilter === 'with' && hasPlayground) ||
        (playgroundFilter === 'without' && !hasPlayground);
      if (!playgroundOk) return false;

      const integrationsOk =
        integrationsFilter === 'all' ||
        (integrationsFilter === 'with' && hasIntegrations) ||
        (integrationsFilter === 'without' && !hasIntegrations);
      return integrationsOk;
    });
  }, [users, search, playgroundFilter, integrationsFilter]);

  const totalUsers = users.length;
  const activeUsers = users.filter(u => u.is_active).length;
  const adminUsers = users.filter(u => u.is_admin).length;

  // Styles
  const pageStyle = { fontFamily: '"Inter Tight", "Inter", sans-serif', color: '#e5e5e5' };
  const statCardStyle = { background: '#1a1a1a', border: '1px solid #2a2a2a', borderRadius: 10, padding: '14px 20px', minWidth: 100 };
  const tableWrapStyle = { background: '#1a1a1a', border: '1px solid #2a2a2a', borderRadius: 10, overflow: 'hidden', marginTop: 16 };
  const thStyle = { padding: '10px 14px', textAlign: 'left', fontSize: 11, fontWeight: 700, color: '#888', textTransform: 'uppercase', letterSpacing: '0.06em', background: '#111', borderBottom: '1px solid #2a2a2a', whiteSpace: 'nowrap' };
  const tdStyle = (extra = {}) => ({ padding: '10px 14px', fontSize: 13, verticalAlign: 'middle', borderBottom: '1px solid #1e1e1e', color: '#e5e5e5', ...extra });
  const inputStyle = { background: '#111', border: '1px solid #2a2a2a', borderRadius: 7, padding: '8px 12px', fontSize: 13, color: '#e5e5e5', fontFamily: 'inherit', outline: 'none', width: 260 };
  const badgeStyle = (color, bg) => ({ display: 'inline-flex', alignItems: 'center', gap: 4, padding: '2px 8px', borderRadius: 5, fontSize: 11.5, fontWeight: 600, color, background: bg, whiteSpace: 'nowrap' });
  const actionBtnStyle = { background: 'none', border: '1px solid #2a2a2a', borderRadius: 5, padding: '4px 10px', fontSize: 12, color: '#888', cursor: 'pointer', fontFamily: 'inherit' };
  const actionBtnDangerStyle = { ...actionBtnStyle, borderColor: 'rgba(255,80,80,0.2)', color: '#ff6b6b' };
  const actionBtnPrimaryStyle = { ...actionBtnStyle, borderColor: 'rgba(255,91,31,0.3)', color: '#ff5b1f' };
  const actionBtnVioletStyle = { ...actionBtnStyle, borderColor: 'rgba(124,58,237,0.3)', color: '#a78bfa' };
  const overlayStyle = { position: 'fixed', inset: 0, zIndex: 900, background: 'rgba(0,0,0,0.7)', backdropFilter: 'blur(4px)', display: 'flex', alignItems: 'center', justifyContent: 'center' };
  const modalCardStyle = { background: '#1a1a1a', border: '1px solid #2a2a2a', borderRadius: 10, padding: '28px 24px', width: 360, fontFamily: '"Inter Tight", "Inter", sans-serif', color: '#e5e5e5', boxShadow: '0 16px 48px rgba(0,0,0,0.5)' };
  const modalLabelStyle = { display: 'block', fontSize: 11.5, fontWeight: 600, color: '#888', textTransform: 'uppercase', letterSpacing: '0.06em', marginBottom: 5 };
  const modalInputStyle = { width: '100%', boxSizing: 'border-box', background: '#111', border: '1px solid #2a2a2a', borderRadius: 6, padding: '8px 11px', fontSize: 13, color: '#e5e5e5', fontFamily: 'inherit', outline: 'none' };
  const drawerStyle = { position: 'fixed', top: 0, right: 0, bottom: 0, zIndex: 950, width: 380, background: '#1a1a1a', borderLeft: '1px solid #2a2a2a', display: 'flex', flexDirection: 'column', fontFamily: '"Inter Tight", "Inter", sans-serif', color: '#e5e5e5', boxShadow: '-8px 0 32px rgba(0,0,0,0.4)' };

  const formatDate = (val) => {
    if (!val) return '—';
    try { return new Date(val).toLocaleDateString('es-ES', { day: '2-digit', month: 'short', year: 'numeric' }); }
    catch (_) { return val; }
  };

  const availableRolesToAdd = ALL_ROLES.filter(r => !userRoles.includes(r));
  const rolesImpact = React.useMemo(() => {
    const before = computeSectionsFromRoles(initialRolesSnapshot);
    const after = computeSectionsFromRoles(userRoles);
    const watched = ['playground', 'integrations'];
    const changes = watched
      .map((section) => ({
        section,
        before: before[section] || null,
        after: after[section] || null,
      }))
      .filter((x) => x.before !== x.after);
    return {
      changed: changes.length > 0,
      changes,
    };
  }, [initialRolesSnapshot, userRoles]);

  return (
    <div style={pageStyle}>
      <div className="page-head">
        <h1>Administración</h1>
        <span className="crumbs mono">panel <span>›</span> <span style={{ color: '#e5e5e5' }}>{adminTab === 'users' ? 'usuarios' : adminTab === 'subs' ? 'suscripciones' : adminTab === 'integrations' ? 'integraciones globales' : 'configuración'}</span></span>
        <div className="actions">
          <div style={{ display:'flex', background:'#111', border:'1px solid #2a2a2a', borderRadius:7, padding:3, gap:2 }}>
            {[['users','Usuarios'],['subs','Suscripciones'],['integrations','Integraciones globales'],['settings','Configuración']].map(([id, lbl]) => (
              <button key={id} onClick={() => setAdminTab(id)} style={{ padding:'5px 14px', borderRadius:5, fontSize:12.5, fontWeight:600, border:'none', cursor:'pointer', fontFamily:'inherit', transition:'all 0.15s', background: adminTab === id ? '#2a2a2a' : 'transparent', color: adminTab === id ? '#e5e5e5' : '#666' }}>{lbl}</button>
            ))}
          </div>
          {adminTab === 'users' && <>
            <button className="btn" onClick={loadUsers}><Icon name="refresh" size={13} /> Recargar</button>
            <button className="btn btn-primary" onClick={() => setShowRegister(true)}><Icon name="plus" size={13} /> Nuevo usuario</button>
          </>}
        </div>
      </div>

      {adminTab === 'settings' && (
        <div className="section">
          {typeof window.SettingsInner !== 'undefined' ? React.createElement(window.SettingsInner) : null}
        </div>
      )}

      {adminTab === 'users' && <div className="section">
        {/* Stats */}
        <div style={{ display: 'flex', gap: 12, marginBottom: 20 }}>
          {[
            { label: 'Total', value: totalUsers, color: '#e5e5e5' },
            { label: 'Activos', value: activeUsers, color: '#4ade80' },
            { label: 'Admins', value: adminUsers, color: '#ff5b1f' },
          ].map(s => (
            <div key={s.label} style={statCardStyle}>
              <div style={{ fontSize: 10.5, color: '#888', textTransform: 'uppercase', letterSpacing: '0.06em', fontWeight: 600 }}>{s.label}</div>
              <div style={{ fontSize: 26, fontWeight: 700, color: s.color, marginTop: 2, letterSpacing: '-0.02em' }}>{loading ? '—' : s.value}</div>
            </div>
          ))}
        </div>

        {/* Search */}
        <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 4, flexWrap: 'wrap' }}>
          <div style={{ position: 'relative' }}>
            <span style={{ position: 'absolute', left: 10, top: '50%', transform: 'translateY(-50%)', color: '#555', pointerEvents: 'none' }}><Icon name="search" size={13} /></span>
            <input style={{ ...inputStyle, paddingLeft: 32 }} type="text" placeholder="Buscar por email o nombre..." value={search} onChange={(e) => setSearch(e.target.value)} />
          </div>
          <select
            style={{ ...inputStyle, width: 190 }}
            value={playgroundFilter}
            onChange={(e) => setPlaygroundFilter(e.target.value)}
          >
            <option value="all">Pruebas: todos</option>
            <option value="with">Pruebas: con acceso</option>
            <option value="without">Pruebas: sin acceso</option>
          </select>
          <select
            style={{ ...inputStyle, width: 220 }}
            value={integrationsFilter}
            onChange={(e) => setIntegrationsFilter(e.target.value)}
          >
            <option value="all">Integraciones: todos</option>
            <option value="with">Integraciones: con acceso</option>
            <option value="without">Integraciones: sin acceso</option>
          </select>
          {search && <span style={{ fontSize: 12, color: '#888' }}>{filteredUsers.length} resultado{filteredUsers.length !== 1 ? 's' : ''}</span>}
        </div>

        {error && <div style={{ padding: '10px 14px', background: 'rgba(255,59,59,0.08)', border: '1px solid rgba(255,59,59,0.2)', borderRadius: 7, color: '#ff6b6b', fontSize: 13, marginBottom: 12 }}>{error}</div>}

        {/* Table */}
        <div style={tableWrapStyle}>
          <table style={{ width: '100%', borderCollapse: 'collapse' }}>
            <thead>
              <tr>
                <th style={thStyle}>Usuario</th>
                <th style={thStyle}>Perfil</th>
                <th style={thStyle}>Roles</th>
                <th style={thStyle}>Pruebas</th>
                <th style={thStyle}>Integraciones</th>
                <th style={thStyle}>Estado</th>
                <th style={thStyle}>MFA</th>
                <th style={thStyle}>Registro</th>
                <th style={{ ...thStyle, paddingRight: 16 }}>Acciones</th>
              </tr>
            </thead>
            <tbody>
              {loading && <tr><td colSpan={9} style={{ ...tdStyle(), textAlign: 'center', color: '#888', padding: '28px 0' }}>Cargando usuarios...</td></tr>}
              {!loading && filteredUsers.length === 0 && (
                <tr><td colSpan={9} style={{ ...tdStyle(), textAlign: 'center', color: '#888', padding: '28px 0' }}>{search ? 'Sin resultados para "' + search + '"' : 'No hay usuarios.'}</td></tr>
              )}
              {!loading && filteredUsers.map(u => (
                (() => {
                  const sections = computeUserSections(u);
                  const playgroundAccess = sections.playground || null;
                  const integrationsAccess = sections.integrations || null;
                  return (
                <tr
                  key={u.id}
                  style={{ background: u.mfa_enabled ? 'rgba(52,211,153,0.06)' : 'transparent' }}
                  onMouseEnter={e => e.currentTarget.style.background = u.mfa_enabled ? 'rgba(52,211,153,0.12)' : '#1f1f1f'}
                  onMouseLeave={e => e.currentTarget.style.background = u.mfa_enabled ? 'rgba(52,211,153,0.06)' : 'transparent'}
                >
                  <td style={tdStyle()}>
                    <div style={{ fontWeight: 600, fontSize: 13 }}>{u.full_name || '—'}</div>
                    <div style={{ fontSize: 12, color: '#888', marginTop: 1, fontFamily: '"JetBrains Mono", monospace' }}>{u.email}</div>
                    {u.company && <div style={{ fontSize: 11, color: '#555', marginTop: 1 }}>{u.company}</div>}
                  </td>
                  <td style={tdStyle()}>
                    {u.is_admin
                      ? <span style={badgeStyle('#ff5b1f', 'rgba(255,91,31,0.12)')}>⊕ Admin</span>
                      : <span style={badgeStyle('#888', 'rgba(255,255,255,0.04)')}>↑ Usuario</span>
                    }
                  </td>
                  <td style={tdStyle()}>
                    <div style={{ display: 'flex', flexWrap: 'wrap', gap: 4 }}>
                      {(u.roles || []).length === 0
                        ? <span style={{ color: '#444', fontSize: 12 }}>—</span>
                        : (u.roles || []).map(r => {
                            const m = ROLE_META[r] || { label: r, color: '#888', bg: 'rgba(255,255,255,0.05)' };
                            return <span key={r} style={{ display: 'inline-block', padding: '1px 7px', borderRadius: 4, fontSize: 11, fontWeight: 600, color: m.color, background: m.bg }}>{m.label}</span>;
                          })
                      }
                    </div>
                  </td>
                  <td style={tdStyle()}>
                    {playgroundAccess
                      ? <span style={badgeStyle('#34d399', 'rgba(52,211,153,0.1)')}>{PERM_LABEL[playgroundAccess] || playgroundAccess}</span>
                      : <span style={badgeStyle('#888', 'rgba(255,255,255,0.04)')}>sin acceso</span>
                    }
                  </td>
                  <td style={tdStyle()}>
                    {integrationsAccess
                      ? <span style={badgeStyle('#60a5fa', 'rgba(96,165,250,0.1)')}>{PERM_LABEL[integrationsAccess] || integrationsAccess}</span>
                      : <span style={badgeStyle('#888', 'rgba(255,255,255,0.04)')}>sin acceso</span>
                    }
                  </td>
                  <td style={tdStyle()}>
                    {u.is_active
                      ? <span style={badgeStyle('#4ade80', 'rgba(74,222,128,0.1)')}><span style={{ width: 6, height: 6, borderRadius: '50%', background: '#4ade80', display: 'inline-block' }} /> Activo</span>
                      : <span style={badgeStyle('#888', 'rgba(255,255,255,0.04)')}><span style={{ width: 6, height: 6, borderRadius: '50%', background: '#555', display: 'inline-block' }} /> Congelado</span>
                    }
                  </td>
                  <td style={tdStyle()}>
                    {u.mfa_enabled
                      ? <span style={badgeStyle('#34d399', 'rgba(52,211,153,0.1)')}>MFA activo</span>
                      : <span style={badgeStyle('#f59e0b', 'rgba(245,158,11,0.12)')}>MFA inactivo</span>
                    }
                  </td>
                  <td style={{ ...tdStyle(), fontFamily: '"JetBrains Mono", monospace', fontSize: 12, color: '#888' }}>{formatDate(u.created_at)}</td>
                  <td style={{ ...tdStyle({ paddingRight: 16 }) }}>
                    <div style={{ display: 'flex', gap: 5, flexWrap: 'wrap' }}>
                      <button style={actionBtnPrimaryStyle} onClick={() => openEdit(u)}>Editar</button>
                      <button style={actionBtnStyle} onClick={() => openPasswordReset(u)}>Clave</button>
                      <button style={actionBtnStyle} onClick={() => toggleActive(u)}>{u.is_active ? 'Congelar' : 'Activar'}</button>
                      <button style={actionBtnStyle} onClick={() => toggleMfaByAdmin(u)}>{u.mfa_enabled ? 'Desactivar MFA' : 'Activar MFA'}</button>
                      <button style={actionBtnVioletStyle} onClick={() => openRoles(u)}>Roles</button>
                      <button style={actionBtnStyle} onClick={() => openAgents(u)}>Agentes</button>
                      <button style={actionBtnDangerStyle} onClick={() => deleteUser(u)}>Eliminar</button>
                    </div>
                  </td>
                </tr>
                  );
                })()
              ))}
            </tbody>
          </table>
        </div>
      </div>}

      {adminTab === 'subs' && (
        <div className="section">
          {/* Stats */}
          {(() => {
            const total = subs.length;
            const activas = subs.filter(s => s.status === 'active' || s.status === 'trial').length;
            const vencidas = subs.filter(s => s.days_overdue > 0 && s.status !== 'frozen').length;
            const congeladas = subs.filter(s => s.status === 'frozen').length;
            return (
              <div style={{ display: 'flex', gap: 12, marginBottom: 20 }}>
                {[
                  { label: 'Total', value: total, color: '#e5e5e5' },
                  { label: 'Activas', value: activas, color: '#4ade80' },
                  { label: 'Vencidas', value: vencidas, color: '#f59e0b' },
                  { label: 'Congeladas', value: congeladas, color: '#60a5fa' },
                ].map(s => (
                  <div key={s.label} style={{ background: '#1a1a1a', border: '1px solid #2a2a2a', borderRadius: 10, padding: '14px 20px', minWidth: 100 }}>
                    <div style={{ fontSize: 10.5, color: '#888', textTransform: 'uppercase', letterSpacing: '0.06em', fontWeight: 600 }}>{s.label}</div>
                    <div style={{ fontSize: 26, fontWeight: 700, color: s.color, marginTop: 2, letterSpacing: '-0.02em' }}>{subsLoading ? '—' : s.value}</div>
                  </div>
                ))}
              </div>
            );
          })()}

          {/* Filtros */}
          <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 12 }}>
            <div style={{ display: 'flex', background: '#111', border: '1px solid #2a2a2a', borderRadius: 7, padding: 3, gap: 2 }}>
              {[['all','Todas'],['active','Activas'],['overdue','Vencidas'],['frozen','Congeladas']].map(([id, lbl]) => (
                <button key={id} onClick={() => { setSubsFilter(id); loadSubscriptions(id); }}
                  style={{ padding: '5px 12px', borderRadius: 5, fontSize: 12, fontWeight: 600, border: 'none', cursor: 'pointer', fontFamily: 'inherit', background: subsFilter === id ? '#2a2a2a' : 'transparent', color: subsFilter === id ? '#e5e5e5' : '#666' }}>
                  {lbl}
                </button>
              ))}
            </div>
            <button onClick={() => loadSubscriptions()} style={{ background: 'none', border: '1px solid #2a2a2a', borderRadius: 6, padding: '5px 12px', fontSize: 12, color: '#888', cursor: 'pointer', fontFamily: 'inherit' }}>
              <Icon name="refresh" size={12} /> Recargar
            </button>
          </div>

          {subsError && <div style={{ padding: '10px 14px', background: 'rgba(255,59,59,0.08)', border: '1px solid rgba(255,59,59,0.2)', borderRadius: 7, color: '#ff6b6b', fontSize: 13, marginBottom: 12 }}>{subsError}</div>}

          {/* Tabla */}
          <div style={{ background: '#1a1a1a', border: '1px solid #2a2a2a', borderRadius: 10, overflow: 'hidden' }}>
            <table style={{ width: '100%', borderCollapse: 'collapse' }}>
              <thead>
                <tr>
                  {['Cliente','Agente','Plan','Estado','Período','Vencida','Acciones'].map(h => (
                    <th key={h} style={{ padding: '10px 14px', textAlign: 'left', fontSize: 11, fontWeight: 700, color: '#888', textTransform: 'uppercase', letterSpacing: '0.06em', background: '#111', borderBottom: '1px solid #2a2a2a', whiteSpace: 'nowrap' }}>{h}</th>
                  ))}
                </tr>
              </thead>
              <tbody>
                {subsLoading && <tr><td colSpan={7} style={{ padding: '28px 0', textAlign: 'center', color: '#888', fontSize: 13 }}>Cargando...</td></tr>}
                {!subsLoading && subs.length === 0 && <tr><td colSpan={7} style={{ padding: '28px 0', textAlign: 'center', color: '#888', fontSize: 13 }}>No hay suscripciones.</td></tr>}
                {!subsLoading && subs.map(sub => {
                  const isOverdue = sub.days_overdue > 0 && sub.status !== 'frozen';
                  const isFrozen = sub.status === 'frozen';
                  const statusColor = isFrozen ? '#60a5fa' : isOverdue ? '#f59e0b' : sub.status === 'active' ? '#4ade80' : '#888';
                  const statusBg = isFrozen ? 'rgba(96,165,250,0.1)' : isOverdue ? 'rgba(245,158,11,0.1)' : sub.status === 'active' ? 'rgba(74,222,128,0.1)' : 'rgba(255,255,255,0.04)';
                  const statusLabel = isFrozen ? '❄ Congelada' : isOverdue ? '⚠ Vencida' : sub.status === 'active' ? '● Activa' : sub.status === 'trial' ? '◌ Trial' : sub.status;
                  return (
                    <tr key={sub.id} style={{ borderBottom: '1px solid #1e1e1e', background: isOverdue && !isFrozen ? 'rgba(245,158,11,0.03)' : 'transparent' }}>
                      <td style={{ padding: '10px 14px', fontSize: 13, verticalAlign: 'middle' }}>
                        <div style={{ fontWeight: 600 }}>{sub.customer_name}</div>
                        <div style={{ fontSize: 11.5, color: '#888', fontFamily: '"JetBrains Mono", monospace' }}>{sub.customer_email}</div>
                      </td>
                      <td style={{ padding: '10px 14px', fontSize: 13, verticalAlign: 'middle' }}>
                        <div>{sub.agent_name}</div>
                        {sub.agent_price_cents > 0 && <div style={{ fontSize: 11.5, color: '#888' }}>{sub.agent_price_cents / 100} €/mes</div>}
                      </td>
                      <td style={{ padding: '10px 14px', fontSize: 12, color: '#aaa', verticalAlign: 'middle', fontFamily: '"JetBrains Mono", monospace' }}>{sub.plan}</td>
                      <td style={{ padding: '10px 14px', verticalAlign: 'middle' }}>
                        <span style={{ display: 'inline-flex', alignItems: 'center', gap: 4, padding: '2px 8px', borderRadius: 5, fontSize: 11.5, fontWeight: 600, color: statusColor, background: statusBg }}>{statusLabel}</span>
                      </td>
                      <td style={{ padding: '10px 14px', fontSize: 12, color: '#888', verticalAlign: 'middle', fontFamily: '"JetBrains Mono", monospace' }}>
                        <div>{sub.current_period_end ? new Date(sub.current_period_end).toLocaleDateString('es-ES') : '—'}</div>
                      </td>
                      <td style={{ padding: '10px 14px', fontSize: 13, verticalAlign: 'middle' }}>
                        {sub.days_overdue > 0
                          ? <span style={{ color: '#f59e0b', fontWeight: 700 }}>{sub.days_overdue}d</span>
                          : <span style={{ color: '#555' }}>—</span>
                        }
                      </td>
                      <td style={{ padding: '10px 14px', verticalAlign: 'middle' }}>
                        <div style={{ display: 'flex', gap: 5, flexWrap: 'wrap' }}>
                          {!isFrozen && <button onClick={() => freezeSub(sub.id)} style={{ background: 'none', border: '1px solid rgba(96,165,250,0.3)', borderRadius: 5, padding: '4px 10px', fontSize: 12, color: '#60a5fa', cursor: 'pointer', fontFamily: 'inherit' }}>❄ Congelar</button>}
                          {isFrozen && <button onClick={() => unfreezeSub(sub.id)} style={{ background: 'none', border: '1px solid rgba(74,222,128,0.3)', borderRadius: 5, padding: '4px 10px', fontSize: 12, color: '#4ade80', cursor: 'pointer', fontFamily: 'inherit' }}>▶ Reactivar</button>}
                          {(isOverdue || isFrozen) && sub.customer_email && (
                            <button onClick={() => remindSub(sub.id)} style={{ background: 'none', border: '1px solid rgba(245,158,11,0.3)', borderRadius: 5, padding: '4px 10px', fontSize: 12, color: '#f59e0b', cursor: 'pointer', fontFamily: 'inherit' }}>✉ Recordar</button>
                          )}
                        </div>
                      </td>
                    </tr>
                  );
                })}
              </tbody>
            </table>
          </div>
        </div>
      )}

      {adminTab === 'integrations' && (
        <div className="section">
          <div style={{ display: 'grid', gridTemplateColumns: '1.2fr 1fr', gap: 14 }}>
            <div style={{ background: '#1a1a1a', border: '1px solid #2a2a2a', borderRadius: 10, padding: 14 }}>
              <div style={{ fontSize: 12.5, fontWeight: 700, marginBottom: 10 }}>Workspace integrations (globales)</div>
              <div style={{ display: 'grid', gridTemplateColumns: '1fr', gap: 8 }}>
                <label style={{ fontSize: 12, color: '#888' }}>Slug</label>
                <select
                  value={globalForm.slug}
                  onChange={(e) => setGlobalForm((p) => ({ ...p, slug: e.target.value }))}
                  style={{ background: '#111', border: '1px solid #2a2a2a', color: '#e5e5e5', borderRadius: 6, padding: '8px 10px' }}
                >
                  {['twenty','salesforce','snowflake','jira','pagerduty','okta','netsuite'].map((slug) => (
                    <option key={slug} value={slug}>{slug}</option>
                  ))}
                </select>
                <label style={{ fontSize: 12, color: '#888' }}>Account name</label>
                <input value={globalForm.account_name} onChange={(e) => setGlobalForm((p) => ({ ...p, account_name: e.target.value }))} style={{ background: '#111', border: '1px solid #2a2a2a', color: '#e5e5e5', borderRadius: 6, padding: '8px 10px' }} />
                <label style={{ fontSize: 12, color: '#888' }}>API key (opcional si ya existe)</label>
                <input value={globalForm.api_key} onChange={(e) => setGlobalForm((p) => ({ ...p, api_key: e.target.value }))} style={{ background: '#111', border: '1px solid #2a2a2a', color: '#e5e5e5', borderRadius: 6, padding: '8px 10px' }} />
                <label style={{ fontSize: 12, color: '#888' }}>Webhook URL (opcional)</label>
                <input value={globalForm.webhook_url} onChange={(e) => setGlobalForm((p) => ({ ...p, webhook_url: e.target.value }))} style={{ background: '#111', border: '1px solid #2a2a2a', color: '#e5e5e5', borderRadius: 6, padding: '8px 10px' }} />
              </div>
              <div style={{ display: 'flex', gap: 8, marginTop: 10 }}>
                <button className="btn btn-primary" onClick={saveGlobalIntegration}><Icon name="check" size={12} /> Guardar global</button>
                <button className="btn" onClick={loadGlobalIntegrations}><Icon name="refresh" size={12} /> Recargar</button>
              </div>
              {globalIntegrationsError && <div style={{ marginTop: 8, color: '#ff6b6b', fontSize: 12 }}>{globalIntegrationsError}</div>}
            </div>

            <div style={{ background: '#1a1a1a', border: '1px solid #2a2a2a', borderRadius: 10, padding: 14 }}>
              <div style={{ fontSize: 12.5, fontWeight: 700, marginBottom: 10 }}>Leads ↔ CRM Sync</div>
              <p style={{ color: '#888', fontSize: 12, lineHeight: 1.45 }}>
                Ejecuta sincronización de leads cualificados hacia Twenty CRM usando la conexión global.
              </p>
              <button className="btn btn-primary" onClick={runTwentySync} disabled={globalSyncRunning}>
                <Icon name="plug" size={12} /> {globalSyncRunning ? 'Sincronizando...' : 'Sincronizar Twenty ahora'}
              </button>
            </div>
          </div>

          <div style={{ marginTop: 14, background: '#1a1a1a', border: '1px solid #2a2a2a', borderRadius: 10, overflow: 'hidden' }}>
            <table style={{ width: '100%', borderCollapse: 'collapse' }}>
              <thead>
                <tr>
                  <th style={{ padding: '10px 12px', textAlign: 'left', color: '#888', fontSize: 11, textTransform: 'uppercase', borderBottom: '1px solid #2a2a2a' }}>Slug</th>
                  <th style={{ padding: '10px 12px', textAlign: 'left', color: '#888', fontSize: 11, textTransform: 'uppercase', borderBottom: '1px solid #2a2a2a' }}>Estado</th>
                  <th style={{ padding: '10px 12px', textAlign: 'left', color: '#888', fontSize: 11, textTransform: 'uppercase', borderBottom: '1px solid #2a2a2a' }}>Cuenta</th>
                  <th style={{ padding: '10px 12px', textAlign: 'left', color: '#888', fontSize: 11, textTransform: 'uppercase', borderBottom: '1px solid #2a2a2a' }}>API key</th>
                  <th style={{ padding: '10px 12px', textAlign: 'left', color: '#888', fontSize: 11, textTransform: 'uppercase', borderBottom: '1px solid #2a2a2a' }}>Último test</th>
                  <th style={{ padding: '10px 12px', textAlign: 'left', color: '#888', fontSize: 11, textTransform: 'uppercase', borderBottom: '1px solid #2a2a2a' }}>Acciones</th>
                </tr>
              </thead>
              <tbody>
                {globalIntegrationsLoading && (
                  <tr><td colSpan={6} style={{ padding: '14px 12px', color: '#888' }}>Cargando...</td></tr>
                )}
                {!globalIntegrationsLoading && globalIntegrations.length === 0 && (
                  <tr><td colSpan={6} style={{ padding: '14px 12px', color: '#888' }}>Sin integraciones globales aún.</td></tr>
                )}
                {!globalIntegrationsLoading && globalIntegrations.map((row) => (
                  <tr key={row.slug}>
                    <td style={{ padding: '10px 12px', borderBottom: '1px solid #1e1e1e', color: '#e5e5e5' }}>{row.slug}</td>
                    <td style={{ padding: '10px 12px', borderBottom: '1px solid #1e1e1e', color: row.status === 'active' ? '#4ade80' : '#f59e0b' }}>{row.status || '—'}</td>
                    <td style={{ padding: '10px 12px', borderBottom: '1px solid #1e1e1e', color: '#ccc' }}>{row.account_name || '—'}</td>
                    <td style={{ padding: '10px 12px', borderBottom: '1px solid #1e1e1e', color: '#bbb', fontFamily: '"JetBrains Mono", monospace' }}>{row.api_key_masked || '—'}</td>
                    <td style={{ padding: '10px 12px', borderBottom: '1px solid #1e1e1e', color: '#999' }}>{row.last_tested_at ? new Date(row.last_tested_at).toLocaleString('es-ES') : 'Nunca'}</td>
                    <td style={{ padding: '10px 12px', borderBottom: '1px solid #1e1e1e' }}>
                      <button onClick={() => removeGlobalIntegration(row.slug)} style={{ background: 'none', border: '1px solid rgba(255,80,80,0.25)', color: '#ff6b6b', borderRadius: 6, padding: '4px 10px', fontSize: 12, cursor: 'pointer' }}>Eliminar</button>
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        </div>
      )}

      {/* Edit modal */}
      {editUser && (
        <div style={overlayStyle} onClick={(e) => { if (e.target === e.currentTarget) setEditUser(null); }}>
          <div style={modalCardStyle}>
            <h3 style={{ margin: '0 0 20px', fontSize: 16, fontWeight: 700 }}>Editar usuario</h3>
            <div style={{ marginBottom: 14 }}>
              <label style={modalLabelStyle}>Nombre completo</label>
              <input style={modalInputStyle} type="text" value={editName} onChange={(e) => setEditName(e.target.value)} autoFocus />
            </div>
            <div style={{ marginBottom: 14 }}>
              <label style={modalLabelStyle}>Email</label>
              <input style={modalInputStyle} type="email" value={editEmail} onChange={(e) => setEditEmail(e.target.value)} />
            </div>
            <div style={{ marginBottom: 14 }}>
              <label style={modalLabelStyle}>Teléfono</label>
              <input style={modalInputStyle} type="text" value={editPhone} onChange={(e) => setEditPhone(e.target.value)} />
            </div>
            <div style={{ marginBottom: 14 }}>
              <label style={modalLabelStyle}>Empresa</label>
              <input style={modalInputStyle} type="text" value={editCompany} onChange={(e) => setEditCompany(e.target.value)} />
            </div>
            <label style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '10px 0', cursor: 'pointer', userSelect: 'none' }} onClick={() => setEditIsActive(v => !v)}>
              <div style={{ width: 18, height: 18, borderRadius: 4, border: '1.5px solid ' + (editIsActive ? '#22c55e' : '#2a2a2a'), background: editIsActive ? '#22c55e' : 'transparent', display: 'grid', placeItems: 'center', flexShrink: 0 }}>
                {editIsActive && <Icon name="check" size={11} stroke={2.5} style={{ color: '#fff' }} />}
              </div>
              <span style={{ fontSize: 13 }}>Usuario activo</span>
            </label>
            <label style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '10px 0', cursor: 'pointer', userSelect: 'none' }} onClick={() => setEditIsAdmin(v => !v)}>
              <div style={{ width: 18, height: 18, borderRadius: 4, border: '1.5px solid ' + (editIsAdmin ? '#ff5b1f' : '#2a2a2a'), background: editIsAdmin ? '#ff5b1f' : 'transparent', display: 'grid', placeItems: 'center', flexShrink: 0 }}>
                {editIsAdmin && <Icon name="check" size={11} stroke={2.5} style={{ color: '#fff' }} />}
              </div>
              <span style={{ fontSize: 13 }}>Rol de administrador (acceso total)</span>
            </label>
            {editError && <div style={{ padding: '8px 10px', background: 'rgba(255,59,59,0.08)', border: '1px solid rgba(255,59,59,0.2)', borderRadius: 6, color: '#ff6b6b', fontSize: 12.5, marginBottom: 14 }}>{editError}</div>}
            <div style={{ display: 'flex', gap: 8, marginTop: 20, justifyContent: 'flex-end' }}>
              <button onClick={() => setEditUser(null)} style={{ background: 'none', border: '1px solid #2a2a2a', borderRadius: 6, padding: '7px 16px', color: '#888', cursor: 'pointer', fontSize: 13, fontFamily: 'inherit' }}>Cancelar</button>
              <button onClick={saveEdit} disabled={editSaving} style={{ background: '#ff5b1f', border: 'none', borderRadius: 6, padding: '7px 18px', color: '#fff', cursor: editSaving ? 'not-allowed' : 'pointer', fontSize: 13, fontWeight: 700, fontFamily: 'inherit', opacity: editSaving ? 0.7 : 1 }}>{editSaving ? 'Guardando...' : 'Guardar'}</button>
            </div>
          </div>
        </div>
      )}

      {/* Password reset modal */}
      {passwordUser && (
        <div style={overlayStyle} onClick={(e) => { if (e.target === e.currentTarget && !passwordSaving) setPasswordUser(null); }}>
          <div style={modalCardStyle}>
            <h3 style={{ margin: '0 0 6px', fontSize: 16, fontWeight: 700 }}>Cambiar contraseña</h3>
            <p style={{ margin: '0 0 18px', fontSize: 12.5, color: '#888', lineHeight: 1.45 }}>
              Usuario: <b style={{ color: '#e5e5e5' }}>{passwordUser.full_name || passwordUser.email}</b>
            </p>
            <div style={{ marginBottom: 12 }}>
              <label style={modalLabelStyle}>Nueva contraseña</label>
              <input
                style={modalInputStyle}
                type="password"
                value={newPassword}
                onChange={(e) => { setNewPassword(e.target.value); setPasswordError(''); }}
                autoComplete="new-password"
                autoFocus
              />
            </div>
            <div style={{ marginBottom: 14 }}>
              <label style={modalLabelStyle}>Confirmar contraseña</label>
              <input
                style={modalInputStyle}
                type="password"
                value={newPasswordConfirm}
                onChange={(e) => { setNewPasswordConfirm(e.target.value); setPasswordError(''); }}
                autoComplete="new-password"
              />
            </div>
            {passwordError && <div style={{ padding: '8px 10px', background: 'rgba(255,59,59,0.08)', border: '1px solid rgba(255,59,59,0.2)', borderRadius: 6, color: '#ff6b6b', fontSize: 12.5, marginBottom: 14 }}>{passwordError}</div>}
            <div style={{ display: 'flex', gap: 8, marginTop: 20, justifyContent: 'flex-end' }}>
              <button onClick={() => setPasswordUser(null)} disabled={passwordSaving} style={{ background: 'none', border: '1px solid #2a2a2a', borderRadius: 6, padding: '7px 16px', color: '#888', cursor: passwordSaving ? 'not-allowed' : 'pointer', fontSize: 13, fontFamily: 'inherit' }}>Cancelar</button>
              <button onClick={savePasswordReset} disabled={passwordSaving} style={{ background: '#ff5b1f', border: 'none', borderRadius: 6, padding: '7px 18px', color: '#fff', cursor: passwordSaving ? 'not-allowed' : 'pointer', fontSize: 13, fontWeight: 700, fontFamily: 'inherit', opacity: passwordSaving ? 0.7 : 1 }}>{passwordSaving ? 'Guardando...' : 'Cambiar clave'}</button>
            </div>
          </div>
        </div>
      )}

      {/* Roles drawer */}
      {rolesUser && (
        <div style={{ position: 'fixed', inset: 0, zIndex: 940 }} onClick={(e) => { if (e.target === e.currentTarget) setRolesUser(null); }}>
          <div style={drawerStyle}>
            <div style={{ padding: '20px 20px 14px', borderBottom: '1px solid #2a2a2a', display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
              <div>
                <div style={{ fontWeight: 700, fontSize: 14 }}>Gestión de roles</div>
                <div style={{ fontSize: 12, color: '#888', marginTop: 2 }}>{rolesUser.full_name || rolesUser.email}</div>
              </div>
              <button onClick={() => setRolesUser(null)} style={{ background: 'none', border: 'none', color: '#888', cursor: 'pointer', padding: 4 }}><Icon name="close" size={16} /></button>
            </div>
            <div style={{ flex: 1, overflowY: 'auto', padding: 20 }}>
              {rolesLoading ? (
                <div style={{ color: '#888', fontSize: 13, textAlign: 'center', paddingTop: 24 }}>Cargando...</div>
              ) : (
                <>
                  <div style={{ fontSize: 11.5, color: '#888', textTransform: 'uppercase', letterSpacing: '0.06em', fontWeight: 600, marginBottom: 10 }}>Roles asignados</div>
                  {userRoles.length === 0
                    ? <div style={{ color: '#555', fontSize: 13, marginBottom: 16 }}>Sin roles asignados. Este usuario solo tiene acceso a las secciones públicas.</div>
                    : (
                      <div style={{ display: 'flex', flexWrap: 'wrap', gap: 8, marginBottom: 20 }}>
                        {userRoles.map(r => {
                          const m = ROLE_META[r] || { label: r, color: '#888', bg: 'rgba(255,255,255,0.05)' };
                          return (
                            <div key={r} style={{ display: 'inline-flex', alignItems: 'center', gap: 6, padding: '4px 10px', borderRadius: 6, fontSize: 12.5, fontWeight: 600, color: m.color, background: m.bg, border: '1px solid ' + m.color + '44' }}>
                              {m.label}
                              <button onClick={() => removeRole(r)} disabled={rolesSaving} style={{ background: 'none', border: 'none', color: m.color, cursor: 'pointer', padding: 0, fontSize: 14, lineHeight: 1, opacity: rolesSaving ? 0.4 : 1 }}>×</button>
                            </div>
                          );
                        })}
                      </div>
                    )
                  }

                  <div style={{ fontSize: 11.5, color: '#888', textTransform: 'uppercase', letterSpacing: '0.06em', fontWeight: 600, marginBottom: 10 }}>Añadir rol</div>
                  {availableRolesToAdd.length === 0
                    ? <div style={{ color: '#555', fontSize: 13 }}>Todos los roles están asignados.</div>
                    : (
                      <div style={{ display: 'flex', gap: 8 }}>
                        <select
                          value={addingRole}
                          onChange={e => setAddingRole(e.target.value)}
                          style={{ flex: 1, background: '#111', border: '1px solid #2a2a2a', borderRadius: 6, padding: '7px 10px', fontSize: 13, color: '#e5e5e5', fontFamily: 'inherit', outline: 'none' }}
                        >
                          <option value="">Seleccionar rol...</option>
                          {availableRolesToAdd.map(r => (
                            <option key={r} value={r}>{ROLE_META[r]?.label || r}</option>
                          ))}
                        </select>
                        <button
                          onClick={addRole}
                          disabled={!addingRole || rolesSaving}
                          style={{ background: '#7c3aed', border: 'none', borderRadius: 6, padding: '7px 14px', color: '#fff', cursor: (!addingRole || rolesSaving) ? 'not-allowed' : 'pointer', fontSize: 13, fontWeight: 700, fontFamily: 'inherit', opacity: (!addingRole || rolesSaving) ? 0.5 : 1 }}
                        >
                          Añadir
                        </button>
                      </div>
                    )
                  }
                  {rolesImpact.changed && (
                    <div style={{ marginTop: 12, marginBottom: 4, padding: '10px 12px', borderRadius: 7, border: '1px solid rgba(255,91,31,0.35)', background: 'rgba(255,91,31,0.08)' }}>
                      <div style={{ fontSize: 11.5, fontWeight: 700, letterSpacing: '0.04em', textTransform: 'uppercase', color: '#ffb089', marginBottom: 6 }}>
                        Impacto de permisos
                      </div>
                      <div style={{ display: 'flex', flexDirection: 'column', gap: 4 }}>
                        {rolesImpact.changes.map((change) => (
                          <div key={change.section} style={{ fontSize: 12, color: '#e5e5e5' }}>
                            <span style={{ color: '#ffb089', fontWeight: 700, textTransform: 'capitalize' }}>{change.section}</span>
                            {' '}
                            {PERM_LABEL[change.before] || 'sin acceso'}
                            {' -> '}
                            {PERM_LABEL[change.after] || 'sin acceso'}
                          </div>
                        ))}
                      </div>
                    </div>
                  )}

                  {/* Secciones accesibles */}
                  {userRoles.length > 0 && (
                    <div style={{ marginTop: 28 }}>
                      <div style={{ fontSize: 11.5, color: '#888', textTransform: 'uppercase', letterSpacing: '0.06em', fontWeight: 600, marginBottom: 10 }}>Secciones accesibles</div>
                      {(() => {
                        const LEVEL_LABEL = { view: 'solo ver', edit: 'editar', manage: 'gestión total' };
                        const LEVEL_COLOR = { view: '#60a5fa', edit: '#34d399', manage: '#f472b6' };
                        const merged = {};
                        for (const role of userRoles) {
                          for (const [sec, lvl] of Object.entries(ROLE_SECTION_PERMS[role] || {})) {
                            if (!merged[sec] || PERM_LEVEL[lvl] > PERM_LEVEL[merged[sec]]) merged[sec] = lvl;
                          }
                        }
                        const entries = Object.entries(merged);
                        if (entries.length === 0) return <div style={{ color: '#555', fontSize: 13 }}>—</div>;
                        return (
                          <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
                            {entries.map(([sec, lvl]) => (
                              <div key={sec} style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', padding: '6px 10px', background: '#111', borderRadius: 6, fontSize: 12.5 }}>
                                <span style={{ textTransform: 'capitalize', color: '#ccc' }}>{sec}</span>
                                <span style={{ fontSize: 11, fontWeight: 600, color: LEVEL_COLOR[lvl] }}>{LEVEL_LABEL[lvl]}</span>
                              </div>
                            ))}
                          </div>
                        );
                      })()}
                    </div>
                  )}
                </>
              )}
            </div>
          </div>
        </div>
      )}

      {/* Agents drawer */}
      {agentsUser && (
        <div style={{ position: 'fixed', inset: 0, zIndex: 940 }} onClick={(e) => { if (e.target === e.currentTarget) setAgentsUser(null); }}>
          <div style={drawerStyle}>
            <div style={{ padding: '20px 20px 14px', borderBottom: '1px solid #2a2a2a', display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
              <div>
                <div style={{ fontWeight: 700, fontSize: 14 }}>Agentes comprados</div>
                <div style={{ fontSize: 12, color: '#888', marginTop: 2 }}>{agentsUser.full_name || agentsUser.email}</div>
              </div>
              <button onClick={() => setAgentsUser(null)} style={{ background: 'none', border: 'none', color: '#888', cursor: 'pointer', padding: 4 }}><Icon name="close" size={16} /></button>
            </div>
            <div style={{ flex: 1, overflowY: 'auto', padding: 16 }}>
              {agentsLoading && <div style={{ color: '#888', fontSize: 13, textAlign: 'center', paddingTop: 24 }}>Cargando agentes...</div>}
              {!agentsLoading && agentsList.length === 0 && <div style={{ color: '#888', fontSize: 13, textAlign: 'center', paddingTop: 24 }}>Este usuario no tiene agentes comprados.</div>}
              {!agentsLoading && agentsList.map((agent, i) => (
                <div key={agent.id || i} style={{ padding: '12px 0', borderBottom: i < agentsList.length - 1 ? '1px solid #1e1e1e' : 'none' }}>
                  <div style={{ fontWeight: 600, fontSize: 13 }}>{agent.name || agent.agent_name || agent.id}</div>
                  {agent.purchased_at && <div style={{ fontSize: 11.5, color: '#888', marginTop: 3, fontFamily: '"JetBrains Mono", monospace' }}>Comprado el {formatDate(agent.purchased_at)}</div>}
                  {agent.status && <div style={{ marginTop: 4 }}><span style={badgeStyle(agent.status === 'active' ? '#4ade80' : '#888', agent.status === 'active' ? 'rgba(74,222,128,0.1)' : 'rgba(255,255,255,0.04)')}>{agent.status}</span></div>}
                </div>
              ))}
            </div>
          </div>
        </div>
      )}

      {/* Register modal */}
      {showRegister && (
        <AuthModal
          isOpen={true}
          onClose={() => setShowRegister(false)}
          onSuccess={() => { setShowRegister(false); loadUsers(); }}
        />
      )}

    </div>
  );
};

window.AdminPanel = AdminPanel;
