// Autenticação (spec 2026-08-05) — sessão JWT + tela de login.
// Carregar ANTES de data.jsx: o patch do fetch abaixo precisa existir quando
// qualquer chamada à API acontecer.

// Base da API (spec 2026-08-06): em dev o frontend roda na porta 5500 e a API na
// 8000; em produção o nginx serve tudo na mesma origem e faz proxy de /api →
// URL relativa. Fonte única — os demais .jsx leem window.FENIX_API_BASE.
const AUTH_API_BASE = location.port === '5500'
  ? 'http://localhost:8000/api/v1'
  : '/api/v1';
window.FENIX_API_BASE = AUTH_API_BASE;
const AUTH_TOKEN_KEY = 'fenix_token';
const AUTH_USER_KEY  = 'fenix_user';

const FenixAuth = {
  token: () => localStorage.getItem(AUTH_TOKEN_KEY),
  user: () => { try { return JSON.parse(localStorage.getItem(AUTH_USER_KEY) || 'null'); } catch { return null; } },
  save(token, user) {
    localStorage.setItem(AUTH_TOKEN_KEY, token);
    localStorage.setItem(AUTH_USER_KEY, JSON.stringify(user));
    window.dispatchEvent(new Event('fenix-auth'));
  },
  logout() {
    const t = localStorage.getItem(AUTH_TOKEN_KEY);
    localStorage.removeItem(AUTH_TOKEN_KEY);
    localStorage.removeItem(AUTH_USER_KEY);
    // registra a saída na auditoria — best-effort, não bloqueia o logout
    if (t) fetch(`${AUTH_API_BASE}/auth/logout`, { method:'POST',
      headers:{ Authorization:`Bearer ${t}` } }).catch(()=>{});
    window.dispatchEvent(new Event('fenix-auth'));
  },
  can: (perm) => !!(FenixAuth.user()?.permissoes?.[perm]),
  // Download autenticado (spec 2026-08-05): window.open não manda o Bearer —
  // baixa via fetch (o patch injeta o token) e dispara o download do blob.
  async download(url) {
    const res = await fetch(url, { signal: AbortSignal.timeout(60000) });
    if (!res.ok) {
      const body = await res.json().catch(() => ({}));
      throw new Error(body.detail || `Export falhou (${res.status})`);
    }
    const cd = res.headers.get('content-disposition') || '';
    const nome = (cd.match(/filename="?([^";]+)"?/) || [])[1]
      || url.split('/').pop().split('?')[0] + '.xlsx';
    const blob = await res.blob();
    const link = document.createElement('a');
    link.href = URL.createObjectURL(blob);
    link.download = nome;
    document.body.appendChild(link);
    link.click();
    link.remove();
    URL.revokeObjectURL(link.href);
  },
};

// Permissões exigidas por item de navegação (espelha SECTION_PERMS do backend —
// aqui é só UX; a segurança de verdade é o middleware barrar o endpoint).
const NAV_PERMS = {
  'visao': ['dashboard.ver', 'afiliados.ver'],  // visão geral usa rankings de afiliados
  'afiliados': ['afiliados.ver'], 'aov-tracker': ['afiliados.ver'], 'dre-afiliados': ['afiliados.ver'],
  'produtos': ['produtos.ver'], 'nichos': ['produtos.ver'], 'ab-test': ['produtos.ver'],
  'funnel-track': ['produtos.ver'], 'eaglelabs-cr': ['produtos.ver'],
  'canais': ['canais.ver'], 'canais-acompanhamento': ['canais.ver'],
  'canais-leads': ['canais.ver'], 'canais-leads-economics': ['canais.ver'],
  'reembolso-calendario': ['reembolso.ver'], 'reembolso-geral': ['reembolso.ver'],
  'usuarios': ['usuarios.ver'], 'perfis': ['perfis.ver'], 'auditoria': ['auditoria.ver'],
};
FenixAuth.canNav = (key) => (NAV_PERMS[key] || []).every(p => FenixAuth.can(p));
// Primeira seção permitida — usada como página inicial pós-login.
FenixAuth.firstNav = () =>
  ['visao','afiliados','produtos','canais','reembolso-calendario','usuarios','perfis']
    .find(k => FenixAuth.canNav(k)) || null;
window.FenixAuth = FenixAuth;

