<script lang="ts">
	import type { RevisionDiff, RevisionPrefix, RevisionRow } from '$lib/api/types.js';
	import { Button } from '$lib/ui/core/button/index.js';
	import {
		Card,
		CardContent,
		CardDescription,
		CardHeader,
		CardTitle
	} from '$lib/ui/core/card/index.js';
	import { Select, SelectContent, SelectItem, SelectTrigger } from '$lib/ui/core/select/index.js';
	import { formatDateTime } from '$lib/modules/display.js';
	import { sortRevisionDiffItems } from '$lib/sort-prefixes.js';

	type Props = {
		revisions: RevisionRow[];
		diffRevA: string;
		diffRevB: string;
		diffData: RevisionDiff | null;
		diffLoading: boolean;
		onDiffRevAChange: (value: string) => void;
		onDiffRevBChange: (value: string) => void;
		onLoadDiff: () => void;
	};

	let {
		revisions,
		diffRevA,
		diffRevB,
		diffData,
		diffLoading,
		onDiffRevAChange,
		onDiffRevBChange,
		onLoadDiff
	}: Props = $props();

	function revisionLabel(rev: RevisionRow): string {
		return `${rev.id.slice(0, 8)}… (${formatDateTime(rev.created_at)})`;
	}

	function diffAddedRaw(d: RevisionDiff | null): (string | RevisionPrefix)[] {
		if (!d) return [];
		if (d.prefixes && Array.isArray(d.prefixes.added)) return d.prefixes.added;
		if (Array.isArray(d.added)) return d.added;
		return [];
	}

	function diffRemovedRaw(d: RevisionDiff | null): (string | RevisionPrefix)[] {
		if (!d) return [];
		if (d.prefixes && Array.isArray(d.prefixes.removed)) return d.prefixes.removed;
		if (Array.isArray(d.removed)) return d.removed;
		return [];
	}

	let addedSorted = $derived(diffData ? sortRevisionDiffItems(diffAddedRaw(diffData)) : []);
	let removedSorted = $derived(diffData ? sortRevisionDiffItems(diffRemovedRaw(diffData)) : []);

	let scrollAddedEl: HTMLDivElement | null = $state(null);
	let scrollRemovedEl: HTMLDivElement | null = $state(null);
	let syncScrollLock = false;

	function syncFromAdded() {
		if (syncScrollLock || !scrollAddedEl || !scrollRemovedEl) return;
		syncScrollLock = true;
		scrollRemovedEl.scrollTop = scrollAddedEl.scrollTop;
		queueMicrotask(() => {
			syncScrollLock = false;
		});
	}

	function syncFromRemoved() {
		if (syncScrollLock || !scrollAddedEl || !scrollRemovedEl) return;
		syncScrollLock = true;
		scrollAddedEl.scrollTop = scrollRemovedEl.scrollTop;
		queueMicrotask(() => {
			syncScrollLock = false;
		});
	}
</script>

