import { describe, it, expect, beforeEach } from 'vitest';
import { promises as fs } from 'node:fs';
import path from 'node:path';
import os from 'node:os';
import { AccountStore } from './accounts';

describe('AccountStore', () => {
  let dir: string;
  let store: AccountStore;
  beforeEach(async () => { dir = await fs.mkdtemp(path.join(os.tmpdir(), 'acct-')); store = new AccountStore(dir); });

  it('registers, logs in, and rejects duplicates / bad input / bad creds', async () => {
    expect((await store.register('alice', 'password123')).ok).toBe(true);
    expect((await store.register('alice', 'password123')).ok).toBe(false); // taken
    expect((await store.register('ab', 'password123')).ok).toBe(false); // username too short
    expect((await store.register('bob', 'short')).ok).toBe(false); // weak password
    expect((await store.login('alice', 'password123')).ok).toBe(true);
    expect((await store.login('alice', 'nope')).ok).toBe(false);
  });

  it('stores + serves a per-user blob behind a bearer token', async () => {
    const r = await store.register('carol', 'password123');
    if (!r.ok) throw new Error('register failed');
    const u = await store.userByToken(r.token);
    expect(u).toBeTruthy();
    await store.saveBlob(u!.id, '{"x":1}');
    expect(await store.loadBlob(u!.id)).toBe('{"x":1}');
    expect(await store.userByToken('garbage-token')).toBeNull();
  });

  it('persists users across instances + logout invalidates the token', async () => {
    const r = await store.register('dave', 'password123');
    if (!r.ok) throw new Error('register failed');
    await store.logout(r.token);
    expect(await store.userByToken(r.token)).toBeNull();

    const store2 = new AccountStore(dir);
    await store2.load();
    expect((await store2.login('dave', 'password123')).ok).toBe(true);
  });

  it('gates admin + stores a quota override', async () => {
    const adminStore = new AccountStore(dir, undefined, ['boss']);
    await adminStore.register('boss', 'password123');
    await adminStore.register('peon', 'password123');
    expect(adminStore.isAdmin('boss')).toBe(true);
    expect(adminStore.isAdmin('Boss')).toBe(true); // case-insensitive
    expect(adminStore.isAdmin('peon')).toBe(false);
    expect(await adminStore.setQuota('peon', 5_000_000_000)).toBe(true);
    expect(await adminStore.setQuota('ghost', 1)).toBe(false);
    expect((await adminStore.listUsers()).find((u) => u.username === 'peon')?.quotaBytes).toBe(5_000_000_000);
  });
});