// Modal "Trocar minha senha" — aberto pela engrenagem do rodapé da sidebar.
// Exige a senha atual (o backend confere) e audita a troca.
function MinhaSenhaModal({ onClose }) {
  const [atual, setAtual] = React.useState('');
  const [nova, setNova] = React.useState('');
  const [confirma, setConfirma] = React.useState('');
  const [erro, setErro] = React.useState(null);
  const [ok, setOk] = React.useState(false);
  const [busy, setBusy] = React.useState(false);

  const salvar = async (e) => {
    e.preventDefault();
    if (busy) return;
    setErro(null);
    if (nova !== confirma) { setErro('A confirmação não confere com a nova senha'); return; }
    setBusy(true);
    try {
      const res = await fetch(`${AUTH_API_BASE}/auth/minha-senha`, {
        method: 'PUT', headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ senha_atual: atual, senha_nova: nova }),
        signal: AbortSignal.timeout(15000),
      });
      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;
      }
      setOk(true);
      setTimeout(onClose, 1600);
    } catch { setErro('Falha de rede — backend está rodando?'); }
    finally { setBusy(false); }
  };

  const stl = {
    overlay:{ position:'fixed', inset:0, background:'rgba(1,27,54,.45)', display:'grid',
      placeItems:'center', zIndex:80 },
    modal:{ width:'min(380px, calc(100vw - 40px))', background:'var(--bg-surface)',
      borderRadius:'var(--r-lg)', boxShadow:'var(--shadow-lg)', padding:'24px 24px 20px',
      display:'flex', flexDirection:'column', gap:12 },
    titulo:{ font:'var(--text-h3)', color:'var(--fg-1)', margin:0 },
    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)', 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' },
    okMsg:{ font:'var(--text-body-sm)', color:'var(--positive)', background:'var(--positive-bg)',
      borderRadius:'var(--r-sm)', padding:'8px 12px' },
    acoes:{ display:'flex', justifyContent:'flex-end', gap:10, marginTop:4 },
    btnGhost:{ font:'var(--text-label)', color:'var(--fg-2)', background:'transparent',
      border:'1px solid var(--border-2)', borderRadius:'var(--r-sm)', padding:'9px 16px', cursor:'pointer' },
    btnPrimary:{ font:'var(--text-label)', color:'var(--fg-on-accent)', background:'var(--fenix-orange)',
      border:'none', borderRadius:'var(--r-sm)', padding:'9px 16px', cursor:'pointer' },
  };

  return (
    <div style={stl.overlay} onClick={e=>{ if(e.target===e.currentTarget) onClose(); }}>
      <form style={stl.modal} onSubmit={salvar}>
        <h3 style={stl.titulo}>Trocar minha senha</h3>
        <label style={stl.label}>Senha atual
          <input style={stl.input} type="password" autoComplete="current-password" autoFocus
            value={atual} onChange={e=>setAtual(e.target.value)} required/></label>
        <label style={stl.label}>Nova senha (mín. 8)
          <input style={stl.input} type="password" autoComplete="new-password"
            value={nova} onChange={e=>setNova(e.target.value)} required/></label>
        <label style={stl.label}>Confirmar nova senha
          <input style={stl.input} type="password" autoComplete="new-password"
            value={confirma} onChange={e=>setConfirma(e.target.value)} required/></label>
        {erro && <div style={stl.erro}>{erro}</div>}
        {ok && <div style={stl.okMsg}>Senha alterada ✓</div>}
        <div style={stl.acoes}>
          <button type="button" style={stl.btnGhost} onClick={onClose}>Cancelar</button>
          <button style={{...stl.btnPrimary, opacity: busy ? .7 : 1}} disabled={busy || ok}>
            {busy ? 'Salvando…' : 'Salvar'}
          </button>
        </div>
      </form>
    </div>
  );
}
window.MinhaSenhaModal = MinhaSenhaModal;

// Usuário autenticado porém sem NENHUMA seção permitida (ex.: "sem nível").
function NoAccessScreen() {
  return (
    <div style={{minHeight:'100vh', display:'grid', placeItems:'center', background:'var(--bg-app)'}}>
      <div style={{textAlign:'center', maxWidth:380}}>
        <img src="assets/mark-navy.png" alt="" style={{width:44, marginBottom:12}}/>
        <h2 style={{font:'var(--text-h3)', color:'var(--fg-1)', margin:'0 0 8px'}}>Sem acesso</h2>
        <p style={{font:'var(--text-body-sm)', color:'var(--fg-3)', margin:'0 0 16px'}}>
          Seu usuário está autenticado mas não tem nenhum perfil de acesso atribuído.
          Peça a um administrador para atribuir um perfil e entre novamente.
        </p>
        <button onClick={()=>FenixAuth.logout()}
          style={{font:'var(--text-label)', color:'var(--fg-2)', background:'transparent',
            border:'1px solid var(--border-2)', borderRadius:'var(--r-sm)',
            padding:'9px 16px', cursor:'pointer'}}>Sair</button>
      </div>
    </div>
  );
}
window.NoAccessScreen = NoAccessScreen;

