/**
 * Shared presence broadcaster for rApps.
 *
 * Any rApp component can call broadcastPresence() or startPresenceHeartbeat()
 * to announce the user's current module and context to all peers in the space.
 * The collab overlay listens for these messages and displays module context
 * in the people panel.
 */

// ── Identity helpers ──

function getSessionInfo(): { username: string; userId: string } {
	try {
		const sess = JSON.parse(localStorage.getItem('encryptid_session') || '{}');
		const c = sess?.claims;
		return {
			username: c?.username || c?.displayName || sess?.username || 'Anonymous',
			userId: c?.sub || sess?.userId || 'anon',
		};
	} catch {
		return { username: 'Anonymous', userId: 'anon' };
	}
}

function userColor(id: string): string {
	let hash = 0;
	for (let i = 0; i < id.length; i++) {
		hash = ((hash << 5) - hash + id.charCodeAt(i)) | 0;
	}
	const hue = Math.abs(hash) % 360;
	return `hsl(${hue}, 70%, 50%)`;
}

// ── Public API ──

export interface PresenceOpts {
	module: string;
	context?: string;       // human-readable label (e.g. "Notebook > Note Title")
	notebookId?: string;    // module-specific metadata
	noteId?: string;        // module-specific metadata
	itemId?: string;        // generic item ID
}

/**
 * Broadcast current user's presence to all peers in the space.
 * Safe to call even if runtime isn't ready — silently no-ops.
 */
export function broadcastPresence(opts: PresenceOpts): void {
	const runtime = (window as any).__rspaceOfflineRuntime;
	if (!runtime?.isInitialized || !runtime.isOnline) return;
	const session = getSessionInfo();
	runtime.sendCustom({
		type: 'presence',
		module: opts.module,
		context: opts.context || '',
		notebookId: opts.notebookId,
		noteId: opts.noteId,
		itemId: opts.itemId,
		username: session.username,
		color: userColor(session.userId),
	});
}

/**
 * Broadcast a leave signal so peers can immediately remove us.
 */
export function broadcastLeave(): void {
	const runtime = (window as any).__rspaceOfflineRuntime;
	if (!runtime?.isInitialized || !runtime.isOnline) return;
	const session = getSessionInfo();
	runtime.sendCustom({
		type: 'presence-leave',
		username: session.username,
	});
}

/**
 * Start a 10-second heartbeat that broadcasts presence.
 * Returns a cleanup function to stop the heartbeat.
 *
 * @param getOpts - Called each heartbeat to get current presence state
 */
export function startPresenceHeartbeat(getOpts: () => PresenceOpts): () => void {
	broadcastPresence(getOpts());
	const timer = setInterval(() => broadcastPresence(getOpts()), 10_000);

	// Clean up immediately on page unload
	const onUnload = () => broadcastLeave();
	window.addEventListener('beforeunload', onUnload);

	return () => {
		clearInterval(timer);
		window.removeEventListener('beforeunload', onUnload);
	};
}
