/* Login + System view (users, audit, sessions, profile) */

function LoginScreen({ onLogin }) {
  const [mode, setMode] = React.useState(() => {
    const saved = localStorage.getItem('iti_login_mode');
    if (saved) return saved;
    return location.search.includes('portal') || location.pathname.startsWith('/portal') ? 'portal' : 'soporte';
  });
  React.useEffect(()=>{ localStorage.setItem('iti_login_mode', mode); },[mode]);

  return (
    <div style={{
      minHeight:'100vh', display:'flex', alignItems:'center', justifyContent:'center',
      padding:20, fontFamily:'-apple-system,BlinkMacSystemFont,"Plus Jakarta Sans",sans-serif',
      background: `
        radial-gradient(ellipse at 15% -10%, rgba(94,92,230,0.35), transparent 55%),
        radial-gradient(ellipse at 85% 15%, rgba(255,45,85,0.18), transparent 50%),
        radial-gradient(ellipse at 50% 100%, rgba(48,209,88,0.15), transparent 55%),
        linear-gradient(180deg,#0b1124 0%,#06091a 100%)
      `,
    }}>
      <div style={{position:'absolute',top:24,left:24,display:'flex',alignItems:'center',gap:10,color:'rgba(255,255,255,0.85)'}}>
        <div style={{width:32,height:32,borderRadius:9,background:'linear-gradient(135deg,#6366f1 0%,#2563eb 100%)',display:'flex',alignItems:'center',justifyContent:'center',color:'#fff',fontSize:13,fontWeight:900,boxShadow:'0 4px 12px rgba(37,99,235,0.4)'}}>IT</div>
        <div>
          <div style={{fontSize:13,fontWeight:800,letterSpacing:'0.02em'}}>INFINITOS TI</div>
          <div style={{fontSize:10,color:'rgba(255,255,255,0.55)',letterSpacing:'0.1em',textTransform:'uppercase'}}>Gestión de soporte</div>
        </div>
      </div>

      <div style={{
        width:'100%', maxWidth: 420, background:'rgba(255,255,255,0.98)',
        borderRadius: 22, overflow:'hidden',
        boxShadow:'0 20px 60px -10px rgba(0,0,0,0.5), 0 1px 0 rgba(255,255,255,0.1) inset',
        backdropFilter:'blur(20px)', WebkitBackdropFilter:'blur(20px)',
      }}>
        <div style={{padding:'32px 32px 0',textAlign:'center'}}>
          <div style={{
            width:64, height:64, borderRadius:18, margin:'0 auto 16px',
            background: mode==='portal' ? 'linear-gradient(135deg,#10b981 0%,#059669 100%)' : 'linear-gradient(135deg,#6366f1 0%,#2563eb 100%)',
            display:'flex', alignItems:'center', justifyContent:'center',
            color:'#fff', fontSize: mode==='portal' ? 28 : 20, fontWeight:900,
            boxShadow: mode==='portal' ? '0 8px 24px -4px rgba(16,185,129,0.5)' : '0 8px 24px -4px rgba(37,99,235,0.5)',
            transition:'all 0.3s ease',
          }}>{mode==='portal' ? '🎫' : 'IT'}</div>
          <h1 style={{fontSize:22,fontWeight:800,color:'#0f172a',margin:'0 0 4px',letterSpacing:'-0.02em'}}>
            {mode==='portal' ? 'Portal de Soporte' : '¡Hola otra vez!'}
          </h1>
          <div style={{fontSize:13,color:'#64748b',marginBottom:24}}>
            {mode==='portal' ? 'Levanta tu ticket con el sticker de tu PC' : 'Ingresa tus credenciales para continuar'}
          </div>
        </div>

        <div style={{display:'flex',padding:'0 24px 14px',gap:6}}>
          <button onClick={()=>setMode('soporte')}
            style={{flex:1,padding:'8px 0',border:'none',background:mode==='soporte'?'#eff6ff':'transparent',borderRadius:9,cursor:'pointer',fontSize:12,fontWeight:700,color:mode==='soporte'?'#2563eb':'#94a3b8',fontFamily:'inherit',transition:'all 0.15s'}}>
            👨‍💼 Soporte / Admin
          </button>
          <button onClick={()=>setMode('portal')}
            style={{flex:1,padding:'8px 0',border:'none',background:mode==='portal'?'#ecfdf5':'transparent',borderRadius:9,cursor:'pointer',fontSize:12,fontWeight:700,color:mode==='portal'?'#10b981':'#94a3b8',fontFamily:'inherit',transition:'all 0.15s'}}>
            🎫 Portal Cliente
          </button>
        </div>

        {mode==='soporte' ? <SoporteLoginForm onLogin={onLogin}/> : <PortalLoginForm onLogin={onLogin}/>}

        <div style={{padding:'18px 32px 24px',borderTop:'1px solid #f1f5f9',background:'#fafbfc',fontSize:10,color:'#94a3b8',textAlign:'center'}}>
          INFINITOS TI · v0.5 · {mode==='portal' ? 'Acceso de cliente' : 'Acceso restringido'}
        </div>
      </div>

      <div style={{position:'absolute',bottom:24,fontSize:10,color:'rgba(255,255,255,0.4)',textAlign:'center'}}>
        © Robert Muesser · Los Infinitos · Consultoría IT
      </div>
    </div>
  );
}

