// Cryptographically random password generator for the user-create
// and reset-password flows. PiCloud has no email yet, so the admin
// invites a user by generating a password locally, posting it to the
// backend, and copying the cleartext out of the one-time reveal panel
// to share through whatever channel they trust.
//
// Charset is alphanumeric plus a small printable symbol set — enough
// entropy at 16 chars (~95 bits) to be uncopyable by hand mistakes,
// avoidant of characters that ship awkwardly through chat clients
// (no quotes, slashes, or backticks).
//
// Sampling: rejection sampling against a Uint8 stream. The naive
// `byte % CHARSET.length` would slightly overweight the first
// (256 mod N) chars; with N = 71 that's ~16 ppm of bias which is
// safe at 16 chars but easy to remove.

const CHARSET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!#$%&*+-?@';

export function generatePassword(length = 16): string {
	if (length < 8) {
		throw new Error('password length must be at least 8');
	}
	const n = CHARSET.length;
	// Largest multiple of `n` that fits in a Uint8 — bytes ≥ MAX get
	// rejected to remove modulo bias.
	const max = 256 - (256 % n);
	const buf = new Uint8Array(length);
	let out = '';
	while (out.length < length) {
		crypto.getRandomValues(buf);
		for (let i = 0; i < buf.length && out.length < length; i++) {
			const byte = buf[i];
			if (byte < max) out += CHARSET[byte % n];
		}
	}
	return out;
}
