import type { components } from '$lib/generated/api';

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

/** Letters shown inside an event card before a "show more" toggle appears (#850, REQ-003). */
export const CLUSTER_PREVIEW = 5;

/** One contained event card's worth of letters within a year band (#850). */
export interface EventCluster {
	/** The curated event's id — also the `{#each}` key. */
	eventId: string;
	/** The curated event's title (from the event lookup). */
	title: string;
	letters: TimelineEntryDTO[];
}

/** The result of splitting a year's letters into event clusters and the loose remainder. */
export interface SplitLetters {
	clusters: EventCluster[];
	loose: TimelineEntryDTO[];
}

/**
 * Maps each curated event present in the (already layer-filtered) timeline to its title. These
 * are the only events a letter may cluster under — a letter whose `linkedEventId` is absent here
 * links to an event the #780 layer filter removed, so it falls back to a loose chronological
 * letter (filter-then-cluster, REQ-008). Curated events carry an `eventId`; derived life-events
 * and letters do not, so they never enter the lookup.
 */
export function buildEventLookup(timeline: TimelineDTO): Map<string, string> {
	const lookup = new Map<string, string>();
	const collect = (entries: TimelineEntryDTO[]) => {
		for (const entry of entries) {
			if (entry.kind === 'EVENT' && entry.eventId) lookup.set(entry.eventId, entry.title ?? '');
		}
	};
	for (const band of timeline.years) collect(band.entries);
	collect(timeline.undated);
	return lookup;
}

/**
 * Splits one year's `LETTER` entries into event clusters and the loose remainder. A letter joins
 * the cluster keyed by its `linkedEventId` IFF that id is set AND present in `eventLookup`
 * (filter-then-cluster, REQ-007/008); every other letter is loose and stays in the chronological
 * flow (REQ-006). Clusters keep first-seen order; each letter appears in exactly one place.
 */
export function splitYearLetters(
	letters: TimelineEntryDTO[],
	eventLookup?: Map<string, string>
): SplitLetters {
	const byEvent = new Map<string, EventCluster>();
	const clusters: EventCluster[] = [];
	const loose: TimelineEntryDTO[] = [];

	for (const letter of letters) {
		const eventId = letter.linkedEventId;
		const title = eventId != null ? eventLookup?.get(eventId) : undefined;
		if (eventId != null && title !== undefined) {
			let cluster = byEvent.get(eventId);
			if (!cluster) {
				cluster = { eventId, title, letters: [] };
				byEvent.set(eventId, cluster);
				clusters.push(cluster);
			}
			cluster.letters.push(letter);
		} else {
			loose.push(letter);
		}
	}

	return { clusters, loose };
}