function SoporteLoginForm({ onLogin }) {
  const [u, setU] = React.useState('');
  const [p, setP] = React.useState('');
  const [otp, setOtp] = React.useState('');
  const [needOtp, setNeedOtp] = React.useState(false);
  const [err, setErr] = React.useState('');
  const [loading, setLoading] = React.useState(false);
  const [showPwd, setShowPwd] = React.useState(false);

  async function submit(e) {
    e.preventDefault(); setErr(''); setLoading(true);
    try { const r = await window.API.login(u.trim(), p, otp || undefined); onLogin(r.user); }
    catch (e) {
      if (e.body?.error === 'totp_requerido' || e.body?.error === 'totp_invalido') {
        setNeedOtp(true); setErr(e.body?.error === 'totp_invalido' ? 'Código 2FA inválido' : 'Ingresa tu código de autenticador');
      } else if (e.body?.error === 'usuario_bloqueado') setErr('🔒 Cuenta bloqueada por intentos fallidos. Intenta en 15 minutos.');
      else if (e.body?.error === 'usuario_inactivo') setErr('Tu cuenta está desactivada. Contacta al admin.');
      else setErr(e.body?.intentos_restantes != null ? `Usuario o contraseña incorrectos. Te quedan ${e.body.intentos_restantes} intentos.` : 'Usuario o contraseña incorrectos');
    } finally { setLoading(false); }
  }

  return (
    <form onSubmit={submit} style={{padding:'4px 32px 24px'}}>
      <div style={{marginBottom:14}}>
        <label style={{display:'block',fontSize:11,fontWeight:700,color:'#475569',textTransform:'uppercase',letterSpacing:'0.05em',marginBottom:6}}>Usuario</label>
        <div style={{position:'relative'}}>
          <span style={{position:'absolute',left:12,top:'50%',transform:'translateY(-50%)',color:'#94a3b8',fontSize:14,pointerEvents:'none'}}>👤</span>
          <input value={u} onChange={e=>setU(e.target.value)} autoFocus autoComplete="username" placeholder="admin"
            style={{width:'100%',padding:'11px 12px 11px 36px',border:'1.5px solid #e2e8f0',borderRadius:10,fontSize:14,outline:'none',fontFamily:'inherit',transition:'all 0.15s',boxSizing:'border-box',background:'#fff'}}
            onFocus={e=>{e.target.style.borderColor='#2563eb';e.target.style.boxShadow='0 0 0 3px rgba(37,99,235,0.1)';}}
            onBlur={e=>{e.target.style.borderColor='#e2e8f0';e.target.style.boxShadow='none';}} />
        </div>
      </div>

      <div style={{marginBottom:14}}>
        <label style={{display:'block',fontSize:11,fontWeight:700,color:'#475569',textTransform:'uppercase',letterSpacing:'0.05em',marginBottom:6}}>Contraseña</label>
        <div style={{position:'relative'}}>
          <span style={{position:'absolute',left:12,top:'50%',transform:'translateY(-50%)',color:'#94a3b8',fontSize:14,pointerEvents:'none'}}>🔒</span>
          <input type={showPwd?'text':'password'} value={p} onChange={e=>setP(e.target.value)} autoComplete="current-password" placeholder="••••••••"
            style={{width:'100%',padding:'11px 38px 11px 36px',border:'1.5px solid #e2e8f0',borderRadius:10,fontSize:14,outline:'none',fontFamily:'inherit',transition:'all 0.15s',boxSizing:'border-box',background:'#fff'}}
            onFocus={e=>{e.target.style.borderColor='#2563eb';e.target.style.boxShadow='0 0 0 3px rgba(37,99,235,0.1)';}}
            onBlur={e=>{e.target.style.borderColor='#e2e8f0';e.target.style.boxShadow='none';}} />
          <button type="button" onClick={()=>setShowPwd(s=>!s)}
            style={{position:'absolute',right:8,top:'50%',transform:'translateY(-50%)',background:'transparent',border:'none',cursor:'pointer',color:'#94a3b8',fontSize:14,padding:'4px 6px',borderRadius:4}}>
            {showPwd?'🙈':'👁'}
          </button>
        </div>
      </div>

      {needOtp && (
        <div style={{marginBottom:14}}>
          <label style={{display:'block',fontSize:11,fontWeight:700,color:'#475569',textTransform:'uppercase',letterSpacing:'0.05em',marginBottom:6}}>Código 2FA (6 dígitos)</label>
          <input value={otp} onChange={e=>setOtp(e.target.value.replace(/\D/g,''))} maxLength={6} autoFocus inputMode="numeric"
            style={{width:'100%',padding:'12px',border:'1.5px solid #e2e8f0',borderRadius:10,fontSize:18,outline:'none',fontFamily:'monospace',letterSpacing:'8px',textAlign:'center',fontWeight:700,boxSizing:'border-box'}} />
        </div>
      )}

      {err && (
        <div style={{padding:'10px 12px',background:'#fef2f2',color:'#dc2626',borderRadius:8,fontSize:12,marginBottom:14,display:'flex',alignItems:'center',gap:6,border:'1px solid #fecaca'}}>
          <span>⚠</span> {err}
        </div>
      )}

      <button type="submit" disabled={loading || !u || !p}
        style={{width:'100%',padding:'12px',background:loading||!u||!p?'#cbd5e1':'linear-gradient(135deg,#6366f1 0%,#2563eb 100%)',color:'#fff',border:'none',borderRadius:11,fontSize:14,fontWeight:700,cursor:loading||!u||!p?'not-allowed':'pointer',fontFamily:'inherit',transition:'all 0.15s',boxShadow:loading||!u||!p?'none':'0 4px 14px -2px rgba(37,99,235,0.4)'}}>
        {loading?'⏳ Verificando…':'Iniciar sesión'}
      </button>

      <div style={{marginTop:16,fontSize:11,color:'#94a3b8',textAlign:'center',lineHeight:1.5}}>
        Demo · admin / supervisor · pwd: <code style={{background:'#f1f5f9',padding:'2px 6px',borderRadius:4,fontSize:10,color:'#475569'}}>{`{Rol}2026!`}</code>
      </div>
    </form>
  );
}

