import type { BuilderModule } from '@nitrogenbuilder/types';

const ALPHA = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
const ALNUM = ALPHA + '0123456789';

// Random 4-char id. Only a FALLBACK now (before a siteId is assigned, or if the
// server runs out of single-char site ids). Primary minting is namespaced and
// collision-free (siteId + base62 counter) — see `nextNamespacedId` / the editor.
export function generateShortId(): string {
	let id = ALPHA[Math.floor(Math.random() * ALPHA.length)];
	for (let i = 0; i < 3; i++) {
		id += ALNUM[Math.floor(Math.random() * ALNUM.length)];
	}
	return id;
}

// base62 codec for the per-client id counter (compact, letter-or-digit chars).
const B62 = ALNUM; // a-zA-Z0-9
export function toBase62(n: number): string {
	if (n <= 0) return B62[0]; // zero-digit, so it round-trips (fromBase62 → 0)
	let s = '';
	while (n > 0) {
		s = B62[n % 62] + s;
		n = Math.floor(n / 62);
	}
	return s;
}
export function fromBase62(s: string): number {
	let n = 0;
	for (const c of s) {
		const i = B62.indexOf(c);
		if (i < 0) return NaN;
		n = n * 62 + i;
	}
	return n;
}

export function collectIds(page: BuilderModule[]): Set<string> {
	const ids = new Set<string>();
	function walk(mods: BuilderModule[]) {
		for (const mod of mods) {
			ids.add(mod.id);
			const children = mod.props?.children;
			if (Array.isArray(children)) {
				walk(children);
			} else if (children && typeof children === 'object') {
				for (const slot of Object.keys(children)) {
					if (Array.isArray(children[slot])) walk(children[slot]);
				}
			}
		}
	}
	walk(page);
	return ids;
}

export function generateUniqueShortId(
	page: BuilderModule[],
	extraUsed?: Set<string>
): string {
	const used = collectIds(page);
	if (extraUsed) {
		for (const id of extraUsed) used.add(id);
	}
	for (let i = 0; i < 100; i++) {
		const id = generateShortId();
		if (!used.has(id)) return id;
	}
	throw new Error('shortId: exhausted attempts generating unique id');
}

export const SHORT_ID_PATTERN = /^[A-Za-z][A-Za-z0-9_-]{0,63}$/;

export function isValidId(id: string): boolean {
	return SHORT_ID_PATTERN.test(id);
}
