// SF Extension — Notify Interceptor
// Wraps ctx.ui.notify() in-place to persist every notification through the
// notification store. Uses a WeakSet to prevent double-wrapping and handle
// UI context replacement on /reload gracefully.

import type { ExtensionContext } from "@singularity-forge/pi-coding-agent";

import { logWarning } from "../workflow-logger.js";
import {
	appendNotification,
	type NotificationMetadata,
	type NotifySeverity,
} from "../notification-store.js";

// Track which ui context objects have been wrapped to prevent double-install.
// WeakSet allows GC to collect replaced uiContext instances after /reload.
const _wrappedContexts = new WeakSet<object>();

/**
 * Install the notify interceptor on a context's UI object.
 * Mutates ctx.ui.notify in place — the original is called after persistence.
 * Safe to call multiple times; no-ops if already installed on the same ui object.
 */
export function installNotifyInterceptor(ctx: ExtensionContext): void {
	if (_wrappedContexts.has(ctx.ui)) return;

	const originalNotify = ctx.ui.notify.bind(ctx.ui);

	(ctx.ui as any).notify = (
		message: string,
		type?: "info" | "warning" | "error" | "success",
		metadata?: NotificationMetadata,
	): void => {
		try {
			appendNotification(
				message,
				(type ?? "info") as NotifySeverity,
				"notify",
				metadata,
			);
		} catch (err) {
			// Non-fatal — never let persistence break the UI.
			// Include a correlation ID (timestamp + truncated message) so the
			// failure can be matched against the notification that was dropped.
			const correlationId = `${Date.now()}-${message.slice(0, 40).replace(/\s+/g, "_")}`;
			logWarning(
				"scaffold",
				`notification persistence failed (non-fatal) [corr:${correlationId}]: ${(err as Error).message}`,
			);
		}
		originalNotify(message, type, metadata as Record<string, unknown>);
	};

	_wrappedContexts.add(ctx.ui);
}