function PortalLoginForm({ onLogin }) {
  const [stickerId, setSticker] = React.useState('');
  const [pin, setPin] = React.useState('');
  const [err, setErr] = React.useState('');
  const [loading, setLoading] = React.useState(false);

  async function submit(e) {
    e.preventDefault(); setErr(''); setLoading(true);
    try { const r = await window.API.portalLogin(stickerId, pin); onLogin(r.user); }
    catch (e) {
      if (e.body?.error === 'demasiados_intentos') setErr('🔒 Demasiados intentos. Espera 5 minutos.');
      else setErr('Sticker o PIN incorrectos. Verifica los datos.');
    } finally { setLoading(false); }
  }

  return (
    <form onSubmit={submit} style={{padding:'4px 32px 24px'}}>
      <div style={{marginBottom:14}}>
        <label style={{display:'block',fontSize:11,fontWeight:700,color:'#475569',textTransform:'uppercase',letterSpacing:'0.05em',marginBottom:6}}>ID del sticker · 5 letras</label>
        <input value={stickerId} onChange={e=>setSticker(e.target.value.toUpperCase().replace(/[^A-Z]/g,'').slice(0,5))} autoFocus
          placeholder="ABCDE" maxLength={5} autoComplete="off"
          style={{width:'100%',padding:'14px 12px',border:'2px solid #e2e8f0',borderRadius:11,fontSize:24,outline:'none',fontFamily:'"SF Mono",monospace,Consolas',letterSpacing:'10px',textAlign:'center',fontWeight:800,textTransform:'uppercase',color:'#0f172a',transition:'all 0.15s',boxSizing:'border-box'}}
          onFocus={e=>{e.target.style.borderColor='#10b981';e.target.style.boxShadow='0 0 0 3px rgba(16,185,129,0.15)';}}
          onBlur={e=>{e.target.style.borderColor='#e2e8f0';e.target.style.boxShadow='none';}} />
      </div>

      <div style={{marginBottom:14}}>
        <label style={{display:'block',fontSize:11,fontWeight:700,color:'#475569',textTransform:'uppercase',letterSpacing:'0.05em',marginBottom:6}}>PIN · 6 dígitos</label>
        <input type="tel" inputMode="numeric" value={pin} onChange={e=>setPin(e.target.value.replace(/\D/g,'').slice(0,6))}
          placeholder="••••••" maxLength={6} autoComplete="off"
          style={{width:'100%',padding:'14px 12px',border:'2px solid #e2e8f0',borderRadius:11,fontSize:24,outline:'none',fontFamily:'"SF Mono",monospace,Consolas',letterSpacing:'12px',textAlign:'center',fontWeight:800,color:'#0f172a',transition:'all 0.15s',boxSizing:'border-box'}}
          onFocus={e=>{e.target.style.borderColor='#10b981';e.target.style.boxShadow='0 0 0 3px rgba(16,185,129,0.15)';}}
          onBlur={e=>{e.target.style.borderColor='#e2e8f0';e.target.style.boxShadow='none';}} />
      </div>

      {err && (
        <div style={{padding:'10px 12px',background:'#fef2f2',color:'#dc2626',borderRadius:8,fontSize:12,marginBottom:14,textAlign:'center',border:'1px solid #fecaca'}}>
          ⚠ {err}
        </div>
      )}

      <button type="submit" disabled={loading || stickerId.length<5 || pin.length<6}
        style={{width:'100%',padding:'12px',background:loading||stickerId.length<5||pin.length<6?'#cbd5e1':'linear-gradient(135deg,#10b981 0%,#059669 100%)',color:'#fff',border:'none',borderRadius:11,fontSize:14,fontWeight:700,cursor:loading||stickerId.length<5||pin.length<6?'not-allowed':'pointer',fontFamily:'inherit',transition:'all 0.15s',boxShadow:loading||stickerId.length<5||pin.length<6?'none':'0 4px 14px -2px rgba(16,185,129,0.4)'}}>
        {loading?'⏳ Verificando…':'Entrar al portal'}
      </button>

      <div style={{marginTop:16,fontSize:11,color:'#94a3b8',textAlign:'center',lineHeight:1.5}}>
        ¿No encuentras tu sticker?<br/>Pregunta al área de soporte.
      </div>
    </form>
  );
}

