<script lang="ts">
import EventPill from './EventPill.svelte';
import WorldBand from './WorldBand.svelte';
import LetterCard from './LetterCard.svelte';
import YearLetterStrip from './YearLetterStrip.svelte';
import { isDense } from './timelineDensity';
import { entryKey } from './entryKey';
import type { components } from '$lib/generated/api';

type TimelineYearDTO = components['schemas']['TimelineYearDTO'];
type TimelineEntryDTO = components['schemas']['TimelineEntryDTO'];

/**
 * One year of the timeline: a <section> with a sticky <h2> (REQ-006). Events
 * render in DTO order as pills/bands; letters render as individual cards while
 * the band holds ≤ 12 (REQ-011) or collapse to a single density strip above that
 * (REQ-012). Entries are never re-sorted — DTO order is preserved (REQ-003).
 */
let { year }: { year: TimelineYearDTO } = $props();

type Row =
	| { t: 'event'; entry: TimelineEntryDTO }
	| { t: 'letter'; entry: TimelineEntryDTO; side: 'left' | 'right' }
	| { t: 'strip' };

const letters = $derived(year.entries.filter((e) => e.kind === 'LETTER'));
const dense = $derived(isDense(letters.length));

const rows = $derived.by<Row[]>(() => {
	const out: Row[] = [];
	let stripInserted = false;
	let letterIndex = 0;
	for (const entry of year.entries) {
		if (entry.kind === 'EVENT') {
			out.push({ t: 'event', entry });
		} else if (!dense) {
			out.push({ t: 'letter', entry, side: letterIndex % 2 === 0 ? 'left' : 'right' });
			letterIndex += 1;
		} else if (!stripInserted) {
			out.push({ t: 'strip' });
			stripInserted = true;
		}
	}
	return out;
});
</script>

<section class="py-2">
	<h2
		class="year-heading w-fit rounded-full bg-brand-navy px-4 py-1 font-serif text-sm font-bold text-white"
	>
		{year.year}
	</h2>

	<div class="mt-3 space-y-3">
		{#each rows as row (row.t === 'strip' ? `strip-${year.year}` : entryKey(row.entry))}
			{#if row.t === 'event'}
				{#if row.entry.type === 'HISTORICAL'}
					<WorldBand entry={row.entry} />
				{:else}
					<EventPill entry={row.entry} />
				{/if}
			{:else if row.t === 'letter'}
				<div class="letter-row" data-side={row.side}>
					<LetterCard entry={row.entry} />
				</div>
			{:else}
				<YearLetterStrip letters={letters} year={year.year} />
			{/if}
		{/each}
	</div>
</section>

<style>
/* Sticky offset in scoped CSS so it holds in unit tests too (the global
	   header is a 64px sticky nav). REQ-006. */
.year-heading {
	position: sticky;
	top: 4rem;
	z-index: 1;
}

/* Phone (< 1024px): single left-anchored column, all letters on one side
	   (REQ-005). Desktop (≥ 1024px): centered axis, letters alternate left/right
	   so consecutive cards sit on opposite sides of the spine (REQ-004). */
@media (min-width: 1024px) {
	.letter-row {
		width: 50%;
	}
	.letter-row[data-side='left'] {
		margin-right: auto;
		padding-right: 1.75rem;
	}
	.letter-row[data-side='right'] {
		margin-left: auto;
		padding-left: 1.75rem;
	}
}
</style>
