import { useEffect, useState, useCallback } from 'react';
import PageHeader from '../../components/PageHeader';
import { listUsers, createUser, deleteUser, listTokens, createToken, revokeToken, type AppUser, type TokenInfo } from '../../services/admin.service';
import { ROLE_LABELS, roleAtLeast, type Role, type CurrentUser } from '../../services/auth.service';
import styles from './Admin.module.scss';

const fmt = (v: string | null) => (v ? new Date(v).toLocaleDateString(undefined, { year: 'numeric', month: 'short', day: 'numeric' }) : '—');

export default function Admin({ user }: { user: CurrentUser }) {
  const isAdmin = user.role === 'admin';
  const [tab, setTab] = useState<'users' | 'tokens'>('users');
  useEffect(() => { if (!isAdmin) setTab('users'); }, [isAdmin]);

  return (
    <div className={styles.page}>
      <PageHeader title="Administration" subtitle="Users and API access" />
      <div className={styles.tabs}>
        <button className={tab === 'users' ? styles.on : ''} onClick={() => setTab('users')}>Users</button>
        {isAdmin && <button className={tab === 'tokens' ? styles.on : ''} onClick={() => setTab('tokens')}>API Tokens</button>}
      </div>
      {tab === 'users' ? <UsersPanel me={user} /> : <TokensPanel />}
    </div>
  );
}

function UsersPanel({ me }: { me: CurrentUser }) {
  const [users, setUsers] = useState<AppUser[]>([]);
  const [error, setError] = useState<string | null>(null);
  const [username, setUsername] = useState('');
  const [password, setPassword] = useState('');
  const [role, setRole] = useState<Role>('viewer');
  const [busy, setBusy] = useState(false);

  const load = useCallback(() => { listUsers().then(setUsers).catch(() => setError('Failed to load users')); }, []);
  useEffect(() => { load(); }, [load]);

  // Leadership can grant up to 'lead'; only admin can grant 'admin'.
  const grantable: Role[] = me.role === 'admin' ? ['viewer', 'pm', 'lead', 'admin'] : ['viewer', 'pm', 'lead'];

  const submit = async (e: React.FormEvent) => {
    e.preventDefault();
    setBusy(true); setError(null);
    try {
      const res = await createUser(username.trim(), password, role);
      if (res.user) { setUsername(''); setPassword(''); setRole('viewer'); load(); }
      else setError(res.message || 'Could not create user');
    } catch { setError('Could not create user'); }
    finally { setBusy(false); }
  };

  const remove = async (u: string) => {
    if (!confirm(`Delete user "${u}"?`)) return;
    await deleteUser(u).catch(() => {});
    load();
  };

  return (
    <div className={styles.grid}>
      <form className={styles.card} onSubmit={submit}>
        <h3 className={styles.cardTitle}>Add user</h3>
        <label className={styles.label}>Username</label>
        <input className={styles.input} value={username} onChange={e => setUsername(e.target.value)} autoComplete="off" />
        <label className={styles.label}>Password</label>
        <input className={styles.input} type="password" value={password} onChange={e => setPassword(e.target.value)} autoComplete="new-password" placeholder="min 6 chars" />
        <label className={styles.label}>Role</label>
        <select className={styles.input} value={role} onChange={e => setRole(e.target.value as Role)}>
          {grantable.map(r => <option key={r} value={r}>{ROLE_LABELS[r]}</option>)}
        </select>
        {error && <div className={styles.err}>{error}</div>}
        <button className={styles.btn} type="submit" disabled={busy || username.trim().length < 2 || password.length < 6}>
          {busy ? 'Creating…' : 'Create user'}
        </button>
      </form>

      <div className={styles.card}>
        <h3 className={styles.cardTitle}>Users ({users.length})</h3>
        <table className={styles.table}>
          <thead><tr><th>Username</th><th>Role</th><th>Last login</th><th></th></tr></thead>
          <tbody>
            {users.map(u => (
              <tr key={u.id}>
                <td>{u.username}</td>
                <td><span className={styles.roleBadge} data-role={u.role}>{ROLE_LABELS[u.role]}</span></td>
                <td className={styles.muted}>{fmt(u.lastLoginAt)}</td>
                <td className={styles.right}>
                  {u.username !== me.username && <button className={styles.danger} onClick={() => remove(u.username)}>Delete</button>}
                </td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
    </div>
  );
}

function TokensPanel() {
  const [tokens, setTokens] = useState<TokenInfo[]>([]);
  const [label, setLabel] = useState('');
  const [minted, setMinted] = useState<string | null>(null);
  const [busy, setBusy] = useState(false);

  const load = useCallback(() => { listTokens().then(setTokens).catch(() => {}); }, []);
  useEffect(() => { load(); }, [load]);

  const create = async (e: React.FormEvent) => {
    e.preventDefault();
    setBusy(true);
    try {
      const res = await createToken(label.trim() || 'sync-extension');
      setMinted(res.token); setLabel(''); load();
    } finally { setBusy(false); }
  };
  const revoke = async (id: number) => { if (confirm('Revoke this token?')) { await revokeToken(id).catch(() => {}); load(); } };

  return (
    <div className={styles.grid}>
      <form className={styles.card} onSubmit={create}>
        <h3 className={styles.cardTitle}>Create API token</h3>
        <p className={styles.hint}>For the FORGE Snow Sync Chrome extension. The raw token is shown once.</p>
        <label className={styles.label}>Label</label>
        <input className={styles.input} value={label} onChange={e => setLabel(e.target.value)} placeholder="e.g. my laptop" />
        <button className={styles.btn} type="submit" disabled={busy}>{busy ? 'Creating…' : 'Create token'}</button>
        {minted && (
          <div className={styles.minted}>
            <div className={styles.mintedLabel}>Copy now — shown once:</div>
            <code className={styles.mintedToken} onClick={() => navigator.clipboard?.writeText(minted)}>{minted}</code>
            <button type="button" className={styles.copy} onClick={() => navigator.clipboard?.writeText(minted)}>Copy</button>
          </div>
        )}
      </form>

      <div className={styles.card}>
        <h3 className={styles.cardTitle}>Tokens ({tokens.length})</h3>
        <table className={styles.table}>
          <thead><tr><th>Label</th><th>ID</th><th>Last used</th><th>Expires</th><th></th></tr></thead>
          <tbody>
            {tokens.map(t => (
              <tr key={t.id} className={t.revoked ? styles.revokedRow : ''}>
                <td>{t.label}</td>
                <td className={styles.mono}>{t.tokenId}</td>
                <td className={styles.muted}>{fmt(t.lastUsedAt)}</td>
                <td className={styles.muted}>{fmt(t.expiresAt)}</td>
                <td className={styles.right}>
                  {t.revoked ? <span className={styles.revoked}>revoked</span> : <button className={styles.danger} onClick={() => revoke(t.id)}>Revoke</button>}
                </td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
    </div>
  );
}