function SystemView({ user, navigate, toast }) {
  const isAdmin = user.rol === 'admin';
  const isSupervisor = user.rol === 'supervisor';
  const canManageUsers = isAdmin || isSupervisor;

  const tabs = [
    { id:'profile',  label:'Mi perfil',     show:true },
    { id:'users',    label:'Usuarios',      show:canManageUsers },
    { id:'config',   label:'Configuración', show:isAdmin },
    { id:'webhooks', label:'Webhooks',      show:isAdmin },
    { id:'audit',    label:'Auditoría',     show:isAdmin },
    { id:'sessions', label:'Mis sesiones',  show:true },
    { id:'tokens',   label:'API tokens',    show:true },
  ].filter(t=>t.show);

  // Estado inicial: si el rol del usuario no puede ver el tab default, ir al primero disponible
  const [tab, setTab] = React.useState(() => tabs[0]?.id || 'profile');
  React.useEffect(()=>{
    if (!tabs.find(t=>t.id===tab)) setTab(tabs[0]?.id || 'profile');
  },[user.rol]); // eslint-disable-line

  function safeRender(panel, name) {
    try { return panel; }
    catch(e) {
      console.error(`[SystemView] panel ${name} crashed`, e);
      return <div style={{padding:'24px',background:'#fef2f2',color:'#dc2626',borderRadius:8,fontSize:13}}>Error cargando {name}: {String(e?.message||e)}</div>;
    }
  }

  return (
    <div style={{padding:'32px 36px',maxWidth:1100}}>
      <h1 style={{margin:'0 0 6px',fontSize:22,fontWeight:800,color:'#0f172a'}}>Sistema</h1>
      <div style={{fontSize:12,color:'#64748b',marginBottom:24}}>Administración de cuentas, seguridad y auditoría · estás como <b>{user.rol}</b></div>
      <div style={{display:'flex',gap:4,marginBottom:20,borderBottom:'1.5px solid #e2e8f0',flexWrap:'wrap'}}>
        {tabs.map(t=>(
          <button key={t.id} onClick={()=>setTab(t.id)}
            style={{padding:'9px 16px',background:'transparent',border:'none',borderBottom:tab===t.id?'2px solid #2563eb':'2px solid transparent',marginBottom:-1.5,cursor:'pointer',fontFamily:'inherit',fontSize:13,fontWeight:600,color:tab===t.id?'#2563eb':'#64748b'}}>
            {t.label}
          </button>
        ))}
      </div>
      <ErrorBoundary fallback={(err)=>
        <div style={{padding:'24px',background:'#fef2f2',color:'#dc2626',borderRadius:8,fontSize:13}}>
          <b>Error en este panel:</b> {String(err?.message || err)}<br/>
          <small style={{color:'#7c2d12'}}>Cambia de tab o recarga la página. Si persiste, reporta a soporte.</small>
        </div>
      }>
        {tab==='profile' && <ProfilePanel user={user} toast={toast} />}
        {tab==='users' && canManageUsers && <UsersAdminPanel user={user} toast={toast} />}
        {tab==='config' && isAdmin && <ConfigPanel toast={toast} />}
        {tab==='webhooks' && isAdmin && <WebhooksPanel toast={toast} />}
        {tab==='audit' && isAdmin && <AuditPanel toast={toast} />}
        {tab==='sessions' && <SessionsPanel toast={toast} />}
        {tab==='tokens' && <TokensPanel toast={toast} />}
      </ErrorBoundary>
    </div>
  );
}

class ErrorBoundary extends React.Component {
  constructor(props){ super(props); this.state = { err: null }; }
  static getDerivedStateFromError(err){ return { err }; }
  componentDidCatch(err, info){ console.error('ErrorBoundary:', err, info); }
  render(){ return this.state.err ? this.props.fallback(this.state.err) : this.props.children; }
}

