import { init_write_file_atomic, writeTextAtomic } from "../../infra/write-file-atomic.js";
import { createLogger } from "../../utils/logger/index.js";
import { init_logger } from "../../utils/logger.js";
import { init_paths, resolveAgentDir } from "../../config/paths.js";
import { mkdir, readFile, readdir, rename } from "fs/promises";
import { join } from "path";
import { existsSync, watch } from "fs";
//#region src/agent/ipc/inbox.ts
init_write_file_atomic();
init_logger();
init_paths();
const log = createLogger("AgentInbox");
var AgentInbox = class AgentInbox {
	pendingDir;
	processedDir;
	watcher;
	constructor(agentDir) {
		this.pendingDir = join(agentDir, "inbox", "pending");
		this.processedDir = join(agentDir, "inbox", "processed");
	}
	/**
	* Static factory using agent ID (paths from config).
	*/
	static forAgent(config, agentId) {
		return new AgentInbox(resolveAgentDir(config, agentId));
	}
	/**
	* Enqueue a message
	*/
	async enqueue(message) {
		await mkdir(this.pendingDir, { recursive: true });
		await writeTextAtomic(join(this.pendingDir, `${message.id}.json`), JSON.stringify(message, null, 2));
		log.debug({
			messageId: message.id,
			to: message.to
		}, "Enqueued message");
	}
	/**
	* Dequeue the oldest pending message
	*/
	async dequeue() {
		await mkdir(this.pendingDir, { recursive: true });
		await mkdir(this.processedDir, { recursive: true });
		const files = await readdir(this.pendingDir).catch(() => []);
		if (files.length === 0) return null;
		const sorted = files.filter((f) => f.endsWith(".json")).sort();
		if (sorted.length === 0) return null;
		const fileName = sorted[0];
		const filePath = join(this.pendingDir, fileName);
		try {
			const content = await readFile(filePath, "utf-8");
			const message = JSON.parse(content);
			await rename(filePath, join(this.processedDir, fileName));
			log.debug({
				messageId: message.id,
				from: message.from
			}, "Dequeued message");
			return message;
		} catch (error) {
			log.warn({
				fileName,
				error
			}, "Failed to dequeue message");
			return null;
		}
	}
	/**
	* Peek at pending messages without removing them
	*/
	async peek(limit = 10) {
		await mkdir(this.pendingDir, { recursive: true });
		const jsonFiles = (await readdir(this.pendingDir).catch(() => [])).filter((f) => f.endsWith(".json")).sort();
		const messages = [];
		for (const fileName of jsonFiles.slice(0, limit)) try {
			const content = await readFile(join(this.pendingDir, fileName), "utf-8");
			const message = JSON.parse(content);
			messages.push(message);
		} catch (error) {
			log.warn({
				fileName,
				error
			}, "Failed to read message");
		}
		return messages;
	}
	/**
	* Count pending messages
	*/
	async count() {
		if (!existsSync(this.pendingDir)) return 0;
		return (await readdir(this.pendingDir).catch(() => [])).filter((f) => f.endsWith(".json")).length;
	}
	/**
	* Watch for new messages
	*/
	async watch(handler) {
		await mkdir(this.pendingDir, { recursive: true });
		await this.processPending(handler);
		this.watcher = watch(this.pendingDir, async (eventType, filename) => {
			if (eventType === "rename" && filename?.endsWith(".json")) await this.processPending(handler);
		});
		return () => {
			this.watcher?.close();
			this.watcher = void 0;
		};
	}
	/**
	* Stop watching
	*/
	stopWatching() {
		this.watcher?.close();
		this.watcher = void 0;
	}
	/**
	* Clear all processed messages
	*/
	async clearProcessed(olderThanMs) {
		if (!existsSync(this.processedDir)) return 0;
		const files = await readdir(this.processedDir).catch(() => []);
		const cutoff = olderThanMs ? Date.now() - olderThanMs : 0;
		let cleared = 0;
		for (const fileName of files) {
			if (!fileName.endsWith(".json")) continue;
			const filePath = join(this.processedDir, fileName);
			try {
				if (olderThanMs) {
					if ((await import("fs/promises").then((fs) => fs.stat(filePath))).mtimeMs < cutoff) {
						await import("fs/promises").then((fs) => fs.unlink(filePath));
						cleared++;
					}
				} else {
					await import("fs/promises").then((fs) => fs.unlink(filePath));
					cleared++;
				}
			} catch (error) {
				log.warn({
					fileName,
					error
				}, "Failed to clear processed message");
			}
		}
		return cleared;
	}
	async processPending(handler) {
		while (true) {
			const msg = await this.dequeue();
			if (!msg) break;
			try {
				await handler(msg);
			} catch (error) {
				log.error({
					messageId: msg.id,
					error
				}, "Error processing message");
			}
		}
	}
};
//#endregion
export { AgentInbox };

//# sourceMappingURL=inbox.js.map