/**
 * Tracks node visit frequency and recency for the context selector.
 * Uses localStorage to persist across sessions.
 *
 * Scoring: combines frequency (visit count) with recency (time decay)
 * to rank nodes in the context switcher dropdown.
 */

const STORAGE_KEY = 'synops_node_recency';
const MAX_ENTRIES = 50;

interface NodeVisit {
	/** Number of times visited */
	count: number;
	/** Last visit timestamp (ms since epoch) */
	lastVisit: number;
}

type RecencyMap = Record<string, NodeVisit>;

function load(): RecencyMap {
	try {
		const raw = localStorage.getItem(STORAGE_KEY);
		if (raw) return JSON.parse(raw) as RecencyMap;
	} catch { /* ignore corrupt data */ }
	return {};
}

function save(map: RecencyMap) {
	// Prune to MAX_ENTRIES, keeping highest-scored
	const entries = Object.entries(map);
	if (entries.length > MAX_ENTRIES) {
		const now = Date.now();
		entries.sort((a, b) => score(b[1], now) - score(a[1], now));
		const pruned: RecencyMap = {};
		for (let i = 0; i < MAX_ENTRIES; i++) {
			pruned[entries[i][0]] = entries[i][1];
		}
		localStorage.setItem(STORAGE_KEY, JSON.stringify(pruned));
	} else {
		localStorage.setItem(STORAGE_KEY, JSON.stringify(map));
	}
}

/** Score combines frequency with time decay (halves every 7 days). */
function score(visit: NodeVisit, now: number): number {
	const daysSince = (now - visit.lastVisit) / (1000 * 60 * 60 * 24);
	const decay = Math.pow(0.5, daysSince / 7);
	return visit.count * decay;
}

/** Record a visit to a node. Call when navigating to a collection. */
export function recordVisit(nodeId: string): void {
	const map = load();
	const existing = map[nodeId];
	map[nodeId] = {
		count: (existing?.count ?? 0) + 1,
		lastVisit: Date.now(),
	};
	save(map);
}

/** Get node IDs sorted by score (most relevant first). */
export function getRankedNodeIds(): string[] {
	const map = load();
	const now = Date.now();
	return Object.entries(map)
		.map(([id, visit]) => ({ id, score: score(visit, now) }))
		.sort((a, b) => b.score - a.score)
		.map(e => e.id);
}