function ProfilePanel({ user, toast }) {
  const [actual, setActual] = React.useState('');
  const [nueva, setNueva] = React.useState('');
  const [conf, setConf] = React.useState('');
  const [totp, setTotp] = React.useState(null);
  const [code, setCode] = React.useState('');

  async function changePwd(e) {
    e.preventDefault();
    if (nueva !== conf) return toast('Las contraseñas no coinciden','error');
    if (nueva.length < 8) return toast('Mínimo 8 caracteres','error');
    try { await window.API.changePassword(actual, nueva); toast('Contraseña actualizada'); setActual(''); setNueva(''); setConf(''); }
    catch(e) { toast(e.body?.error || 'error', 'error'); }
  }

  async function setupTotp() {
    const r = await window.API.totpSetup(); setTotp(r);
  }
  async function enableTotp() {
    try { await window.API.totpEnable(code); toast('2FA activado'); setTotp(null); setCode(''); user.totp_enabled = true; }
    catch(e) { toast('Código inválido','error'); }
  }
  async function disableTotp() {
    if (!confirm('¿Desactivar 2FA?')) return;
    await window.API.totpDisable(); toast('2FA desactivado'); user.totp_enabled = false;
  }

  return (
    <div style={{display:'grid',gridTemplateColumns:'1fr 1fr',gap:20}}>
      <Card style={{padding:'20px 22px'}}>
        <h3 style={{margin:'0 0 14px',fontSize:14,fontWeight:700,color:'#0f172a'}}>Datos de la cuenta</h3>
        <Row label="Usuario" value={user.username} />
        <Row label="Nombre"  value={user.nombre} />
        <Row label="Rol"     value={user.rol} />
      </Card>
      <Card style={{padding:'20px 22px'}}>
        <h3 style={{margin:'0 0 14px',fontSize:14,fontWeight:700,color:'#0f172a'}}>Cambiar contraseña</h3>
        <form onSubmit={changePwd} style={{display:'flex',flexDirection:'column',gap:10}}>
          <Field label="Contraseña actual" type="password" value={actual} onChange={setActual} />
          <Field label="Nueva contraseña" type="password" value={nueva} onChange={setNueva} hint="Mín 8 caracteres" />
          <Field label="Confirmar" type="password" value={conf} onChange={setConf} />
          <Btn type="submit" size="sm">Actualizar</Btn>
        </form>
      </Card>
      <Card style={{padding:'20px 22px',gridColumn:'span 2'}}>
        <h3 style={{margin:'0 0 14px',fontSize:14,fontWeight:700,color:'#0f172a'}}>Autenticación de 2 factores (TOTP)</h3>
        {!user.totp_enabled && !totp && (
          <div>
            <p style={{fontSize:13,color:'#64748b',margin:'0 0 12px'}}>Asegura tu cuenta con Google Authenticator, 1Password, Authy, etc.</p>
            <Btn size="sm" onClick={setupTotp}>Activar 2FA</Btn>
          </div>
        )}
        {totp && (
          <div>
            <p style={{fontSize:13,color:'#64748b',margin:'0 0 8px'}}>Escanea con tu app o introduce manualmente:</p>
            <code style={{display:'inline-block',padding:'6px 10px',background:'#f1f5f9',borderRadius:6,fontSize:12,marginBottom:10}}>{totp.secret}</code>
            <div style={{fontSize:11,color:'#94a3b8',marginBottom:10,wordBreak:'break-all'}}>URI: {totp.uri}</div>
            <input value={code} onChange={e=>setCode(e.target.value.replace(/\D/g,''))} maxLength={6} placeholder="Código 6 dígitos"
              style={{padding:'8px 12px',border:'1.5px solid #e2e8f0',borderRadius:8,fontFamily:'monospace',letterSpacing:3,marginRight:10}} />
            <Btn size="sm" onClick={enableTotp}>Confirmar</Btn>
          </div>
        )}
        {user.totp_enabled && (
          <div>
            <Badge label="2FA activo" color="green" />
            <Btn size="sm" variant="danger" onClick={disableTotp} style={{marginLeft:10}}>Desactivar</Btn>
          </div>
        )}
      </Card>
    </div>
  );
}

function UsersAdminPanel({ user, toast }) {
  const [list, setList] = React.useState([]);
  const [roles, setRoles] = React.useState([]);
  const [showAdd, setShowAdd] = React.useState(false);
  const [editing, setEditing] = React.useState(null);

  React.useEffect(() => { reload(); window.API.listRoles().then(setRoles); }, []);
  function reload() { window.API.listUsers().then(setList); }

  return (
    <div>
      <div style={{display:'flex',justifyContent:'space-between',alignItems:'center',marginBottom:14}}>
        <div style={{fontSize:13,color:'#64748b'}}>{list.length} usuarios del sistema</div>
        <Btn size="sm" onClick={()=>setShowAdd(true)}>+ Nuevo usuario</Btn>
      </div>
      <Card style={{padding:0}}>
        <table style={{width:'100%',borderCollapse:'collapse'}}>
          <thead style={{background:'#f8fafc',fontSize:11,color:'#64748b',fontWeight:700,textTransform:'uppercase'}}>
            <tr>
              <th style={{textAlign:'left',padding:'10px 14px'}}>Usuario</th>
              <th style={{textAlign:'left',padding:'10px 14px'}}>Nombre</th>
              <th style={{textAlign:'left',padding:'10px 14px'}}>Rol</th>
              <th style={{textAlign:'left',padding:'10px 14px'}}>Estado</th>
              <th style={{textAlign:'left',padding:'10px 14px'}}>Último login</th>
              <th></th>
            </tr>
          </thead>
          <tbody>
            {list.map(u=>(
              <tr key={u.id} style={{borderTop:'1px solid #f1f5f9',fontSize:13}}>
                <td style={{padding:'10px 14px',fontWeight:600}}>
                  {u.username}
                  {u.totp_enabled && <span style={{marginLeft:6,fontSize:10,padding:'1px 5px',background:'#dcfce7',color:'#166534',borderRadius:3}}>2FA</span>}
                </td>
                <td style={{padding:'10px 14px'}}>{u.nombre}</td>
                <td style={{padding:'10px 14px'}}><Badge label={u.rol} color={u.rol==='admin'?'red':u.rol==='operador'?'blue':'slate'}/></td>
                <td style={{padding:'10px 14px'}}>{u.activo?<Badge label="activo" color="green"/>:<Badge label="inactivo" color="slate"/>}{u.bloqueado_hasta && <Badge label="bloqueado" color="red"/>}</td>
                <td style={{padding:'10px 14px',fontSize:11,color:'#94a3b8'}}>{u.ultimo_login?DB.timeAgo(u.ultimo_login):'nunca'}</td>
                <td style={{padding:'10px 14px',textAlign:'right'}}>
                  <Btn size="sm" variant="secondary" onClick={()=>setEditing(u)}>Editar</Btn>
                  {u.id!==user.id && <Btn size="sm" variant="danger" style={{marginLeft:6}} onClick={async()=>{
                    if (confirm(`¿Borrar usuario ${u.username}?`)) { await window.API.deleteUser(u.id); reload(); toast('Usuario borrado'); }
                  }}>Borrar</Btn>}
                </td>
              </tr>
            ))}
          </tbody>
        </table>
      </Card>
      {showAdd && <UserFormModal roles={roles} onSave={async (form, empresaIds)=>{
        try {
          const r = await window.API.createUser(form);
          if (form.rol === 'supervisor' && r?.id && Array.isArray(empresaIds)) {
            await window.API.setUserEmpresas(r.id, empresaIds);
          }
          reload(); setShowAdd(false); toast('Usuario creado');
        }
        catch(e){ toast(e.body?.error || 'error','error'); }
      }} onClose={()=>setShowAdd(false)} />}
      {editing && <UserFormModal roles={roles} initial={editing} onSave={async (form, empresaIds)=>{
        try {
          await window.API.updateUser(editing.id, form);
          if (form.rol === 'supervisor' && Array.isArray(empresaIds)) {
            await window.API.setUserEmpresas(editing.id, empresaIds);
          }
          reload(); setEditing(null); toast('Usuario actualizado');
        }
        catch(e){ toast(e.body?.error || 'error','error'); }
      }} onClose={()=>setEditing(null)} />}
    </div>
  );
}

