// Gestão de perfis e permissões (spec 2026-08-05).
// A matriz de checkboxes vem do catálogo do backend (/permissoes-catalogo) —
// fonte única de verdade. Mudança de permissão vale a partir do PRÓXIMO login
// de cada usuário (o token de 12h carrega o snapshot das permissões).

const PA_API = window.FENIX_API_BASE;

function PerfisAdminView() {
  const can = (p) => window.FenixAuth.can(p);
  const [rows, setRows] = React.useState(null);
  const [catalogo, setCatalogo] = React.useState([]);
  const [erro, setErro] = React.useState(null);
  const [modal, setModal] = React.useState(null); // {tipo:'novo'|'editar'|'excluir', perfil}

  const carrega = React.useCallback(async () => {
    setErro(null);
    try {
      const [rp, rc] = await Promise.all([
        fetch(`${PA_API}/perfis`, { signal: AbortSignal.timeout(15000) }),
        fetch(`${PA_API}/permissoes-catalogo`, { signal: AbortSignal.timeout(15000) }),
      ]);
      if (!rp.ok) throw new Error(`API ${rp.status}`);
      setRows((await rp.json()).rows);
      if (rc.ok) setCatalogo((await rc.json()).rows);
    } catch (e) { setErro(String(e.message || e)); }
  }, []);
  React.useEffect(() => { carrega(); }, [carrega]);

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

  const fecha = (recarregar) => { setModal(null); if (recarregar) carrega(); };
  const nPerms = (p) => Object.values(p.permissoes || {}).filter(Boolean).length;

  return (
    <div>
      <div style={pa.head}>
        <div>
          <div className="fenix-eyebrow">Administração</div>
          <h2 style={pa.h2}>Perfis e permissões</h2>
        </div>
        {can('perfis.editar') &&
          <button style={pa.btnPrimary} onClick={()=>setModal({tipo:'novo'})}>+ Novo perfil</button>}
      </div>

      <div style={pa.aviso}>
        Permissões alteradas valem a partir do <b>próximo login</b> de cada usuário
        (a sessão atual carrega as permissões de quando entrou).
      </div>

      <div style={pa.grid}>
        {rows.map(p => (
          <div key={p.id} style={pa.card}>
            <div style={{display:'flex', justifyContent:'space-between', alignItems:'flex-start'}}>
              <div>
                <div style={pa.cardNome}>{p.nome}</div>
                {p.descricao && <div style={pa.cardDesc}>{p.descricao}</div>}
              </div>
              <span style={pa.badge}>{p.usuarios} usuário{p.usuarios === 1 ? '' : 's'}</span>
            </div>
            <div style={pa.permResumo}>
              {catalogo.filter(c => p.permissoes?.[c.key]).map(c =>
                <span key={c.key} style={pa.permChip}>{c.label}</span>)}
              {!nPerms(p) && <i style={{color:'var(--fg-4)'}}>nenhuma permissão</i>}
            </div>
            <div style={{display:'flex', gap:8, marginTop:'auto'}}>
              {can('perfis.editar') &&
                <button style={pa.btnMini} onClick={()=>setModal({tipo:'editar', perfil:p})}>Editar</button>}
              {can('perfis.excluir') &&
                <button style={{...pa.btnMini, color:'var(--negative)'}}
                  onClick={()=>setModal({tipo:'excluir', perfil:p})}>Excluir</button>}
            </div>
          </div>
        ))}
      </div>

      {modal && <PerfilModal modal={modal} catalogo={catalogo} onClose={fecha}/>}
    </div>
  );
}

