// Path: Frontend/src/lib/api.ts

type ApiRequestOptions = RequestInit & {
	notFoundAsNull?: boolean;
	allowNoContent?: boolean;
	parseErrorMessage?: boolean;
};

export const apiFetchJson = async <T>(path: string, options: ApiRequestOptions = {}): Promise<T> => {
	const { notFoundAsNull = false, allowNoContent = false, parseErrorMessage = false, ...init } = options;
	const headers = new Headers(init.headers ?? undefined);

	if (!headers.has("accept")) {
		headers.set("accept", "application/json");
	}

	if (init.body && !headers.has("content-type")) {
		headers.set("content-type", "application/json");
	}

	const response = await fetch(path, {
		credentials: "include",
		...init,
		headers,
	});

	if (!response.ok) {
		if (response.status === 404) {
			if (notFoundAsNull) {
				return null as T;
			}

			const error = new Error("not_found");
			(error as Error & { status?: number }).status = 404;
			throw error;
		}

		let message = `Request failed: ${response.status}`;
		if (parseErrorMessage) {
			try {
				const payload = (await response.json()) as { message?: string };
				if (payload.message) message = payload.message;
			} catch {
				// ignore malformed payloads
			}
		}

		const error = new Error(message);
		(error as Error & { status?: number }).status = response.status;
		throw error;
	}

	if (response.status === 204 && allowNoContent) {
		return null as T;
	}

	return (await response.json()) as T;
};