function UserFormModal({ initial = {}, roles = [], onSave, onClose }) {
  const [f, setF] = React.useState({
    username: initial.username || '', nombre: initial.nombre || '', email: initial.email || '',
    rol: initial.rol || 'operador', password: '', activo: initial.activo !== false,
    company_db_id: initial.company_db_id || '',
  });
  const [companies, setCompanies] = React.useState([]);
  // empresaIds === null  → "todas las empresas" (default abierto, 0 filas)
  // empresaIds === []    → ninguna asignada explícitamente
  // empresaIds === [...] → solo esas
  const [empresaIds, setEmpresaIds] = React.useState(null);
  React.useEffect(() => {
    window.API.getState().then(r => setCompanies(r?.data?.companies || []));
    if (initial.id && initial.rol === 'supervisor') {
      window.API.getUserEmpresas(initial.id).then(rows => {
        const ids = (rows || []).map(r => r.company_db_id);
        setEmpresaIds(ids.length === 0 ? null : ids);
      }).catch(() => setEmpresaIds(null));
    }
  }, []);
  const set = k => v => setF(p => ({...p, [k]:v}));
  const todas = empresaIds === null;
  function toggleEmpresa(id) {
    setEmpresaIds(prev => {
      const cur = prev === null ? companies.map(c => c.id) : prev;
      return cur.includes(id) ? cur.filter(x => x !== id) : [...cur, id];
    });
  }
  return (
    <Modal title={initial.id?`Editar ${initial.username}`:'Nuevo usuario'} onClose={onClose}>
      <div style={{display:'flex',flexDirection:'column',gap:12}}>
        <Field label="Usuario (login)" value={f.username} onChange={set('username')} disabled={!!initial.id} />
        <Field label="Nombre completo" value={f.nombre} onChange={set('nombre')} />
        <Field label="Email" value={f.email} onChange={set('email')} />
        <Selector label="Rol" value={f.rol} onChange={set('rol')} options={roles.map(r=>({value:r.id,label:`${r.nombre} — ${r.descripcion}`}))} />
        {f.rol === 'cliente' && (
          <Selector label="Empresa del cliente" value={f.company_db_id} onChange={set('company_db_id')} options={[
            {value:'',label:'— Selecciona empresa —'},
            ...companies.map(c=>({value:c.id,label:c.name})),
          ]} hint="Solo verá los datos de esta empresa" />
        )}
        {f.rol === 'supervisor' && (
          <div style={{display:'flex',flexDirection:'column',gap:8,padding:'12px 14px',background:'#f8fafc',border:'1px solid #e2e8f0',borderRadius:10}}>
            <div style={{fontSize:12,fontWeight:700,color:'#475569',textTransform:'uppercase',letterSpacing:'0.05em'}}>Empresas asignadas</div>
            <label style={{display:'flex',alignItems:'center',gap:8,fontSize:13,fontWeight:600,color:'#0f172a'}}>
              <input type="checkbox" checked={todas} onChange={e=>setEmpresaIds(e.target.checked?null:[])} />
              Todas las empresas (acceso completo)
            </label>
            {!todas && (
              <div style={{display:'flex',flexDirection:'column',gap:4,maxHeight:220,overflowY:'auto',paddingTop:4,borderTop:'1px solid #e2e8f0'}}>
                {companies.length === 0 && <div style={{fontSize:12,color:'#94a3b8'}}>No hay empresas todavía.</div>}
                {companies.map(c => (
                  <label key={c.id} style={{display:'flex',alignItems:'center',gap:8,fontSize:13,padding:'4px 0'}}>
                    <input type="checkbox" checked={(empresaIds||[]).includes(c.id)} onChange={()=>toggleEmpresa(c.id)} />
                    {c.name}
                  </label>
                ))}
              </div>
            )}
            <div style={{fontSize:11,color:'#94a3b8'}}>
              {todas ? 'Verá todas las empresas y sus tickets/equipos.' : `Verá solo las empresas seleccionadas (${(empresaIds||[]).length}).`}
            </div>
          </div>
        )}
        <Field label={initial.id?'Nueva contraseña (vacío = sin cambio)':'Contraseña'} type="password" value={f.password} onChange={set('password')} hint="Mín 8 caracteres" />
        <label style={{display:'flex',alignItems:'center',gap:8,fontSize:13}}>
          <input type="checkbox" checked={f.activo} onChange={e=>set('activo')(e.target.checked)} /> Activo
        </label>
        <div style={{display:'flex',gap:8,justifyContent:'flex-end',marginTop:6}}>
          <Btn size="sm" variant="secondary" onClick={onClose}>Cancelar</Btn>
          <Btn size="sm" onClick={()=>{
            const out = {...f};
            if (initial.id && !out.password) delete out.password;
            if (out.rol !== 'cliente') out.company_db_id = null;
            // empresaIds: null → [] (sin filas = ve todas), array → tal cual
            const empresasToSend = out.rol === 'supervisor'
              ? (empresaIds === null ? [] : empresaIds)
              : null;
            onSave(out, empresasToSend);
          }}>Guardar</Btn>
        </div>
      </div>
    </Modal>
  );
}

