/* screen_admin_users.jsx — Admin · Users (lista master).
   Hash routing: #screen=admin-users abre lista; #screen=admin-users&user=42 abre drawer.

   Depende:
     window.AdminUsersData      (admin_users_data.js)
     window.AdminUsers          (admin_users_components.jsx)
     window.AdminUserDrawer     (screen_admin_users_detail.jsx — opcional, gracefully degraded)
     window.Icon

   Visível só a tipos: admin, c_suite, director, manager (RBAC mock).
*/
const AdminUsersScreen = ({ user }) => {
  const D  = window.AdminUsersData;
  const UI = window.AdminUsers;
  if (!D || !UI) return <div style={{ padding: 40, color: 'var(--err)' }}>Erro: módulos AdminUsers/Data não carregados.</div>;

  // ── Re-render quando dados reais chegam da BD ──
  const [_tick, setTick] = React.useState(0);
  React.useEffect(() => {
    const handler = () => setTick(t => t + 1);
    window.addEventListener('digi-users-loaded', handler);
    return () => window.removeEventListener('digi-users-loaded', handler);
  }, []);

  // ── Gate RBAC ──
  const allowed = ['admin','c_suite','director','manager'].includes(user?.tipo || user?.role);
  if (!allowed) {
    return (
      <div style={{ padding: 60, textAlign: 'center', color: 'var(--text-muted)' }}>
        <Icon name="warning" size={32} style={{ color: 'var(--warn)' }} />
        <div style={{ fontSize: 16, fontWeight: 600, marginTop: 12 }}>Acesso restrito</div>
        <div style={{ fontSize: 13, marginTop: 4 }}>Esta secção é visível apenas a Admin / C-Suite / Director / Manager.</div>
      </div>
    );
  }

  // ── State ──
  const [search,    setSearch]    = React.useState('');
  const [filters,   setFilters]   = React.useState({
    empresa: 'all', tipo: 'all', seniority: 'all', modo_digi: 'all',
    portal: 'all', enriched: 'all', pais: 'all', office: 'all', overrides: 'all',
  });
  const [sortBy,    setSortBy]    = React.useState({ key: 'nome_apresentar', dir: 'asc' });
  const [selected,  setSelected]  = React.useState(new Set());
  const [density,   setDensity]   = React.useState(() => { try { return localStorage.getItem('au-density') || 'comfortable'; } catch { return 'comfortable'; } });
  const [columns,   setColumns]   = React.useState(() => {
    try {
      const stored = JSON.parse(localStorage.getItem('au-columns') || 'null');
      if (stored) return stored;
    } catch {}
    return DEFAULT_COLUMNS();
  });
  const [colsOpen,  setColsOpen]  = React.useState(false);
  const [editingUser, setEditingUser] = React.useState(null);

  // ── Modais ──
  const [modal, setModal] = React.useState(null); // 'novo' | 'csv' | null
  const [syncOpen, setSyncOpen] = React.useState(false);
  const syncBtnRef = React.useRef(null);
  const [toast, setToast] = React.useState(null);
  const showToast = (msg, kind = 'ok') => {
    setToast({ msg, kind });
    setTimeout(() => setToast(null), 4000);
  };

  // ── Hash routing (drawer) ──
  React.useEffect(() => {
    const handler = () => {
      const m = location.hash.match(/[#&]user=(\d+)/);
      if (m) {
        const u = D.ALL_USERS.find(x => x.id === Number(m[1]));
        if (u) { setEditingUser(u); return; }
      }
      setEditingUser(null);
    };
    handler();
    window.addEventListener('hashchange', handler);
    return () => window.removeEventListener('hashchange', handler);
  }, []);

  const openUser = (u) => {
    const base = location.hash.split('&user=')[0] || '#screen=admin-users';
    location.hash = `${base}&user=${u.id}`;
  };
  const closeUser = () => {
    const base = location.hash.split('&user=')[0] || '#screen=admin-users';
    history.replaceState(null, '', `${location.pathname}${location.search}${base}`);
    setEditingUser(null);
  };

  // ── Persistence ──
  React.useEffect(() => { try { localStorage.setItem('au-density', density); } catch {} }, [density]);
  React.useEffect(() => { try { localStorage.setItem('au-columns', JSON.stringify(columns)); } catch {} }, [columns]);

  // ── Filtering + sort ──
  const filtered = React.useMemo(() => {
    const q = search.trim().toLowerCase();
    let list = D.ALL_USERS.filter(u => {
      if (q) {
        const hay = `${u.nome_completo} ${u.nome_apresentar} ${u.email_profissional} ${u.telemovel || ''} ${u.areas_expertise || ''}`.toLowerCase();
        if (!hay.includes(q)) return false;
      }
      if (filters.empresa   !== 'all' && !u.empresas.some(e => e.id === filters.empresa)) return false;
      if (filters.tipo      !== 'all' && u.tipo_utilizador !== filters.tipo) return false;
      if (filters.seniority !== 'all' && u.seniority !== filters.seniority) return false;
      if (filters.modo_digi !== 'all' && u.modo_digi !== filters.modo_digi) return false;
      if (filters.portal    === 'on'  && !u.portal_activo) return false;
      if (filters.portal    === 'off' &&  u.portal_activo) return false;
      if (filters.enriched  === 'on'  && !u.apollo_enriched) return false;
      if (filters.enriched  === 'off' &&  u.apollo_enriched) return false;
      if (filters.pais      !== 'all' && u.pais !== filters.pais) return false;
      if (filters.office    !== 'all' && u.office !== filters.office) return false;
      if (filters.overrides === 'on') {
        const def = D.TIPOS_DEFAULTS[u.tipo_utilizador];
        const cur = u.permissoes;
        if (!cur) return false;
        const same = JSON.stringify({...cur, modos: undefined}) === JSON.stringify({...def, modos: undefined});
        if (same) return false;
      }
      return true;
    });

    const cmp = (a, b) => {
      let av, bv;
      switch (sortBy.key) {
        case 'nome_apresentar': av = a.nome_apresentar.toLowerCase();   bv = b.nome_apresentar.toLowerCase(); break;
        case 'tipo':            av = a.tipo_utilizador;                 bv = b.tipo_utilizador; break;
        case 'empresas_count':  av = a.empresas.length;                 bv = b.empresas.length; break;
        case 'last_seen':       av = a.ultima_interacao_digi || '';     bv = b.ultima_interacao_digi || ''; break;
        case 'criado_em':       av = a.criado_em || '';                 bv = b.criado_em || ''; break;
        default:                av = a[sortBy.key] || '';               bv = b[sortBy.key] || '';
      }
      if (av < bv) return sortBy.dir === 'asc' ? -1 : 1;
      if (av > bv) return sortBy.dir === 'asc' ? 1 : -1;
      return 0;
    };
    return list.sort(cmp);
  }, [search, filters, sortBy]);

  // ── Bulk ──
  const allVisibleSelected = filtered.length > 0 && filtered.every(u => selected.has(u.id));
  const toggleSelect = (id) => {
    const next = new Set(selected);
    if (next.has(id)) next.delete(id); else next.add(id);
    setSelected(next);
  };
  const toggleSelectAll = () => {
    if (allVisibleSelected) setSelected(new Set());
    else setSelected(new Set(filtered.map(u => u.id)));
  };

  // ── KPI ──
  const kpi = D.HEADER_KPIS;

  // ── Active filter pills (clearable) ──
  const activePills = [];
  if (filters.empresa   !== 'all') activePills.push({ k: 'empresa',   label: `Empresa: ${D.getEmpresa(filters.empresa)?.short || filters.empresa}` });
  if (filters.tipo      !== 'all') activePills.push({ k: 'tipo',      label: `Tipo: ${D.getTipo(filters.tipo)?.label || filters.tipo}` });
  if (filters.seniority !== 'all') activePills.push({ k: 'seniority', label: `Seniority: ${filters.seniority}` });
  if (filters.modo_digi !== 'all') activePills.push({ k: 'modo_digi', label: `Modo: ${filters.modo_digi}` });
  if (filters.portal    !== 'all') activePills.push({ k: 'portal',    label: `Portal: ${filters.portal === 'on' ? 'activo' : 'inactivo'}` });
  if (filters.enriched  !== 'all') activePills.push({ k: 'enriched',  label: `Apollo: ${filters.enriched === 'on' ? '✓' : '∅'}` });
  if (filters.pais      !== 'all') activePills.push({ k: 'pais',      label: `País: ${filters.pais}` });
  if (filters.office    !== 'all') activePills.push({ k: 'office',    label: `Office: ${filters.office}` });
  if (filters.overrides === 'on')  activePills.push({ k: 'overrides', label: 'Permissões: override' });
  const clearFilter = (k) => setFilters(f => ({ ...f, [k]: k === 'overrides' ? 'all' : 'all' }));
  const clearAll = () => setFilters({
    empresa: 'all', tipo: 'all', seniority: 'all', modo_digi: 'all',
    portal: 'all', enriched: 'all', pais: 'all', office: 'all', overrides: 'all',
  });

  return (
    <div style={{ height: '100%', display: 'flex', flexDirection: 'column', background: 'var(--bg)', overflow: 'hidden' }}>
      {/* ═══ HEADER ═══ */}
      <header style={{
        padding: '20px 28px 14px',
        borderBottom: '1px solid var(--border)',
        background: 'var(--bg)',
      }}>
        <div style={{ display: 'flex', alignItems: 'flex-start', gap: 16, marginBottom: 14 }}>
          <div style={{ flex: 1 }}>
            <h2 className="font-display" style={{ margin: 0, fontSize: 22, fontWeight: 600, letterSpacing: '-0.01em' }}>Admin · Users</h2>
            <div style={{ fontSize: 12, color: 'var(--text-muted)', marginTop: 4 }}>
              Tabela <code style={codeStyle}>colaboradores</code> · {kpi.total} utilizadores · 10 empresas Grupo Farben
            </div>
          </div>
          <div style={{ display: 'flex', gap: 6 }}>
            <button onClick={() => setModal('novo')} className="btn btn-sm btn-primary"><Icon name="plus" size={13} />Novo utilizador</button>
            <button onClick={() => setModal('csv')} className="btn btn-sm"><Icon name="download" size={13} />Importar CSV</button>
            <button ref={syncBtnRef} onClick={() => setSyncOpen(o => !o)} className="btn btn-sm" style={{ background: syncOpen ? 'var(--bg-elev)' : undefined }}><Icon name="refresh" size={13} />Sync MS Graph</button>
          </div>
        </div>

        {/* KPI strip */}
        <div style={{
          display: 'grid', gridTemplateColumns: 'repeat(7, 1fr)', gap: 1,
          background: 'var(--border)', border: '1px solid var(--border)',
          borderRadius: 8, overflow: 'hidden',
        }}>
          <Kpi label="Total"            value={kpi.total} />
          <Kpi label="Portal activo"    value={kpi.portalActivo}   suffix={`/ ${kpi.total}`}     pct={kpi.portalActivo / kpi.total} accent="var(--ok)" />
          <Kpi label="C/ telemóvel"     value={kpi.comTelemovel}   suffix={`/ ${kpi.total}`}     pct={kpi.comTelemovel / kpi.total} />
          <Kpi label="C/ foto"          value={kpi.comFoto}        suffix={`/ ${kpi.total}`}     pct={kpi.comFoto / kpi.total} />
          <Kpi label="Portugal"         value={kpi.pt}             suffix="PT" />
          <Kpi label="España"           value={kpi.es}             suffix="ES" />
          <Kpi label="Apollo enriched"  value={kpi.apolloEnriched} suffix={`/ ${kpi.total}`}     pct={kpi.apolloEnriched / kpi.total} accent="var(--ai-500)" />
        </div>
      </header>

      {/* ═══ FILTERS ═══ */}
      <div style={{
        padding: '10px 28px',
        borderBottom: '1px solid var(--border)',
        background: 'var(--bg-elev)',
        display: 'flex', flexDirection: 'column', gap: 8,
      }}>
        <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap', alignItems: 'center' }}>
          {/* Search */}
          <div style={{ position: 'relative', flex: '0 0 280px' }}>
            <Icon name="search" size={13} style={{ position: 'absolute', left: 10, top: '50%', transform: 'translateY(-50%)', color: 'var(--text-muted)' }} />
            <input
              placeholder="Pesquisar nome, email, tel, expertise…"
              value={search} onChange={e => setSearch(e.target.value)}
              style={{
                width: '100%', padding: '6px 10px 6px 30px',
                border: '1px solid var(--border)', borderRadius: 6,
                background: 'var(--bg)', fontSize: 12, color: 'var(--text)',
                outline: 'none',
              }}
            />
          </div>

          <FilterSelect label="Empresa"   value={filters.empresa}   onChange={v => setFilters(f => ({...f, empresa: v}))}   options={[{id:'all',label:'Todas'}, ...D.EMPRESAS.map(e => ({id: e.id, label: `${e.short} · ${e.count}`}))]} />
          <FilterSelect label="Tipo"      value={filters.tipo}      onChange={v => setFilters(f => ({...f, tipo: v}))}      options={[{id:'all',label:'Todos'}, ...D.TIPOS.map(t => ({id: t.id, label: t.label}))]} />
          <FilterSelect label="Seniority" value={filters.seniority} onChange={v => setFilters(f => ({...f, seniority: v}))} options={[{id:'all',label:'Todos'}, ...D.SENIORITIES.map(s => ({id: s, label: s}))]} />
          <FilterSelect label="Modo Digi" value={filters.modo_digi} onChange={v => setFilters(f => ({...f, modo_digi: v}))} options={[{id:'all',label:'Todos'}, ...D.MODOS_DIGI.map(m => ({id: m.id, label: m.label}))]} />
          <FilterSelect label="Portal"    value={filters.portal}    onChange={v => setFilters(f => ({...f, portal: v}))}    options={[{id:'all',label:'Todos'},{id:'on',label:'Activo'},{id:'off',label:'Sem acesso'}]} />
          <FilterSelect label="Apollo"    value={filters.enriched}  onChange={v => setFilters(f => ({...f, enriched: v}))}  options={[{id:'all',label:'Todos'},{id:'on',label:'Enriched'},{id:'off',label:'Pendente'}]} />
          <FilterSelect label="País"      value={filters.pais}      onChange={v => setFilters(f => ({...f, pais: v}))}      options={[{id:'all',label:'Todos'}, ...D.PAISES.map(p => ({id: p, label: p}))]} />
          <FilterSelect label="Office"    value={filters.office}    onChange={v => setFilters(f => ({...f, office: v}))}    options={[{id:'all',label:'Todos'}, ...D.OFFICES.map(o => ({id: o, label: o}))]} />
          <FilterSelect label="Permissões"value={filters.overrides} onChange={v => setFilters(f => ({...f, overrides: v}))} options={[{id:'all',label:'Todos'},{id:'on',label:'Override'}]} />

          <div style={{ flex: 1 }} />

          {/* Density */}
          <div style={{ display: 'inline-flex', gap: 2, padding: 2, background: 'var(--bg-sunken)', borderRadius: 999, border: '1px solid var(--border)' }}>
            {[{id:'comfortable',label:'Conf.'},{id:'compact',label:'Comp.'}].map(d => (
              <button key={d.id} onClick={() => setDensity(d.id)} style={{
                padding: '4px 10px', borderRadius: 999, fontSize: 10.5,
                fontFamily: 'var(--font-display)', fontWeight: 600, letterSpacing: '0.04em',
                border: 'none', cursor: 'pointer',
                background: density === d.id ? 'var(--bg-elev)' : 'transparent',
                color: density === d.id ? 'var(--text)' : 'var(--text-muted)',
                boxShadow: density === d.id ? 'var(--shadow-sm)' : 'none',
              }}>{d.label}</button>
            ))}
          </div>

          {/* Columns */}
          <div style={{ position: 'relative' }}>
            <button onClick={() => setColsOpen(o => !o)} className="btn btn-sm" style={{ background: colsOpen ? 'var(--bg-elev)' : undefined }}>
              <Icon name="filter" size={12} />Colunas
            </button>
            {colsOpen && (
              <ColumnsMenu columns={columns} setColumns={setColumns} onClose={() => setColsOpen(false)} />
            )}
          </div>
        </div>

        {/* Active pills + counter */}
        <div style={{ display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap' }}>
          <span style={{ fontSize: 11.5, color: 'var(--text-muted)', fontFamily: 'var(--font-mono)' }}>
            {filtered.length} {filtered.length === 1 ? 'resultado' : 'resultados'}
            {filtered.length !== kpi.total && <span style={{ color: 'var(--text-dim)' }}> · de {kpi.total}</span>}
          </span>
          {activePills.map(p => (
            <button key={p.k} onClick={() => clearFilter(p.k)} style={pillStyle}>
              {p.label}
              <Icon name="close" size={10} style={{ marginLeft: 4, opacity: 0.7 }} />
            </button>
          ))}
          {activePills.length > 1 && (
            <button onClick={clearAll} style={{ ...pillStyle, color: 'var(--text-dim)', borderStyle: 'dashed' }}>limpar tudo</button>
          )}
        </div>
      </div>

      {/* ═══ BULK BAR (slide-in) ═══ */}
      {selected.size > 0 && (
        <BulkBar
          count={selected.size}
          onClear={() => setSelected(new Set())}
        />
      )}

      {/* ═══ LOADING ═══ */}
      {D.ALL_USERS.length === 0 && (
        <div style={{ flex: 1, display: 'grid', placeItems: 'center', color: 'var(--text-muted)', fontFamily: 'var(--font-mono)', fontSize: 12 }}>
          A carregar colaboradores…
        </div>
      )}

      {/* ═══ TABLE ═══ */}
      {D.ALL_USERS.length > 0 && <div className="scrollbar" style={{ flex: 1, overflow: 'auto' }}>
        <table style={{
          width: '100%', borderCollapse: 'collapse',
          fontSize: density === 'compact' ? 12 : 12.5,
          fontFamily: 'var(--font-sans)',
        }}>
          <thead style={{ position: 'sticky', top: 0, zIndex: 2, background: 'var(--bg-elev)' }}>
            <tr style={{ borderBottom: '1px solid var(--border)' }}>
              <th style={{ ...thStyle, width: 36, padding: '8px 8px 8px 28px' }}>
                <input type="checkbox" checked={allVisibleSelected}
                  onChange={toggleSelectAll}
                  style={{ accentColor: 'var(--ai-500)', cursor: 'pointer' }} />
              </th>
              <th style={{ ...thStyle, width: 36 }}></th>
              {columns.filter(c => c.visible).map(c => (
                <SortHeader key={c.id} col={c} sortBy={sortBy} onSort={(k) => setSortBy(s => ({ key: k, dir: s.key === k && s.dir === 'asc' ? 'desc' : 'asc' }))} />
              ))}
              <th style={{ ...thStyle, width: 30 }}></th>
            </tr>
          </thead>
          <tbody>
            {filtered.map(u => (
              <UserRow
                key={u.id} user={u}
                density={density} columns={columns}
                checked={selected.has(u.id)}
                onCheck={() => toggleSelect(u.id)}
                onOpen={() => openUser(u)}
              />
            ))}
          </tbody>
        </table>

        {filtered.length === 0 && (
          <div style={{ padding: 60, textAlign: 'center', color: 'var(--text-muted)' }}>
            <Icon name="search" size={28} style={{ color: 'var(--text-dim)', marginBottom: 8 }} />
            <div style={{ fontSize: 13 }}>Sem resultados para os filtros actuais.</div>
            <button onClick={clearAll} className="btn btn-sm" style={{ marginTop: 12 }}>Limpar filtros</button>
          </div>
        )}
      </div>}

      {/* ═══ DRAWER ═══ */}
      {editingUser && window.AdminUserDrawer && (
        <window.AdminUserDrawer
          user={editingUser}
          currentUserTipo={user?.tipo || user?.role}
          onClose={closeUser}
          onNext={() => {
            const idx = filtered.findIndex(x => x.id === editingUser.id);
            const next = filtered[idx + 1] || filtered[0];
            if (next) openUser(next);
          }}
          onPrev={() => {
            const idx = filtered.findIndex(x => x.id === editingUser.id);
            const prev = filtered[idx - 1] || filtered[filtered.length - 1];
            if (prev) openUser(prev);
          }}
        />
      )}
      {editingUser && !window.AdminUserDrawer && (
        <div style={{
          position: 'fixed', inset: 0, background: 'rgba(0,0,0,0.5)', zIndex: 1300,
          display: 'grid', placeItems: 'center',
        }} onClick={closeUser}>
          <div style={{ background: 'var(--bg-elev)', padding: 24, borderRadius: 8, color: 'var(--text)', maxWidth: 400 }}>
            <strong>AdminUserDrawer</strong> não carregado. (próxima task: AU4)
          </div>
        </div>
      )}

      {/* ═══ MODAIS · gestão ═══ */}
      {modal === 'novo' && window.AdminUsersModals && (
        <window.AdminUsersModals.NovoUtilizadorModal
          onClose={() => setModal(null)}
          onCreate={(u) => showToast(`Utilizador "${u.nome_completo}" criado · magic link enviado`, 'ok')}
        />
      )}
      {modal === 'csv' && window.AdminUsersModals && (
        <window.AdminUsersModals.ImportCSVModal
          onClose={() => setModal(null)}
          onImport={({ created, errors, dryRun }) => showToast(
            dryRun
              ? `Dry-run completo: ${created} OK · ${errors} erros · nada foi escrito`
              : `${created} utilizadores importados · ${errors} ignorados`,
            errors > 0 ? 'warn' : 'ok'
          )}
        />
      )}
      {syncOpen && window.AdminUsersModals && (
        <window.AdminUsersModals.SyncGraphPanel
          anchorRef={syncBtnRef}
          onClose={() => setSyncOpen(false)}
        />
      )}

      {/* ═══ TOAST ═══ */}
      {toast && (
        <div style={{
          position: 'fixed', bottom: 24, right: 24, zIndex: 1500,
          padding: '12px 16px', borderRadius: 8,
          background: 'var(--bg-elev)',
          border: `1px solid ${toast.kind === 'warn' ? 'var(--warn)' : 'var(--ok)'}`,
          boxShadow: '0 8px 24px rgba(0,0,0,0.32)',
          display: 'flex', alignItems: 'center', gap: 10,
          maxWidth: 420, fontSize: 13, color: 'var(--text)',
          fontFamily: 'var(--font-sans)',
          animation: 'toastIn 240ms cubic-bezier(0.4,0,0.2,1)',
        }}>
          <Icon name={toast.kind === 'warn' ? 'warning' : 'check'} size={14}
            style={{ color: toast.kind === 'warn' ? 'var(--warn)' : 'var(--ok)', flexShrink: 0 }} />
          <span style={{ flex: 1 }}>{toast.msg}</span>
          <button onClick={() => setToast(null)} className="btn btn-sm btn-ghost" style={{ padding: '2px 4px' }}>
            <Icon name="close" size={11} />
          </button>
        </div>
      )}
    </div>
  );
};

// ════════════════════════════════════════════════════════════════
// COLUMNS
// ════════════════════════════════════════════════════════════════
function DEFAULT_COLUMNS() {
  return [
    { id: 'foto',        label: 'Foto',           visible: true,  width: 56,  sortable: false },
    { id: 'nome',        label: 'Nome',           visible: true,  width: 240, sortable: 'nome_apresentar' },
    { id: 'tipo',        label: 'Tipo',           visible: true,  width: 110, sortable: 'tipo' },
    { id: 'empresa',     label: 'Empresa(s)',     visible: true,  width: 180, sortable: 'empresas_count' },
    { id: 'cargo',       label: 'Cargo',          visible: true,  width: 200, sortable: false },
    { id: 'email',       label: 'Email',          visible: true,  width: 220, sortable: 'email_profissional' },
    { id: 'telefone',    label: 'Telefone',       visible: false, width: 140, sortable: false },
    { id: 'office',      label: 'Office',         visible: false, width: 110, sortable: 'office' },
    { id: 'modo_digi',   label: 'Modo Digi',      visible: true,  width: 90,  sortable: false },
    { id: 'portal',      label: 'Portal',         visible: true,  width: 110, sortable: 'portal_activo' },
    { id: 'apollo',      label: 'Apollo',         visible: false, width: 90,  sortable: 'apollo_enriched' },
    { id: 'last_seen',   label: 'Última actividade', visible: true, width: 100, sortable: 'last_seen' },
    { id: 'criado',      label: 'Criado',         visible: false, width: 100, sortable: 'criado_em' },
  ];
}

// ════════════════════════════════════════════════════════════════
// SUB-COMPONENTS
// ════════════════════════════════════════════════════════════════

const Kpi = ({ label, value, suffix, pct, accent }) => (
  <div style={{
    background: 'var(--bg-elev)',
    padding: '10px 14px',
    display: 'flex', flexDirection: 'column', gap: 4,
  }}>
    <div className="font-display" style={{
      fontSize: 9.5, fontWeight: 600, letterSpacing: '0.10em',
      textTransform: 'uppercase', color: 'var(--text-muted)',
    }}>{label}</div>
    <div style={{ display: 'flex', alignItems: 'baseline', gap: 5 }}>
      <span style={{ fontSize: 18, fontWeight: 600, fontFamily: 'var(--font-display)', color: accent || 'var(--text)', lineHeight: 1 }}>{value}</span>
      {suffix && <span style={{ fontSize: 10, color: 'var(--text-dim)', fontFamily: 'var(--font-mono)' }}>{suffix}</span>}
    </div>
    {pct != null && (
      <div style={{ height: 2, background: 'var(--bg-sunken)', borderRadius: 1, overflow: 'hidden' }}>
        <div style={{ height: '100%', width: `${pct * 100}%`, background: accent || 'var(--text-muted)' }} />
      </div>
    )}
  </div>
);

const FilterSelect = ({ label, value, onChange, options }) => {
  const isActive = value !== 'all';
  return (
    <div style={{ display: 'inline-flex', flexDirection: 'column', gap: 1 }}>
      <select value={value} onChange={e => onChange(e.target.value)} style={{
        padding: '5px 8px',
        border: `1px solid ${isActive ? 'var(--ai-500)' : 'var(--border)'}`,
        borderRadius: 6, background: 'var(--bg)', fontSize: 11.5,
        color: isActive ? 'var(--text)' : 'var(--text-muted)',
        outline: 'none', fontFamily: 'var(--font-sans)',
        fontWeight: isActive ? 500 : 400,
      }}>
        {options.map(o => <option key={o.id} value={o.id}>{label}: {o.label}</option>)}
      </select>
    </div>
  );
};

const SortHeader = ({ col, sortBy, onSort }) => {
  const sortable = !!col.sortable;
  const active = sortBy.key === col.sortable;
  return (
    <th style={{
      ...thStyle, width: col.width,
      cursor: sortable ? 'pointer' : 'default',
      userSelect: 'none',
    }} onClick={() => sortable && onSort(col.sortable)}>
      <span style={{ display: 'inline-flex', alignItems: 'center', gap: 4 }}>
        {col.label}
        {active && <Icon name={sortBy.dir === 'asc' ? 'arrowUp' : 'arrowDown'} size={9} style={{ color: 'var(--ai-500)' }} />}
      </span>
    </th>
  );
};

const UserRow = ({ user: u, density, columns, checked, onCheck, onOpen }) => {
  const D  = window.AdminUsersData;
  const UI = window.AdminUsers;
  const rowPad = density === 'compact' ? '6px 10px' : '10px 12px';
  const primary = u.empresas.find(e => e.is_primary) || u.empresas[0];
  const cargo   = primary?.cargo || u.perfil_cargo || '—';

  const cellByCol = {
    foto:      <UI.Avatar user={u} size={density === 'compact' ? 26 : 32} />,
    nome: (
      <div>
        <div style={{ fontWeight: 500, color: 'var(--text)' }}>
          {u.nome_apresentar}
          {u.nome_apresentar !== u.nome_completo && (
            <span style={{ fontSize: 10.5, color: 'var(--text-dim)', marginLeft: 6, fontWeight: 400 }}>
              ({u.nome_completo.split(' ').slice(-1)[0]})
            </span>
          )}
        </div>
        {density === 'comfortable' && (
          <div style={{ fontSize: 10.5, color: 'var(--text-dim)', fontFamily: 'var(--font-mono)' }}>
            {u.email_profissional}
          </div>
        )}
      </div>
    ),
    tipo:      <UI.TipoBadge tipo={u.tipo_utilizador} />,
    empresa:   <UI.EmpresaTags user={u} />,
    cargo:     <span style={{ color: 'var(--text)' }}>{cargo}</span>,
    email:     <span style={{ fontFamily: 'var(--font-mono)', fontSize: 11, color: 'var(--text-muted)' }}>{u.email_profissional}</span>,
    telefone:  <span style={{ fontFamily: 'var(--font-mono)', fontSize: 11, color: 'var(--text-muted)' }}>{u.telemovel || '—'}</span>,
    office:    <span style={{ color: 'var(--text-muted)' }}>{u.office || '—'}</span>,
    modo_digi: <ModoDigiPill modo={u.modo_digi} />,
    portal:    <UI.PortalBadge activo={u.portal_activo} />,
    apollo:    <UI.ApolloBadge enriched={u.apollo_enriched} />,
    last_seen: <UI.RelativeTime iso={u.ultima_interacao_digi} />,
    criado:    <span style={{ fontFamily: 'var(--font-mono)', fontSize: 11, color: 'var(--text-muted)' }}>{u.criado_em || '—'}</span>,
  };

  return (
    <tr
      onClick={onOpen}
      style={{
        borderBottom: '1px solid var(--border)',
        cursor: 'pointer',
        background: checked ? 'color-mix(in oklch, var(--ai-500) 6%, transparent)' : 'transparent',
        transition: 'background 80ms',
      }}
      onMouseEnter={e => { if (!checked) e.currentTarget.style.background = 'var(--bg-hover, var(--bg-elev))'; }}
      onMouseLeave={e => { if (!checked) e.currentTarget.style.background = 'transparent'; }}
    >
      <td style={{ padding: rowPad, paddingLeft: 28 }} onClick={e => e.stopPropagation()}>
        <input type="checkbox" checked={checked} onChange={onCheck}
          style={{ accentColor: 'var(--ai-500)', cursor: 'pointer' }} />
      </td>
      <td style={{ padding: rowPad }}>
        {/* hand-drag affordance ghost (placeholder) */}
      </td>
      {columns.filter(c => c.visible).map(c => (
        <td key={c.id} style={{ padding: rowPad, verticalAlign: 'middle' }}>
          {cellByCol[c.id] ?? <span style={{ color: 'var(--text-dim)' }}>—</span>}
        </td>
      ))}
      <td style={{ padding: rowPad, textAlign: 'right' }}>
        <Icon name="chevronRight" size={13} style={{ color: 'var(--text-dim)' }} />
      </td>
    </tr>
  );
};

const ModoDigiPill = ({ modo }) => {
  const D = window.AdminUsersData;
  const m = D.MODOS_DIGI.find(x => x.id === modo);
  if (!m) return <span style={{ color: 'var(--text-dim)' }}>—</span>;
  return (
    <span style={{
      display: 'inline-flex', alignItems: 'center', gap: 4,
      padding: '2px 7px', borderRadius: 4, fontSize: 10.5,
      background: `color-mix(in oklch, ${m.color} 14%, transparent)`,
      color: m.color, fontFamily: 'var(--font-mono)',
      letterSpacing: '0.04em', textTransform: 'lowercase',
    }}>{m.label}</span>
  );
};

const ColumnsMenu = ({ columns, setColumns, onClose }) => {
  React.useEffect(() => {
    const h = (e) => { if (!e.target.closest('[data-cols-menu]')) onClose(); };
    setTimeout(() => document.addEventListener('click', h), 0);
    return () => document.removeEventListener('click', h);
  }, [onClose]);
  return (
    <div data-cols-menu style={{
      position: 'absolute', top: 'calc(100% + 4px)', right: 0,
      width: 220, background: 'var(--bg-elev)',
      border: '1px solid var(--border)', borderRadius: 8,
      boxShadow: 'var(--shadow-md)', padding: 6,
      zIndex: 100, fontSize: 12,
    }}>
      <div style={{
        padding: '6px 8px 8px',
        fontSize: 9.5, fontFamily: 'var(--font-display)', fontWeight: 600,
        letterSpacing: '0.12em', textTransform: 'uppercase',
        color: 'var(--text-muted)',
        borderBottom: '1px solid var(--border)',
        marginBottom: 4,
      }}>Mostrar colunas</div>
      {columns.map((c, i) => (
        <label key={c.id} style={{
          display: 'flex', alignItems: 'center', gap: 8,
          padding: '6px 8px', borderRadius: 4,
          cursor: 'pointer',
        }} onMouseEnter={e => e.currentTarget.style.background = 'var(--bg-sunken)'}
           onMouseLeave={e => e.currentTarget.style.background = 'transparent'}>
          <input type="checkbox" checked={c.visible}
            onChange={() => {
              const next = [...columns]; next[i] = { ...c, visible: !c.visible };
              setColumns(next);
            }}
            style={{ accentColor: 'var(--ai-500)' }}
          />
          <span style={{ flex: 1, color: c.visible ? 'var(--text)' : 'var(--text-muted)' }}>{c.label}</span>
        </label>
      ))}
      <div style={{ borderTop: '1px solid var(--border)', marginTop: 4, padding: '6px 4px 0', display: 'flex', gap: 6 }}>
        <button onClick={() => setColumns(DEFAULT_COLUMNS())} className="btn btn-sm btn-ghost" style={{ flex: 1 }}>
          <Icon name="refresh" size={11} />Repor
        </button>
      </div>
    </div>
  );
};

const BulkBar = ({ count, onClear }) => (
  <div style={{
    background: 'var(--bg-elev)',
    borderBottom: '1px solid var(--ai-500)',
    boxShadow: 'inset 0 1px 0 color-mix(in oklch, var(--ai-500) 40%, transparent)',
    padding: '8px 28px',
    display: 'flex', alignItems: 'center', gap: 12,
    animation: 'slideDown 160ms cubic-bezier(0.4, 0, 0.2, 1)',
  }}>
    <div style={{
      display: 'inline-flex', alignItems: 'center', gap: 8,
      padding: '3px 10px', borderRadius: 4,
      background: 'color-mix(in oklch, var(--ai-500) 14%, transparent)',
      color: 'var(--ai-500)', fontFamily: 'var(--font-mono)',
      fontSize: 11.5, fontWeight: 600,
    }}>
      <strong>{count}</strong>
      <span style={{ fontWeight: 400, opacity: 0.7 }}>seleccionado{count > 1 ? 's' : ''}</span>
    </div>
    <div style={{ flex: 1, display: 'flex', gap: 6 }}>
      <button className="btn btn-sm"><Icon name="user" size={12} />Atribuir empresa</button>
      <button className="btn btn-sm"><Icon name="layers" size={12} />Atribuir tipo</button>
      <button className="btn btn-sm"><Icon name="zap" size={12} />Mudar modo Digi</button>
      <button className="btn btn-sm"><Icon name="mail" size={12} />Reset password</button>
      <button className="btn btn-sm"><Icon name="sparkle" size={12} />Enriquecer Apollo</button>
      <button className="btn btn-sm" style={{ color: 'var(--err)' }}><Icon name="warning" size={12} />Suspender</button>
    </div>
    <button onClick={onClear} className="btn btn-sm btn-ghost"><Icon name="close" size={12} />Limpar</button>
  </div>
);

// ════════════════════════════════════════════════════════════════
// SHARED STYLES
// ════════════════════════════════════════════════════════════════
const thStyle = {
  textAlign: 'left', padding: '8px 12px',
  fontSize: 10, fontFamily: 'var(--font-display)', fontWeight: 600,
  letterSpacing: '0.10em', textTransform: 'uppercase',
  color: 'var(--text-muted)',
  whiteSpace: 'nowrap',
};
const codeStyle = {
  fontFamily: 'var(--font-mono)', fontSize: 10.5,
  padding: '1px 5px', background: 'var(--bg-sunken)',
  borderRadius: 3, color: 'var(--text-muted)',
};
const pillStyle = {
  display: 'inline-flex', alignItems: 'center',
  padding: '3px 8px 3px 10px',
  borderRadius: 999, fontSize: 11,
  background: 'color-mix(in oklch, var(--ai-500) 10%, transparent)',
  border: '1px solid color-mix(in oklch, var(--ai-500) 30%, transparent)',
  color: 'var(--ai-500)', fontFamily: 'var(--font-mono)',
  cursor: 'pointer',
};

// Inject keyframes once
if (typeof document !== 'undefined' && !document.getElementById('au-keyframes')) {
  const s = document.createElement('style');
  s.id = 'au-keyframes';
  s.textContent = `
    @keyframes slideDown { from { transform: translateY(-6px); opacity: 0; } to { transform: translateY(0); opacity: 1; } }
  `;
  document.head.appendChild(s);
}

window.AdminUsersScreen = AdminUsersScreen;