<Card class="min-h-0">
	<CardHeader>
		<CardTitle class="text-base">Сравнение ревизий</CardTitle>
		<CardDescription>Выберите ID двух ревизий для сравнения</CardDescription>
	</CardHeader>
	<CardContent class="min-h-0 space-y-4">
		<div class="flex flex-col gap-2 sm:flex-row">
			<Select type="single" value={diffRevA} onValueChange={(v) => onDiffRevAChange(v ?? '')}>
				<SelectTrigger class="min-w-0 flex-1">
					{diffRevA
						? revisions.find((r) => r.id === diffRevA)
							? revisionLabel(revisions.find((r) => r.id === diffRevA)!)
							: diffRevA
						: 'Ревизия A'}
				</SelectTrigger>
				<SelectContent>
					<SelectItem value="">Ревизия A</SelectItem>
					{#each revisions as rev (rev.id)}
						<SelectItem value={rev.id}>{revisionLabel(rev)}</SelectItem>
					{/each}
				</SelectContent>
			</Select>
			<Select type="single" value={diffRevB} onValueChange={(v) => onDiffRevBChange(v ?? '')}>
				<SelectTrigger class="min-w-0 flex-1">
					{diffRevB
						? revisions.find((r) => r.id === diffRevB)
							? revisionLabel(revisions.find((r) => r.id === diffRevB)!)
							: diffRevB
						: 'Ревизия B'}
				</SelectTrigger>
				<SelectContent>
					<SelectItem value="">Ревизия B</SelectItem>
					{#each revisions as rev (rev.id)}
						<SelectItem value={rev.id}>{revisionLabel(rev)}</SelectItem>
					{/each}
				</SelectContent>
			</Select>
			<Button
				size="sm"
				class="shrink-0 self-start sm:self-auto"
				onclick={onLoadDiff}
				disabled={diffLoading}
			>
				{diffLoading ? 'Загрузка…' : 'Сравнить'}
			</Button>
		</div>

		{#if diffData}
			<div
				class="grid min-h-0 grid-cols-1 overflow-hidden rounded-md border border-border sm:grid-cols-2"
				style="scrollbar-gutter: stable;"
			>
				<div class="flex min-h-0 min-w-0 flex-col border-b border-border sm:border-r sm:border-b-0">
					<div
						class="flex shrink-0 items-center border-b border-border bg-muted/60 px-3 py-2 font-mono text-xs font-semibold text-success"
					>
						<span class="mr-2 w-10 shrink-0 text-right text-muted-foreground select-none">+</span>
						<span>Добавлено ({addedSorted.length})</span>
					</div>
					<div
						bind:this={scrollAddedEl}
						class="max-h-[min(28rem,70vh)] min-h-0 overflow-x-auto overflow-y-scroll overscroll-contain bg-background/50"
						onscroll={syncFromAdded}
					>
						{#if addedSorted.length === 0}
							<p class="p-3 font-mono text-xs text-muted-foreground">Нет изменений</p>
						{:else}
							<table class="w-full border-collapse font-mono text-xs">
								<tbody>
									{#each addedSorted as line, i (`a-${i}-${line}`)}
										<tr
											class="border-b border-l-2 border-success/30 bg-success/5 hover:bg-muted/30"
										>
											<td
												class="w-10 shrink-0 border-r border-transparent py-0.5 pr-1 pl-2 text-right align-top text-[11px] text-muted-foreground tabular-nums select-none"
											>
												{i + 1}
											</td>
											<td
												class="max-w-0 py-0.5 pr-3 pl-1 break-all whitespace-pre-wrap text-foreground"
											>
												{line}
											</td>
										</tr>
									{/each}
								</tbody>
							</table>
						{/if}
					</div>
				</div>

				<div class="flex min-h-0 min-w-0 flex-col">
					<div
						class="flex shrink-0 items-center border-b border-border bg-muted/60 px-3 py-2 font-mono text-xs font-semibold text-destructive"
					>
						<span class="mr-2 w-10 shrink-0 text-right text-muted-foreground select-none">−</span>
						<span>Удалено ({removedSorted.length})</span>
					</div>
					<div
						bind:this={scrollRemovedEl}
						class="max-h-[min(28rem,70vh)] min-h-0 overflow-x-auto overflow-y-scroll overscroll-contain bg-background/50"
						onscroll={syncFromRemoved}
					>
						{#if removedSorted.length === 0}
							<p class="p-3 font-mono text-xs text-muted-foreground">Нет изменений</p>
						{:else}
							<table class="w-full border-collapse font-mono text-xs">
								<tbody>
									{#each removedSorted as line, i (`r-${i}-${line}`)}
										<tr
											class="border-b border-l-2 border-destructive/30 bg-destructive/5 hover:bg-muted/30"
										>
											<td
												class="w-10 shrink-0 border-r border-transparent py-0.5 pr-1 pl-2 text-right align-top text-[11px] text-muted-foreground tabular-nums select-none"
											>
												{i + 1}
											</td>
											<td
												class="max-w-0 py-0.5 pr-3 pl-1 break-all whitespace-pre-wrap text-foreground"
											>
												{line}
											</td>
										</tr>
									{/each}
								</tbody>
							</table>
						{/if}
					</div>
				</div>
			</div>
		{/if}
	</CardContent>
</Card>
