const calculatePercentile = (arr, percentile) => {
	const sorted = arr.slice().sort((a, b) => a.responseTime - b.responseTime);
	const index = (percentile / 100) * (sorted.length - 1);
	const lower = Math.floor(index);
	const upper = lower + 1;
	const weight = index % 1;
	if (upper >= sorted.length) return sorted[lower].responseTime;
	return sorted[lower].responseTime * (1 - weight) + sorted[upper].responseTime * weight;
};

const calculatePercentileUptimeDetails = (arr, percentile) => {
	const sorted = arr.slice().sort((a, b) => a.avgResponseTime - b.avgResponseTime);
	const index = (percentile / 100) * (sorted.length - 1);
	const lower = Math.floor(index);
	const upper = lower + 1;
	const weight = index % 1;
	if (upper >= sorted.length) return sorted[lower].avgResponseTime;
	return (
		sorted[lower].avgResponseTime * (1 - weight) + sorted[upper].avgResponseTime * weight
	);
};

const NormalizeData = (checks, rangeMin, rangeMax) => {
	if (checks.length > 1) {
		// Get the 5th and 95th percentile
		const min = calculatePercentile(checks, 0);
		const max = calculatePercentile(checks, 95);
		const normalizedChecks = checks.map((check) => {
			const originalResponseTime = check.responseTime;
			// Normalize the response time between 1 and 100
			let normalizedResponseTime =
				rangeMin + ((check.responseTime - min) * (rangeMax - rangeMin)) / (max - min);

			// Put a floor on the response times so we don't have extreme outliers
			// Better visuals
			normalizedResponseTime = Math.max(
				rangeMin,
				Math.min(rangeMax, normalizedResponseTime)
			);
			return {
				...check,
				responseTime: normalizedResponseTime,
				originalResponseTime: originalResponseTime,
			};
		});

		return normalizedChecks;
	} else {
		return checks.map((check) => {
			return { ...check, originalResponseTime: check.responseTime };
		});
	}
};
const NormalizeDataUptimeDetails = (checks, rangeMin, rangeMax) => {
	if (checks.length > 1) {
		// Get the 5th and 95th percentile
		const min = calculatePercentileUptimeDetails(checks, 0);
		const max = calculatePercentileUptimeDetails(checks, 95);

		const normalizedChecks = checks.map((check) => {
			const originalResponseTime = check.avgResponseTime;
			// Normalize the response time between 1 and 100
			let normalizedResponseTime =
				rangeMin + ((check.avgResponseTime - min) * (rangeMax - rangeMin)) / (max - min);

			// Put a floor on the response times so we don't have extreme outliers
			// Better visuals
			normalizedResponseTime = Math.max(
				rangeMin,
				Math.min(rangeMax, normalizedResponseTime)
			);
			return {
				...check,
				avgResponseTime: normalizedResponseTime,
				originalAvgResponseTime: originalResponseTime,
			};
		});

		return normalizedChecks;
	} else {
		return checks.map((check) => {
			return { ...check, originalResponseTime: check.responseTime };
		});
	}
};

const safelyParseFloat = (value, defaultValue = 0) => {
	if (value === null || typeof value === "undefined") {
		return defaultValue;
	}
	const stringValue = String(value).trim();

	if (typeof value === "number" && !isNaN(value)) {
		return value;
	}

	if (stringValue === "") {
		return defaultValue;
	}

	const parsedValue = parseFloat(stringValue);

	if (isNaN(parsedValue) || !isFinite(parsedValue)) {
		return defaultValue;
	}

	return parsedValue;
};

export {
	safelyParseFloat,
	calculatePercentile,
	NormalizeData,
	calculatePercentileUptimeDetails,
	NormalizeDataUptimeDetails,
};