function AuditPanel({ toast }) {
  const [list, setList] = React.useState([]);
  React.useEffect(()=>{ window.API.audit(300).then(setList); },[]);
  return (
    <Card style={{padding:0}}>
      <table style={{width:'100%',borderCollapse:'collapse',fontSize:12}}>
        <thead style={{background:'#f8fafc',fontWeight:700,color:'#64748b',textTransform:'uppercase',fontSize:11}}>
          <tr>
            <th style={{textAlign:'left',padding:'10px 14px'}}>Cuándo</th>
            <th style={{textAlign:'left',padding:'10px 14px'}}>Quién</th>
            <th style={{textAlign:'left',padding:'10px 14px'}}>Acción</th>
            <th style={{textAlign:'left',padding:'10px 14px'}}>Recurso</th>
            <th style={{textAlign:'left',padding:'10px 14px'}}>IP</th>
          </tr>
        </thead>
        <tbody>
          {list.map(a=>(
            <tr key={a.id} style={{borderTop:'1px solid #f1f5f9'}}>
              <td style={{padding:'8px 14px',color:'#64748b',whiteSpace:'nowrap'}}>{DB.formatDateTime(a.ts)}</td>
              <td style={{padding:'8px 14px',fontWeight:600}}>{a.username}</td>
              <td style={{padding:'8px 14px'}}><code style={{background:'#f1f5f9',padding:'1px 6px',borderRadius:4,fontSize:11}}>{a.accion}</code></td>
              <td style={{padding:'8px 14px',fontSize:11,color:'#64748b'}}>{a.recurso||'—'}</td>
              <td style={{padding:'8px 14px',fontSize:11,color:'#94a3b8',fontFamily:'monospace'}}>{a.ip||'—'}</td>
            </tr>
          ))}
        </tbody>
      </table>
    </Card>
  );
}

function SessionsPanel({ toast }) {
  const [list, setList] = React.useState([]);
  React.useEffect(()=>{ window.API.sessions().then(setList); },[]);
  return (
    <Card style={{padding:0}}>
      <table style={{width:'100%',borderCollapse:'collapse',fontSize:13}}>
        <thead style={{background:'#f8fafc',fontWeight:700,color:'#64748b',textTransform:'uppercase',fontSize:11}}>
          <tr>
            <th style={{textAlign:'left',padding:'10px 14px'}}>Iniciada</th>
            <th style={{textAlign:'left',padding:'10px 14px'}}>IP</th>
            <th style={{textAlign:'left',padding:'10px 14px'}}>Navegador</th>
            <th style={{textAlign:'left',padding:'10px 14px'}}>Expira</th>
          </tr>
        </thead>
        <tbody>
          {list.map(s=>(
            <tr key={s.id} style={{borderTop:'1px solid #f1f5f9'}}>
              <td style={{padding:'8px 14px',color:'#64748b'}}>{DB.formatDateTime(s.iniciada)}</td>
              <td style={{padding:'8px 14px',fontFamily:'monospace',fontSize:11}}>{s.ip||'—'}</td>
              <td style={{padding:'8px 14px',fontSize:11,color:'#64748b',maxWidth:300,overflow:'hidden',textOverflow:'ellipsis',whiteSpace:'nowrap'}}>{s.user_agent||'—'}</td>
              <td style={{padding:'8px 14px',fontSize:11,color:'#94a3b8'}}>{DB.formatDateTime(s.expira)}</td>
            </tr>
          ))}
        </tbody>
      </table>
    </Card>
  );
}

