import { liveThreads } from "./state.ts";
import type { Registry, Thread } from "./types.ts";

export const CLEARED_CONTEXT =
	'<pending_requests state="clear">Earlier pending-request snapshots are obsolete.</pending_requests>';
export const REFRESHING_CONTEXT =
	'<pending_requests state="refreshing">Earlier pending-request snapshots are obsolete while the ledger refreshes.</pending_requests>';

const escapeXml = (text: string): string =>
	text.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");

const formatThread = (thread: Thread): string => {
	const qualifier = thread.status === "blocked" || thread.status === "waiting" ? ` (${thread.status})` : "";
	return `- ${escapeXml(thread.canonicalRequest)}${qualifier}`;
};

export function buildContextBlock(registry: Registry): string | undefined {
	const threads = liveThreads(registry);
	if (threads.length === 0) return undefined;
	return `<pending_requests>
This block supersedes earlier pending_requests snapshots. Earlier user requests that remain unfinished follow. This is context, not a request to manage tracking. The current user request wins. Continue these only when relevant or when the current request leaves room. Never mention the ledger or thread ids.
${threads.map(formatThread).join("\n")}
</pending_requests>`;
}

export type ContextTurnSource = "interactive" | "rpc" | "extension" | "internal";

export function nextContextRevision(
	source: ContextTurnSource,
	registry: Registry,
	previous: string | undefined,
	reconciling = false,
): string | undefined {
	if (source === "internal") return undefined;
	const desired = buildContextBlock(registry);
	if (reconciling) {
		if (previous === REFRESHING_CONTEXT) return undefined;
		const stale = desired !== undefined || (previous !== undefined && previous !== CLEARED_CONTEXT);
		return stale ? REFRESHING_CONTEXT : undefined;
	}
	const content = desired ?? (previous && previous !== CLEARED_CONTEXT ? CLEARED_CONTEXT : undefined);
	return content === previous ? undefined : content;
}