// Injeta o Bearer em toda chamada à API e derruba a sessão num 401 (token
// expirado/revogado) — data.jsx usa fetch puro em ~20 lugares, o patch evita
// tocar em todos.
const _fenixOrigFetch = window.fetch.bind(window);
window.fetch = (input, init = {}) => {
  const url = typeof input === 'string' ? input : (input && input.url) || '';
  const isApi = url.startsWith(AUTH_API_BASE) && !url.includes('/auth/login');
  if (isApi) {
    const t = FenixAuth.token();
    if (t) init = { ...init, headers: { ...(init.headers || {}), Authorization: `Bearer ${t}` } };
  }
  return _fenixOrigFetch(input, init).then(res => {
    if (isApi && res.status === 401 && FenixAuth.token()) FenixAuth.logout();
    return res;
  });
};

function LoginScreen() {
  const [email, setEmail] = React.useState('');
  const [senha, setSenha] = React.useState('');
  const [erro, setErro] = React.useState(null);
  const [loading, setLoading] = React.useState(false);

  const submit = async (e) => {
    e.preventDefault();
    if (loading) return;
    setErro(null); setLoading(true);
    try {
      const res = await fetch(`${AUTH_API_BASE}/auth/login`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ email, senha }),
        signal: AbortSignal.timeout(15000),
      });
      const body = await res.json().catch(() => ({}));
      if (!res.ok) { setErro(body.detail || `Erro ${res.status}`); return; }
      FenixAuth.save(body.token, body.user);
    } catch {
      setErro('Não foi possível falar com a API. Backend está rodando?');
    } finally {
      setLoading(false);
    }
  };

  return (
    <div style={lg.wrap}>
      <form style={lg.card} onSubmit={submit}>
        <img src="assets/mark-navy.png" alt="" style={lg.mark}/>
        <div className="fenix-eyebrow" style={{textAlign:'center'}}>Grupo Fênix</div>
        <h1 style={lg.title}>Painel de Afiliados</h1>

        <label style={lg.label}>Email
          <input style={lg.input} type="email" value={email} autoFocus autoComplete="username"
            onChange={e=>setEmail(e.target.value)} placeholder="voce@grupofenix.com" required/>
        </label>
        <label style={lg.label}>Senha
          <input style={lg.input} type="password" value={senha} autoComplete="current-password"
            onChange={e=>setSenha(e.target.value)} placeholder="••••••••" required/>
        </label>

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

        <button style={{...lg.btn, opacity: loading ? .7 : 1}} disabled={loading}>
          {loading ? 'Entrando…' : 'Entrar'}
        </button>
      </form>
    </div>
  );
}

function AuthGate({ children }) {
  const [authed, setAuthed] = React.useState(!!FenixAuth.token());
  React.useEffect(() => {
    const sync = () => setAuthed(!!FenixAuth.token());
    window.addEventListener('fenix-auth', sync);
    return () => window.removeEventListener('fenix-auth', sync);
  }, []);
  return authed ? children : <LoginScreen/>;
}
window.AuthGate = AuthGate;

const lg = {
  wrap:{ minHeight:'100vh', display:'grid', placeItems:'center', background:'var(--bg-app)', padding:20 },
  card:{ width:'min(380px, 100%)', display:'flex', flexDirection:'column', gap:14,
    background:'var(--bg-surface)', border:'1px solid var(--border-1)', borderRadius:'var(--r-lg)',
    boxShadow:'var(--shadow-lg)', padding:'36px 32px' },
  mark:{ width:44, height:44, objectFit:'contain', margin:'0 auto 4px' },
  title:{ font:'var(--text-h2)', letterSpacing:'var(--tracking-tight)', color:'var(--fg-1)',
    textAlign:'center', margin:'0 0 10px' },
  label:{ font:'var(--text-label)', color:'var(--fg-2)', display:'flex', flexDirection:'column', gap:6 },
  input:{ font:'var(--text-body)', color:'var(--fg-1)', background:'var(--bg-surface)',
    border:'1px solid var(--border-2)', borderRadius:'var(--r-sm)', padding:'10px 12px', outline:'none' },
  erro:{ font:'var(--text-body-sm)', color:'var(--negative)', background:'var(--negative-bg)',
    borderRadius:'var(--r-sm)', padding:'8px 12px' },
  btn:{ font:'var(--text-h4)', color:'var(--fg-on-accent)', background:'var(--fenix-orange)',
    border:'none', borderRadius:'var(--r-sm)', padding:'12px', cursor:'pointer', marginTop:4 },
};
