/**
 * Universal creation-log enumerators.
 *
 * Where `MarkwhenSourceFactory` projects *scheduled* events (when will X
 * happen), a `CreationEnumerator` projects *creations* (when did X come
 * into being). Every rApp that stores CRDT records with a `createdAt`
 * field registers one here — and automatically appears in rPast, the
 * unified chronicle-of-self viewer.
 *
 * The contract is deliberately minimal: the enumerator walks whichever
 * docs it owns and emits one `Creation` per record. The meta-adapter
 * below turns the merged stream into a single `MwSource` per module.
 */

import type { MwSource, MwEvent } from './types';

export interface Creation {
	/** Unix ms — when the record was created. Required. */
	createdAt: number;
	/** Unix ms — last edit. Omit if never updated. */
	updatedAt?: number;
	/** Single-line display name. */
	title: string;
	/** Record-type label (e.g. "event", "note", "task", "vote"). Used as a sub-tag. */
	recordType: string;
	/** Stable ID within the module (prefix not required; registry prefixes with module). */
	recordId: string;
	/** Optional deep-link back to the canonical record. */
	href?: string;
	/** Extra per-record tags (status, category, etc.). */
	tags?: string[];
	/** Short body shown indented under the event. */
	description?: string;
}

export interface CreationEnumerator {
	/** Module id, e.g. "rcal". */
	module: string;
	/** Human label shown in the rPast chip bar / filter UI. */
	label: string;
	/** Emoji for chip + section header. */
	icon: string;
	/** Color for the module tag in frontmatter. */
	color?: string;
	/** Walk owned docs and emit one Creation per record. */
	enumerate(ctx: { space: string; from?: number; to?: number }): Promise<Creation[]>;
}

const enumerators: Map<string, CreationEnumerator> = new Map();

export function registerCreationEnumerator(e: CreationEnumerator): void {
	enumerators.set(e.module, e);
}

export function listCreationEnumerators(): CreationEnumerator[] {
	return [...enumerators.values()];
}

export async function enumerateCreations(
	space: string,
	opts: { modules?: string[]; from?: number; to?: number } = {},
): Promise<MwSource[]> {
	const chosen = opts.modules
		? opts.modules.map(m => enumerators.get(m)).filter((e): e is CreationEnumerator => !!e)
		: [...enumerators.values()];

	const sources: MwSource[] = [];
	for (const e of chosen) {
		try {
			const creations = await e.enumerate({ space, from: opts.from, to: opts.to });
			if (creations.length === 0) continue;

			const events: MwEvent[] = creations.map(c => ({
				start: c.createdAt,
				// A creation is a point in time by default. If updatedAt is
				// meaningfully later, span it so the timeline can show the
				// "alive" range of the record.
				end: c.updatedAt && c.updatedAt - c.createdAt > 24 * 3600_000 ? c.updatedAt : undefined,
				title: `${c.title}`,
				description: c.description,
				tags: [c.recordType, ...(c.tags ?? [])],
				href: c.href,
				sourceId: `${e.module}:${c.recordType}:${c.recordId}`,
			}));

			sources.push({
				id: e.module,
				label: `${e.icon} ${e.label}`,
				tag: e.module,
				color: e.color,
				events,
			});
		} catch (err) {
			console.warn(`[rpast] enumerator ${e.module} failed:`, err);
		}
	}
	return sources;
}
