import { intlNumberFormatter } from "./intlNumberFormatter";

/**
 * The adjustDecimals function rounds a numerical value to a specified number of
 * decimal places, retaining the original formatting for values with fewer decimals
 * and preserving very small values in their entirety.
 *
 * @param value - The number or string to format
 * @param decimals - Number of decimal places to show (default: 2)
 * @param locale - Locale for number formatting (default: "en-US")
 * @param showApproximateZero - If true, shows "~0" for extremely small values like 1e-4 (default: false)
 *
 * Note: not to be used for calculations, only for display purposes
 */
export function adjustDecimals({
	value,
	decimals = 2,
	locale = "en-US",
	showApproximateZero = false,
}: {
	value: number | string;
	decimals?: number;
	locale?: string;
	showApproximateZero?: boolean;
}): string {
	const formatter = intlNumberFormatter(locale);

	const _value = Number(value);

	// Handle zero
	if (_value === 0) {
		return "0";
	}

	// Define extremely small threshold (smaller than typical token precision)
	const extremelySmallThreshold = 1e-4;

	// Handle extremely small values that are essentially zero (only if opt-in)
	if (showApproximateZero && Math.abs(_value) < extremelySmallThreshold) {
		return "0";
	}

	// Handle very small values or values smaller than the decimal precision
	if (Math.abs(_value) < 10 ** -decimals) {
		// Use toFixed with a higher precision to avoid exponential notation
		const expandedValue = _value.toFixed(20);
		const decimalPart = expandedValue.split(".")[1] || "";

		// Convert the decimal part into an array of characters
		const decimalPartArray = Array.from(decimalPart);
		const decimalPartToShow = [];
		let foundFirstNonZero = false;

		for (const digit of decimalPartArray) {
			// Always add zeros until the first non-zero is found
			if (!foundFirstNonZero) {
				decimalPartToShow.push(digit);
				if (digit !== "0") {
					foundFirstNonZero = true; // Mark that we've found the first non-zero digit
				}
			} else {
				// After the first non-zero, continue adding digits until we reach the specified decimals
				if (decimalPartToShow.length < decimals) {
					decimalPartToShow.push(digit);
				} else {
					break; // Stop if we've reached the specified number of decimal places
				}
			}
		}

		const integer = expandedValue.split(".")[0];
		// Join the decimal part and remove any trailing zeros
		const decimalResult = decimalPartToShow.join("").replace(/0+$/, "");
		//  biome-ignore format:
		return decimalResult ? `${integer}.${decimalResult}` : `${integer}`; // Return the formatted number
	}

	// Round to the specified number of decimals
	const roundedValue = _value.toFixed(decimals);

	// Remove trailing zeros and unnecessary decimal point
	return formatter.format(Number(Number(roundedValue).toString()));
}

// Test cases
// const locale = "en-US";
// console.log(adjustDecimals({ value: 0.000608213999999996, decimals: 2, locale })); // "0.0006"
// console.log(adjustDecimals({ value: 0.0608213999999996, decimals: 4, locale })); // "0.0608"
// console.log(adjustDecimals({ value: 1.000001, decimals: 2, locale })); // "1"
// console.log(adjustDecimals({ value: 0.000001, decimals: 2, locale })); // "0.000001"
// console.log(adjustDecimals({ value: 100.38300001, decimals: 2, locale })); // "100.38"
// console.log(adjustDecimals({ value: 0.001, decimals: 2, locale })); // "0.001"
// console.log(adjustDecimals({ value: 0.00001, decimals: 2, locale })); // "0.00001"
// console.log(adjustDecimals({ value: 0.50001, decimals: 2, locale })); // "0.50"
// console.log(adjustDecimals({ value: 46.38393, decimals: 2, locale })); // "46.39"
// console.log(adjustDecimals({ value: 1.298e-15, decimals: 2, locale })); // "0.000000000000001298" (default behavior)
// console.log(adjustDecimals({ value: 1.298e-15, decimals: 2, locale, showApproximateZero: true })); // "~0" (with showApproximateZero = true)
// console.log(adjustDecimals({ value: "1.298e-15", decimals: 2, locale, showApproximateZero: true })); // "~0"
// console.log(adjustDecimals({ value: 8.298e-8, decimals: 2, locale })); // "0.000000083"
// console.log(adjustDecimals({ value: 0.00000001, decimals: 2, locale })); // "0.00000001"
// console.log(adjustDecimals({ value: 0.00001, decimals: 2, locale, showApproximateZero: true })); // "0"
