import { parallel } from "$lib/api/load";
import { branches, gitTarget, log, tags } from "$lib/api/gitclient";
import { REF_LIMIT } from "$lib/api/repoIndex";
import { tagsByCommitHash, toBranchSummary, toCommitSummary, toTagSummary } from "$lib/api/repo";
import type { PageLoad } from "./$types";

// same page size as the appview's log
const COMMIT_LIMIT = 60;

export const load: PageLoad = async (event) => {
	const parent = await event.parent();
	const git = gitTarget(parent.publicConfig, parent.repo, event.fetch);
	const ref = event.params.ref;

	// Number accepts hex/exponents/whitespace that the appview's Atoi rejects,
	// gate first
	const rawPage = event.url.searchParams.get("page") ?? "";
	const parsed = /^\d+$/.test(rawPage) ? Number(rawPage) : 1;
	const page = parsed >= 1 ? parsed : 1;
	// the log cursor is a numeric offset
	const cursor = page > 1 ? String((page - 1) * COMMIT_LIMIT) : undefined;

	const results = await parallel({
		log: log(git, { ref, limit: COMMIT_LIMIT, cursor }),
		tags: tags(git, REF_LIMIT),
		branches: branches(git, REF_LIMIT)
	});

	const commits = (results.log.commits ?? []).map(toCommitSummary);
	const totalCommits = results.log.total ?? 0;
	// knot2 answers an exact total when it can, without one a full page hints
	// at another
	const pageCount =
		totalCommits > 0
			? Math.ceil(totalCommits / COMMIT_LIMIT)
			: page + (commits.length === COMMIT_LIMIT ? 1 : 0);

	const tagsByCommit = tagsByCommitHash(commits, (results.tags.tags ?? []).map(toTagSummary));
	// branch tips go into the same badge map as tags
	const shown = new Set(commits.map((commit) => commit.hash));
	for (const branch of (results.branches.branches ?? []).map(toBranchSummary)) {
		if (shown.has(branch.hash)) (tagsByCommit[branch.hash] ??= []).push(branch.name);
	}

	return {
		ref,
		page,
		pageCount,
		commits,
		totalCommits,
		tagsByCommit
	};
};
