<script lang="ts">
import * as m from '$lib/paraglide/messages.js';
import { formatTickLabel } from '$lib/shared/utils/monthBuckets';
import { getLocale } from '$lib/paraglide/runtime';
import type { components } from '$lib/generated/api';

type MonthBucket = components['schemas']['MonthBucket'];

const ZERO_COUNT_BAR_HEIGHT = 2; // px — minimum visible signal for empty months

let {
	filled,
	maxCount,
	barAreaHeight,
	isSelected,
	isInDragPreview,
	isDragging,
	dragWindowLeftPct,
	dragWindowRightPct,
	rowEl = $bindable(),
	onbarpointerdown,
	onbarpointerenter,
	onbarclick
}: {
	filled: MonthBucket[];
	maxCount: number;
	barAreaHeight: number;
	isSelected: (label: string) => boolean;
	isInDragPreview: (index: number) => boolean;
	isDragging: boolean;
	dragWindowLeftPct: number;
	dragWindowRightPct: number;
	rowEl?: HTMLDivElement;
	onbarpointerdown: (event: PointerEvent, index: number) => void;
	onbarpointerenter: (index: number) => void;
	onbarclick: (index: number) => void;
} = $props();

function barHeight(count: number): number {
	if (count === 0) return ZERO_COUNT_BAR_HEIGHT;
	return Math.max(ZERO_COUNT_BAR_HEIGHT, (count / maxCount) * barAreaHeight);
}
</script>

<div
	bind:this={rowEl}
	class="relative flex items-end border-b border-line"
	style="height: {barAreaHeight}px;"
>
	{#each filled as bucket, i (bucket.month)}
		<button
			type="button"
			data-testid="timeline-bar"
			aria-label={bucket.count === 1
				? m.timeline_bar_aria_singular({ when: formatTickLabel(bucket.month, getLocale()) })
				: m.timeline_bar_aria_plural({
						when: formatTickLabel(bucket.month, getLocale()),
						count: bucket.count
					})}
			aria-pressed={isSelected(bucket.month)}
			onpointerdown={(e) => onbarpointerdown(e, i)}
			onpointerenter={() => onbarpointerenter(i)}
			onclick={() => onbarclick(i)}
			class="bar group flex h-full min-w-px flex-1 cursor-pointer items-end justify-center bg-transparent p-0 transition-colors focus-visible:ring-2 focus-visible:ring-brand-navy focus-visible:ring-offset-2 focus-visible:outline-none"
			class:selected={isSelected(bucket.month)}
			class:in-drag-preview={isInDragPreview(i)}
		>
			<span
				class="bar-fill block w-full rounded-t-[2px]"
				style="height: {barHeight(bucket.count)}px;"
			></span>
		</button>
	{/each}
	{#if isDragging}
		<div
			class="drag-window"
			data-testid="timeline-drag-window"
			style="left: {dragWindowLeftPct}%; right: {dragWindowRightPct}%;"
		></div>
	{/if}
</div>

<style>
/* Timeline-specific tokens (--timeline-bar-idle, --timeline-bar-outside) live
   in layout.css next to the rest of the design tokens; this <style> only
   consumes them. */
.bar .bar-fill {
	background-color: var(--timeline-bar-idle);
	transition: background-color 100ms ease;
}

@media (prefers-reduced-motion: reduce) {
	.bar .bar-fill {
		transition: none;
	}
}

.bar.selected .bar-fill,
.bar.in-drag-preview .bar-fill {
	background-color: var(--palette-mint, #a1dcd8);
}

.bar.in-drag-preview .bar-fill {
	opacity: 0.7;
}

/* Gate hover under (hover: hover) so emulated mouse events on touch devices
   don't leave a tapped bar stuck in :hover until the next tap elsewhere. */
@media (hover: hover) {
	.bar:hover .bar-fill {
		background-color: var(--palette-mint, #a1dcd8);
		opacity: 0.85;
	}
}

/* Graylog-style range selector window: left/right borders mark the dragged
   range, tinted body fills the area. pointer-events:none keeps the bars below
   reachable so pointermove still fires their pointerenter. */
.drag-window {
	position: absolute;
	top: 0;
	bottom: 0;
	background-color: rgba(161, 220, 216, 0.22);
	border-left: 2px solid var(--palette-mint, #a1dcd8);
	border-right: 2px solid var(--palette-mint, #a1dcd8);
	pointer-events: none;
}
</style>
