import crypto from "node:crypto";

import { PASSWORD_POLICY, validateNewPassword } from "@/lib/auth/passwordPolicy";

const LETTERS = "ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
const DIGITS = "23456789";
const SPECIALS = "!@#$%&*_-";
const CHARSET = `${LETTERS}${DIGITS}${SPECIALS}`;

const DEFAULT_TEMP_PASSWORD_LENGTH = Math.max(PASSWORD_POLICY.minLength, 12);
const MAX_GENERATION_ATTEMPTS = 20;

function randomChar(chars) {
	const i = crypto.randomInt(0, chars.length);
	return chars[i];
}

function shuffle(input) {
	const chars = String(input).split("");
	for (let i = chars.length - 1; i > 0; i -= 1) {
		const j = crypto.randomInt(0, i + 1);
		[chars[i], chars[j]] = [chars[j], chars[i]];
	}
	return chars.join("");
}

function normalizeLength(length) {
	if (!Number.isInteger(length)) return DEFAULT_TEMP_PASSWORD_LENGTH;
	return Math.max(PASSWORD_POLICY.minLength, length);
}

export function generateAdminTemporaryPassword({ length } = {}) {
	const targetLength = normalizeLength(length);

	for (let attempt = 0; attempt < MAX_GENERATION_ATTEMPTS; attempt += 1) {
		const base = [randomChar(LETTERS), randomChar(DIGITS)];

		while (base.length < targetLength) {
			base.push(randomChar(CHARSET));
		}

		const candidate = shuffle(base.join(""));
		if (validateNewPassword({ newPassword: candidate }).ok) {
			return candidate;
		}
	}

	throw new Error("Unable to generate temporary password");
}

