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

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

/**
 * The three visibility layers a reader can toggle on the global `/zeitstrahl`
 * (#780). Purely a presentation concern — the whole timeline is loaded once by
 * #779; these toggles derive a client-side filtered view of it.
 */
export interface TimelineLayerFilters {
	/** Personal events — curated `PERSONAL` events and derived life-events. */
	personalOn: boolean;
	/** Historical events (`type === 'HISTORICAL'`). */
	historicalOn: boolean;
	/** Letters (`kind === 'LETTER'`). */
	lettersOn: boolean;
}

/** The default view: every layer visible. */
export const ALL_LAYERS_ON: TimelineLayerFilters = {
	personalOn: true,
	historicalOn: true,
	lettersOn: true
};

/** True when no layer is hidden — the default, all-on state (REQ-007). */
export function isDefaultState(filters: TimelineLayerFilters): boolean {
	return filters.personalOn && filters.historicalOn && filters.lettersOn;
}

/** How many layers are currently hidden — the "N active" trigger count (REQ-007). */
export function hiddenLayerCount(filters: TimelineLayerFilters): number {
	return (
		(filters.personalOn ? 0 : 1) + (filters.historicalOn ? 0 : 1) + (filters.lettersOn ? 0 : 1)
	);
}

/**
 * Decides whether one entry survives the active layer toggles. A letter rides
 * the Letters layer; a historical event the Historical layer; everything else
 * (curated `PERSONAL` events and derived life-events, which also carry
 * `type === 'PERSONAL'`) the Personal layer.
 */
function isVisible(entry: TimelineEntryDTO, filters: TimelineLayerFilters): boolean {
	if (entry.kind === 'LETTER') return filters.lettersOn;
	if (entry.type === 'HISTORICAL') return filters.historicalOn;
	return filters.personalOn;
}

/**
 * Derives a client-side filtered copy of the timeline (REQ-003/004/005/006).
 * Year bands left empty by the active toggles are dropped so `TimelineView`
 * never renders a hollow band, and the undated bucket is filtered the same way.
 * Pure — the input DTO is never mutated.
 */
export function filterTimeline(timeline: TimelineDTO, filters: TimelineLayerFilters): TimelineDTO {
	const years = timeline.years
		.map((band) => ({ ...band, entries: band.entries.filter((e) => isVisible(e, filters)) }))
		.filter((band) => band.entries.length > 0);
	const undated = timeline.undated.filter((e) => isVisible(e, filters));
	return { years, undated };
}
