/**
 * rNotes → markwhen projection.
 *
 * Two strategies, applied in order:
 *   1. **Daily notes**: paths matching `YYYY-MM-DD` (anywhere in the path)
 *      become all-day events at that date. Title = note title.
 *   2. **Frontmatter dates**: any note with `frontmatter.date` (ISO) or
 *      `frontmatter.created` / `frontmatter.event_date` becomes a point
 *      event at that moment.
 *
 * Notes without extractable dates are silently skipped — this is a view
 * layer, not a completeness contract.
 */

import type { MarkwhenSourceFactory, MwEvent, MwSource } from '../types';
import type { VaultDoc, VaultNoteMeta } from '../../../modules/rnotes/schemas';
import { vaultDocId } from '../../../modules/rnotes/schemas';
import { loadDoc, listDocIds } from '../doc-loader';

const DAILY_RE = /(\d{4}-\d{2}-\d{2})(?!\d)/;

function extractDate(note: VaultNoteMeta): number | null {
	// Strategy 1: path-embedded YYYY-MM-DD
	const m = note.path.match(DAILY_RE);
	if (m) {
		const d = new Date(m[1] + 'T00:00:00Z');
		if (!isNaN(d.getTime())) return d.getTime();
	}
	// Strategy 2: frontmatter
	const fm = note.frontmatter ?? {};
	for (const key of ['date', 'created', 'event_date', 'published']) {
		const v = fm[key];
		if (typeof v === 'string' || typeof v === 'number') {
			const d = new Date(v);
			if (!isNaN(d.getTime())) return d.getTime();
		}
	}
	return null;
}

function noteToMw(vaultId: string, note: VaultNoteMeta): MwEvent | null {
	const ts = extractDate(note);
	if (ts === null) return null;

	const tags = note.tags?.length ? [...note.tags] : undefined;

	return {
		start: ts,
		title: note.title || note.path,
		description: undefined, // content is on-demand from ZIP — don't inline
		tags,
		href: `rspace://rnotes/${vaultId}/${encodeURIComponent(note.path)}`,
		sourceId: `rnotes:${vaultId}:${note.path}`,
	};
}

export const rnotesMarkwhenSource: MarkwhenSourceFactory = {
	module: 'rnotes',
	label: 'Notes',
	icon: '📓',
	async build({ space, from, to }): Promise<MwSource | null> {
		// Each vault is its own doc — fan out over all vaults in the space.
		const prefix = `${space}:rnotes:vaults:`;
		const docIds = await listDocIds(prefix);
		if (docIds.length === 0) return null;

		const events: MwEvent[] = [];
		for (const docId of docIds) {
			const vaultId = docId.slice(prefix.length);
			const doc = await loadDoc<VaultDoc>(vaultDocId(space, vaultId));
			if (!doc) continue;
			for (const note of Object.values(doc.notes)) {
				const mw = noteToMw(vaultId, note);
				if (!mw) continue;
				if (from !== undefined && mw.start < from) continue;
				if (to !== undefined && mw.start > to) continue;
				events.push(mw);
			}
		}

		if (events.length === 0) return null;

		return {
			id: 'rnotes',
			label: 'Notes',
			tag: 'rnotes',
			color: 'green',
			events,
		};
	},
};
