// Gestão de usuários (spec 2026-08-05) — painel espelhado do sistema de gestão.
// View independente (fetch próprio, como FunnelTrackView). Ações respeitam as
// permissões do usuário logado: usuarios.ver/editar/excluir, auditoria.ver.

const UA_API = window.FENIX_API_BASE;

function UsersAdminView() {
  const can = (p) => window.FenixAuth.can(p);
  const [rows, setRows] = React.useState(null);
  const [niveis, setNiveis] = React.useState([]);
  const [audit, setAudit] = React.useState(null);
  const [erro, setErro] = React.useState(null);
  const [modal, setModal] = React.useState(null); // {tipo:'novo'|'editar'|'senha'|'excluir', user}
  const [busca, setBusca] = React.useState('');

  const carrega = React.useCallback(async () => {
    setErro(null);
    try {
      const [ru, rn] = await Promise.all([
        fetch(`${UA_API}/usuarios`, { signal: AbortSignal.timeout(15000) }),
        fetch(`${UA_API}/niveis-acesso`, { signal: AbortSignal.timeout(15000) }),
      ]);
      if (!ru.ok) throw new Error(`API ${ru.status}`);
      setRows((await ru.json()).rows);
      if (rn.ok) setNiveis((await rn.json()).rows);
      if (can('auditoria.ver')) {
        const ra = await fetch(`${UA_API}/audit-logs?limit=30`, { signal: AbortSignal.timeout(15000) });
        if (ra.ok) setAudit((await ra.json()).rows);
      }
    } catch (e) {
      setErro(String(e.message || e));
    }
  }, []);
  React.useEffect(() => { carrega(); }, [carrega]);

  if (!can('usuarios.ver')) return (
    <div style={ua.semAcesso}>Seu perfil não tem acesso à gestão de usuários.</div>
  );
  if (erro) return <div style={ua.semAcesso}>Erro ao carregar: {erro}</div>;
  if (!rows) return <div style={ua.semAcesso}>Carregando…</div>;

  const q = busca.trim().toLowerCase();
  const vis = q ? rows.filter(r =>
    (r.nome || '').toLowerCase().includes(q) || (r.email || '').toLowerCase().includes(q) ||
    (r.nivel || '').toLowerCase().includes(q)) : rows;

  const fecha = (recarregar) => { setModal(null); if (recarregar) carrega(); };

  return (
    <div>
      <div style={ua.head}>
        <div>
          <div className="fenix-eyebrow">Administração</div>
          <h2 style={ua.h2}>Usuários <span style={ua.badge}>{rows.length}</span></h2>
        </div>
        <div style={{display:'flex', gap:10}}>
          {/* autoComplete off + name genérico: sem eles o Chrome trata a página como
              formulário de login e preenche aqui o email salvo ao abrir o modal de senha */}
          <input style={ua.busca} placeholder="Buscar nome, email, nível…"
            autoComplete="off" name="filtro-usuarios"
            value={busca} onChange={e=>setBusca(e.target.value)}/>
          {can('usuarios.editar') &&
            <button style={ua.btnPrimary} onClick={()=>setModal({tipo:'novo'})}>+ Novo usuário</button>}
        </div>
      </div>

      <div style={ua.card}>
        <table style={ua.table}>
          <thead>
            <tr>
              {['Nome','Email','Nível de acesso','Último login','Status','Ações'].map(h =>
                <th key={h} style={{...ua.th, textAlign: h==='Ações'?'right':'left'}}>{h}</th>)}
            </tr>
          </thead>
          <tbody>
            {vis.map(u => (
              <tr key={u.id} style={{opacity: u.ativo ? 1 : .55}}>
                <td style={ua.td}>
                  <div style={{display:'flex', alignItems:'center', gap:10}}>
                    <span style={ua.avatar}>{u.nome.slice(0,2).toUpperCase()}</span>
                    <b>{u.nome}</b>
                  </div>
                </td>
                <td style={ua.td}>{u.email}</td>
                <td style={ua.td}>{u.nivel || <i style={{color:'var(--fg-4)'}}>sem nível</i>}</td>
                <td style={{...ua.td, fontFamily:'var(--font-mono)', fontSize:12}}>
                  {u.ultimo_login ? new Date(u.ultimo_login).toLocaleString('pt-BR') : 'nunca'}</td>
                <td style={ua.td}>
                  <span style={{...ua.pill, ...(u.ativo ? ua.pillOn : ua.pillOff)}}>
                    {u.ativo ? 'Ativo' : 'Inativo'}</span>
                </td>
                <td style={{...ua.td, textAlign:'right', whiteSpace:'nowrap'}}>
                  {can('usuarios.editar') && <>
                    <button style={ua.btnMini} onClick={()=>setModal({tipo:'editar', user:u})}>Editar</button>
                    <button style={ua.btnMini} onClick={()=>setModal({tipo:'senha', user:u})}>Senha</button>
                  </>}
                  {can('usuarios.excluir') &&
                    <button style={{...ua.btnMini, color:'var(--negative)'}}
                      onClick={()=>setModal({tipo:'excluir', user:u})}>Excluir</button>}
                </td>
              </tr>
            ))}
            {!vis.length && <tr><td colSpan={6} style={{...ua.td, textAlign:'center', color:'var(--fg-3)'}}>
              Nenhum usuário encontrado.</td></tr>}
          </tbody>
        </table>
      </div>

      {audit && (
        <div style={{...ua.card, marginTop:16}}>
          <div style={ua.cardTitle}>Atividade recente</div>
          <table style={ua.table}>
            <tbody>
              {audit.map(a => (
                <tr key={a.id}>
                  <td style={{...ua.td, width:150, fontFamily:'var(--font-mono)', fontSize:12, color:'var(--fg-3)'}}>
                    {new Date(a.criado_em).toLocaleString('pt-BR')}</td>
                  <td style={{...ua.td, width:170}}><b>{a.usuario_nome}</b></td>
                  <td style={{...ua.td, width:110}}><span style={ua.acao}>{a.acao}</span></td>
                  <td style={ua.td}>{a.descricao}</td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      )}

      {modal && <UserModal modal={modal} niveis={niveis} onClose={fecha}/>}
    </div>
  );
}

function UserModal({ modal, niveis, onClose }) {
  const { tipo, user } = modal;
  const [f, setF] = React.useState(tipo === 'editar'
    ? { nome:user.nome, email:user.email,
        nivel_acesso_id:user.nivel_acesso_id||'', ativo:user.ativo }
    : { nome:'', email:'', senha:'', nivel_acesso_id:'' });
  const [erro, setErro] = React.useState(null);
  const [busy, setBusy] = React.useState(false);
  const set = (k) => (e) => setF(v => ({...v, [k]: e.target ? e.target.value : e}));

  const salvar = async () => {
    if (busy) return;
    setErro(null); setBusy(true);
    try {
      let res;
      const nivel = f.nivel_acesso_id === '' ? null : Number(f.nivel_acesso_id);
      if (tipo === 'novo') {
        res = await fetch(`${UA_API}/usuarios`, { method:'POST',
          headers:{'Content-Type':'application/json'},
          body: JSON.stringify({ nome:f.nome, email:f.email, senha:f.senha,
            nivel_acesso_id:nivel })});
      } else if (tipo === 'editar') {
        res = await fetch(`${UA_API}/usuarios/${user.id}`, { method:'PUT',
          headers:{'Content-Type':'application/json'},
          body: JSON.stringify({ nome:f.nome, email:f.email,
            nivel_acesso_id:nivel, ativo:f.ativo })});
      } else if (tipo === 'senha') {
        res = await fetch(`${UA_API}/usuarios/${user.id}/senha`, { method:'PUT',
          headers:{'Content-Type':'application/json'}, body: JSON.stringify({ senha:f.senha })});
      } else {
        res = await fetch(`${UA_API}/usuarios/${user.id}`, { method:'DELETE' });
      }
      const body = await res.json().catch(()=> ({}));
      if (!res.ok) {
        const d = body.detail;
        setErro(typeof d === 'string' ? d : (d?.[0]?.msg || `Erro ${res.status}`));
        return;
      }
      onClose(true);
    } catch { setErro('Falha de rede — backend está rodando?'); }
    finally { setBusy(false); }
  };

  const titulo = { novo:'Novo usuário', editar:`Editar — ${user?.nome}`,
    senha:`Nova senha — ${user?.nome}`, excluir:'Excluir usuário' }[tipo];

  return (
    <div style={ua.overlay} onClick={e=>{ if(e.target===e.currentTarget) onClose(false); }}>
      <div style={ua.modal}>
        <div style={ua.modalTitle}>{titulo}</div>

        {tipo === 'excluir' ? (
          <p style={{font:'var(--text-body)', color:'var(--fg-2)', margin:'4px 0 8px'}}>
            Excluir <b>{user.nome}</b> ({user.email})? Essa ação não pode ser desfeita —
            para bloquear o acesso preservando o histórico, prefira <b>desativar</b> na edição.
          </p>
        ) : (
          <div style={{display:'flex', flexDirection:'column', gap:10}}>
            {(tipo === 'novo' || tipo === 'editar') && <>
              <label style={ua.label}>Nome
                <input style={ua.input} value={f.nome} onChange={set('nome')} autoFocus/></label>
              <label style={ua.label}>Email
                <input style={ua.input} type="email" autoComplete="off" name="email-do-usuario"
                  value={f.email} onChange={set('email')}/></label>
              <label style={ua.label}>Nível de acesso
                <select style={ua.input} value={f.nivel_acesso_id}
                  onChange={e=>setF(v=>({...v, nivel_acesso_id:e.target.value}))}>
                  <option value="">— sem nível (não loga) —</option>
                  {niveis.map(n => <option key={n.id} value={n.id}>{n.nome}</option>)}
                </select></label>
            </>}
            {(tipo === 'novo' || tipo === 'senha') &&
              <label style={ua.label}>{tipo==='senha' ? 'Nova senha' : 'Senha inicial'} (mín. 8)
                {/* new-password: impede o Chrome de injetar a senha salva do usuário logado */}
                <input style={ua.input} type="password" autoComplete="new-password"
                  value={f.senha} onChange={set('senha')} autoFocus={tipo==='senha'}/></label>}
            {tipo === 'editar' &&
              <label style={{...ua.label, flexDirection:'row', alignItems:'center', gap:8}}>
                <input type="checkbox" checked={!!f.ativo}
                  onChange={e=>setF(v=>({...v, ativo:e.target.checked}))}/> Usuário ativo</label>}
          </div>
        )}

        {erro && <div style={ua.erro}>{erro}</div>}

        <div style={{display:'flex', justifyContent:'flex-end', gap:10, marginTop:14}}>
          <button style={ua.btnGhost} onClick={()=>onClose(false)}>Cancelar</button>
          <button style={{...(tipo==='excluir' ? ua.btnDanger : ua.btnPrimary), opacity:busy?.7:1}}
            disabled={busy} onClick={salvar}>
            {busy ? 'Salvando…' : (tipo === 'excluir' ? 'Excluir' : 'Salvar')}
          </button>
        </div>
      </div>
    </div>
  );
}

const ua = {
  head:{ display:'flex', justifyContent:'space-between', alignItems:'flex-end', marginBottom:16, gap:16, flexWrap:'wrap' },
  h2:{ font:'var(--text-h2)', color:'var(--fg-1)', margin:'2px 0 0' },
  badge:{ font:'600 13px/1 var(--font-mono)', color:'var(--fg-3)', background:'var(--bg-sunken)',
    borderRadius:'var(--r-pill)', padding:'4px 10px', verticalAlign:'middle', marginLeft:8 },
  busca:{ font:'var(--text-body-sm)', color:'var(--fg-1)', border:'1px solid var(--border-2)',
    borderRadius:'var(--r-sm)', padding:'9px 12px', width:240, outline:'none', background:'var(--bg-surface)' },
  card:{ background:'var(--bg-surface)', border:'1px solid var(--border-1)', borderRadius:'var(--r-lg)',
    boxShadow:'var(--shadow-sm)', overflow:'auto' },
  cardTitle:{ font:'var(--text-label)', letterSpacing:'var(--tracking-eyebrow)', textTransform:'uppercase',
    color:'var(--fg-3)', padding:'14px 16px 4px' },
  table:{ width:'100%', borderCollapse:'collapse' },
  th:{ font:'var(--text-label)', textTransform:'uppercase', letterSpacing:'.06em', color:'var(--fg-3)',
    padding:'12px 16px', borderBottom:'1px solid var(--border-1)' },
  td:{ font:'var(--text-body-sm)', color:'var(--fg-1)', padding:'11px 16px', borderBottom:'1px solid var(--border-1)' },
  avatar:{ width:30, height:30, borderRadius:'50%', background:'var(--fenix-blue-100)', color:'var(--fenix-blue)',
    font:'700 11px/1 var(--font-sans)', display:'inline-flex', alignItems:'center', justifyContent:'center', flex:'none' },
  pill:{ font:'var(--text-caption)', fontWeight:700, borderRadius:'var(--r-pill)', padding:'4px 10px' },
  pillOn:{ color:'var(--positive)', background:'var(--positive-bg)' },
  pillOff:{ color:'var(--fg-3)', background:'var(--bg-sunken)' },
  acao:{ font:'var(--text-caption)', fontWeight:700, color:'var(--fenix-blue)', background:'var(--fenix-blue-100)',
    borderRadius:'var(--r-pill)', padding:'3px 9px' },
  btnPrimary:{ font:'var(--text-label)', color:'var(--fg-on-accent)', background:'var(--fenix-orange)',
    border:'none', borderRadius:'var(--r-sm)', padding:'10px 16px', cursor:'pointer' },
  btnDanger:{ font:'var(--text-label)', color:'#fff', background:'var(--negative)',
    border:'none', borderRadius:'var(--r-sm)', padding:'10px 16px', cursor:'pointer' },
  btnGhost:{ font:'var(--text-label)', color:'var(--fg-2)', background:'transparent',
    border:'1px solid var(--border-2)', borderRadius:'var(--r-sm)', padding:'10px 16px', cursor:'pointer' },
  btnMini:{ font:'var(--text-caption)', fontWeight:700, color:'var(--fg-2)', background:'transparent',
    border:'1px solid var(--border-2)', borderRadius:'var(--r-sm)', padding:'5px 10px', cursor:'pointer', marginLeft:6 },
  semAcesso:{ font:'var(--text-body)', color:'var(--fg-3)', textAlign:'center', padding:'60px 0' },
  overlay:{ position:'fixed', inset:0, background:'rgba(1,27,54,.45)', display:'grid', placeItems:'center', zIndex:60 },
  modal:{ width:'min(440px, calc(100vw - 40px))', background:'var(--bg-surface)', borderRadius:'var(--r-lg)',
    boxShadow:'var(--shadow-lg)', padding:'24px 24px 20px', display:'flex', flexDirection:'column' },
  modalTitle:{ font:'var(--text-h3)', color:'var(--fg-1)', marginBottom:14 },
  label:{ font:'var(--text-label)', color:'var(--fg-2)', display:'flex', flexDirection:'column', gap:5 },
  input:{ font:'var(--text-body-sm)', color:'var(--fg-1)', background:'var(--bg-surface)',
    border:'1px solid var(--border-2)', borderRadius:'var(--r-sm)', padding:'9px 11px', outline:'none' },
  erro:{ font:'var(--text-body-sm)', color:'var(--negative)', background:'var(--negative-bg)',
    borderRadius:'var(--r-sm)', padding:'8px 12px', marginTop:12 },
};

window.UsersAdminView = UsersAdminView;
