import { error } from "@sveltejs/kit";
import { browser } from "$app/environment";
import { ClientResponseError, createBobbinClient } from "$lib/api/client";
import { diffFor, type DiffFile } from "$lib/api/diff";
import { toHttpError } from "$lib/api/load";
import { diffRowKey, toFileDiffMetadata } from "$lib/components/repo/fileDiff";
import { pierreDiffOptions, type DiffStyle } from "$lib/components/repo/pierre";
import type { PageLoad } from "./$types";

// the first paint ships highlighted: prerender each file's shadow dom on
// the server. skipped on client navigations, pierre paints those itself
const prerenderDiffs = async (
	files: DiffFile[],
	style: DiffStyle
): Promise<Record<string, string> | undefined> => {
	if (browser) return undefined;
	const { preloadFileDiff } = await import("@pierre/diffs/ssr");
	const options = pierreDiffOptions(style);
	const entries = await Promise.all(
		files
			.filter((file) => !file.is_binary)
			.map(async (file) => {
				const { prerenderedHTML } = await preloadFileDiff({
					fileDiff: toFileDiffMetadata(file),
					options
				});
				return [diffRowKey(file), prerenderedHTML] as const;
			})
	);
	return Object.fromEntries(entries);
};

// the ref is a single encoded segment, `feature/x` arrives intact
export const load: PageLoad = async (event) => {
	const parent = await event.parent();
	const ctx = createBobbinClient({
		serviceUrl: parent.publicConfig.bobbinUrl,
		fetch: event.fetch
	});
	const repo = parent.repo.uri;

	const result = await diffFor(ctx, repo, event.params.ref).catch((cause: unknown): never => {
		if (cause instanceof ClientResponseError && cause.status === 404) {
			error(404, "Commit not found");
		}
		return toHttpError(cause, "Could not load commit");
	});
	if (!result?.diff?.commit) error(404, "Commit not found");

	const style = event.url.searchParams.get("diff") === "split" ? "split" : "unified";
	const prerendered = await prerenderDiffs(result.diff.diff ?? [], style);

	return { ref: event.params.ref, commitDiff: result.diff, prerendered };
};