function PerfilModal({ modal, catalogo, onClose }) {
  const { tipo, perfil } = modal;
  const [nome, setNome] = React.useState(perfil?.nome || '');
  const [descricao, setDescricao] = React.useState(perfil?.descricao || '');
  const [perms, setPerms] = React.useState(() => {
    const base = {};
    catalogo.forEach(c => { base[c.key] = !!perfil?.permissoes?.[c.key]; });
    return base;
  });
  const [erro, setErro] = React.useState(null);
  const [busy, setBusy] = React.useState(false);

  const grupos = [...new Set(catalogo.map(c => c.grupo))];
  const toggleGrupo = (g, valor) => setPerms(v => {
    const nv = {...v};
    catalogo.filter(c => c.grupo === g).forEach(c => { nv[c.key] = valor; });
    return nv;
  });

  const salvar = async () => {
    if (busy) return;
    setErro(null); setBusy(true);
    try {
      let res;
      if (tipo === 'excluir') {
        res = await fetch(`${PA_API}/perfis/${perfil.id}`, { method:'DELETE' });
      } else {
        res = await fetch(tipo === 'novo' ? `${PA_API}/perfis` : `${PA_API}/perfis/${perfil.id}`, {
          method: tipo === 'novo' ? 'POST' : 'PUT',
          headers: {'Content-Type':'application/json'},
          body: JSON.stringify({ nome, descricao: descricao || null, permissoes: perms }),
        });
      }
      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); }
  };

  return (
    <div style={pa.overlay} onClick={e=>{ if(e.target===e.currentTarget) onClose(false); }}>
      <div style={pa.modal}>
        <div style={pa.modalTitle}>
          {{novo:'Novo perfil', editar:`Editar — ${perfil?.nome}`, excluir:'Excluir perfil'}[tipo]}
        </div>

        {tipo === 'excluir' ? (
          <p style={{font:'var(--text-body)', color:'var(--fg-2)', margin:'4px 0 8px'}}>
            Excluir o perfil <b>{perfil.nome}</b>?
            {perfil.usuarios > 0
              ? <> Ele está em uso por <b>{perfil.usuarios} usuário(s)</b> — a exclusão será
                  bloqueada; reatribua esses usuários primeiro.</>
              : ' Essa ação não pode ser desfeita.'}
          </p>
        ) : (
          <div style={{display:'flex', flexDirection:'column', gap:12, overflow:'auto'}}>
            <div style={{display:'grid', gridTemplateColumns:'1fr 2fr', gap:10}}>
              <label style={pa.label}>Nome
                <input style={pa.input} value={nome} onChange={e=>setNome(e.target.value)}
                  autoComplete="off" autoFocus/></label>
              <label style={pa.label}>Descrição
                <input style={pa.input} value={descricao} onChange={e=>setDescricao(e.target.value)}
                  autoComplete="off"/></label>
            </div>

            {grupos.map(g => {
              const doGrupo = catalogo.filter(c => c.grupo === g);
              const todas = doGrupo.every(c => perms[c.key]);
              return (
                <div key={g} style={pa.grupo}>
                  <div style={pa.grupoHead}>
                    <span style={pa.grupoNome}>{g}</span>
                    <button type="button" style={pa.btnLink} onClick={()=>toggleGrupo(g, !todas)}>
                      {todas ? 'desmarcar todas' : 'marcar todas'}
                    </button>
                  </div>
                  {doGrupo.map(c => (
                    <label key={c.key} style={pa.permLinha} title={c.ajuda || c.key}>
                      <input type="checkbox" checked={!!perms[c.key]}
                        onChange={e=>setPerms(v=>({...v, [c.key]: e.target.checked}))}/>
                      <span>{c.label}</span>
                      <code style={pa.permKey}>{c.key}</code>
                    </label>
                  ))}
                </div>
              );
            })}
          </div>
        )}

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

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

const pa = {
  head:{ display:'flex', justifyContent:'space-between', alignItems:'flex-end', marginBottom:12, gap:16 },
  h2:{ font:'var(--text-h2)', color:'var(--fg-1)', margin:'2px 0 0' },
  aviso:{ font:'var(--text-body-sm)', color:'var(--fg-2)', background:'var(--info-bg)',
    borderRadius:'var(--r-md)', padding:'10px 14px', marginBottom:16 },
  grid:{ display:'grid', gridTemplateColumns:'repeat(auto-fill, minmax(320px, 1fr))', gap:16 },
  card:{ display:'flex', flexDirection:'column', gap:10, background:'var(--bg-surface)',
    border:'1px solid var(--border-1)', borderRadius:'var(--r-lg)', boxShadow:'var(--shadow-sm)',
    padding:'18px 18px 14px' },
  cardNome:{ font:'var(--text-h3)', color:'var(--fg-1)' },
  cardDesc:{ font:'var(--text-body-sm)', color:'var(--fg-3)', marginTop:3 },
  badge:{ font:'600 12px/1 var(--font-mono)', color:'var(--fg-3)', background:'var(--bg-sunken)',
    borderRadius:'var(--r-pill)', padding:'5px 10px', whiteSpace:'nowrap' },
  permResumo:{ display:'flex', flexWrap:'wrap', gap:6 },
  permChip:{ font:'var(--text-caption)', color:'var(--fenix-blue)', background:'var(--fenix-blue-100)',
    borderRadius:'var(--r-pill)', padding:'4px 10px' },
  vazio:{ font:'var(--text-body)', color:'var(--fg-3)', textAlign:'center', padding:'60px 0' },
  grupo:{ border:'1px solid var(--border-1)', borderRadius:'var(--r-md)', padding:'10px 14px' },
  grupoHead:{ display:'flex', justifyContent:'space-between', alignItems:'center', marginBottom:6 },
  grupoNome:{ font:'var(--text-label)', letterSpacing:'var(--tracking-eyebrow)',
    textTransform:'uppercase', color:'var(--fg-3)' },
  permLinha:{ display:'flex', alignItems:'center', gap:9, font:'var(--text-body-sm)',
    color:'var(--fg-1)', padding:'5px 0', cursor:'pointer' },
  permKey:{ font:'500 11px/1 var(--font-mono)', color:'var(--fg-4)', marginLeft:'auto' },
  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:'6px 12px', cursor:'pointer' },
  btnLink:{ font:'var(--text-caption)', color:'var(--fenix-blue)', background:'none',
    border:'none', cursor:'pointer', padding:0 },
  overlay:{ position:'fixed', inset:0, background:'rgba(1,27,54,.45)', display:'grid',
    placeItems:'center', zIndex:60 },
  modal:{ width:'min(560px, calc(100vw - 40px))', maxHeight:'calc(100vh - 60px)',
    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.PerfisAdminView = PerfisAdminView;
