/**
 * Masks a string by replacing characters with a mask character
 * @param value - The string to mask
 * @param visibleStart - Number of characters to show at start (default: 0)
 * @param visibleEnd - Number of characters to show at end (default: 4)
 * @param maskChar - Character to use for masking (default: '*')
 * @returns The masked string
 */
const maskChar = "*";
export function mask(
	value: string,
	options?: { visibleStart?: number; visibleEnd?: number; maxLength?: number },
): string {
	if (!value) return "";

	const { visibleStart = 2, visibleEnd = 2, maxLength = 10 } = options ?? {};

	if (isEmail(value)) {
		return maskEmail(value);
	}

	const totalVisible = visibleStart + visibleEnd;
	if (value.length <= totalVisible) {
		return maskChar.repeat(value.length);
	}

	const start = value.slice(0, visibleStart);
	const middle = value.slice(visibleStart, -visibleEnd || undefined);
	const end = visibleEnd ? value.slice(-visibleEnd) : "";

	const maskedLength = Math.min(middle.length, maxLength);
	return start + maskChar.repeat(maskedLength) + end;
}

function maskEmail(email: string): string {
	const [local, domain] = email.split("@");
	if (!domain || !local) return mask(email);
	const [subDomain, tld] = domain.split(/\.(?=[^.]+$)/);
	return `${mask(local)}@${mask(subDomain ?? "")}.${tld}`;
}

const isEmail = (value: string) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value);
