<script lang="ts">
	import ArrowRight from "$icon/arrow-right";
	import ChevronDown from "$icon/chevron-down";
	import ChevronRight from "$icon/chevron-right";
	import Eye from "$icon/eye";
	import type { DiffFile, DiffStat } from "$lib/api/diff";
	import type { FileDiffMetadata } from "@pierre/diffs";
	import Button from "$lib/components/ui/Button.svelte";
	import type { Snippet } from "svelte";
	import DiffStatPill from "./DiffStatPill.svelte";
	import PierreDiff from "./PierreDiff.svelte";
	import type { DiffStyle } from "./pierre";

	interface Props {
		file: DiffFile;
		// resolved display path (new name, falling back to old)
		name: string;
		stat: DiffStat;
		// pierre's structured diff, absent for binaries
		fileDiff?: FileDiffMetadata;
		// server-prerendered shadow dom for fileDiff
		prerenderedHTML?: string;
		// side-by-side or stacked
		diffStyle?: DiffStyle;
		// blob route for the "view file" link, hidden when absent
		blobUrl?: string;
		open?: boolean;
		// review-button slot on the file header (pull pages)
		headerActions?: Snippet<[DiffFile]>;
	}

	let {
		file,
		name,
		stat,
		fileDiff,
		prerenderedHTML,
		diffStyle = "unified",
		blobUrl,
		open = $bindable(true),
		headerActions
	}: Props = $props();
</script>

<!-- the summary sticks below the site header + topbar and needs a solid bg
     or the diff shows through. z-[5] keeps it under the z-10 topbar it
     shares its sticky band with -->
<details
	bind:open
	id="file-{name}"
	class="group mx-auto w-full rounded border border-border-default bg-background-default"
>
	<summary
		class="sticky top-[calc(5.75rem+env(safe-area-inset-top))] z-5 cursor-pointer list-none rounded bg-background-default group-open:rounded-b-none group-open:border-b group-open:border-border-default"
	>
		<div class="flex cursor-pointer justify-between">
			<div class="flex items-center gap-2 overflow-x-auto p-2">
				{#if open}
					<ChevronDown class="size-4" />
				{:else}
					<ChevronRight class="size-4" />
				{/if}
				<DiffStatPill {stat} />

				<div class="flex items-center gap-2 overflow-x-auto">
					{#if file.name.old && file.name.new && file.name.old !== file.name.new}
						{file.name.old}
						<ArrowRight class="size-4" />
						{file.name.new}
					{:else}
						{name}
					{/if}
				</div>
			</div>
			<div class="flex items-center pr-1">
				{#if blobUrl}
					<Button
						href={blobUrl as "/"}
						variant="ghost"
						size="sm"
						icon={Eye}
						class="hidden md:inline-flex"
						onclick={(event) => event.stopPropagation()}
					>
						View file
					</Button>
				{/if}
				{@render headerActions?.(file)}
			</div>
		</div>
	</summary>

	{#if file.is_binary}
		<p class="p-4 text-center text-foreground-placeholder">
			This is a binary file and will not be displayed.
		</p>
	{:else}
		<PierreDiff files={fileDiff ? [fileDiff] : []} {diffStyle} prerenderedHTML={[prerenderedHTML]} />
	{/if}
</details>