function TokensPanel({ toast }) {
  const [list, setList] = React.useState([]);
  const [showAdd, setShowAdd] = React.useState(false);
  const [created, setCreated] = React.useState(null);
  React.useEffect(()=>{ reload(); },[]);
  function reload() { window.API.listTokens().then(setList); }
  return (
    <div>
      <div style={{display:'flex',justifyContent:'space-between',alignItems:'center',marginBottom:14}}>
        <div style={{fontSize:13,color:'#64748b'}}>Tokens API para integraciones (n8n, monitoring, scripts)</div>
        <Btn size="sm" onClick={()=>setShowAdd(true)}>+ Nuevo token</Btn>
      </div>
      {created && (
        <Card style={{padding:'14px 18px',marginBottom:14,background:'#fef3c7',border:'1.5px solid #fbbf24'}}>
          <div style={{fontSize:12,fontWeight:700,color:'#92400e',marginBottom:6}}>⚠ Copia este token AHORA — no se mostrará otra vez:</div>
          <code style={{display:'block',padding:8,background:'#fff',borderRadius:6,fontSize:12,wordBreak:'break-all'}}>{created.token}</code>
          <Btn size="sm" variant="secondary" style={{marginTop:8}} onClick={()=>{navigator.clipboard.writeText(created.token); toast('Copiado al portapapeles');}}>Copiar</Btn>
          <Btn size="sm" variant="secondary" style={{marginTop:8,marginLeft:6}} onClick={()=>setCreated(null)}>Cerrar</Btn>
        </Card>
      )}
      <Card style={{padding:0}}>
        <table style={{width:'100%',borderCollapse:'collapse',fontSize:13}}>
          <thead style={{background:'#f8fafc',fontWeight:700,color:'#64748b',textTransform:'uppercase',fontSize:11}}>
            <tr>
              <th style={{textAlign:'left',padding:'10px 14px'}}>Nombre</th>
              <th style={{textAlign:'left',padding:'10px 14px'}}>Prefijo</th>
              <th style={{textAlign:'left',padding:'10px 14px'}}>Alcance</th>
              <th style={{textAlign:'left',padding:'10px 14px'}}>Estado</th>
              <th></th>
            </tr>
          </thead>
          <tbody>
            {list.map(t=>(
              <tr key={t.id} style={{borderTop:'1px solid #f1f5f9'}}>
                <td style={{padding:'8px 14px',fontWeight:600}}>{t.nombre}</td>
                <td style={{padding:'8px 14px',fontFamily:'monospace',fontSize:11}}>{t.prefijo}…</td>
                <td style={{padding:'8px 14px'}}><Badge label={t.alcance} color={t.alcance==='write'?'red':'slate'}/></td>
                <td style={{padding:'8px 14px'}}>{t.revocado?<Badge label="revocado" color="slate"/>:<Badge label="activo" color="green"/>}</td>
                <td style={{padding:'8px 14px',textAlign:'right'}}>
                  {!t.revocado && <Btn size="sm" variant="danger" onClick={async()=>{ if(confirm('¿Revocar?')){await window.API.revokeToken(t.id); reload(); toast('Token revocado');}}}>Revocar</Btn>}
                </td>
              </tr>
            ))}
          </tbody>
        </table>
      </Card>
      {showAdd && (
        <Modal title="Nuevo API token" onClose={()=>setShowAdd(false)}>
          <NewTokenForm onSave={async (f)=>{
            const r = await window.API.createToken(f.nombre, f.alcance);
            setCreated(r); setShowAdd(false); reload();
          }} onCancel={()=>setShowAdd(false)} />
        </Modal>
      )}
    </div>
  );
}

function NewTokenForm({ onSave, onCancel }) {
  const [f, setF] = React.useState({ nombre:'', alcance:'read' });
  return (
    <div style={{display:'flex',flexDirection:'column',gap:12}}>
      <Field label="Nombre descriptivo" value={f.nombre} onChange={v=>setF({...f,nombre:v})} placeholder="Integración n8n" />
      <Selector label="Alcance" value={f.alcance} onChange={v=>setF({...f,alcance:v})} options={[
        {value:'read',label:'Solo lectura'},
        {value:'write',label:'Lectura y escritura'},
      ]} />
      <div style={{display:'flex',gap:8,justifyContent:'flex-end'}}>
        <Btn size="sm" variant="secondary" onClick={onCancel}>Cancelar</Btn>
        <Btn size="sm" onClick={()=>onSave(f)} disabled={!f.nombre}>Crear</Btn>
      </div>
    </div>
  );
}

function Row({ label, value }) {
  return (
    <div style={{display:'flex',justifyContent:'space-between',padding:'8px 0',borderBottom:'1px solid #f1f5f9',fontSize:13}}>
      <span style={{color:'#64748b'}}>{label}</span>
      <span style={{fontWeight:600,color:'#0f172a'}}>{value}</span>
    </div>
  );
}
